|
1 | 1 | // Core command handlers for SQLite snapshot artifacts. |
| 2 | +import { normalizeAgentId } from "../routing/session-key.js"; |
| 3 | +import { type RuntimeEnv, writeRuntimeJson } from "../runtime.js"; |
2 | 4 | import { createLocalSqliteSnapshotProvider } from "../snapshot/local-repository.js"; |
3 | 5 | import type { |
4 | 6 | SnapshotManifest, |
5 | 7 | SnapshotSummary, |
6 | 8 | SnapshotVerificationResult, |
7 | 9 | } from "../snapshot/snapshot-provider.js"; |
8 | | -import { type RuntimeEnv, writeRuntimeJson } from "../runtime.js"; |
| 10 | +import { resolveOpenClawAgentSqlitePath } from "../state/openclaw-agent-db.paths.js"; |
| 11 | +import { resolveOpenClawStateSqlitePath } from "../state/openclaw-state-db.paths.js"; |
9 | 12 |
|
10 | 13 | export interface SnapshotCreateOptions { |
11 | 14 | readonly db?: string; |
| 15 | + readonly target?: string; |
| 16 | + readonly agent?: string; |
12 | 17 | readonly repository?: string; |
13 | 18 | readonly id?: string; |
14 | 19 | readonly kind?: string; |
@@ -48,18 +53,24 @@ type SnapshotListReport = { |
48 | 53 | readonly snapshots: readonly SnapshotSummary[]; |
49 | 54 | }; |
50 | 55 |
|
| 56 | +type SnapshotCreateSource = { |
| 57 | + readonly path: string; |
| 58 | + readonly id?: string; |
| 59 | + readonly kind?: string; |
| 60 | +}; |
| 61 | + |
51 | 62 | export async function snapshotCreateCommand( |
52 | 63 | options: SnapshotCreateOptions, |
53 | 64 | runtime: RuntimeEnv, |
54 | 65 | ): Promise<number> { |
55 | 66 | try { |
56 | 67 | const repositoryPath = requireOption(options.repository, "--repository"); |
57 | | - const dbPath = requireOption(options.db, "--db"); |
| 68 | + const source = resolveSnapshotCreateSource(options); |
58 | 69 | const provider = createLocalSqliteSnapshotProvider({ repositoryPath }); |
59 | 70 | const result = await provider.create({ |
60 | | - path: dbPath, |
61 | | - ...(options.id ? { id: options.id } : {}), |
62 | | - ...(options.kind ? { kind: options.kind } : {}), |
| 71 | + path: source.path, |
| 72 | + ...(source.id ? { id: source.id } : {}), |
| 73 | + ...(source.kind ? { kind: source.kind } : {}), |
63 | 74 | }); |
64 | 75 | writeCreateReport( |
65 | 76 | { ok: true, snapshotPath: result.ref.path, manifest: result.manifest }, |
@@ -125,6 +136,46 @@ export async function snapshotListCommand( |
125 | 136 | } |
126 | 137 | } |
127 | 138 |
|
| 139 | +function resolveSnapshotCreateSource(options: SnapshotCreateOptions): SnapshotCreateSource { |
| 140 | + const selectors = [ |
| 141 | + hasValue(options.db), |
| 142 | + hasValue(options.target), |
| 143 | + hasValue(options.agent), |
| 144 | + ].filter(Boolean).length; |
| 145 | + if (selectors === 0) { |
| 146 | + throw new Error( |
| 147 | + "Missing snapshot source. Provide one of --db <path>, --target global, or --agent <id>.", |
| 148 | + ); |
| 149 | + } |
| 150 | + if (selectors > 1) { |
| 151 | + throw new Error("Choose only one snapshot source: --db, --target, or --agent."); |
| 152 | + } |
| 153 | + if (hasValue(options.db)) { |
| 154 | + return { |
| 155 | + path: requireValue(options.db, "--db"), |
| 156 | + ...(options.id ? { id: options.id } : {}), |
| 157 | + ...(options.kind ? { kind: options.kind } : {}), |
| 158 | + }; |
| 159 | + } |
| 160 | + if (hasValue(options.target)) { |
| 161 | + const target = requireValue(options.target, "--target").toLowerCase(); |
| 162 | + if (target !== "global") { |
| 163 | + throw new Error(`Unsupported snapshot target "${target}". Supported targets: global.`); |
| 164 | + } |
| 165 | + return { |
| 166 | + path: resolveOpenClawStateSqlitePath(), |
| 167 | + id: options.id ?? "global", |
| 168 | + kind: options.kind ?? "global-control-plane", |
| 169 | + }; |
| 170 | + } |
| 171 | + const agentId = normalizeAgentId(requireValue(options.agent, "--agent")); |
| 172 | + return { |
| 173 | + path: resolveOpenClawAgentSqlitePath({ agentId }), |
| 174 | + id: options.id ?? `agent:${agentId}`, |
| 175 | + kind: options.kind ?? "agent-data-plane", |
| 176 | + }; |
| 177 | +} |
| 178 | + |
128 | 179 | function writeCreateReport( |
129 | 180 | report: SnapshotCreateReport, |
130 | 181 | options: SnapshotJsonOptions, |
@@ -193,6 +244,10 @@ function requireOption(value: string | undefined, flag: string): string { |
193 | 244 | return requireValue(value, flag); |
194 | 245 | } |
195 | 246 |
|
| 247 | +function hasValue(value: string | undefined): boolean { |
| 248 | + return value !== undefined && value.trim() !== ""; |
| 249 | +} |
| 250 | + |
196 | 251 | function requireValue(value: string | undefined, label: string): string { |
197 | 252 | if (value === undefined || value.trim() === "") { |
198 | 253 | throw new Error(`Missing required ${label} value.`); |
|
0 commit comments