@mycadet/assistant 0.12.10 → 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.
Files changed (180) hide show
  1. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
  2. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
  3. package/node_modules/@mycadet/ces-client/src/http-credentials.ts +18 -1
  4. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
  5. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
  6. package/node_modules/@mycadet/gateway-client/src/gateway-ipc-contracts.ts +0 -20
  7. package/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
  8. package/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
  9. package/openapi.yaml +2 -708
  10. package/package.json +2 -3
  11. package/scripts/sync-web-search-catalog.ts +1 -2
  12. package/src/__tests__/cloud-profile-guard.test.ts +41 -5
  13. package/src/__tests__/config-schema.test.ts +6 -38
  14. package/src/__tests__/conversation-queue.test.ts +45 -6
  15. package/src/__tests__/db-readiness-http-gate.test.ts +0 -6
  16. package/src/__tests__/persist-onboarding-artifacts.test.ts +0 -1
  17. package/src/__tests__/persona-resolver.test.ts +0 -51
  18. package/src/__tests__/provider-cloud-proxy-integration.test.ts +2 -110
  19. package/src/__tests__/run-due-schedules.test.ts +0 -4
  20. package/src/__tests__/schedule-store.test.ts +0 -12
  21. package/src/__tests__/stt-stream-session.test.ts +4 -4
  22. package/src/__tests__/telephony-tts-guard.test.ts +2 -50
  23. package/src/__tests__/voice-config-update.test.ts +12 -167
  24. package/src/__tests__/web-search-catalog-parity.test.ts +0 -2
  25. package/src/__tests__/workspace-migration-130-speech-mode-to-provider.test.ts +9 -7
  26. package/src/__tests__/workspace-migration-132-web-search-mode-to-provider.test.ts +6 -6
  27. package/src/calls/__tests__/voice-session-bridge.test.ts +1 -4
  28. package/src/calls/resolve-call-tts-provider.ts +6 -25
  29. package/src/calls/telephony-credential-preflight.ts +0 -10
  30. package/src/calls/telephony-tts-capability.ts +1 -17
  31. package/src/cli/commands/tts.ts +1 -2
  32. package/src/cli/index.help.ts +0 -2
  33. package/src/cli/program.ts +0 -2
  34. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +4 -42
  35. package/src/config/schemas/__tests__/stt.test.ts +10 -14
  36. package/src/config/schemas/llm.ts +3 -5
  37. package/src/config/schemas/services.ts +5 -6
  38. package/src/config/schemas/stt.ts +1 -3
  39. package/src/config/schemas/tts.ts +1 -30
  40. package/src/daemon/daemon-readiness.ts +4 -29
  41. package/src/daemon/lifecycle.ts +0 -31
  42. package/src/daemon/providers-setup.ts +0 -8
  43. package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -1
  44. package/src/heartbeat/heartbeat-service.ts +1 -66
  45. package/src/ipc/__tests__/db-readiness-ipc-gate.test.ts +1 -9
  46. package/src/live-voice/__tests__/live-voice-credential-preflight.test.ts +0 -44
  47. package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +4 -6
  48. package/src/live-voice/__tests__/live-voice-stt.test.ts +1 -1
  49. package/src/live-voice/live-voice-credential-preflight.ts +9 -33
  50. package/src/live-voice/live-voice-session.ts +10 -6
  51. package/src/live-voice/live-voice-tts.ts +1 -8
  52. package/src/plugins/defaults/memory/worker.ts +3 -3
  53. package/src/prompts/persona-resolver.ts +0 -35
  54. package/src/providers/__tests__/search-provider-catalog.test.ts +5 -8
  55. package/src/providers/__tests__/voice-error-copy.test.ts +9 -10
  56. package/src/providers/search-provider-catalog.ts +7 -39
  57. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +3 -47
  58. package/src/providers/speech-to-text/__tests__/resolve.test.ts +6 -372
  59. package/src/providers/speech-to-text/provider-catalog.ts +2 -73
  60. package/src/providers/speech-to-text/resolve.ts +3 -120
  61. package/src/runtime/http-router-types.ts +1 -3
  62. package/src/runtime/http-server.ts +1 -1
  63. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +13 -11
  64. package/src/runtime/routes/__tests__/tts-routes.test.ts +2 -6
  65. package/src/runtime/routes/conversation-query-routes.ts +0 -96
  66. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +7 -7
  67. package/src/runtime/routes/index.ts +0 -4
  68. package/src/runtime/routes/live-voice-routes.test.ts +4 -11
  69. package/src/runtime/routes/live-voice-routes.ts +8 -11
  70. package/src/runtime/routes/secret-routes.ts +0 -6
  71. package/src/runtime/routes/tts-routes.ts +0 -38
  72. package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1 -7
  73. package/src/schedule/__tests__/worker-mcp-readiness.test.ts +0 -4
  74. package/src/schedule/schedule-store.ts +0 -7
  75. package/src/schedule/scheduler.ts +0 -5
  76. package/src/schedule/worker.ts +1 -1
  77. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +2 -10
  78. package/src/stt/daemon-batch-transcriber.ts +4 -38
  79. package/src/stt/types.ts +1 -9
  80. package/src/tools/network/__tests__/web-search.test.ts +3 -250
  81. package/src/tools/network/web-search.ts +4 -165
  82. package/src/tts/__tests__/provider-resolution.test.ts +0 -5
  83. package/src/tts/provider-catalog.ts +0 -4
  84. package/src/tts/types.ts +0 -1
  85. package/src/__tests__/cloud-speech-defaults.test.ts +0 -330
  86. package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1708
  87. package/src/__tests__/migration-export-http.test.ts +0 -557
  88. package/src/__tests__/migration-export-streaming.test.ts +0 -350
  89. package/src/__tests__/migration-export-to-gcs.test.ts +0 -706
  90. package/src/__tests__/migration-import-commit-http.test.ts +0 -1176
  91. package/src/__tests__/migration-import-from-gcs.test.ts +0 -534
  92. package/src/__tests__/migration-import-from-path.test.ts +0 -324
  93. package/src/__tests__/migration-import-from-url.test.ts +0 -588
  94. package/src/__tests__/migration-import-preflight-http.test.ts +0 -739
  95. package/src/__tests__/migration-jobs-status.test.ts +0 -139
  96. package/src/__tests__/migration-parity-persistence.test.ts +0 -1891
  97. package/src/__tests__/migration-transport.test.ts +0 -1089
  98. package/src/__tests__/migration-validate-http.test.ts +0 -634
  99. package/src/__tests__/migration-wizard.test.ts +0 -1395
  100. package/src/__tests__/rebind-secrets-screen.test.ts +0 -876
  101. package/src/__tests__/sanitize-config-for-transfer.test.ts +0 -259
  102. package/src/__tests__/transfer-progress-screen.test.ts +0 -1217
  103. package/src/__tests__/validation-results-screen.test.ts +0 -1130
  104. package/src/__tests__/vbundle-pax-and-symlink.test.ts +0 -147
  105. package/src/background-wake/background-wake-routes.test.ts +0 -906
  106. package/src/background-wake/cloud-client.test.ts +0 -328
  107. package/src/background-wake/cloud-client.ts +0 -196
  108. package/src/background-wake/next-wake.test.ts +0 -335
  109. package/src/background-wake/next-wake.ts +0 -188
  110. package/src/background-wake/publisher.ts +0 -93
  111. package/src/background-wake/wake-intent-hooks.test.ts +0 -234
  112. package/src/cli/commands/__tests__/backup.test.ts +0 -363
  113. package/src/cli/commands/backup.help.ts +0 -180
  114. package/src/cli/commands/backup.ts +0 -398
  115. package/src/cloud/cloud-speech.test.ts +0 -335
  116. package/src/cloud/cloud-speech.ts +0 -300
  117. package/src/config/cloud-speech-defaults.ts +0 -300
  118. package/src/config/sanitize-for-transfer.ts +0 -111
  119. package/src/live-voice/__tests__/live-voice-cloud-speech-fallback.test.ts +0 -250
  120. package/src/providers/speech-to-text/__tests__/cadet-cloud-realtime.test.ts +0 -457
  121. package/src/providers/speech-to-text/__tests__/cadet-cloud.test.ts +0 -271
  122. package/src/providers/speech-to-text/__tests__/cadet-speech-relay-connection.test.ts +0 -126
  123. package/src/providers/speech-to-text/cadet-cloud-flux-realtime.ts +0 -309
  124. package/src/providers/speech-to-text/cadet-cloud-realtime.ts +0 -315
  125. package/src/providers/speech-to-text/cadet-cloud.ts +0 -108
  126. package/src/providers/speech-to-text/cadet-speech-relay-connection.ts +0 -176
  127. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +0 -254
  128. package/src/runtime/migrations/__tests__/job-registry.test.ts +0 -346
  129. package/src/runtime/migrations/__tests__/origin-mode.test.ts +0 -62
  130. package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +0 -184
  131. package/src/runtime/migrations/__tests__/staged-import-path.test.ts +0 -110
  132. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +0 -112
  133. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +0 -285
  134. package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +0 -126
  135. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +0 -253
  136. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +0 -208
  137. package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +0 -485
  138. package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +0 -349
  139. package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +0 -196
  140. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +0 -551
  141. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +0 -428
  142. package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +0 -220
  143. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +0 -1823
  144. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +0 -598
  145. package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +0 -463
  146. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -538
  147. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +0 -515
  148. package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +0 -453
  149. package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +0 -319
  150. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +0 -240
  151. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +0 -473
  152. package/src/runtime/migrations/gcs-signed-url.ts +0 -190
  153. package/src/runtime/migrations/job-registry.ts +0 -297
  154. package/src/runtime/migrations/migration-transport.ts +0 -612
  155. package/src/runtime/migrations/migration-wizard.ts +0 -747
  156. package/src/runtime/migrations/origin-mode.ts +0 -42
  157. package/src/runtime/migrations/rebind-secrets-screen.ts +0 -412
  158. package/src/runtime/migrations/staged-import-path.ts +0 -116
  159. package/src/runtime/migrations/transfer-progress-screen.ts +0 -323
  160. package/src/runtime/migrations/validation-results-screen.ts +0 -469
  161. package/src/runtime/migrations/vbundle-builder.ts +0 -1382
  162. package/src/runtime/migrations/vbundle-import-analyzer.ts +0 -405
  163. package/src/runtime/migrations/vbundle-import-policy.ts +0 -241
  164. package/src/runtime/migrations/vbundle-importer.ts +0 -826
  165. package/src/runtime/migrations/vbundle-metadata-merge.ts +0 -113
  166. package/src/runtime/migrations/vbundle-streaming-importer.ts +0 -2844
  167. package/src/runtime/migrations/vbundle-streaming-validator.ts +0 -426
  168. package/src/runtime/migrations/vbundle-tar-stream.ts +0 -244
  169. package/src/runtime/migrations/vbundle-validator.ts +0 -724
  170. package/src/runtime/routes/__tests__/migration-cadet-metadata-reconcile.test.ts +0 -227
  171. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +0 -54
  172. package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +0 -70
  173. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +0 -257
  174. package/src/runtime/routes/background-wake-routes.ts +0 -387
  175. package/src/runtime/routes/migration-routes.ts +0 -2584
  176. package/src/tools/network/__tests__/cloud-search-proxy.test.ts +0 -282
  177. package/src/tools/network/cloud-search-proxy.ts +0 -211
  178. package/src/tts/__tests__/cadet-provider.test.ts +0 -253
  179. package/src/tts/providers/cadet-provider.ts +0 -244
  180. package/src/types/tar-stream.d.ts +0 -66
@@ -1,469 +0,0 @@
1
- /**
2
- * Validation results screen — view model for the validate + preflight-review steps.
3
- *
4
- * Derives display state from the migration wizard state machine for rendering
5
- * a validation results and dry-run summary UI. Usable from macOS/iOS web views,
6
- * CLI, or any TypeScript consumer.
7
- *
8
- * The screen combines two wizard steps into one logical view:
9
- * 1. validate — bundle integrity and schema validation
10
- * 2. preflight-review — dry-run import analysis (what would change)
11
- *
12
- * View model states:
13
- * - disabled: step is not yet accessible (earlier steps incomplete)
14
- * - loading: validation or preflight analysis is in progress
15
- * - validation-error: bundle validation failed with errors
16
- * - preflight-error: preflight analysis failed
17
- * - transport-error: network/HTTP error occurred
18
- * - success: both validation and preflight passed, ready to proceed
19
- */
20
-
21
- import type {
22
- ImportPreflightConflict,
23
- ImportPreflightFileReport,
24
- ImportPreflightSuccessResponse,
25
- ValidateSuccessResponse,
26
- ValidationError,
27
- } from "./migration-transport.js";
28
- import type {
29
- MigrationWizardState,
30
- StepError,
31
- StepExecutorOptions,
32
- } from "./migration-wizard.js";
33
- import {
34
- canRetryCurrentStep,
35
- executePreflightStep,
36
- executeValidateStep,
37
- goBackTo,
38
- isStepAccessible,
39
- resetStepForRetry,
40
- } from "./migration-wizard.js";
41
-
42
- // ---------------------------------------------------------------------------
43
- // View model types
44
- // ---------------------------------------------------------------------------
45
-
46
- /** Summary counts for the preflight dry-run analysis. */
47
- export interface PreflightSummary {
48
- totalFiles: number;
49
- filesToCreate: number;
50
- filesToOverwrite: number;
51
- filesUnchanged: number;
52
- filesToSkip: number;
53
- }
54
-
55
- /** A file entry in the preflight analysis, normalized for display. */
56
- export interface PreflightFileEntry {
57
- path: string;
58
- action: "create" | "overwrite" | "unchanged" | "skip";
59
- bundleSize: number;
60
- currentSize: number | null;
61
- bundleSha256: string;
62
- currentSha256: string | null;
63
- }
64
-
65
- /** A conflict detected during preflight analysis. */
66
- export interface PreflightConflictEntry {
67
- code: string;
68
- message: string;
69
- path?: string;
70
- }
71
-
72
- /**
73
- * Discriminated union representing the current display state of the
74
- * validation results screen.
75
- */
76
- export type ValidationScreenState =
77
- | { phase: "disabled" }
78
- | { phase: "loading"; message: string }
79
- | {
80
- phase: "validation-error";
81
- errors: ValidationError[];
82
- canRetry: boolean;
83
- }
84
- | {
85
- phase: "preflight-error";
86
- error: StepError;
87
- canRetry: boolean;
88
- }
89
- | {
90
- phase: "transport-error";
91
- error: StepError;
92
- step: "validate" | "preflight-review";
93
- canRetry: boolean;
94
- }
95
- | {
96
- phase: "success";
97
- validation: {
98
- isValid: true;
99
- manifest: ValidateSuccessResponse["manifest"];
100
- };
101
- preflight: {
102
- summary: PreflightSummary;
103
- files: PreflightFileEntry[];
104
- conflicts: PreflightConflictEntry[];
105
- manifest: ImportPreflightSuccessResponse["manifest"];
106
- };
107
- canContinue: boolean;
108
- };
109
-
110
- // ---------------------------------------------------------------------------
111
- // State derivation
112
- // ---------------------------------------------------------------------------
113
-
114
- /**
115
- * Normalize an ImportPreflightFileReport to a display-friendly shape.
116
- */
117
- function normalizeFileReport(
118
- report: ImportPreflightFileReport,
119
- ): PreflightFileEntry {
120
- return {
121
- path: report.path,
122
- action: report.action,
123
- bundleSize: report.bundle_size,
124
- currentSize: report.current_size,
125
- bundleSha256: report.bundle_sha256,
126
- currentSha256: report.current_sha256,
127
- };
128
- }
129
-
130
- /**
131
- * Normalize an ImportPreflightConflict to a display-friendly shape.
132
- */
133
- function normalizeConflict(
134
- conflict: ImportPreflightConflict,
135
- ): PreflightConflictEntry {
136
- return {
137
- code: conflict.code,
138
- message: conflict.message,
139
- ...(conflict.path !== undefined ? { path: conflict.path } : {}),
140
- };
141
- }
142
-
143
- /**
144
- * Derive the current validation screen state from the wizard state.
145
- *
146
- * This is a pure function — no side effects. Call it whenever the wizard
147
- * state changes to get the latest display state.
148
- */
149
- export function deriveValidationScreenState(
150
- wizardState: MigrationWizardState,
151
- ): ValidationScreenState {
152
- const validateStep = wizardState.steps["validate"];
153
- const preflightStep = wizardState.steps["preflight-review"];
154
-
155
- // Check if the validate step is accessible at all
156
- if (
157
- !isStepAccessible(wizardState, "validate") &&
158
- wizardState.currentStep !== "validate" &&
159
- wizardState.currentStep !== "preflight-review"
160
- ) {
161
- // Also check if we're past these steps (success case from later steps)
162
- if (
163
- validateStep.status !== "success" ||
164
- preflightStep.status !== "success"
165
- ) {
166
- return { phase: "disabled" };
167
- }
168
- }
169
-
170
- // Validate step is loading
171
- if (
172
- wizardState.currentStep === "validate" &&
173
- validateStep.status === "loading"
174
- ) {
175
- return { phase: "loading", message: "Validating bundle..." };
176
- }
177
-
178
- // Preflight step is loading
179
- if (
180
- wizardState.currentStep === "preflight-review" &&
181
- preflightStep.status === "loading"
182
- ) {
183
- return { phase: "loading", message: "Analyzing import changes..." };
184
- }
185
-
186
- // Validate step idle (not yet started)
187
- if (
188
- wizardState.currentStep === "validate" &&
189
- validateStep.status === "idle"
190
- ) {
191
- return { phase: "loading", message: "Preparing validation..." };
192
- }
193
-
194
- // Preflight step idle (not yet started, validation passed)
195
- if (
196
- wizardState.currentStep === "preflight-review" &&
197
- preflightStep.status === "idle"
198
- ) {
199
- return { phase: "loading", message: "Preparing import analysis..." };
200
- }
201
-
202
- // Validate step errored
203
- if (
204
- wizardState.currentStep === "validate" &&
205
- validateStep.status === "error"
206
- ) {
207
- // Check if this is a validation failure (bundle invalid) vs transport error
208
- if (wizardState.validateResult && !wizardState.validateResult.is_valid) {
209
- return {
210
- phase: "validation-error",
211
- errors: wizardState.validateResult.errors,
212
- canRetry: canRetryCurrentStep(wizardState),
213
- };
214
- }
215
-
216
- // Transport/network error
217
- return {
218
- phase: "transport-error",
219
- error: validateStep.error ?? {
220
- message: "Validation failed",
221
- retryable: false,
222
- },
223
- step: "validate",
224
- canRetry: canRetryCurrentStep(wizardState),
225
- };
226
- }
227
-
228
- // Preflight step errored
229
- if (
230
- wizardState.currentStep === "preflight-review" &&
231
- preflightStep.status === "error"
232
- ) {
233
- // Check if this is a preflight validation failure vs transport error
234
- if (
235
- wizardState.preflightResult &&
236
- !wizardState.preflightResult.can_import
237
- ) {
238
- return {
239
- phase: "preflight-error",
240
- error: preflightStep.error ?? {
241
- message: "Import preflight validation failed",
242
- retryable: false,
243
- },
244
- canRetry: canRetryCurrentStep(wizardState),
245
- };
246
- }
247
-
248
- // Transport/network error
249
- return {
250
- phase: "transport-error",
251
- error: preflightStep.error ?? {
252
- message: "Preflight analysis failed",
253
- retryable: false,
254
- },
255
- step: "preflight-review",
256
- canRetry: canRetryCurrentStep(wizardState),
257
- };
258
- }
259
-
260
- // Both steps succeeded — show full results
261
- if (
262
- validateStep.status === "success" &&
263
- preflightStep.status === "success" &&
264
- wizardState.validateResult?.is_valid &&
265
- wizardState.preflightResult?.can_import
266
- ) {
267
- const validateResult =
268
- wizardState.validateResult as ValidateSuccessResponse;
269
- const preflightResult =
270
- wizardState.preflightResult as ImportPreflightSuccessResponse;
271
-
272
- return {
273
- phase: "success",
274
- validation: {
275
- isValid: true,
276
- manifest: validateResult.manifest,
277
- },
278
- preflight: {
279
- summary: {
280
- totalFiles: preflightResult.summary.total_files,
281
- filesToCreate: preflightResult.summary.files_to_create,
282
- filesToOverwrite: preflightResult.summary.files_to_overwrite,
283
- filesUnchanged: preflightResult.summary.files_unchanged,
284
- filesToSkip: preflightResult.summary.files_to_skip,
285
- },
286
- files: preflightResult.files.map(normalizeFileReport),
287
- conflicts: preflightResult.conflicts.map(normalizeConflict),
288
- manifest: preflightResult.manifest,
289
- },
290
- canContinue: isStepAccessible(wizardState, "transfer"),
291
- };
292
- }
293
-
294
- // Fallback: if we're on a step past preflight-review and both succeeded,
295
- // still show success (viewing results from a later step)
296
- if (validateStep.status === "success" && preflightStep.status === "success") {
297
- const validateResult = wizardState.validateResult;
298
- const preflightResult = wizardState.preflightResult;
299
-
300
- if (validateResult?.is_valid && preflightResult?.can_import) {
301
- const vr = validateResult as ValidateSuccessResponse;
302
- const pr = preflightResult as ImportPreflightSuccessResponse;
303
-
304
- return {
305
- phase: "success",
306
- validation: {
307
- isValid: true,
308
- manifest: vr.manifest,
309
- },
310
- preflight: {
311
- summary: {
312
- totalFiles: pr.summary.total_files,
313
- filesToCreate: pr.summary.files_to_create,
314
- filesToOverwrite: pr.summary.files_to_overwrite,
315
- filesUnchanged: pr.summary.files_unchanged,
316
- filesToSkip: pr.summary.files_to_skip,
317
- },
318
- files: pr.files.map(normalizeFileReport),
319
- conflicts: pr.conflicts.map(normalizeConflict),
320
- manifest: pr.manifest,
321
- },
322
- canContinue: isStepAccessible(wizardState, "transfer"),
323
- };
324
- }
325
- }
326
-
327
- return { phase: "disabled" };
328
- }
329
-
330
- // ---------------------------------------------------------------------------
331
- // Actions — delegate to wizard state machine
332
- // ---------------------------------------------------------------------------
333
-
334
- /**
335
- * Execute both the validate and preflight steps in sequence.
336
- *
337
- * Runs validation first; if it succeeds, automatically proceeds to
338
- * preflight analysis. Returns the final wizard state after both steps.
339
- */
340
- export async function executeValidationFlow(
341
- state: MigrationWizardState,
342
- options: StepExecutorOptions,
343
- ): Promise<MigrationWizardState> {
344
- // Run validation
345
- let current = await executeValidateStep(state, options);
346
-
347
- // If validation succeeded, the wizard advances to preflight-review.
348
- // Automatically run the preflight step.
349
- if (
350
- current.currentStep === "preflight-review" &&
351
- current.steps["validate"].status === "success"
352
- ) {
353
- current = await executePreflightStep(current, options);
354
- }
355
-
356
- return current;
357
- }
358
-
359
- /**
360
- * Retry the current step after an error.
361
- *
362
- * Resets the step to idle and re-executes the appropriate step.
363
- * If the validate step is retried and succeeds, automatically
364
- * proceeds to the preflight step.
365
- */
366
- export async function retryValidationFlow(
367
- state: MigrationWizardState,
368
- options: StepExecutorOptions,
369
- ): Promise<MigrationWizardState> {
370
- let reset = resetStepForRetry(state);
371
-
372
- // Clear stale results so a new transport error isn't misclassified
373
- // as a validation/preflight failure based on the previous attempt's result.
374
- if (reset.currentStep === "validate") {
375
- reset = { ...reset, validateResult: undefined };
376
- } else if (reset.currentStep === "preflight-review") {
377
- reset = { ...reset, preflightResult: undefined };
378
- }
379
-
380
- options.onStateChange?.(reset);
381
-
382
- if (reset.currentStep === "validate") {
383
- return executeValidationFlow(reset, options);
384
- }
385
-
386
- if (reset.currentStep === "preflight-review") {
387
- return executePreflightStep(reset, options);
388
- }
389
-
390
- throw new Error(
391
- `Cannot retry validation flow from step "${reset.currentStep}"`,
392
- );
393
- }
394
-
395
- /**
396
- * Navigate back to the upload-bundle step.
397
- */
398
- export function goBackToUpload(
399
- state: MigrationWizardState,
400
- ): MigrationWizardState {
401
- return goBackTo(state, "upload-bundle");
402
- }
403
-
404
- // ---------------------------------------------------------------------------
405
- // Query helpers
406
- // ---------------------------------------------------------------------------
407
-
408
- /**
409
- * Check if the validation results screen is accessible from the current state.
410
- */
411
- export function isValidationScreenAccessible(
412
- state: MigrationWizardState,
413
- ): boolean {
414
- return (
415
- isStepAccessible(state, "validate") ||
416
- state.currentStep === "validate" ||
417
- state.currentStep === "preflight-review"
418
- );
419
- }
420
-
421
- /**
422
- * Get the file entries grouped by action for display.
423
- */
424
- export function groupFilesByAction(files: PreflightFileEntry[]): {
425
- create: PreflightFileEntry[];
426
- overwrite: PreflightFileEntry[];
427
- unchanged: PreflightFileEntry[];
428
- skip: PreflightFileEntry[];
429
- } {
430
- const create: PreflightFileEntry[] = [];
431
- const overwrite: PreflightFileEntry[] = [];
432
- const unchanged: PreflightFileEntry[] = [];
433
- const skip: PreflightFileEntry[] = [];
434
-
435
- for (const file of files) {
436
- switch (file.action) {
437
- case "create":
438
- create.push(file);
439
- break;
440
- case "overwrite":
441
- overwrite.push(file);
442
- break;
443
- case "unchanged":
444
- unchanged.push(file);
445
- break;
446
- case "skip":
447
- skip.push(file);
448
- break;
449
- }
450
- }
451
-
452
- return { create, overwrite, unchanged, skip };
453
- }
454
-
455
- /**
456
- * Format a byte size as a human-readable string.
457
- */
458
- export function formatFileSize(bytes: number): string {
459
- if (bytes <= 0) {
460
- return "0 B";
461
- }
462
- const units = ["B", "KB", "MB", "GB"];
463
- const exponent = Math.min(
464
- Math.max(0, Math.floor(Math.log(bytes) / Math.log(1024))),
465
- units.length - 1,
466
- );
467
- const value = bytes / Math.pow(1024, exponent);
468
- return `${exponent === 0 ? value : value.toFixed(1)} ${units[exponent]}`;
469
- }