@x-otto/cli 0.0.1-alpha.20 → 0.0.1-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/otto.js +1 -1
- package/dist/{auth-command-kkJh-O5y.js → auth-command-D1T16ed-.js} +1 -1
- package/dist/{auth-command-kkJh-O5y.js.map → auth-command-D1T16ed-.js.map} +1 -1
- package/dist/bundled-extensions/plugin-otto-wire-protocols/plugin-dist/plugin.cjs +14 -12
- package/dist/command-dispatcher-ZyrfHgIk.js +21 -0
- package/dist/command-dispatcher-ZyrfHgIk.js.map +1 -0
- package/dist/{config-migration-0zdXsEDB.js → config-migration-DatflIxs.js} +1 -1
- package/dist/{config-migration-0zdXsEDB.js.map → config-migration-DatflIxs.js.map} +1 -1
- package/dist/{daemon-BtiaXSxn.js → daemon-COESl-zU.js} +1 -1
- package/dist/{daemon-BtiaXSxn.js.map → daemon-COESl-zU.js.map} +1 -1
- package/dist/{daemon-base-BzhYY4FS.js → daemon-base-YOWgYYN7.js} +1 -1
- package/dist/{daemon-base-BzhYY4FS.js.map → daemon-base-YOWgYYN7.js.map} +1 -1
- package/dist/{doctor-DbQC8Z7p.js → doctor-CuNvDmyA.js} +3 -3
- package/dist/{doctor-DbQC8Z7p.js.map → doctor-CuNvDmyA.js.map} +1 -1
- package/dist/{doctor-attach-OJHn8L52.js → doctor-attach-_zeIJewx.js} +2 -2
- package/dist/{doctor-attach-OJHn8L52.js.map → doctor-attach-_zeIJewx.js.map} +1 -1
- package/dist/{doctor-cdp-D66ChCCN.js → doctor-cdp-K_mIFRfA.js} +1 -1
- package/dist/{doctor-cdp-D66ChCCN.js.map → doctor-cdp-K_mIFRfA.js.map} +1 -1
- package/dist/{doctor-heap-Brsro5QJ.js → doctor-heap-Rr2nNvcw.js} +2 -2
- package/dist/{doctor-heap-Brsro5QJ.js.map → doctor-heap-Rr2nNvcw.js.map} +1 -1
- package/dist/{doctor-ps-B4Syy9qa.js → doctor-ps-OL3FGQYu.js} +2 -2
- package/dist/{doctor-ps-B4Syy9qa.js.map → doctor-ps-OL3FGQYu.js.map} +1 -1
- package/dist/feedback-B-d-GV2J.js +2 -0
- package/dist/{feedback-DrUjMuKw.js → feedback-DuTIx3-K.js} +1 -1
- package/dist/{feedback-DrUjMuKw.js.map → feedback-DuTIx3-K.js.map} +1 -1
- package/dist/{feishu-setup-C2UDdpIm.js → feishu-setup-B6ETf-8Y.js} +1 -1
- package/dist/{feishu-setup-C2UDdpIm.js.map → feishu-setup-B6ETf-8Y.js.map} +1 -1
- package/dist/{ftue-doctor-recovery-DhiseXnP.js → ftue-doctor-recovery-DeAf8jVo.js} +1 -1
- package/dist/{ftue-doctor-recovery-DhiseXnP.js.map → ftue-doctor-recovery-DeAf8jVo.js.map} +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/{install-hTDjeo61.js → install-DlVJRHRT.js} +1 -1
- package/dist/{install-hTDjeo61.js.map → install-DlVJRHRT.js.map} +1 -1
- package/dist/install-WCcQ9k9M.js +2 -0
- package/dist/{mcp-BDfBf6gx.js → mcp-DbTYT7hB.js} +1 -1
- package/dist/{mcp-BDfBf6gx.js.map → mcp-DbTYT7hB.js.map} +1 -1
- package/dist/{migrate-4QDwYLf6.js → migrate-boDXhEyV.js} +2 -2
- package/dist/{migrate-4QDwYLf6.js.map → migrate-boDXhEyV.js.map} +1 -1
- package/dist/observe-CZ96Vre9.js +83 -0
- package/dist/observe-CZ96Vre9.js.map +1 -0
- package/dist/{parse-cli-klcuBpG2.js → parse-cli-CqocMnXY.js} +2 -2
- package/dist/{parse-cli-klcuBpG2.js.map → parse-cli-CqocMnXY.js.map} +1 -1
- package/dist/persistence-CTXa-OyC.js +85 -0
- package/dist/persistence-CTXa-OyC.js.map +1 -0
- package/dist/{plugin-assembly-check-CvuJ4dHf.js → plugin-assembly-check-C2TephMb.js} +1 -1
- package/dist/{plugin-assembly-check-CvuJ4dHf.js.map → plugin-assembly-check-C2TephMb.js.map} +1 -1
- package/dist/proxy-BvdBsB1O.js +2 -0
- package/dist/{proxy-CMQBvdZC.js → proxy-evg7ZvoD.js} +1 -1
- package/dist/{proxy-CMQBvdZC.js.map → proxy-evg7ZvoD.js.map} +1 -1
- package/dist/{ps-Kb6ZsEpC.js → ps-DKrluEuy.js} +1 -1
- package/dist/{ps-Kb6ZsEpC.js.map → ps-DKrluEuy.js.map} +1 -1
- package/dist/registry-BOX7DaxS.js +2 -0
- package/dist/{registry-Cr5To_5r.js → registry-BdCcwyGy.js} +2 -2
- package/dist/{registry-Cr5To_5r.js.map → registry-BdCcwyGy.js.map} +1 -1
- package/dist/{run-attach-CgYMem8s.js → run-attach-CvGCWF_i.js} +1 -1
- package/dist/{run-attach-CgYMem8s.js.map → run-attach-CvGCWF_i.js.map} +1 -1
- package/dist/{serve-Bq21zw1O.js → serve-Dbn3THez.js} +2 -2
- package/dist/{serve-Bq21zw1O.js.map → serve-Dbn3THez.js.map} +1 -1
- package/package.json +2 -2
- package/dist/command-dispatcher-CahuAJnO.js +0 -17
- package/dist/command-dispatcher-CahuAJnO.js.map +0 -1
- package/dist/debug-DfgcrVCI.js +0 -34
- package/dist/debug-DfgcrVCI.js.map +0 -1
- package/dist/extension-plugin-BEQlmUET.js +0 -2
- package/dist/extension-plugin-BYR-MJ1U.js +0 -7
- package/dist/extension-plugin-BYR-MJ1U.js.map +0 -1
- package/dist/feedback-DjNFsjeN.js +0 -2
- package/dist/install-DkJgbg2p.js +0 -2
- package/dist/model-auth-BMY86Bk4.js +0 -3
- package/dist/model-auth-BMY86Bk4.js.map +0 -1
- package/dist/model-auth-CSLiEFJ-.js +0 -2
- package/dist/observe-DSrUS2YI.js +0 -34
- package/dist/observe-DSrUS2YI.js.map +0 -1
- package/dist/persistenced-CW8sdhd0.js +0 -36
- package/dist/persistenced-CW8sdhd0.js.map +0 -1
- package/dist/proxy-TzOLqtkc.js +0 -2
- package/dist/registry-DAJ7oZTe.js +0 -2
- package/dist/remote-persistence-server-BLBIop0u.js +0 -35
- package/dist/remote-persistence-server-BLBIop0u.js.map +0 -1
- package/dist/time-travel-8X-uAgHw.js +0 -21
- package/dist/time-travel-8X-uAgHw.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"observe-DSrUS2YI.js","names":[],"sources":["../src/commands/observe.ts"],"sourcesContent":["/**\n * `otto observe` 子命令 —— 观测面板:trace 时间线 / 摘要 / span 树。\n *\n * 设计依据:design/observability-platform.md §4/§5 + design/m17-platform-activation.md §3。\n * 数据源 = service REST。\n * 默认连 `http://127.0.0.1:${SERVICE_PORT}`(`otto serve` 启动),`--remote <url>` 覆盖;\n * service 不可达 → 明确报错而非静默空数据。聚合算法在 @x-otto/agent,两端同源。\n */\nimport { SERVICE_URL } from '@x-otto/env'\n\nimport {\n createServiceClient,\n reportServiceError,\n resolveRemote,\n type ServiceClient,\n} from './service-client'\nimport { runDebugCommand } from './debug'\nimport { runTimeTravelCommand } from './time-travel'\nimport type { TraceSpan, TraceSummary } from '@x-otto/agent'\nimport type { TraceTimelineView } from '@x-otto/trace-view'\n\nexport interface ObserveDeps {\n /** 输出(便于测试注入)。 */\n stdout?: (s: string) => void\n stderr?: (s: string) => void\n /** fetch 注入(测试用)。 */\n fetch?: typeof globalThis.fetch\n}\n\nexport async function runObserveCommand(\n args: string[],\n deps: ObserveDeps = {},\n): Promise<number> {\n const stdout = deps.stdout ?? ((s) => process.stdout.write(s))\n const stderr = deps.stderr ?? ((s) => process.stderr.write(s))\n\n // RFC-367 M4:observe 吸收 debug/time-travel 为子命令。\n // `otto observe debug ...` → runDebugCommand\n // `otto observe replay ...` → runTimeTravelCommand\n const [subCommand, ...subRest] = args\n if (subCommand === 'debug') {\n return runDebugCommand(subRest, deps)\n }\n if (subCommand === 'replay') {\n return runTimeTravelCommand(subRest, deps)\n }\n\n // 提取 --json 标志(在 resolveRemote 之前,避免被当作 remote URL)\n const jsonIdx = args.indexOf('--json')\n const json = jsonIdx >= 0\n const cleanArgs = json ? args.filter((_, i) => i !== jsonIdx) : args\n\n let baseUrl: string\n let rest: string[]\n try {\n ;({ baseUrl, rest } = resolveRemote(cleanArgs))\n } catch (error) {\n return reportServiceError('observe', error, stderr)\n }\n\n const [action, sessionId] = rest\n\n if (!action || action === 'help') {\n stdout(`otto observe — 观测面板(trace 时间线 / 摘要 / span 树)\n\n用法:\n otto observe summary <session-id> trace 聚合统计\n otto observe timeline <session-id> 文本时间线\n otto observe spans <session-id> span 树视图\n otto observe debug <action> [...] 调试面板(breakpoints / points / state)\n otto observe replay <action> <id> 时间旅行(checkpoints / scrubber / restore / fork / replay)\n\n选项:\n --remote <url> service 地址(默认 OTTO_SERVICE_URL 或 ${SERVICE_URL})\n --json 输出结构化 JSON(需 service 运行)\n`)\n return 0\n }\n\n if (!sessionId) {\n stderr('otto observe: session-id is required.\\n')\n return 1\n }\n\n const client = createServiceClient(baseUrl, deps.fetch)\n\n try {\n // --json 模式:调用 /trace/timeline 输出结构化 JSON\n if (json) {\n return await observeJson(client, sessionId, stdout, stderr)\n }\n switch (action) {\n case 'summary':\n return await observeSummary(client, sessionId, stdout)\n case 'timeline':\n return await observeTimeline(client, sessionId, stdout)\n case 'spans':\n return await observeSpans(client, sessionId, stdout)\n default:\n stderr(`otto observe: unknown action '${action}'. Use summary | timeline | spans.\\n`)\n return 1\n }\n } catch (error) {\n return reportServiceError('observe', error, stderr)\n }\n}\n\nfunction fetchSpans(client: ServiceClient, sessionId: string): Promise<{ spans: TraceSpan[] }> {\n return client.get<{ spans: TraceSpan[] }>(`/api/sessions/${sessionId}/trace/spans`)\n}\n\nasync function observeSummary(\n client: ServiceClient,\n sessionId: string,\n stdout: (s: string) => void,\n): Promise<number> {\n const summary = await client.get<TraceSummary>(`/api/sessions/${sessionId}/trace/summary`)\n\n if (summary.totalEvents === 0) {\n stdout(`Session ${sessionId}: no trace events found.\\n`)\n return 0\n }\n\n const { totalEvents, kinds, turns, toolCalls, firstTs, lastTs } = summary\n const duration = firstTs !== undefined && lastTs !== undefined ? `${lastTs - firstTs}ms` : 'N/A'\n\n stdout(`Trace Summary — ${sessionId}\n──────────────────────────────────────────\n Total events: ${totalEvents}\n Turns: ${turns}\n Tool calls: ${toolCalls}\n Time span: ${duration}\n First event: ${firstTs ? new Date(firstTs).toISOString() : 'N/A'}\n Last event: ${lastTs ? new Date(lastTs).toISOString() : 'N/A'}\n\n By kind:\n${Object.entries(kinds).map(([k, v]) => ` ${k.padEnd(14)} ${v}`).join('\\n')}\n`)\n return 0\n}\n\nasync function observeTimeline(\n client: ServiceClient,\n sessionId: string,\n stdout: (s: string) => void,\n): Promise<number> {\n const { spans } = await fetchSpans(client, sessionId)\n if (spans.length === 0) {\n stdout(`Session ${sessionId}: no trace events found.\\n`)\n return 0\n }\n\n const lines = spans.map((span) => {\n const ts = new Date(span.ts).toISOString().slice(11, 23)\n const turn = span.turn !== undefined ? `T${String(span.turn).padStart(2)}` : ' -'\n const node = (span.node ?? '').padEnd(26)\n return `${String(span.seq).padStart(5)} ${ts} ${turn} ${span.kind.padEnd(12)} ${node}${span.digest ?? ''}`\n })\n\n stdout(`Trace Timeline — ${sessionId} (${lines.length} events)\n${'seq'.padStart(5)} ${'time'} ${'turn'} ${'kind'.padEnd(12)} ${'node'.padEnd(26)} digest\n${'-'.repeat(100)}\n${lines.join('\\n')}\n`)\n return 0\n}\n\nasync function observeSpans(\n client: ServiceClient,\n sessionId: string,\n stdout: (s: string) => void,\n): Promise<number> {\n const { spans } = await fetchSpans(client, sessionId)\n if (spans.length === 0) {\n stdout(`Session ${sessionId}: no trace events found.\\n`)\n return 0\n }\n\n const turnSpans = new Map<number, TraceSpan[]>()\n let maxTurn = -1\n for (const span of spans) {\n const turn = span.turn ?? 0\n if (turn > maxTurn) maxTurn = turn\n const group = turnSpans.get(turn) ?? []\n group.push(span)\n turnSpans.set(turn, group)\n }\n\n stdout(`Trace Spans — ${sessionId} (${maxTurn + 1} turns)\n`)\n for (let t = 0; t <= maxTurn; t++) {\n const group = turnSpans.get(t)\n if (!group) continue\n stdout(`▼ Turn ${t} (${group.length} events)\\n`)\n for (const span of group) {\n const node = span.node ? `[${span.node}] ` : ''\n stdout(` ├─ ${span.kind.padEnd(12)} ${node}${span.digest ?? ''}\\n`)\n }\n }\n return 0\n}\n\nasync function observeJson(\n client: ServiceClient,\n sessionId: string,\n stdout: (s: string) => void,\n stderr: (s: string) => void,\n): Promise<number> {\n try {\n const timeline = await client.get<TraceTimelineView>(\n `/api/sessions/${sessionId}/trace/timeline`,\n )\n stdout(`${JSON.stringify(timeline, null, 2)}\\n`)\n return 0\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n stderr(`observe --json: ${msg}\\n`)\n return 1\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import{t as e}from"./daemon-base-BzhYY4FS.js";import{PERSISTENCED_DEFAULT_PORT as t,startPersistenced as n}from"@x-otto/service";const r=t,i=`127.0.0.1`;async function a(t,a={}){let s=a.stdout??(e=>process.stdout.write(e)),c=a.stderr??(e=>process.stderr.write(e));if(t[0]===`help`||t[0]===`--help`)return o(s),0;let l,u=r,d=i,f;for(let e=0;e<t.length;e++){let n=t[e];if(n===`--dir`||n===`-d`)l=t[++e];else if(n===`--port`||n===`-p`){let n=t[++e],r=Number(n);if(!Number.isInteger(r)||r<1||r>65535)return c(`otto persistenced: invalid --port value: ${n??`(missing)`}\n`),1;u=r}else n===`--host`||n===`-h`?d=t[++e]??i:(n===`--token`||n===`-t`)&&(f=t[++e])}if(!l)return c(`otto persistenced: --dir is required
|
|
3
|
-
`),1;if(!f)return c(`otto persistenced: --token is required
|
|
4
|
-
`),1;try{let{url:t}=await n({dir:l,port:u,host:d,token:f});return s(`persistenced listening on ${t}
|
|
5
|
-
storage: ${t}/api/storage/:namespace
|
|
6
|
-
events: ${t}/api/events/:namespace (SSE)
|
|
7
|
-
sync: ${t}/api/sync/:namespace
|
|
8
|
-
health: ${t}/health
|
|
9
|
-
stop: Ctrl-C
|
|
10
|
-
`),await e(a.signal),s(`persistenced shutting down
|
|
11
|
-
`),0}catch(e){return c(`otto persistenced: ${e instanceof Error?e.message:String(e)}\n`),1}}function o(e){e(`otto persistenced — 独立持久化存储服务(SQLite + HTTP API)
|
|
12
|
-
|
|
13
|
-
用法:
|
|
14
|
-
otto persistenced --dir <path> --token <token> [--port <n>] [--host <ip>]
|
|
15
|
-
|
|
16
|
-
选项:
|
|
17
|
-
--dir, -d <path> 数据目录(SQLite db 文件存放位置,必填)
|
|
18
|
-
--token, -t <token> Bearer token(所有 /api/* 请求必须携带,必填)
|
|
19
|
-
--port, -p <n> 监听端口(默认 ${r})
|
|
20
|
-
--host, -h <ip> 监听地址(默认 ${i},0.0.0.0 = 公网暴露)
|
|
21
|
-
|
|
22
|
-
示例:
|
|
23
|
-
otto persistenced --dir /var/lib/otto/storage --token "\$TOKEN"
|
|
24
|
-
otto persistenced --dir ./data --port 3002 --token dev-secret
|
|
25
|
-
|
|
26
|
-
端点:
|
|
27
|
-
GET /health 健康检查
|
|
28
|
-
GET /api/storage/:namespace 列出文档 ID / 分页列表
|
|
29
|
-
GET /api/storage/:namespace/:id 读取文档
|
|
30
|
-
PUT /api/storage/:namespace/:id 写入文档
|
|
31
|
-
DELETE /api/storage/:namespace/:id 删除文档
|
|
32
|
-
GET /api/events/:namespace SSE 变更推送
|
|
33
|
-
POST /api/sync/:namespace/push 批量写入(离线同步)
|
|
34
|
-
GET /api/sync/:namespace/pull 增量拉取
|
|
35
|
-
`)}export{a as runPersistencedCommand};
|
|
36
|
-
//# sourceMappingURL=persistenced-CW8sdhd0.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"persistenced-CW8sdhd0.js","names":[],"sources":["../src/commands/persistenced.ts"],"sourcesContent":["import { startPersistenced, PERSISTENCED_DEFAULT_PORT } from '@x-otto/service'\n\nimport { waitForShutdown } from './daemon-base'\n\nexport interface PersistencedDeps {\n stdout?: (s: string) => void\n stderr?: (s: string) => void\n signal?: AbortSignal\n}\n\n/** 复用 @x-otto/service 的族内单源默认端口,消除双源漂移。 */\nconst DEFAULT_PORT = PERSISTENCED_DEFAULT_PORT\nconst DEFAULT_HOST = '127.0.0.1'\n\nexport async function runPersistencedCommand(\n args: string[],\n deps: PersistencedDeps = {},\n): Promise<number> {\n const stdout = deps.stdout ?? ((s) => process.stdout.write(s))\n const stderr = deps.stderr ?? ((s) => process.stderr.write(s))\n\n if (args[0] === 'help' || args[0] === '--help') {\n printHelp(stdout)\n return 0\n }\n\n let dir: string | undefined\n let port = DEFAULT_PORT\n let host = DEFAULT_HOST\n let token: string | undefined\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]\n if (arg === '--dir' || arg === '-d') {\n dir = args[++i]\n } else if (arg === '--port' || arg === '-p') {\n const raw = args[++i]\n const n = Number(raw)\n if (!Number.isInteger(n) || n < 1 || n > 65535) {\n stderr(`otto persistenced: invalid --port value: ${raw ?? '(missing)'}\\n`)\n return 1\n }\n port = n\n } else if (arg === '--host' || arg === '-h') {\n host = args[++i] ?? DEFAULT_HOST\n } else if (arg === '--token' || arg === '-t') {\n token = args[++i]\n }\n }\n\n if (!dir) {\n stderr('otto persistenced: --dir is required\\n')\n return 1\n }\n\n if (!token) {\n stderr('otto persistenced: --token is required\\n')\n return 1\n }\n\n try {\n const { url } = await startPersistenced({ dir, port, host, token })\n\n stdout(`persistenced listening on ${url}\n storage: ${url}/api/storage/:namespace\n events: ${url}/api/events/:namespace (SSE)\n sync: ${url}/api/sync/:namespace\n health: ${url}/health\n stop: Ctrl-C\n`)\n\n await waitForShutdown(deps.signal)\n stdout('persistenced shutting down\\n')\n return 0\n } catch (error) {\n stderr(\n `otto persistenced: ${error instanceof Error ? error.message : String(error)}\\n`,\n )\n return 1\n }\n}\n\nfunction printHelp(stdout: (s: string) => void): void {\n stdout(`otto persistenced — 独立持久化存储服务(SQLite + HTTP API)\n\n用法:\n otto persistenced --dir <path> --token <token> [--port <n>] [--host <ip>]\n\n选项:\n --dir, -d <path> 数据目录(SQLite db 文件存放位置,必填)\n --token, -t <token> Bearer token(所有 /api/* 请求必须携带,必填)\n --port, -p <n> 监听端口(默认 ${DEFAULT_PORT})\n --host, -h <ip> 监听地址(默认 ${DEFAULT_HOST},0.0.0.0 = 公网暴露)\n\n示例:\n otto persistenced --dir /var/lib/otto/storage --token \"\\$TOKEN\"\n otto persistenced --dir ./data --port 3002 --token dev-secret\n\n端点:\n GET /health 健康检查\n GET /api/storage/:namespace 列出文档 ID / 分页列表\n GET /api/storage/:namespace/:id 读取文档\n PUT /api/storage/:namespace/:id 写入文档\n DELETE /api/storage/:namespace/:id 删除文档\n GET /api/events/:namespace SSE 变更推送\n POST /api/sync/:namespace/push 批量写入(离线同步)\n GET /api/sync/:namespace/pull 增量拉取\n`)\n}\n\n"],"mappings":";iIAWA,MAAM,EAAe,EACf,EAAe,YAErB,eAAsB,EACpB,EACA,EAAyB,EAAE,CACV,CACjB,IAAM,EAAS,EAAK,SAAY,GAAM,QAAQ,OAAO,MAAM,EAAE,EACvD,EAAS,EAAK,SAAY,GAAM,QAAQ,OAAO,MAAM,EAAE,EAE7D,GAAI,EAAK,KAAO,QAAU,EAAK,KAAO,SAEpC,OADA,EAAU,EAAO,CACV,EAGT,IAAI,EACA,EAAO,EACP,EAAO,EACP,EAEJ,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAQ,IAAK,CACpC,IAAM,EAAM,EAAK,GACjB,GAAI,IAAQ,SAAW,IAAQ,KAC7B,EAAM,EAAK,EAAE,WACJ,IAAQ,UAAY,IAAQ,KAAM,CAC3C,IAAM,EAAM,EAAK,EAAE,GACb,EAAI,OAAO,EAAI,CACrB,GAAI,CAAC,OAAO,UAAU,EAAE,EAAI,EAAI,GAAK,EAAI,MAEvC,OADA,EAAO,4CAA4C,GAAO,YAAY,IAAI,CACnE,EAET,EAAO,OACE,IAAQ,UAAY,IAAQ,KACrC,EAAO,EAAK,EAAE,IAAM,GACX,IAAQ,WAAa,IAAQ,QACtC,EAAQ,EAAK,EAAE,IAInB,GAAI,CAAC,EAEH,OADA,EAAO;EAAyC,CACzC,EAGT,GAAI,CAAC,EAEH,OADA,EAAO;EAA2C,CAC3C,EAGT,GAAI,CACF,GAAM,CAAE,OAAQ,MAAM,EAAkB,CAAE,MAAK,OAAM,OAAM,QAAO,CAAC,CAYnE,OAVA,EAAO,6BAA6B,EAAI;cAC9B,EAAI;cACJ,EAAI;cACJ,EAAI;cACJ,EAAI;;EAEhB,CAEE,MAAM,EAAgB,EAAK,OAAO,CAClC,EAAO;EAA+B,CAC/B,QACA,EAAO,CAId,OAHA,EACE,sBAAsB,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAAC,IAC9E,CACM,GAIX,SAAS,EAAU,EAAmC,CACpD,EAAO;;;;;;;;gCAQuB,EAAa;gCACb,EAAa;;;;;;;;;;;;;;;EAe3C"}
|
package/dist/proxy-TzOLqtkc.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import{t as e}from"./daemon-base-BzhYY4FS.js";import{REMOTE_PERSISTENCE_DEFAULT_PORT as t}from"@x-otto/remote-persistence-server";const n=t,r=`127.0.0.1`;async function i(t,i={}){let o=i.stdout??(e=>process.stdout.write(e)),s=i.stderr??(e=>process.stderr.write(e));if(t[0]===`help`||t[0]===`--help`)return a(o),0;let c,l=n,u=r,d;for(let e=0;e<t.length;e++){let n=t[e];if(n===`--dir`||n===`-d`)c=t[++e];else if(n===`--port`||n===`-p`){let n=t[++e],r=Number(n);if(!Number.isInteger(r)||r<1||r>65535)return s(`otto remote-persistence-server: invalid --port value: ${n??`(missing)`}\n`),1;l=r}else n===`--host`||n===`-h`?u=t[++e]??r:(n===`--token`||n===`-t`)&&(d=t[++e])}if(!c)return s(`otto remote-persistence-server: --dir is required
|
|
3
|
-
`),1;if(d===void 0)return s(`otto remote-persistence-server: --token is required (use --token "" to disable auth for dev only)
|
|
4
|
-
`),1;let{startServer:f}=await import(`@x-otto/remote-persistence-server`);try{let{url:t,server:n,store:r}=await f({dataDir:c,port:l,authToken:d},{host:u});return o(`remote-persistence-server listening on ${t}
|
|
5
|
-
sessions: ${t}/sessions
|
|
6
|
-
health: ${t}/health
|
|
7
|
-
stop: Ctrl-C
|
|
8
|
-
`),await e(i.signal),o(`remote-persistence-server shutting down
|
|
9
|
-
`),await new Promise(e=>n.close(()=>e())),r.close(),0}catch(e){return s(`otto remote-persistence-server: ${e instanceof Error?e.message:String(e)}\n`),1}}function a(e){e(`otto remote-persistence-server — 最小化远程持久化服务(Hono + SQLite,5 REST 端点)
|
|
10
|
-
|
|
11
|
-
用法:
|
|
12
|
-
otto remote-persistence-server --dir <path> --token <token> [--port <n>] [--host <ip>]
|
|
13
|
-
|
|
14
|
-
选项:
|
|
15
|
-
--dir, -d <path> 数据目录(SQLite db 文件存放位置,必填)
|
|
16
|
-
--token, -t <token> Bearer token(所有 /sessions/* 请求必须携带,必填)
|
|
17
|
-
--port, -p <n> 监听端口(默认 ${n})
|
|
18
|
-
--host, -h <ip> 监听地址(默认 ${r},0.0.0.0 = 公网暴露)
|
|
19
|
-
|
|
20
|
-
示例:
|
|
21
|
-
otto remote-persistence-server --dir ./data --token dev-secret
|
|
22
|
-
otto remote-persistence-server --dir /var/lib/otto/storage --port 3002 --token "\$TOKEN"
|
|
23
|
-
|
|
24
|
-
端点(:wsKey 为客户端工作区分区段,本服务 accept-and-ignore,按 token 派生 userId 分区):
|
|
25
|
-
GET /health 健康检查(无需认证)
|
|
26
|
-
GET /sessions/:wsKey 列出会话 ID(需要 Bearer token)
|
|
27
|
-
GET /sessions/:wsKey/:id 读取会话快照
|
|
28
|
-
PUT /sessions/:wsKey/:id 写入/更新会话快照
|
|
29
|
-
DELETE /sessions/:wsKey/:id 删除会话快照
|
|
30
|
-
|
|
31
|
-
对端客户端:
|
|
32
|
-
另一台机器上的 Otto CLI:
|
|
33
|
-
otto --session-url http://<host>:<port>/sessions --session-token <token>
|
|
34
|
-
`)}export{i as runRemotePersistenceServerCommand};
|
|
35
|
-
//# sourceMappingURL=remote-persistence-server-BLBIop0u.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"remote-persistence-server-BLBIop0u.js","names":[],"sources":["../src/commands/remote-persistence-server.ts"],"sourcesContent":["import { REMOTE_PERSISTENCE_DEFAULT_PORT, type ServerConfig } from '@x-otto/remote-persistence-server'\n\nimport { waitForShutdown } from './daemon-base'\n\nexport interface RemotePersistenceServerDeps {\n stdout?: (s: string) => void\n stderr?: (s: string) => void\n signal?: AbortSignal\n}\n\n/** 复用 @x-otto/remote-persistence-server 的族内单源默认端口,消除双源漂移。 */\nconst DEFAULT_PORT = REMOTE_PERSISTENCE_DEFAULT_PORT\nconst DEFAULT_HOST = '127.0.0.1'\n\nexport async function runRemotePersistenceServerCommand(\n args: string[],\n deps: RemotePersistenceServerDeps = {},\n): Promise<number> {\n const stdout = deps.stdout ?? ((s) => process.stdout.write(s))\n const stderr = deps.stderr ?? ((s) => process.stderr.write(s))\n\n if (args[0] === 'help' || args[0] === '--help') {\n printHelp(stdout)\n return 0\n }\n\n let dir: string | undefined\n let port = DEFAULT_PORT\n let host = DEFAULT_HOST\n let token: string | undefined\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]\n if (arg === '--dir' || arg === '-d') {\n dir = args[++i]\n } else if (arg === '--port' || arg === '-p') {\n const raw = args[++i]\n const n = Number(raw)\n if (!Number.isInteger(n) || n < 1 || n > 65535) {\n stderr(\n `otto remote-persistence-server: invalid --port value: ${raw ?? '(missing)'}\\n`,\n )\n return 1\n }\n port = n\n } else if (arg === '--host' || arg === '-h') {\n host = args[++i] ?? DEFAULT_HOST\n } else if (arg === '--token' || arg === '-t') {\n token = args[++i]\n }\n }\n\n if (!dir) {\n stderr('otto remote-persistence-server: --dir is required\\n')\n return 1\n }\n\n if (token === undefined) {\n stderr(\n 'otto remote-persistence-server: --token is required (use --token \"\" to disable auth for dev only)\\n',\n )\n return 1\n }\n\n const { startServer } = await import('@x-otto/remote-persistence-server')\n\n try {\n const config: ServerConfig = { dataDir: dir, port, authToken: token }\n const { url, server, store } = await startServer(config, { host })\n\n stdout(`remote-persistence-server listening on ${url}\n sessions: ${url}/sessions\n health: ${url}/health\n stop: Ctrl-C\n`)\n\n await waitForShutdown(deps.signal)\n stdout('remote-persistence-server shutting down\\n')\n await new Promise<void>((resolve) => server.close(() => resolve()))\n store.close()\n return 0\n } catch (error) {\n stderr(\n `otto remote-persistence-server: ${error instanceof Error ? error.message : String(error)}\\n`,\n )\n return 1\n }\n}\n\nfunction printHelp(stdout: (s: string) => void): void {\n stdout(`otto remote-persistence-server — 最小化远程持久化服务(Hono + SQLite,5 REST 端点)\n\n用法:\n otto remote-persistence-server --dir <path> --token <token> [--port <n>] [--host <ip>]\n\n选项:\n --dir, -d <path> 数据目录(SQLite db 文件存放位置,必填)\n --token, -t <token> Bearer token(所有 /sessions/* 请求必须携带,必填)\n --port, -p <n> 监听端口(默认 ${DEFAULT_PORT})\n --host, -h <ip> 监听地址(默认 ${DEFAULT_HOST},0.0.0.0 = 公网暴露)\n\n示例:\n otto remote-persistence-server --dir ./data --token dev-secret\n otto remote-persistence-server --dir /var/lib/otto/storage --port 3002 --token \"\\$TOKEN\"\n\n端点(:wsKey 为客户端工作区分区段,本服务 accept-and-ignore,按 token 派生 userId 分区):\n GET /health 健康检查(无需认证)\n GET /sessions/:wsKey 列出会话 ID(需要 Bearer token)\n GET /sessions/:wsKey/:id 读取会话快照\n PUT /sessions/:wsKey/:id 写入/更新会话快照\n DELETE /sessions/:wsKey/:id 删除会话快照\n\n对端客户端:\n 另一台机器上的 Otto CLI:\n otto --session-url http://<host>:<port>/sessions --session-token <token>\n`)\n}\n"],"mappings":";kIAWA,MAAM,EAAe,EACf,EAAe,YAErB,eAAsB,EACpB,EACA,EAAoC,EAAE,CACrB,CACjB,IAAM,EAAS,EAAK,SAAY,GAAM,QAAQ,OAAO,MAAM,EAAE,EACvD,EAAS,EAAK,SAAY,GAAM,QAAQ,OAAO,MAAM,EAAE,EAE7D,GAAI,EAAK,KAAO,QAAU,EAAK,KAAO,SAEpC,OADA,EAAU,EAAO,CACV,EAGT,IAAI,EACA,EAAO,EACP,EAAO,EACP,EAEJ,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAQ,IAAK,CACpC,IAAM,EAAM,EAAK,GACjB,GAAI,IAAQ,SAAW,IAAQ,KAC7B,EAAM,EAAK,EAAE,WACJ,IAAQ,UAAY,IAAQ,KAAM,CAC3C,IAAM,EAAM,EAAK,EAAE,GACb,EAAI,OAAO,EAAI,CACrB,GAAI,CAAC,OAAO,UAAU,EAAE,EAAI,EAAI,GAAK,EAAI,MAIvC,OAHA,EACE,yDAAyD,GAAO,YAAY,IAC7E,CACM,EAET,EAAO,OACE,IAAQ,UAAY,IAAQ,KACrC,EAAO,EAAK,EAAE,IAAM,GACX,IAAQ,WAAa,IAAQ,QACtC,EAAQ,EAAK,EAAE,IAInB,GAAI,CAAC,EAEH,OADA,EAAO;EAAsD,CACtD,EAGT,GAAI,IAAU,IAAA,GAIZ,OAHA,EACE;EACD,CACM,EAGT,GAAM,CAAE,eAAgB,MAAM,OAAO,qCAErC,GAAI,CAEF,GAAM,CAAE,MAAK,SAAQ,SAAU,MAAM,EADR,CAAE,QAAS,EAAK,OAAM,UAAW,EAAO,CACZ,CAAE,OAAM,CAAC,CAYlE,OAVA,EAAO,0CAA0C,EAAI;eAC1C,EAAI;eACJ,EAAI;;EAEjB,CAEE,MAAM,EAAgB,EAAK,OAAO,CAClC,EAAO;EAA4C,CACnD,MAAM,IAAI,QAAe,GAAY,EAAO,UAAY,GAAS,CAAC,CAAC,CACnE,EAAM,OAAO,CACN,QACA,EAAO,CAId,OAHA,EACE,mCAAmC,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAAC,IAC3F,CACM,GAIX,SAAS,EAAU,EAAmC,CACpD,EAAO;;;;;;;;gCAQuB,EAAa;gCACb,EAAa;;;;;;;;;;;;;;;;EAgB3C"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import{a as e,i as t,r as n}from"./service-client-Cr4sxDVM.js";import{SERVICE_URL as r}from"@x-otto/env";async function i(i,d={}){let f=d.stdout??(e=>process.stdout.write(e)),p=d.stderr??(e=>process.stderr.write(e)),m,h;try{({baseUrl:m,rest:h}=e(i))}catch(e){return t(`time-travel`,e,p)}let[g,_,...v]=h;if(!g||g===`help`)return f(`otto time-travel — 回放+回滚面板
|
|
3
|
-
|
|
4
|
-
用法:
|
|
5
|
-
otto time-travel checkpoints <session-id> 列出所有 checkpoint
|
|
6
|
-
otto time-travel checkpoint <session-id> [--label X] 创建新 checkpoint
|
|
7
|
-
otto time-travel scrubber <session-id> <seq> 显示 traceback 视图
|
|
8
|
-
otto time-travel restore <session-id> <seq> [--mode M] [--rollback]
|
|
9
|
-
恢复/回滚 (mode: conversation|code|both)
|
|
10
|
-
otto time-travel fork <session-id> <seq> 从 checkpoint 分叉新会话
|
|
11
|
-
otto time-travel replay <session-id> 启动确定性重放
|
|
12
|
-
|
|
13
|
-
选项:
|
|
14
|
-
--remote <url> service 地址(默认 OTTO_SERVICE_URL 或 ${r})
|
|
15
|
-
`),0;if(!_)return p(`otto time-travel: session-id is required.
|
|
16
|
-
`),1;let y=n(m,d.fetch);try{switch(g){case`checkpoints`:return await a(y,_,f);case`checkpoint`:return await o(y,_,v,f);case`scrubber`:return await s(y,_,v[0],f,p);case`restore`:return await c(y,_,v,f,p);case`fork`:return await l(y,_,v[0],f,p);case`replay`:return await u(y,_,f);default:return p(`otto time-travel: unknown action '${g}'.\n`),1}}catch(e){return t(`time-travel`,e,p)}}async function a(e,t,n){let{checkpoints:r}=await e.get(`/api/sessions/${t}/checkpoints`);if(r.length===0)return n(`Session ${t}: no checkpoints found.\n`),0;n(`Checkpoints — ${t} (${r.length})\n`),n(`${`seq`.padStart(4)} ${`traceSeq`.padStart(9)} ${`label`.padEnd(24)} created\n`),n(`${`-`.repeat(70)}\n`);for(let e of r){let t=(e.label??``).padEnd(24),r=new Date(e.createdAt).toISOString(),i=e.traceSeq===void 0?` -`:String(e.traceSeq).padStart(9);n(`${String(e.seq).padStart(4)} ${i} ${t} ${r}\n`)}return 0}async function o(e,t,n,r){let i=n.indexOf(`--label`),a=i>=0?n[i+1]:void 0,{checkpoint:o}=await e.post(`/api/sessions/${t}/checkpoints`,{label:a});return r(`Checkpoint created: seq=${o.seq}${o.label?` label="${o.label}"`:``} traceSeq=${o.traceSeq}\n`),0}async function s(e,t,n,r,i){let a=Number(n);if(!Number.isInteger(a))return i(`otto time-travel scrubber: seq (integer) is required.
|
|
17
|
-
`),1;let o=await e.get(`/api/sessions/${t}/traceback?to=${a}`);r(`Traceback — ${t} @ seq=${o.toSeq}\n`),o.baselineCheckpointSeq===null?r(` Baseline: none (folded from seq 0)
|
|
18
|
-
`):r(` Baseline: checkpoint seq=${o.baselineCheckpointSeq} (fromTraceSeq=${o.fromTraceSeq})\n`),r(` Events folded: ${o.events.length}\n`),r(` Messages reconstructed: ${o.messages.length}\n\n`);for(let e of o.messages)r(` ${e.role.padEnd(12)} ${typeof e.content==`string`?e.content.slice(0,120):JSON.stringify(e.content).slice(0,120)}\n`);return 0}async function c(e,t,n,r,i){let a=Number(n[0]);if(!Number.isInteger(a))return i(`otto time-travel restore: seq (integer) is required.
|
|
19
|
-
`),1;let o=n.indexOf(`--mode`),s=o>=0?n[o+1]:`both`;if(s!==`conversation`&&s!==`code`&&s!==`both`)return i(`otto time-travel restore: invalid mode '${s}'. Use conversation | code | both.\n`),1;let c=n.includes(`--rollback`);return await e.post(`/api/sessions/${t}/checkpoints/${a}/restore`,{mode:s,truncate:c}),r(`Restored to checkpoint seq=${a} mode=${s} rollback=${c}\n`),0}async function l(e,t,n,r,i){let a=Number(n);return Number.isInteger(a)?(r(`Forked session: ${(await e.post(`/api/sessions/${t}/checkpoints/${a}/fork`,{})).forkedSessionId} (from ${t} @ seq=${a})\n`),0):(i(`otto time-travel fork: seq (integer) is required.
|
|
20
|
-
`),1)}async function u(e,t,n){return n(`Replay session created: ${(await e.post(`/api/sessions/${t}/replay`,{})).replaySessionId} (source: ${t})\n`),0}export{i as runTimeTravelCommand};
|
|
21
|
-
//# sourceMappingURL=time-travel-8X-uAgHw.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"time-travel-8X-uAgHw.js","names":[],"sources":["../src/commands/time-travel.ts"],"sourcesContent":["/**\n * `otto time-travel` 子命令 —— 回放+回滚面板。\n *\n * 设计依据:design/observability-platform.md §4/§5 + design/m17-platform-activation.md §3。\n * 数据源 = service REST(timetravel 路由)。默认连 `otto serve` 实例,`--remote <url>` 覆盖。\n */\nimport { SERVICE_URL } from '@x-otto/env'\n\nimport {\n createServiceClient,\n reportServiceError,\n resolveRemote,\n type ServiceClient,\n} from './service-client'\n\nexport interface TimeTravelDeps {\n stdout?: (s: string) => void\n stderr?: (s: string) => void\n /** fetch 注入(测试用)。 */\n fetch?: typeof globalThis.fetch\n}\n\ninterface CheckpointInfo {\n seq: number\n label?: string\n createdAt: number\n traceSeq?: number\n}\n\ninterface TracebackView {\n toSeq: number\n baselineCheckpointSeq: number | null\n fromTraceSeq: number\n events: unknown[]\n messages: { role: string; content: unknown }[]\n}\n\nexport async function runTimeTravelCommand(\n args: string[],\n deps: TimeTravelDeps = {},\n): Promise<number> {\n const stdout = deps.stdout ?? ((s) => process.stdout.write(s))\n const stderr = deps.stderr ?? ((s) => process.stderr.write(s))\n\n let baseUrl: string\n let rest: string[]\n try {\n ;({ baseUrl, rest } = resolveRemote(args))\n } catch (error) {\n return reportServiceError('time-travel', error, stderr)\n }\n\n const [action, sessionId, ...extra] = rest\n\n if (!action || action === 'help') {\n stdout(`otto time-travel — 回放+回滚面板\n\n用法:\n otto time-travel checkpoints <session-id> 列出所有 checkpoint\n otto time-travel checkpoint <session-id> [--label X] 创建新 checkpoint\n otto time-travel scrubber <session-id> <seq> 显示 traceback 视图\n otto time-travel restore <session-id> <seq> [--mode M] [--rollback]\n 恢复/回滚 (mode: conversation|code|both)\n otto time-travel fork <session-id> <seq> 从 checkpoint 分叉新会话\n otto time-travel replay <session-id> 启动确定性重放\n\n选项:\n --remote <url> service 地址(默认 OTTO_SERVICE_URL 或 ${SERVICE_URL})\n`)\n return 0\n }\n\n if (!sessionId) {\n stderr('otto time-travel: session-id is required.\\n')\n return 1\n }\n\n const client = createServiceClient(baseUrl, deps.fetch)\n\n try {\n switch (action) {\n case 'checkpoints':\n return await listCheckpoints(client, sessionId, stdout)\n case 'checkpoint':\n return await createCheckpoint(client, sessionId, extra, stdout)\n case 'scrubber':\n return await showScrubber(client, sessionId, extra[0], stdout, stderr)\n case 'restore':\n return await restoreCheckpoint(client, sessionId, extra, stdout, stderr)\n case 'fork':\n return await forkCheckpoint(client, sessionId, extra[0], stdout, stderr)\n case 'replay':\n return await startReplay(client, sessionId, stdout)\n default:\n stderr(`otto time-travel: unknown action '${action}'.\\n`)\n return 1\n }\n } catch (error) {\n return reportServiceError('time-travel', error, stderr)\n }\n}\n\nasync function listCheckpoints(\n client: ServiceClient,\n sessionId: string,\n stdout: (s: string) => void,\n): Promise<number> {\n const { checkpoints } = await client.get<{ checkpoints: CheckpointInfo[] }>(\n `/api/sessions/${sessionId}/checkpoints`,\n )\n if (checkpoints.length === 0) {\n stdout(`Session ${sessionId}: no checkpoints found.\\n`)\n return 0\n }\n\n stdout(`Checkpoints — ${sessionId} (${checkpoints.length})\\n`)\n stdout(`${'seq'.padStart(4)} ${'traceSeq'.padStart(9)} ${'label'.padEnd(24)} ${'created'}\\n`)\n stdout(`${'-'.repeat(70)}\\n`)\n for (const cp of checkpoints) {\n const label = (cp.label ?? '').padEnd(24)\n const created = new Date(cp.createdAt).toISOString()\n const traceSeq = cp.traceSeq !== undefined ? String(cp.traceSeq).padStart(9) : ' -'\n stdout(`${String(cp.seq).padStart(4)} ${traceSeq} ${label} ${created}\\n`)\n }\n return 0\n}\n\nasync function createCheckpoint(\n client: ServiceClient,\n sessionId: string,\n rest: string[],\n stdout: (s: string) => void,\n): Promise<number> {\n const labelIdx = rest.indexOf('--label')\n const label = labelIdx >= 0 ? rest[labelIdx + 1] : undefined\n\n const { checkpoint } = await client.post<{ checkpoint: CheckpointInfo }>(\n `/api/sessions/${sessionId}/checkpoints`,\n { label },\n )\n stdout(\n `Checkpoint created: seq=${checkpoint.seq}${checkpoint.label ? ` label=\"${checkpoint.label}\"` : ''} traceSeq=${checkpoint.traceSeq}\\n`,\n )\n return 0\n}\n\nasync function showScrubber(\n client: ServiceClient,\n sessionId: string,\n seqRaw: string | undefined,\n stdout: (s: string) => void,\n stderr: (s: string) => void,\n): Promise<number> {\n const seq = Number(seqRaw)\n if (!Number.isInteger(seq)) {\n stderr('otto time-travel scrubber: seq (integer) is required.\\n')\n return 1\n }\n\n const view = await client.get<TracebackView>(`/api/sessions/${sessionId}/traceback?to=${seq}`)\n\n stdout(`Traceback — ${sessionId} @ seq=${view.toSeq}\\n`)\n if (view.baselineCheckpointSeq !== null) {\n stdout(` Baseline: checkpoint seq=${view.baselineCheckpointSeq} (fromTraceSeq=${view.fromTraceSeq})\\n`)\n } else {\n stdout(` Baseline: none (folded from seq 0)\\n`)\n }\n stdout(` Events folded: ${view.events.length}\\n`)\n stdout(` Messages reconstructed: ${view.messages.length}\\n\\n`)\n\n for (const msg of view.messages) {\n const role = msg.role.padEnd(12)\n const content =\n typeof msg.content === 'string'\n ? msg.content.slice(0, 120)\n : JSON.stringify(msg.content).slice(0, 120)\n stdout(` ${role} ${content}\\n`)\n }\n return 0\n}\n\nasync function restoreCheckpoint(\n client: ServiceClient,\n sessionId: string,\n rest: string[],\n stdout: (s: string) => void,\n stderr: (s: string) => void,\n): Promise<number> {\n const seq = Number(rest[0])\n if (!Number.isInteger(seq)) {\n stderr('otto time-travel restore: seq (integer) is required.\\n')\n return 1\n }\n\n const modeIdx = rest.indexOf('--mode')\n const modeRaw = modeIdx >= 0 ? rest[modeIdx + 1] : 'both'\n if (modeRaw !== 'conversation' && modeRaw !== 'code' && modeRaw !== 'both') {\n stderr(`otto time-travel restore: invalid mode '${modeRaw}'. Use conversation | code | both.\\n`)\n return 1\n }\n const rollback = rest.includes('--rollback')\n\n await client.post(`/api/sessions/${sessionId}/checkpoints/${seq}/restore`, {\n mode: modeRaw,\n truncate: rollback,\n })\n stdout(`Restored to checkpoint seq=${seq} mode=${modeRaw} rollback=${rollback}\\n`)\n return 0\n}\n\nasync function forkCheckpoint(\n client: ServiceClient,\n sessionId: string,\n seqRaw: string | undefined,\n stdout: (s: string) => void,\n stderr: (s: string) => void,\n): Promise<number> {\n const seq = Number(seqRaw)\n if (!Number.isInteger(seq)) {\n stderr('otto time-travel fork: seq (integer) is required.\\n')\n return 1\n }\n\n const result = await client.post<{ forkedSessionId: string }>(\n `/api/sessions/${sessionId}/checkpoints/${seq}/fork`,\n {},\n )\n stdout(`Forked session: ${result.forkedSessionId} (from ${sessionId} @ seq=${seq})\\n`)\n return 0\n}\n\nasync function startReplay(\n client: ServiceClient,\n sessionId: string,\n stdout: (s: string) => void,\n): Promise<number> {\n const result = await client.post<{ replaySessionId: string }>(\n `/api/sessions/${sessionId}/replay`,\n {},\n )\n stdout(`Replay session created: ${result.replaySessionId} (source: ${sessionId})\\n`)\n return 0\n}\n"],"mappings":"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"}
|