@mycadet/assistant 0.12.11 → 0.13.0
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/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
- package/node_modules/@mycadet/gateway-client/src/gateway-ipc-contracts.ts +0 -20
- package/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
- package/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
- package/openapi.yaml +2 -708
- package/package.json +2 -3
- package/scripts/sync-web-search-catalog.ts +1 -2
- package/src/__tests__/cloud-profile-guard.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +6 -38
- package/src/__tests__/conversation-queue.test.ts +45 -6
- package/src/__tests__/db-readiness-http-gate.test.ts +0 -6
- package/src/__tests__/persist-onboarding-artifacts.test.ts +0 -1
- package/src/__tests__/persona-resolver.test.ts +0 -51
- package/src/__tests__/provider-cloud-proxy-integration.test.ts +2 -110
- package/src/__tests__/run-due-schedules.test.ts +0 -4
- package/src/__tests__/schedule-store.test.ts +0 -12
- package/src/__tests__/stt-stream-session.test.ts +4 -4
- package/src/__tests__/telephony-tts-guard.test.ts +2 -50
- package/src/__tests__/voice-config-update.test.ts +12 -167
- package/src/__tests__/web-search-catalog-parity.test.ts +0 -2
- package/src/__tests__/workspace-migration-130-speech-mode-to-provider.test.ts +9 -7
- package/src/__tests__/workspace-migration-132-web-search-mode-to-provider.test.ts +6 -6
- package/src/calls/__tests__/voice-session-bridge.test.ts +1 -4
- package/src/calls/resolve-call-tts-provider.ts +6 -25
- package/src/calls/telephony-credential-preflight.ts +0 -10
- package/src/calls/telephony-tts-capability.ts +1 -17
- package/src/cli/commands/tts.ts +1 -2
- package/src/cli/index.help.ts +0 -2
- package/src/cli/program.ts +0 -2
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +4 -42
- package/src/config/schemas/__tests__/stt.test.ts +10 -14
- package/src/config/schemas/services.ts +5 -6
- package/src/config/schemas/stt.ts +1 -3
- package/src/config/schemas/tts.ts +1 -30
- package/src/daemon/daemon-readiness.ts +4 -29
- package/src/daemon/lifecycle.ts +0 -31
- package/src/daemon/providers-setup.ts +0 -8
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -1
- package/src/heartbeat/heartbeat-service.ts +1 -66
- package/src/ipc/__tests__/db-readiness-ipc-gate.test.ts +1 -9
- package/src/live-voice/__tests__/live-voice-credential-preflight.test.ts +0 -44
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +4 -6
- package/src/live-voice/__tests__/live-voice-stt.test.ts +1 -1
- package/src/live-voice/live-voice-credential-preflight.ts +9 -33
- package/src/live-voice/live-voice-session.ts +10 -6
- package/src/live-voice/live-voice-tts.ts +1 -8
- package/src/plugins/defaults/memory/worker.ts +3 -3
- package/src/prompts/persona-resolver.ts +0 -35
- package/src/providers/__tests__/search-provider-catalog.test.ts +5 -8
- package/src/providers/__tests__/voice-error-copy.test.ts +9 -10
- package/src/providers/search-provider-catalog.ts +7 -39
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +3 -47
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +6 -372
- package/src/providers/speech-to-text/provider-catalog.ts +2 -73
- package/src/providers/speech-to-text/resolve.ts +3 -120
- package/src/runtime/http-router-types.ts +1 -3
- package/src/runtime/http-server.ts +1 -1
- package/src/runtime/routes/__tests__/tts-routes.test.ts +2 -6
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +7 -7
- package/src/runtime/routes/index.ts +0 -4
- package/src/runtime/routes/live-voice-routes.test.ts +4 -11
- package/src/runtime/routes/live-voice-routes.ts +8 -11
- package/src/runtime/routes/secret-routes.ts +0 -6
- package/src/runtime/routes/tts-routes.ts +0 -38
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1 -7
- package/src/schedule/__tests__/worker-mcp-readiness.test.ts +0 -4
- package/src/schedule/schedule-store.ts +0 -7
- package/src/schedule/scheduler.ts +0 -5
- package/src/schedule/worker.ts +1 -1
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +2 -10
- package/src/stt/daemon-batch-transcriber.ts +4 -38
- package/src/stt/types.ts +1 -9
- package/src/tools/network/__tests__/web-search.test.ts +3 -250
- package/src/tools/network/web-search.ts +4 -165
- package/src/tts/__tests__/provider-resolution.test.ts +0 -5
- package/src/tts/provider-catalog.ts +0 -4
- package/src/tts/types.ts +0 -1
- package/src/__tests__/cloud-speech-defaults.test.ts +0 -330
- package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1708
- package/src/__tests__/migration-export-http.test.ts +0 -557
- package/src/__tests__/migration-export-streaming.test.ts +0 -350
- package/src/__tests__/migration-export-to-gcs.test.ts +0 -706
- package/src/__tests__/migration-import-commit-http.test.ts +0 -1176
- package/src/__tests__/migration-import-from-gcs.test.ts +0 -534
- package/src/__tests__/migration-import-from-path.test.ts +0 -324
- package/src/__tests__/migration-import-from-url.test.ts +0 -588
- package/src/__tests__/migration-import-preflight-http.test.ts +0 -739
- package/src/__tests__/migration-jobs-status.test.ts +0 -139
- package/src/__tests__/migration-parity-persistence.test.ts +0 -1891
- package/src/__tests__/migration-transport.test.ts +0 -1089
- package/src/__tests__/migration-validate-http.test.ts +0 -634
- package/src/__tests__/migration-wizard.test.ts +0 -1395
- package/src/__tests__/rebind-secrets-screen.test.ts +0 -876
- package/src/__tests__/sanitize-config-for-transfer.test.ts +0 -259
- package/src/__tests__/transfer-progress-screen.test.ts +0 -1217
- package/src/__tests__/validation-results-screen.test.ts +0 -1130
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +0 -147
- package/src/background-wake/background-wake-routes.test.ts +0 -906
- package/src/background-wake/cloud-client.test.ts +0 -328
- package/src/background-wake/cloud-client.ts +0 -196
- package/src/background-wake/next-wake.test.ts +0 -335
- package/src/background-wake/next-wake.ts +0 -188
- package/src/background-wake/publisher.ts +0 -93
- package/src/background-wake/wake-intent-hooks.test.ts +0 -234
- package/src/cli/commands/__tests__/backup.test.ts +0 -363
- package/src/cli/commands/backup.help.ts +0 -180
- package/src/cli/commands/backup.ts +0 -398
- package/src/cloud/cloud-speech.test.ts +0 -335
- package/src/cloud/cloud-speech.ts +0 -300
- package/src/config/cloud-speech-defaults.ts +0 -300
- package/src/config/sanitize-for-transfer.ts +0 -111
- package/src/live-voice/__tests__/live-voice-cloud-speech-fallback.test.ts +0 -250
- package/src/providers/speech-to-text/__tests__/cadet-cloud-realtime.test.ts +0 -457
- package/src/providers/speech-to-text/__tests__/cadet-cloud.test.ts +0 -271
- package/src/providers/speech-to-text/__tests__/cadet-speech-relay-connection.test.ts +0 -126
- package/src/providers/speech-to-text/cadet-cloud-flux-realtime.ts +0 -309
- package/src/providers/speech-to-text/cadet-cloud-realtime.ts +0 -315
- package/src/providers/speech-to-text/cadet-cloud.ts +0 -108
- package/src/providers/speech-to-text/cadet-speech-relay-connection.ts +0 -176
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +0 -254
- package/src/runtime/migrations/__tests__/job-registry.test.ts +0 -346
- package/src/runtime/migrations/__tests__/origin-mode.test.ts +0 -62
- package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +0 -184
- package/src/runtime/migrations/__tests__/staged-import-path.test.ts +0 -110
- package/src/runtime/migrations/__tests__/v1-test-helpers.ts +0 -112
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +0 -285
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +0 -126
- package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +0 -253
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +0 -208
- package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +0 -485
- package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +0 -349
- package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +0 -196
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +0 -551
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +0 -428
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +0 -220
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +0 -1823
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +0 -598
- package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +0 -463
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -538
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +0 -515
- package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +0 -453
- package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +0 -319
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +0 -240
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +0 -473
- package/src/runtime/migrations/gcs-signed-url.ts +0 -190
- package/src/runtime/migrations/job-registry.ts +0 -297
- package/src/runtime/migrations/migration-transport.ts +0 -612
- package/src/runtime/migrations/migration-wizard.ts +0 -747
- package/src/runtime/migrations/origin-mode.ts +0 -42
- package/src/runtime/migrations/rebind-secrets-screen.ts +0 -412
- package/src/runtime/migrations/staged-import-path.ts +0 -116
- package/src/runtime/migrations/transfer-progress-screen.ts +0 -323
- package/src/runtime/migrations/validation-results-screen.ts +0 -469
- package/src/runtime/migrations/vbundle-builder.ts +0 -1382
- package/src/runtime/migrations/vbundle-import-analyzer.ts +0 -405
- package/src/runtime/migrations/vbundle-import-policy.ts +0 -241
- package/src/runtime/migrations/vbundle-importer.ts +0 -826
- package/src/runtime/migrations/vbundle-metadata-merge.ts +0 -113
- package/src/runtime/migrations/vbundle-streaming-importer.ts +0 -2844
- package/src/runtime/migrations/vbundle-streaming-validator.ts +0 -426
- package/src/runtime/migrations/vbundle-tar-stream.ts +0 -244
- package/src/runtime/migrations/vbundle-validator.ts +0 -724
- package/src/runtime/routes/__tests__/migration-cadet-metadata-reconcile.test.ts +0 -227
- package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +0 -54
- package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +0 -70
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +0 -257
- package/src/runtime/routes/background-wake-routes.ts +0 -387
- package/src/runtime/routes/migration-routes.ts +0 -2584
- package/src/tools/network/__tests__/cloud-search-proxy.test.ts +0 -282
- package/src/tools/network/cloud-search-proxy.ts +0 -211
- package/src/tts/__tests__/cadet-provider.test.ts +0 -253
- package/src/tts/providers/cadet-provider.ts +0 -244
- package/src/types/tar-stream.d.ts +0 -66
|
@@ -1,612 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared transport methods for managed and runtime migration APIs.
|
|
3
|
-
*
|
|
4
|
-
* Provides typed functions for each migration endpoint, usable by
|
|
5
|
-
* client web views (macOS/iOS WKWebView), the gateway, or any
|
|
6
|
-
* TypeScript consumer that needs to call migration APIs.
|
|
7
|
-
*
|
|
8
|
-
* Two target APIs:
|
|
9
|
-
*
|
|
10
|
-
* Runtime (local daemon):
|
|
11
|
-
* POST /v1/migrations/validate
|
|
12
|
-
* POST /v1/migrations/export
|
|
13
|
-
* POST /v1/migrations/import-preflight
|
|
14
|
-
* POST /v1/migrations/import
|
|
15
|
-
*
|
|
16
|
-
* Managed (platform/Django):
|
|
17
|
-
* POST /v1/migrations/validate/
|
|
18
|
-
* POST /v1/migrations/export/
|
|
19
|
-
* POST /v1/migrations/import-preflight/
|
|
20
|
-
* POST /v1/migrations/import/
|
|
21
|
-
* GET /v1/migrations/export/{job_id}/status/
|
|
22
|
-
* GET /v1/migrations/import/{job_id}/status/
|
|
23
|
-
*
|
|
24
|
-
* All methods accept a `fetchFn` parameter for testability (defaults to
|
|
25
|
-
* the global `fetch`). Auth headers are passed via `TransportConfig`.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
import { z } from "zod";
|
|
29
|
-
|
|
30
|
-
export type MigrationTarget = "runtime" | "managed";
|
|
31
|
-
|
|
32
|
-
export interface TransportConfig {
|
|
33
|
-
/** Base URL of the target API (e.g. "https://cloud.mycadet.ai"). */
|
|
34
|
-
baseURL: string;
|
|
35
|
-
/** Which API surface to target. Managed endpoints use trailing slashes. */
|
|
36
|
-
target: MigrationTarget;
|
|
37
|
-
/** Authorization header value (e.g. "Bearer <jwt>" or session token). */
|
|
38
|
-
authHeader?: string;
|
|
39
|
-
/** Header name for auth. Defaults to "Authorization" for runtime, "X-Session-Token" for managed. */
|
|
40
|
-
authHeaderName?: string;
|
|
41
|
-
/**
|
|
42
|
-
* Additional headers to include with every request.
|
|
43
|
-
* Merged after Content-Type but before auth-header injection,
|
|
44
|
-
* so an explicit auth header from the transport always wins
|
|
45
|
-
* over a same-named entry in defaultHeaders.
|
|
46
|
-
*/
|
|
47
|
-
defaultHeaders?: Record<string, string>;
|
|
48
|
-
/** Custom fetch implementation for testing or environments without global fetch. */
|
|
49
|
-
fetchFn?: typeof fetch;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export interface ValidationError {
|
|
53
|
-
code: string;
|
|
54
|
-
message: string;
|
|
55
|
-
path?: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
interface ManifestFileEntry {
|
|
59
|
-
path: string;
|
|
60
|
-
sha256: string;
|
|
61
|
-
size_bytes: number;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
interface ManifestAssistantInfo {
|
|
65
|
-
id: string;
|
|
66
|
-
name: string;
|
|
67
|
-
runtime_version: string;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
interface ManifestOrigin {
|
|
71
|
-
mode: "managed" | "self-hosted-remote" | "self-hosted-local";
|
|
72
|
-
platform_version?: string;
|
|
73
|
-
hostname?: string;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
interface ManifestCompatibility {
|
|
77
|
-
min_runtime_version: string;
|
|
78
|
-
max_runtime_version: string | null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
interface ManifestExportOptions {
|
|
82
|
-
include_logs: boolean;
|
|
83
|
-
include_browser_state: boolean;
|
|
84
|
-
include_memory_vectors: boolean;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export interface Manifest {
|
|
88
|
-
schema_version: number;
|
|
89
|
-
bundle_id: string;
|
|
90
|
-
created_at: string;
|
|
91
|
-
assistant: ManifestAssistantInfo;
|
|
92
|
-
origin: ManifestOrigin;
|
|
93
|
-
compatibility: ManifestCompatibility;
|
|
94
|
-
contents: ManifestFileEntry[];
|
|
95
|
-
checksum: string;
|
|
96
|
-
secrets_redacted: boolean;
|
|
97
|
-
export_options: ManifestExportOptions;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface ValidateSuccessResponse {
|
|
101
|
-
is_valid: true;
|
|
102
|
-
errors: ValidationError[];
|
|
103
|
-
manifest: Manifest;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export interface ValidateFailureResponse {
|
|
107
|
-
is_valid: false;
|
|
108
|
-
errors: ValidationError[];
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export type ValidateResponse =
|
|
112
|
-
| ValidateSuccessResponse
|
|
113
|
-
| ValidateFailureResponse;
|
|
114
|
-
|
|
115
|
-
/** Runtime export returns the binary archive directly. */
|
|
116
|
-
export interface ExportRuntimeResult {
|
|
117
|
-
ok: true;
|
|
118
|
-
archive: ArrayBuffer;
|
|
119
|
-
filename: string;
|
|
120
|
-
schemaVersion: number;
|
|
121
|
-
checksum: string;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/** Managed export initiates an async job and returns a job ID. */
|
|
125
|
-
export interface ExportManagedResult {
|
|
126
|
-
ok: true;
|
|
127
|
-
jobId: string;
|
|
128
|
-
status: string;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
type ExportResult = ExportRuntimeResult | ExportManagedResult;
|
|
132
|
-
|
|
133
|
-
export interface ImportPreflightFileReport {
|
|
134
|
-
path: string;
|
|
135
|
-
action: "create" | "overwrite" | "unchanged" | "skip";
|
|
136
|
-
bundle_size: number;
|
|
137
|
-
current_size: number | null;
|
|
138
|
-
bundle_sha256: string;
|
|
139
|
-
current_sha256: string | null;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export interface ImportPreflightConflict {
|
|
143
|
-
code: string;
|
|
144
|
-
message: string;
|
|
145
|
-
path?: string;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export interface ImportPreflightSuccessResponse {
|
|
149
|
-
can_import: true;
|
|
150
|
-
summary: {
|
|
151
|
-
total_files: number;
|
|
152
|
-
files_to_create: number;
|
|
153
|
-
files_to_overwrite: number;
|
|
154
|
-
files_unchanged: number;
|
|
155
|
-
files_to_skip: number;
|
|
156
|
-
};
|
|
157
|
-
files: ImportPreflightFileReport[];
|
|
158
|
-
conflicts: ImportPreflightConflict[];
|
|
159
|
-
manifest: Manifest;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export interface ImportPreflightValidationFailedResponse {
|
|
163
|
-
can_import: false;
|
|
164
|
-
validation: {
|
|
165
|
-
is_valid: false;
|
|
166
|
-
errors: ValidationError[];
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
export interface ImportPreflightConflictResponse {
|
|
171
|
-
can_import: false;
|
|
172
|
-
summary: {
|
|
173
|
-
total_files: number;
|
|
174
|
-
files_to_create: number;
|
|
175
|
-
files_to_overwrite: number;
|
|
176
|
-
files_unchanged: number;
|
|
177
|
-
files_to_skip: number;
|
|
178
|
-
};
|
|
179
|
-
files: ImportPreflightFileReport[];
|
|
180
|
-
conflicts: ImportPreflightConflict[];
|
|
181
|
-
manifest: Manifest;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export type ImportPreflightResponse =
|
|
185
|
-
| ImportPreflightSuccessResponse
|
|
186
|
-
| ImportPreflightValidationFailedResponse
|
|
187
|
-
| ImportPreflightConflictResponse;
|
|
188
|
-
|
|
189
|
-
export interface ImportedFileReport {
|
|
190
|
-
path: string;
|
|
191
|
-
disk_path: string;
|
|
192
|
-
action: "created" | "overwritten" | "skipped";
|
|
193
|
-
size: number;
|
|
194
|
-
sha256: string;
|
|
195
|
-
backup_path: string | null;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
export interface ImportCommitSuccessResponse {
|
|
199
|
-
success: true;
|
|
200
|
-
summary: {
|
|
201
|
-
total_files: number;
|
|
202
|
-
files_created: number;
|
|
203
|
-
files_overwritten: number;
|
|
204
|
-
files_skipped: number;
|
|
205
|
-
backups_created: number;
|
|
206
|
-
};
|
|
207
|
-
files: ImportedFileReport[];
|
|
208
|
-
manifest: Manifest;
|
|
209
|
-
warnings: string[];
|
|
210
|
-
credentialsImported?: {
|
|
211
|
-
total: number;
|
|
212
|
-
succeeded: number;
|
|
213
|
-
failed: number;
|
|
214
|
-
failedAccounts: string[];
|
|
215
|
-
skippedPlatform?: number;
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export interface ImportCommitFailureResponse {
|
|
220
|
-
success: false;
|
|
221
|
-
reason: "validation_failed" | "extraction_failed" | "write_failed";
|
|
222
|
-
errors?: ValidationError[];
|
|
223
|
-
message?: string;
|
|
224
|
-
partial_report?: unknown;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export type ImportCommitResponse =
|
|
228
|
-
| ImportCommitSuccessResponse
|
|
229
|
-
| ImportCommitFailureResponse;
|
|
230
|
-
|
|
231
|
-
export interface JobStatusPending {
|
|
232
|
-
status: "pending" | "processing";
|
|
233
|
-
jobId: string;
|
|
234
|
-
progress?: number;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
export interface JobStatusComplete {
|
|
238
|
-
status: "complete";
|
|
239
|
-
jobId: string;
|
|
240
|
-
downloadUrl?: string;
|
|
241
|
-
result?: unknown;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export interface JobStatusFailed {
|
|
245
|
-
status: "failed";
|
|
246
|
-
jobId: string;
|
|
247
|
-
error: string;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
export type JobStatusResponse =
|
|
251
|
-
| JobStatusPending
|
|
252
|
-
| JobStatusComplete
|
|
253
|
-
| JobStatusFailed;
|
|
254
|
-
|
|
255
|
-
export class MigrationTransportError extends Error {
|
|
256
|
-
readonly statusCode: number;
|
|
257
|
-
readonly responseBody: string;
|
|
258
|
-
|
|
259
|
-
constructor(message: string, statusCode: number, responseBody: string) {
|
|
260
|
-
super(message);
|
|
261
|
-
this.name = "MigrationTransportError";
|
|
262
|
-
this.statusCode = statusCode;
|
|
263
|
-
this.responseBody = responseBody;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
function resolveFetch(config: TransportConfig): typeof fetch {
|
|
268
|
-
return config.fetchFn ?? globalThis.fetch;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
function buildURL(config: TransportConfig, path: string): string {
|
|
272
|
-
const base = config.baseURL.replace(/\/+$/, "");
|
|
273
|
-
const trailingSlash = config.target === "managed" ? "/" : "";
|
|
274
|
-
return `${base}/v1/migrations/${path}${trailingSlash}`;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function buildHeaders(
|
|
278
|
-
config: TransportConfig,
|
|
279
|
-
contentType?: string,
|
|
280
|
-
): Record<string, string> {
|
|
281
|
-
const headers: Record<string, string> = {};
|
|
282
|
-
const headerKeysByLowerName = new Map<string, string>();
|
|
283
|
-
|
|
284
|
-
const setHeader = (headerName: string, headerValue: string): void => {
|
|
285
|
-
const lowerName = headerName.toLowerCase();
|
|
286
|
-
const existingHeaderName = headerKeysByLowerName.get(lowerName);
|
|
287
|
-
if (existingHeaderName && existingHeaderName !== headerName) {
|
|
288
|
-
delete headers[existingHeaderName];
|
|
289
|
-
}
|
|
290
|
-
headerKeysByLowerName.set(lowerName, headerName);
|
|
291
|
-
headers[headerName] = headerValue;
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
if (contentType) {
|
|
295
|
-
setHeader("Content-Type", contentType);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// Merge defaultHeaders after Content-Type but before auth injection
|
|
299
|
-
if (config.defaultHeaders) {
|
|
300
|
-
for (const [headerName, headerValue] of Object.entries(
|
|
301
|
-
config.defaultHeaders,
|
|
302
|
-
)) {
|
|
303
|
-
setHeader(headerName, headerValue);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// Auth header is applied last so it always wins over defaultHeaders
|
|
308
|
-
if (config.authHeader) {
|
|
309
|
-
const headerName =
|
|
310
|
-
config.authHeaderName ??
|
|
311
|
-
(config.target === "managed" ? "X-Session-Token" : "Authorization");
|
|
312
|
-
setHeader(headerName, config.authHeader);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
return headers;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
async function assertOk(response: Response, context: string): Promise<void> {
|
|
319
|
-
if (!response.ok) {
|
|
320
|
-
const body = await response.text().catch(() => "<unreadable>");
|
|
321
|
-
throw new MigrationTransportError(
|
|
322
|
-
`${context}: HTTP ${response.status}`,
|
|
323
|
-
response.status,
|
|
324
|
-
body,
|
|
325
|
-
);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* Validate a .vbundle archive.
|
|
331
|
-
*
|
|
332
|
-
* Sends the archive as binary body and returns structured validation results.
|
|
333
|
-
*/
|
|
334
|
-
export async function validateBundle(
|
|
335
|
-
config: TransportConfig,
|
|
336
|
-
fileData: ArrayBuffer,
|
|
337
|
-
): Promise<ValidateResponse> {
|
|
338
|
-
const doFetch = resolveFetch(config);
|
|
339
|
-
const url = buildURL(config, "validate");
|
|
340
|
-
|
|
341
|
-
const response = await doFetch(url, {
|
|
342
|
-
method: "POST",
|
|
343
|
-
headers: buildHeaders(config, "application/octet-stream"),
|
|
344
|
-
body: fileData,
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
await assertOk(response, "validate");
|
|
348
|
-
return (await response.json()) as ValidateResponse;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/**
|
|
352
|
-
* Export assistant data as a .vbundle archive.
|
|
353
|
-
*
|
|
354
|
-
* Runtime target: returns the binary archive directly.
|
|
355
|
-
* Managed target: initiates an async export job and returns the job ID.
|
|
356
|
-
*/
|
|
357
|
-
export async function exportBundle(
|
|
358
|
-
config: TransportConfig,
|
|
359
|
-
options?: { description?: string },
|
|
360
|
-
): Promise<ExportResult> {
|
|
361
|
-
const doFetch = resolveFetch(config);
|
|
362
|
-
const url = buildURL(config, "export");
|
|
363
|
-
|
|
364
|
-
const body = options?.description
|
|
365
|
-
? JSON.stringify({ description: options.description })
|
|
366
|
-
: undefined;
|
|
367
|
-
|
|
368
|
-
const contentType = body ? "application/json" : undefined;
|
|
369
|
-
|
|
370
|
-
const response = await doFetch(url, {
|
|
371
|
-
method: "POST",
|
|
372
|
-
headers: buildHeaders(config, contentType),
|
|
373
|
-
...(body ? { body } : {}),
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
await assertOk(response, "export");
|
|
377
|
-
|
|
378
|
-
if (config.target === "managed") {
|
|
379
|
-
const json = (await response.json()) as {
|
|
380
|
-
job_id: string;
|
|
381
|
-
status: string;
|
|
382
|
-
};
|
|
383
|
-
return {
|
|
384
|
-
ok: true,
|
|
385
|
-
jobId: json.job_id,
|
|
386
|
-
status: json.status,
|
|
387
|
-
} as ExportManagedResult;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Runtime returns the binary archive. The legacy
|
|
391
|
-
// `X-Vbundle-Manifest-Sha256` response header name is preserved for
|
|
392
|
-
// cross-version client compat — its value is now sourced from the
|
|
393
|
-
// renamed manifest `checksum` field.
|
|
394
|
-
const archive = await response.arrayBuffer();
|
|
395
|
-
const schemaVersionHeader =
|
|
396
|
-
response.headers.get("X-Vbundle-Schema-Version") ?? "";
|
|
397
|
-
const parsedSchemaVersion = Number.parseInt(schemaVersionHeader, 10);
|
|
398
|
-
return {
|
|
399
|
-
ok: true,
|
|
400
|
-
archive,
|
|
401
|
-
filename:
|
|
402
|
-
response.headers
|
|
403
|
-
.get("Content-Disposition")
|
|
404
|
-
?.match(/filename="?(.+?)"?$/)?.[1] ?? "export.vbundle",
|
|
405
|
-
schemaVersion: Number.isFinite(parsedSchemaVersion)
|
|
406
|
-
? parsedSchemaVersion
|
|
407
|
-
: 0,
|
|
408
|
-
checksum: response.headers.get("X-Vbundle-Manifest-Sha256") ?? "",
|
|
409
|
-
} as ExportRuntimeResult;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Dry-run import analysis of a .vbundle archive.
|
|
414
|
-
*
|
|
415
|
-
* Returns a detailed report of what would change if the bundle were imported,
|
|
416
|
-
* without modifying any data on disk.
|
|
417
|
-
*/
|
|
418
|
-
export async function importPreflight(
|
|
419
|
-
config: TransportConfig,
|
|
420
|
-
fileData: ArrayBuffer,
|
|
421
|
-
): Promise<ImportPreflightResponse> {
|
|
422
|
-
const doFetch = resolveFetch(config);
|
|
423
|
-
const url = buildURL(config, "import-preflight");
|
|
424
|
-
|
|
425
|
-
const response = await doFetch(url, {
|
|
426
|
-
method: "POST",
|
|
427
|
-
headers: buildHeaders(config, "application/octet-stream"),
|
|
428
|
-
body: fileData,
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
await assertOk(response, "import-preflight");
|
|
432
|
-
return (await response.json()) as ImportPreflightResponse;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
/**
|
|
436
|
-
* Commit a .vbundle archive import.
|
|
437
|
-
*
|
|
438
|
-
* This is a destructive operation that writes bundle files to their
|
|
439
|
-
* target locations. For managed targets, this may initiate an async
|
|
440
|
-
* import job.
|
|
441
|
-
*/
|
|
442
|
-
export async function importCommit(
|
|
443
|
-
config: TransportConfig,
|
|
444
|
-
fileData: ArrayBuffer,
|
|
445
|
-
): Promise<ImportCommitResponse> {
|
|
446
|
-
const doFetch = resolveFetch(config);
|
|
447
|
-
const url = buildURL(config, "import");
|
|
448
|
-
|
|
449
|
-
const response = await doFetch(url, {
|
|
450
|
-
method: "POST",
|
|
451
|
-
headers: buildHeaders(config, "application/octet-stream"),
|
|
452
|
-
body: fileData,
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
// The import endpoint can return non-2xx for server errors but
|
|
456
|
-
// also returns 200 with success: false for validation/write failures.
|
|
457
|
-
// We only throw on non-2xx status codes.
|
|
458
|
-
if (response.status >= 500) {
|
|
459
|
-
const body = await response.text().catch(() => "<unreadable>");
|
|
460
|
-
throw new MigrationTransportError(
|
|
461
|
-
`import: HTTP ${response.status}`,
|
|
462
|
-
response.status,
|
|
463
|
-
body,
|
|
464
|
-
);
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// 400-level errors are also transport failures
|
|
468
|
-
if (response.status >= 400 && response.status < 500) {
|
|
469
|
-
const body = await response.text().catch(() => "<unreadable>");
|
|
470
|
-
throw new MigrationTransportError(
|
|
471
|
-
`import: HTTP ${response.status}`,
|
|
472
|
-
response.status,
|
|
473
|
-
body,
|
|
474
|
-
);
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
return (await response.json()) as ImportCommitResponse;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
/**
|
|
481
|
-
* Poll the status of a cloud export job.
|
|
482
|
-
*
|
|
483
|
-
* Only applicable to managed targets. Runtime exports are synchronous
|
|
484
|
-
* and do not require status polling.
|
|
485
|
-
*/
|
|
486
|
-
export async function pollExportStatus(
|
|
487
|
-
config: TransportConfig,
|
|
488
|
-
jobId: string,
|
|
489
|
-
): Promise<JobStatusResponse> {
|
|
490
|
-
return fetchJobStatus(config, "export", jobId);
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
/**
|
|
494
|
-
* Poll the status of a cloud import job.
|
|
495
|
-
*
|
|
496
|
-
* Only applicable to managed targets. Runtime imports are synchronous
|
|
497
|
-
* and do not require status polling.
|
|
498
|
-
*/
|
|
499
|
-
export async function pollImportStatus(
|
|
500
|
-
config: TransportConfig,
|
|
501
|
-
jobId: string,
|
|
502
|
-
): Promise<JobStatusResponse> {
|
|
503
|
-
return fetchJobStatus(config, "import", jobId);
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
const jobStatusWireSchema = z.object({
|
|
507
|
-
status: z.enum(["pending", "processing", "complete", "failed"]),
|
|
508
|
-
job_id: z.string().optional(),
|
|
509
|
-
download_url: z.string().optional(),
|
|
510
|
-
progress: z.number().optional(),
|
|
511
|
-
error: z.string().optional(),
|
|
512
|
-
result: z.unknown().optional(),
|
|
513
|
-
});
|
|
514
|
-
|
|
515
|
-
function jobStatusFromWire(
|
|
516
|
-
wire: z.infer<typeof jobStatusWireSchema>,
|
|
517
|
-
fallbackJobId: string,
|
|
518
|
-
): JobStatusResponse {
|
|
519
|
-
const jobId = wire.job_id ?? fallbackJobId;
|
|
520
|
-
if (wire.status === "complete") {
|
|
521
|
-
return {
|
|
522
|
-
status: "complete",
|
|
523
|
-
jobId,
|
|
524
|
-
downloadUrl: wire.download_url,
|
|
525
|
-
result: wire.result,
|
|
526
|
-
};
|
|
527
|
-
}
|
|
528
|
-
if (wire.status === "failed") {
|
|
529
|
-
return {
|
|
530
|
-
status: "failed",
|
|
531
|
-
jobId,
|
|
532
|
-
error: wire.error ?? "unknown export error",
|
|
533
|
-
};
|
|
534
|
-
}
|
|
535
|
-
return { status: wire.status, jobId, progress: wire.progress };
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
async function fetchJobStatus(
|
|
539
|
-
config: TransportConfig,
|
|
540
|
-
kind: "export" | "import",
|
|
541
|
-
jobId: string,
|
|
542
|
-
): Promise<JobStatusResponse> {
|
|
543
|
-
if (config.target !== "managed") {
|
|
544
|
-
throw new Error(
|
|
545
|
-
`poll${kind === "export" ? "Export" : "Import"}Status is only supported for managed targets`,
|
|
546
|
-
);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
const doFetch = resolveFetch(config);
|
|
550
|
-
const base = config.baseURL.replace(/\/+$/, "");
|
|
551
|
-
const url = `${base}/v1/migrations/${kind}/${encodeURIComponent(
|
|
552
|
-
jobId,
|
|
553
|
-
)}/status/`;
|
|
554
|
-
|
|
555
|
-
const response = await doFetch(url, {
|
|
556
|
-
method: "GET",
|
|
557
|
-
headers: buildHeaders(config),
|
|
558
|
-
});
|
|
559
|
-
|
|
560
|
-
await assertOk(response, `${kind} status (job ${jobId})`);
|
|
561
|
-
const parsed = jobStatusWireSchema.safeParse(await response.json());
|
|
562
|
-
if (!parsed.success) {
|
|
563
|
-
throw new MigrationTransportError(
|
|
564
|
-
`${kind} status (job ${jobId}): malformed response`,
|
|
565
|
-
response.status,
|
|
566
|
-
"",
|
|
567
|
-
);
|
|
568
|
-
}
|
|
569
|
-
return jobStatusFromWire(parsed.data, jobId);
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
interface PollOptions {
|
|
573
|
-
/** Polling interval in milliseconds. Defaults to 2000. */
|
|
574
|
-
intervalMs?: number;
|
|
575
|
-
/** Maximum number of polls before giving up. Defaults to 60. */
|
|
576
|
-
maxAttempts?: number;
|
|
577
|
-
/** Callback invoked on each poll with the latest status. */
|
|
578
|
-
onProgress?: (status: JobStatusResponse) => void;
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
/**
|
|
582
|
-
* Poll a cloud job until it reaches a terminal state (complete or failed).
|
|
583
|
-
*
|
|
584
|
-
* Returns the final status response. Throws if maxAttempts is exceeded.
|
|
585
|
-
*/
|
|
586
|
-
export async function pollUntilComplete(
|
|
587
|
-
config: TransportConfig,
|
|
588
|
-
jobType: "export" | "import",
|
|
589
|
-
jobId: string,
|
|
590
|
-
options?: PollOptions,
|
|
591
|
-
): Promise<JobStatusComplete | JobStatusFailed> {
|
|
592
|
-
const intervalMs = options?.intervalMs ?? 2000;
|
|
593
|
-
const maxAttempts = options?.maxAttempts ?? 60;
|
|
594
|
-
const pollFn = jobType === "export" ? pollExportStatus : pollImportStatus;
|
|
595
|
-
|
|
596
|
-
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
597
|
-
const status = await pollFn(config, jobId);
|
|
598
|
-
options?.onProgress?.(status);
|
|
599
|
-
|
|
600
|
-
if (status.status === "complete" || status.status === "failed") {
|
|
601
|
-
return status;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
throw new MigrationTransportError(
|
|
608
|
-
`${jobType} job ${jobId} did not complete within ${maxAttempts} polls`,
|
|
609
|
-
0,
|
|
610
|
-
"",
|
|
611
|
-
);
|
|
612
|
-
}
|