refactor(cli): convert export command to effectCmd (#25471)
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
import type { Argv } from "yargs"
|
|
||||||
import { Session } from "@/session/session"
|
import { Session } from "@/session/session"
|
||||||
import { MessageV2 } from "../../session/message-v2"
|
import { MessageV2 } from "../../session/message-v2"
|
||||||
import { SessionID } from "../../session/schema"
|
import { SessionID } from "../../session/schema"
|
||||||
import { cmd } from "./cmd"
|
import { effectCmd, fail } from "../effect-cmd"
|
||||||
import { bootstrap } from "../bootstrap"
|
|
||||||
import { UI } from "../ui"
|
import { UI } from "../ui"
|
||||||
import * as prompts from "@clack/prompts"
|
import * as prompts from "@clack/prompts"
|
||||||
import { EOL } from "os"
|
import { EOL } from "os"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
import { Effect } from "effect"
|
||||||
|
import { InstanceRef } from "@/effect/instance-ref"
|
||||||
|
import { InstanceStore } from "@/project/instance-store"
|
||||||
|
|
||||||
function redact(kind: string, id: string, value: string) {
|
function redact(kind: string, id: string, value: string) {
|
||||||
return value.trim() ? `[redacted:${kind}:${id}]` : value
|
return value.trim() ? `[redacted:${kind}:${id}]` : value
|
||||||
@@ -220,11 +220,11 @@ function sanitize(data: { info: Session.Info; messages: MessageV2.WithParts[] })
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ExportCommand = cmd({
|
export const ExportCommand = effectCmd({
|
||||||
command: "export [sessionID]",
|
command: "export [sessionID]",
|
||||||
describe: "export session data as JSON",
|
describe: "export session data as JSON",
|
||||||
builder: (yargs: Argv) => {
|
builder: (yargs) =>
|
||||||
return yargs
|
yargs
|
||||||
.positional("sessionID", {
|
.positional("sessionID", {
|
||||||
describe: "session id to export",
|
describe: "session id to export",
|
||||||
type: "string",
|
type: "string",
|
||||||
@@ -232,72 +232,65 @@ export const ExportCommand = cmd({
|
|||||||
.option("sanitize", {
|
.option("sanitize", {
|
||||||
describe: "redact sensitive transcript and file data",
|
describe: "redact sensitive transcript and file data",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
})
|
}),
|
||||||
},
|
handler: Effect.fn("Cli.export")(function* (args) {
|
||||||
handler: async (args) => {
|
const ctx = yield* InstanceRef
|
||||||
await bootstrap(process.cwd(), async () => {
|
if (!ctx) return
|
||||||
let sessionID = args.sessionID ? SessionID.make(args.sessionID) : undefined
|
const store = yield* InstanceStore.Service
|
||||||
process.stderr.write(`Exporting session: ${sessionID ?? "latest"}\n`)
|
return yield* run(args).pipe(Effect.ensuring(store.dispose(ctx)))
|
||||||
|
}),
|
||||||
if (!sessionID) {
|
})
|
||||||
UI.empty()
|
|
||||||
prompts.intro("Export session", {
|
const run = Effect.fn("Cli.export.body")(function* (args: { sessionID?: string; sanitize?: boolean }) {
|
||||||
output: process.stderr,
|
const svc = yield* Session.Service
|
||||||
})
|
let sessionID = args.sessionID ? SessionID.make(args.sessionID) : undefined
|
||||||
|
process.stderr.write(`Exporting session: ${sessionID ?? "latest"}\n`)
|
||||||
const sessions = await AppRuntime.runPromise(Session.Service.use((svc) => svc.list()))
|
|
||||||
|
if (!sessionID) {
|
||||||
if (sessions.length === 0) {
|
UI.empty()
|
||||||
prompts.log.error("No sessions found", {
|
prompts.intro("Export session", { output: process.stderr })
|
||||||
output: process.stderr,
|
|
||||||
})
|
const sessions = yield* svc.list()
|
||||||
prompts.outro("Done", {
|
|
||||||
output: process.stderr,
|
if (sessions.length === 0) {
|
||||||
})
|
prompts.log.error("No sessions found", { output: process.stderr })
|
||||||
return
|
prompts.outro("Done", { output: process.stderr })
|
||||||
}
|
return
|
||||||
|
}
|
||||||
sessions.sort((a, b) => b.time.updated - a.time.updated)
|
|
||||||
|
sessions.sort((a, b) => b.time.updated - a.time.updated)
|
||||||
const selectedSession = await prompts.autocomplete({
|
|
||||||
message: "Select session to export",
|
const selectedSession = yield* Effect.promise(() =>
|
||||||
maxItems: 10,
|
prompts.autocomplete({
|
||||||
options: sessions.map((session) => ({
|
message: "Select session to export",
|
||||||
label: session.title,
|
maxItems: 10,
|
||||||
value: session.id,
|
options: sessions.map((session) => ({
|
||||||
hint: `${new Date(session.time.updated).toLocaleString()} • ${session.id.slice(-8)}`,
|
label: session.title,
|
||||||
})),
|
value: session.id,
|
||||||
output: process.stderr,
|
hint: `${new Date(session.time.updated).toLocaleString()} • ${session.id.slice(-8)}`,
|
||||||
})
|
})),
|
||||||
|
output: process.stderr,
|
||||||
if (prompts.isCancel(selectedSession)) {
|
}),
|
||||||
throw new UI.CancelledError()
|
)
|
||||||
}
|
|
||||||
|
if (prompts.isCancel(selectedSession)) {
|
||||||
sessionID = selectedSession
|
return yield* Effect.die(new UI.CancelledError())
|
||||||
|
}
|
||||||
prompts.outro("Exporting session...", {
|
|
||||||
output: process.stderr,
|
sessionID = selectedSession
|
||||||
})
|
|
||||||
}
|
prompts.outro("Exporting session...", { output: process.stderr })
|
||||||
|
}
|
||||||
try {
|
|
||||||
const sessionInfo = await AppRuntime.runPromise(Session.Service.use((svc) => svc.get(sessionID!)))
|
// Match legacy try/catch — catches both typed failures and defects
|
||||||
const messages = await AppRuntime.runPromise(
|
// (Session.Service.get throws NotFoundError as a defect, not a typed E).
|
||||||
Session.Service.use((svc) => svc.messages({ sessionID: sessionInfo.id })),
|
return yield* Effect.gen(function* () {
|
||||||
)
|
const sessionInfo = yield* svc.get(sessionID!)
|
||||||
|
const messages = yield* svc.messages({ sessionID: sessionInfo.id })
|
||||||
const exportData = {
|
|
||||||
info: sessionInfo,
|
const exportData = { info: sessionInfo, messages }
|
||||||
messages,
|
|
||||||
}
|
process.stdout.write(JSON.stringify(args.sanitize ? sanitize(exportData) : exportData, null, 2))
|
||||||
|
process.stdout.write(EOL)
|
||||||
process.stdout.write(JSON.stringify(args.sanitize ? sanitize(exportData) : exportData, null, 2))
|
}).pipe(Effect.catchCause(() => fail(`Session not found: ${sessionID!}`)))
|
||||||
process.stdout.write(EOL)
|
|
||||||
} catch {
|
|
||||||
UI.error(`Session not found: ${sessionID!}`)
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user