@superblocksteam/vite-plugin-file-sync 2.0.140 → 2.0.141-next.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/dist/ai-service/agent/prompts/build-base-system-prompt.js +1 -0
- package/dist/ai-service/agent/prompts/build-base-system-prompt.js.map +1 -1
- package/dist/ai-service/agent/tools/apis/api-testing-state.d.ts +1 -0
- package/dist/ai-service/agent/tools/apis/api-testing-state.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/apis/api-testing-state.js +16 -0
- package/dist/ai-service/agent/tools/apis/api-testing-state.js.map +1 -1
- package/dist/ai-service/agent/tools/apis/get-api-docs.d.ts +1 -1
- package/dist/ai-service/agent/tools/apis/test-api.d.ts +1 -1
- package/dist/ai-service/agent/tools/apis/test-api.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/apis/test-api.js +13 -7
- package/dist/ai-service/agent/tools/apis/test-api.js.map +1 -1
- package/dist/ai-service/agent/tools/build-copy-directory.d.ts +1 -1
- package/dist/ai-service/agent/tools/build-copy-file.d.ts +1 -1
- package/dist/ai-service/agent/tools/build-copy-utils.d.ts +8 -8
- package/dist/ai-service/agent/tools/build-delete-file.d.ts +1 -1
- package/dist/ai-service/agent/tools/build-finalize.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/build-finalize.js +1 -2
- package/dist/ai-service/agent/tools/build-finalize.js.map +1 -1
- package/dist/ai-service/agent/tools/build-manage-checklist.d.ts +4 -4
- package/dist/ai-service/agent/tools/databases/dev-database-tasks.d.ts +4 -4
- package/dist/ai-service/agent/tools/get-logs.d.ts +3 -3
- package/dist/ai-service/agent/tools/integrations/execute-request.d.ts +9 -9
- package/dist/ai-service/agent/tools2/tools/end-test-run.d.ts +2 -2
- package/dist/ai-service/agent/tools2/tools/exit-plan-mode.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/tools/exit-plan-mode.js +93 -6
- package/dist/ai-service/agent/tools2/tools/exit-plan-mode.js.map +1 -1
- package/dist/ai-service/agent/tools2/tools/git.d.ts +1 -1
- package/dist/ai-service/agent/tools2/tools/grep-metadata.d.ts +1 -1
- package/dist/ai-service/agent/tools2/tools/grep.d.ts +1 -1
- package/dist/ai-service/agent/tools2/tools/list-attachments.d.ts +1 -1
- package/dist/ai-service/app-interface/npm-package-lookup.d.ts +3 -2
- package/dist/ai-service/app-interface/npm-package-lookup.d.ts.map +1 -1
- package/dist/ai-service/app-interface/npm-package-lookup.js +21 -13
- package/dist/ai-service/app-interface/npm-package-lookup.js.map +1 -1
- package/dist/ai-service/app-interface/shell.d.ts.map +1 -1
- package/dist/ai-service/app-interface/shell.js +119 -0
- package/dist/ai-service/app-interface/shell.js.map +1 -1
- package/dist/ai-service/checklist/api-migration-checklist-gate.js +1 -1
- package/dist/ai-service/checklist/api-migration-checklist-gate.js.map +1 -1
- package/dist/ai-service/features.d.ts +11 -0
- package/dist/ai-service/features.d.ts.map +1 -1
- package/dist/ai-service/features.js +24 -0
- package/dist/ai-service/features.js.map +1 -1
- package/dist/ai-service/index.d.ts +38 -4
- package/dist/ai-service/index.d.ts.map +1 -1
- package/dist/ai-service/index.js +210 -13
- package/dist/ai-service/index.js.map +1 -1
- package/dist/ai-service/llm/client.d.ts.map +1 -1
- package/dist/ai-service/llm/client.js +23 -0
- package/dist/ai-service/llm/client.js.map +1 -1
- package/dist/ai-service/llm/context-v2/context.d.ts +31 -2
- package/dist/ai-service/llm/context-v2/context.d.ts.map +1 -1
- package/dist/ai-service/llm/context-v2/context.js +81 -8
- package/dist/ai-service/llm/context-v2/context.js.map +1 -1
- package/dist/ai-service/llm/context-v2/turns.d.ts.map +1 -1
- package/dist/ai-service/llm/context-v2/turns.js +25 -1
- package/dist/ai-service/llm/context-v2/turns.js.map +1 -1
- package/dist/ai-service/llm/context-v2/types.d.ts +9 -0
- package/dist/ai-service/llm/context-v2/types.d.ts.map +1 -1
- package/dist/ai-service/llm/context-v2/types.js.map +1 -1
- package/dist/ai-service/llm/stream/config.d.ts +15 -0
- package/dist/ai-service/llm/stream/config.d.ts.map +1 -1
- package/dist/ai-service/llm/stream/config.js +9 -0
- package/dist/ai-service/llm/stream/config.js.map +1 -1
- package/dist/ai-service/llm/stream/errors.d.ts +1 -1
- package/dist/ai-service/llm/stream/errors.d.ts.map +1 -1
- package/dist/ai-service/llm/stream/errors.js.map +1 -1
- package/dist/ai-service/llm/stream/idle-monitor.d.ts +8 -0
- package/dist/ai-service/llm/stream/idle-monitor.d.ts.map +1 -1
- package/dist/ai-service/llm/stream/idle-monitor.js +51 -0
- package/dist/ai-service/llm/stream/idle-monitor.js.map +1 -1
- package/dist/ai-service/llm/stream/index.d.ts +1 -1
- package/dist/ai-service/llm/stream/index.d.ts.map +1 -1
- package/dist/ai-service/llm/stream/index.js.map +1 -1
- package/dist/ai-service/llm/stream/managed-stream.d.ts.map +1 -1
- package/dist/ai-service/llm/stream/managed-stream.js +2 -5
- package/dist/ai-service/llm/stream/managed-stream.js.map +1 -1
- package/dist/ai-service/llm/stream/orchestrator.d.ts +2 -0
- package/dist/ai-service/llm/stream/orchestrator.d.ts.map +1 -1
- package/dist/ai-service/llm/stream/orchestrator.js +67 -3
- package/dist/ai-service/llm/stream/orchestrator.js.map +1 -1
- package/dist/ai-service/llm/stream/structured-output-chunk.d.ts +16 -0
- package/dist/ai-service/llm/stream/structured-output-chunk.d.ts.map +1 -0
- package/dist/ai-service/llm/stream/structured-output-chunk.js +26 -0
- package/dist/ai-service/llm/stream/structured-output-chunk.js.map +1 -0
- package/dist/ai-service/migration-auto-dispatch-readiness.d.ts +18 -0
- package/dist/ai-service/migration-auto-dispatch-readiness.d.ts.map +1 -0
- package/dist/ai-service/migration-auto-dispatch-readiness.js +17 -0
- package/dist/ai-service/migration-auto-dispatch-readiness.js.map +1 -0
- package/dist/ai-service/migration-autodispatch-metrics.d.ts +3 -0
- package/dist/ai-service/migration-autodispatch-metrics.d.ts.map +1 -0
- package/dist/ai-service/migration-autodispatch-metrics.js +51 -0
- package/dist/ai-service/migration-autodispatch-metrics.js.map +1 -0
- package/dist/ai-service/migration-llm-config.d.ts +12 -0
- package/dist/ai-service/migration-llm-config.d.ts.map +1 -0
- package/dist/ai-service/migration-llm-config.js +130 -0
- package/dist/ai-service/migration-llm-config.js.map +1 -0
- package/dist/ai-service/migration-session-active.d.ts +14 -0
- package/dist/ai-service/migration-session-active.d.ts.map +1 -0
- package/dist/ai-service/migration-session-active.js +29 -0
- package/dist/ai-service/migration-session-active.js.map +1 -0
- package/dist/ai-service/resolve-generation-state-for-ui.d.ts +8 -0
- package/dist/ai-service/resolve-generation-state-for-ui.d.ts.map +1 -0
- package/dist/ai-service/resolve-generation-state-for-ui.js +25 -0
- package/dist/ai-service/resolve-generation-state-for-ui.js.map +1 -0
- package/dist/ai-service/skills/system/superblocks-migration/skill.generated.d.ts +1 -1
- package/dist/ai-service/skills/system/superblocks-migration/skill.generated.d.ts.map +1 -1
- package/dist/ai-service/skills/system/superblocks-migration/skill.generated.js +5 -1
- package/dist/ai-service/skills/system/superblocks-migration/skill.generated.js.map +1 -1
- package/dist/ai-service/state-machine/helpers/peer.d.ts +19 -1
- package/dist/ai-service/state-machine/helpers/peer.d.ts.map +1 -1
- package/dist/ai-service/state-machine/helpers/peer.js +81 -7
- package/dist/ai-service/state-machine/helpers/peer.js.map +1 -1
- package/dist/ai-service/state-machine/mocks.d.ts.map +1 -1
- package/dist/ai-service/state-machine/mocks.js +1 -0
- package/dist/ai-service/state-machine/mocks.js.map +1 -1
- package/dist/ai-service/types.d.ts +6 -0
- package/dist/ai-service/types.d.ts.map +1 -1
- package/dist/ai-service/types.js.map +1 -1
- package/dist/ai-service/util/inference-jwt.d.ts +15 -0
- package/dist/ai-service/util/inference-jwt.d.ts.map +1 -0
- package/dist/ai-service/util/inference-jwt.js +56 -0
- package/dist/ai-service/util/inference-jwt.js.map +1 -0
- package/dist/file-sync-vite-plugin.d.ts.map +1 -1
- package/dist/file-sync-vite-plugin.js +3 -6
- package/dist/file-sync-vite-plugin.js.map +1 -1
- package/dist/file-system-helpers.d.ts +14 -0
- package/dist/file-system-helpers.d.ts.map +1 -1
- package/dist/file-system-helpers.js +30 -0
- package/dist/file-system-helpers.js.map +1 -1
- package/dist/migration/integration-write-policy.d.ts +12 -0
- package/dist/migration/integration-write-policy.d.ts.map +1 -0
- package/dist/migration/integration-write-policy.js +31 -0
- package/dist/migration/integration-write-policy.js.map +1 -0
- package/dist/migration/migration-metrics.d.ts +69 -0
- package/dist/migration/migration-metrics.d.ts.map +1 -0
- package/dist/migration/migration-metrics.js +98 -0
- package/dist/migration/migration-metrics.js.map +1 -0
- package/dist/migration/migration-routes.d.ts.map +1 -1
- package/dist/migration/migration-routes.js +53 -121
- package/dist/migration/migration-routes.js.map +1 -1
- package/dist/migration/migration-verification.d.ts +49 -7
- package/dist/migration/migration-verification.d.ts.map +1 -1
- package/dist/migration/migration-verification.js +92 -28
- package/dist/migration/migration-verification.js.map +1 -1
- package/dist/migration/restructure.d.ts +10 -4
- package/dist/migration/restructure.d.ts.map +1 -1
- package/dist/migration/restructure.js +3 -2
- package/dist/migration/restructure.js.map +1 -1
- package/dist/server-rpc/client.d.ts.map +1 -1
- package/dist/server-rpc/client.js +11 -2
- package/dist/server-rpc/client.js.map +1 -1
- package/dist/socket-manager.d.ts.map +1 -1
- package/dist/socket-manager.js +5 -0
- package/dist/socket-manager.js.map +1 -1
- package/package.json +10 -10
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { FALLBACK_STRATEGIES } from "@superblocksteam/library-shared/types";
|
|
2
|
+
/**
|
|
3
|
+
* LaunchDarkly keys mirrored from the UI `Flag` enum for Clark LLM config.
|
|
4
|
+
* Keep in sync with `packages/ui/src/app/store/slices/featureFlags/models/Flags.ts`.
|
|
5
|
+
*/
|
|
6
|
+
const FLAG_KEYS = {
|
|
7
|
+
chaosOptions: "ui.clark-ai.chaos.options",
|
|
8
|
+
contextOptionsV2: "ai.context-v2.options",
|
|
9
|
+
coreModelName: "superblocks.ai.core-model.name",
|
|
10
|
+
defaultThinkingBudget: "ui.clark-ai.default-thinking-budget",
|
|
11
|
+
fallbackStrategy: "ai.fallback.strategy",
|
|
12
|
+
llmProvider: "ui.clark-ai.llm-provider",
|
|
13
|
+
migrationAutoDispatchEnabled: "clark.migration-autodispatch.enabled",
|
|
14
|
+
navigationToolEnabled: "ui.clark-ai.tool.navigation",
|
|
15
|
+
screenshotToolEnabled: "ai.screenshot-tool.enabled",
|
|
16
|
+
serverContextManagement: "ai.server-context-management.options",
|
|
17
|
+
testingEnabled: "ai.playwright-app-test.enabled",
|
|
18
|
+
unifiedProviderEnabled: "superblocks.ai.provider.unified",
|
|
19
|
+
};
|
|
20
|
+
const VALID_CORE_MODELS = [
|
|
21
|
+
"claude-opus-4-5",
|
|
22
|
+
"claude-opus-4-6",
|
|
23
|
+
"claude-opus-4-7",
|
|
24
|
+
"claude-sonnet-4-5",
|
|
25
|
+
"claude-sonnet-4-6",
|
|
26
|
+
];
|
|
27
|
+
const DEFAULT_CORE_MODEL = "claude-sonnet-4-5";
|
|
28
|
+
const isValidProvider = (provider) => provider === "vertex" ||
|
|
29
|
+
provider === "bedrock" ||
|
|
30
|
+
provider === "anthropic" ||
|
|
31
|
+
provider === "snowflake";
|
|
32
|
+
const normalizeProvider = (provider, defaultProvider) => {
|
|
33
|
+
if (isValidProvider(provider)) {
|
|
34
|
+
return provider;
|
|
35
|
+
}
|
|
36
|
+
return defaultProvider;
|
|
37
|
+
};
|
|
38
|
+
const getDisabledToolsForMigration = (flags) => {
|
|
39
|
+
const disabledTools = [];
|
|
40
|
+
if (!flags.isScreenshotToolEnabled) {
|
|
41
|
+
disabledTools.push("build_captureScreenshot");
|
|
42
|
+
}
|
|
43
|
+
if (!flags.isNavigationToolEnabled) {
|
|
44
|
+
disabledTools.push("build_navigatePreview");
|
|
45
|
+
}
|
|
46
|
+
if (!flags.isTestingEnabled) {
|
|
47
|
+
disabledTools.push("startTestRun");
|
|
48
|
+
disabledTools.push("endTestRun");
|
|
49
|
+
disabledTools.push("browser_playwright_action");
|
|
50
|
+
}
|
|
51
|
+
return disabledTools;
|
|
52
|
+
};
|
|
53
|
+
const readFlag = (flagBootstrap, key, fallback) => {
|
|
54
|
+
const raw = flagBootstrap?.[key];
|
|
55
|
+
// Flag bootstrap values are typed at the LaunchDarkly source; callers supply fallbacks.
|
|
56
|
+
return raw === undefined ? fallback : raw;
|
|
57
|
+
};
|
|
58
|
+
const readOptionalRecord = (flagBootstrap, key) => {
|
|
59
|
+
const raw = flagBootstrap?.[key];
|
|
60
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
return raw;
|
|
64
|
+
};
|
|
65
|
+
const readFallbackStrategy = (flagBootstrap) => {
|
|
66
|
+
const raw = flagBootstrap?.[FLAG_KEYS.fallbackStrategy];
|
|
67
|
+
if (typeof raw === "string" &&
|
|
68
|
+
FALLBACK_STRATEGIES.includes(raw)) {
|
|
69
|
+
return raw;
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Builds a migration-safe LLM config on the dev server using org flag
|
|
75
|
+
* bootstrap values. Checklist + migration tools are always enabled.
|
|
76
|
+
*/
|
|
77
|
+
export function buildServerMigrationLlmConfig(flagBootstrap) {
|
|
78
|
+
const llmProvider = readFlag(flagBootstrap, FLAG_KEYS.llmProvider, "vertex");
|
|
79
|
+
const defaultThinkingBudget = readFlag(flagBootstrap, FLAG_KEYS.defaultThinkingBudget, 5000);
|
|
80
|
+
const coreModelName = readFlag(flagBootstrap, FLAG_KEYS.coreModelName, DEFAULT_CORE_MODEL);
|
|
81
|
+
let coreModel = DEFAULT_CORE_MODEL;
|
|
82
|
+
if (VALID_CORE_MODELS.includes(coreModelName)) {
|
|
83
|
+
coreModel = coreModelName;
|
|
84
|
+
}
|
|
85
|
+
else if (coreModelName !== DEFAULT_CORE_MODEL) {
|
|
86
|
+
console.warn(`[migration-llm-config] Unrecognized core model "${coreModelName}"; falling back to ${DEFAULT_CORE_MODEL}`);
|
|
87
|
+
}
|
|
88
|
+
const unifiedProviderEnabled = readFlag(flagBootstrap, FLAG_KEYS.unifiedProviderEnabled, false);
|
|
89
|
+
const isNavigationToolEnabled = readFlag(flagBootstrap, FLAG_KEYS.navigationToolEnabled, true);
|
|
90
|
+
const isScreenshotToolEnabled = readFlag(flagBootstrap, FLAG_KEYS.screenshotToolEnabled, true);
|
|
91
|
+
const isTestingEnabled = readFlag(flagBootstrap, FLAG_KEYS.testingEnabled, false);
|
|
92
|
+
const chaosOptionsRaw = readOptionalRecord(flagBootstrap, FLAG_KEYS.chaosOptions);
|
|
93
|
+
const chaosOptions = chaosOptionsRaw && Object.keys(chaosOptionsRaw).length > 0
|
|
94
|
+
? chaosOptionsRaw
|
|
95
|
+
: undefined;
|
|
96
|
+
const migrationFlags = {
|
|
97
|
+
isChecklistEnabled: true,
|
|
98
|
+
isNavigationToolEnabled,
|
|
99
|
+
isScreenshotToolEnabled,
|
|
100
|
+
isTestingEnabled,
|
|
101
|
+
isFactsEnabled: false,
|
|
102
|
+
isAppKnowledgeEnabled: false,
|
|
103
|
+
};
|
|
104
|
+
return {
|
|
105
|
+
provider: normalizeProvider(llmProvider, "vertex"),
|
|
106
|
+
thinkingEnabled: true,
|
|
107
|
+
thinkingBudgetTokens: String(defaultThinkingBudget),
|
|
108
|
+
interleavedThinking: true,
|
|
109
|
+
disabledTools: getDisabledToolsForMigration({
|
|
110
|
+
isNavigationToolEnabled,
|
|
111
|
+
isScreenshotToolEnabled,
|
|
112
|
+
isTestingEnabled,
|
|
113
|
+
}),
|
|
114
|
+
contextOptionsV2: readOptionalRecord(flagBootstrap, FLAG_KEYS.contextOptionsV2),
|
|
115
|
+
serverContextManagement: readOptionalRecord(flagBootstrap, FLAG_KEYS.serverContextManagement),
|
|
116
|
+
chaosOptions: chaosOptions,
|
|
117
|
+
coreModel,
|
|
118
|
+
unifiedProviderEnabled,
|
|
119
|
+
fallbackStrategy: readFallbackStrategy(flagBootstrap),
|
|
120
|
+
flags: migrationFlags,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Whether the dev server may auto-dispatch the post-flip migration turn.
|
|
125
|
+
* Default off — soak via LaunchDarkly before enabling broadly.
|
|
126
|
+
*/
|
|
127
|
+
export function isMigrationAutoDispatchEnabled(flagBootstrap) {
|
|
128
|
+
return readFlag(flagBootstrap, FLAG_KEYS.migrationAutoDispatchEnabled, false);
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=migration-llm-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-llm-config.js","sourceRoot":"","sources":["../../src/ai-service/migration-llm-config.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAE5E;;;GAGG;AACH,MAAM,SAAS,GAAG;IAChB,YAAY,EAAE,2BAA2B;IACzC,gBAAgB,EAAE,uBAAuB;IACzC,aAAa,EAAE,gCAAgC;IAC/C,qBAAqB,EAAE,qCAAqC;IAC5D,gBAAgB,EAAE,sBAAsB;IACxC,WAAW,EAAE,0BAA0B;IACvC,4BAA4B,EAAE,sCAAsC;IACpE,qBAAqB,EAAE,6BAA6B;IACpD,qBAAqB,EAAE,4BAA4B;IACnD,uBAAuB,EAAE,sCAAsC;IAC/D,cAAc,EAAE,gCAAgC;IAChD,sBAAsB,EAAE,iCAAiC;CACjD,CAAC;AAEX,MAAM,iBAAiB,GAAsB;IAC3C,iBAAiB;IACjB,iBAAiB;IACjB,iBAAiB;IACjB,mBAAmB;IACnB,mBAAmB;CACpB,CAAC;AAEF,MAAM,kBAAkB,GAAkB,mBAAmB,CAAC;AAE9D,MAAM,eAAe,GAAG,CAAC,QAAiB,EAAkC,EAAE,CAC5E,QAAQ,KAAK,QAAQ;IACrB,QAAQ,KAAK,SAAS;IACtB,QAAQ,KAAK,WAAW;IACxB,QAAQ,KAAK,WAAW,CAAC;AAE3B,MAAM,iBAAiB,GAAG,CACxB,QAA4B,EAC5B,eAAmC,EACf,EAAE;IACtB,IAAI,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9B,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,4BAA4B,GAAG,CAAC,KAIrC,EAAY,EAAE;IACb,MAAM,aAAa,GAAa,EAAE,CAAC;IACnC,IAAI,CAAC,KAAK,CAAC,uBAAuB,EAAE,CAAC;QACnC,aAAa,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,uBAAuB,EAAE,CAAC;QACnC,aAAa,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC;QAC5B,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACnC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACjC,aAAa,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,CACf,aAAkD,EAClD,GAAW,EACX,QAAW,EACR,EAAE;IACL,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC;IACjC,wFAAwF;IACxF,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAE,GAAS,CAAC;AACnD,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CACzB,aAAkD,EAClD,GAAW,EAC0B,EAAE;IACvC,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,GAA8B,CAAC;AACxC,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAC3B,aAAkD,EACpB,EAAE;IAChC,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IACxD,IACE,OAAO,GAAG,KAAK,QAAQ;QACtB,mBAAyC,CAAC,QAAQ,CAAC,GAAG,CAAC,EACxD,CAAC;QACD,OAAO,GAAuB,CAAC;IACjC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAC3C,aAAuC;IAEvC,MAAM,WAAW,GAAG,QAAQ,CAC1B,aAAa,EACb,SAAS,CAAC,WAAW,EACrB,QAAQ,CACT,CAAC;IACF,MAAM,qBAAqB,GAAG,QAAQ,CACpC,aAAa,EACb,SAAS,CAAC,qBAAqB,EAC/B,IAAI,CACL,CAAC;IACF,MAAM,aAAa,GAAG,QAAQ,CAC5B,aAAa,EACb,SAAS,CAAC,aAAa,EACvB,kBAAkB,CACnB,CAAC;IACF,IAAI,SAAS,GAAkB,kBAAkB,CAAC;IAClD,IAAI,iBAAiB,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9C,SAAS,GAAG,aAA8B,CAAC;IAC7C,CAAC;SAAM,IAAI,aAAa,KAAK,kBAAkB,EAAE,CAAC;QAChD,OAAO,CAAC,IAAI,CACV,mDAAmD,aAAa,sBAAsB,kBAAkB,EAAE,CAC3G,CAAC;IACJ,CAAC;IACD,MAAM,sBAAsB,GAAG,QAAQ,CACrC,aAAa,EACb,SAAS,CAAC,sBAAsB,EAChC,KAAK,CACN,CAAC;IACF,MAAM,uBAAuB,GAAG,QAAQ,CACtC,aAAa,EACb,SAAS,CAAC,qBAAqB,EAC/B,IAAI,CACL,CAAC;IACF,MAAM,uBAAuB,GAAG,QAAQ,CACtC,aAAa,EACb,SAAS,CAAC,qBAAqB,EAC/B,IAAI,CACL,CAAC;IACF,MAAM,gBAAgB,GAAG,QAAQ,CAC/B,aAAa,EACb,SAAS,CAAC,cAAc,EACxB,KAAK,CACN,CAAC;IACF,MAAM,eAAe,GAAG,kBAAkB,CACxC,aAAa,EACb,SAAS,CAAC,YAAY,CACvB,CAAC;IACF,MAAM,YAAY,GAChB,eAAe,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,GAAG,CAAC;QACxD,CAAC,CAAC,eAAe;QACjB,CAAC,CAAC,SAAS,CAAC;IAEhB,MAAM,cAAc,GAAG;QACrB,kBAAkB,EAAE,IAAI;QACxB,uBAAuB;QACvB,uBAAuB;QACvB,gBAAgB;QAChB,cAAc,EAAE,KAAK;QACrB,qBAAqB,EAAE,KAAK;KAC7B,CAAC;IAEF,OAAO;QACL,QAAQ,EAAE,iBAAiB,CAAC,WAAW,EAAE,QAAQ,CAAC;QAClD,eAAe,EAAE,IAAI;QACrB,oBAAoB,EAAE,MAAM,CAAC,qBAAqB,CAAC;QACnD,mBAAmB,EAAE,IAAI;QACzB,aAAa,EAAE,4BAA4B,CAAC;YAC1C,uBAAuB;YACvB,uBAAuB;YACvB,gBAAgB;SACjB,CAAC;QACF,gBAAgB,EAAE,kBAAkB,CAClC,aAAa,EACb,SAAS,CAAC,gBAAgB,CACc;QAC1C,uBAAuB,EAAE,kBAAkB,CACzC,aAAa,EACb,SAAS,CAAC,uBAAuB,CACc;QACjD,YAAY,EAAE,YAAiD;QAC/D,SAAS;QACT,sBAAsB;QACtB,gBAAgB,EAAE,oBAAoB,CAAC,aAAa,CAAC;QACrD,KAAK,EAAE,cAAc;KACtB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,8BAA8B,CAC5C,aAAuC;IAEvC,OAAO,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Positive migration-session gate for auto-dispatch. Returns true only while a
|
|
3
|
+
* migration session is genuinely in flight on disk — the dev server writes
|
|
4
|
+
* `scratch/migration-state.json` when a migration starts and removes it on
|
|
5
|
+
* every terminal path (completion removes the scratch dir; abort removes the
|
|
6
|
+
* file). A never-migrated or cleanly-completed app therefore has no state file,
|
|
7
|
+
* so a stale `checklist.json` alone can never arm auto-dispatch during normal
|
|
8
|
+
* app usage. On fresh post-flip pods the file is restored by
|
|
9
|
+
* `rehydrateMigrationScratchOnBoot`, which only downloads scratch when the
|
|
10
|
+
* server session phase is active — so presence here is a proxy for a
|
|
11
|
+
* server-confirmed active session.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isMigrationSessionActive(appRootDirPath: string): Promise<boolean>;
|
|
14
|
+
//# sourceMappingURL=migration-session-active.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-session-active.d.ts","sourceRoot":"","sources":["../../src/ai-service/migration-session-active.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;GAWG;AACH,wBAAsB,wBAAwB,CAC5C,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,OAAO,CAAC,CAOlB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { access } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
// Mirrored from `migration/restructure.ts`. Duplicated locally (as
|
|
4
|
+
// `migration-session-reconcile.ts` does) to keep the ai-service free of a
|
|
5
|
+
// dependency edge into the migration route module.
|
|
6
|
+
const SCRATCH_DIR_NAME = "scratch";
|
|
7
|
+
const MIGRATION_STATE_FILE = "migration-state.json";
|
|
8
|
+
/**
|
|
9
|
+
* Positive migration-session gate for auto-dispatch. Returns true only while a
|
|
10
|
+
* migration session is genuinely in flight on disk — the dev server writes
|
|
11
|
+
* `scratch/migration-state.json` when a migration starts and removes it on
|
|
12
|
+
* every terminal path (completion removes the scratch dir; abort removes the
|
|
13
|
+
* file). A never-migrated or cleanly-completed app therefore has no state file,
|
|
14
|
+
* so a stale `checklist.json` alone can never arm auto-dispatch during normal
|
|
15
|
+
* app usage. On fresh post-flip pods the file is restored by
|
|
16
|
+
* `rehydrateMigrationScratchOnBoot`, which only downloads scratch when the
|
|
17
|
+
* server session phase is active — so presence here is a proxy for a
|
|
18
|
+
* server-confirmed active session.
|
|
19
|
+
*/
|
|
20
|
+
export async function isMigrationSessionActive(appRootDirPath) {
|
|
21
|
+
try {
|
|
22
|
+
await access(join(appRootDirPath, SCRATCH_DIR_NAME, MIGRATION_STATE_FILE));
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=migration-session-active.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-session-active.js","sourceRoot":"","sources":["../../src/ai-service/migration-session-active.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,mEAAmE;AACnE,0EAA0E;AAC1E,mDAAmD;AACnD,MAAM,gBAAgB,GAAG,SAAS,CAAC;AACnC,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAEpD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,cAAsB;IAEtB,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,gBAAgB,EAAE,oBAAoB,CAAC,CAAC,CAAC;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AiGenerationStateSnapshot } from "@superblocksteam/library-shared/types";
|
|
2
|
+
import type { ClarkState } from "./state-machine/clark-fsm.js";
|
|
3
|
+
export type UiGenerationStateSnapshot = AiGenerationStateSnapshot;
|
|
4
|
+
export declare function resolveGenerationStateForUi(input: {
|
|
5
|
+
clarkState: ClarkState;
|
|
6
|
+
lastGenerationState?: UiGenerationStateSnapshot;
|
|
7
|
+
}): UiGenerationStateSnapshot | undefined;
|
|
8
|
+
//# sourceMappingURL=resolve-generation-state-for-ui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-generation-state-for-ui.d.ts","sourceRoot":"","sources":["../../src/ai-service/resolve-generation-state-for-ui.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AAEvF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D,MAAM,MAAM,yBAAyB,GAAG,yBAAyB,CAAC;AASlE,wBAAgB,2BAA2B,CAAC,KAAK,EAAE;IACjD,UAAU,EAAE,UAAU,CAAC;IACvB,mBAAmB,CAAC,EAAE,yBAAyB,CAAC;CACjD,GAAG,yBAAyB,GAAG,SAAS,CAmBxC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AiGenerationState } from "@superblocksteam/library-shared/types";
|
|
2
|
+
const TERMINAL_FSM = ["Idle", "AwaitingUser", "Dead"];
|
|
3
|
+
const ACTIVE_CACHE = [
|
|
4
|
+
AiGenerationState.GENERATING,
|
|
5
|
+
AiGenerationState.DEBUGGING,
|
|
6
|
+
AiGenerationState.SUMMARIZING,
|
|
7
|
+
];
|
|
8
|
+
export function resolveGenerationStateForUi(input) {
|
|
9
|
+
const { clarkState, lastGenerationState: cache } = input;
|
|
10
|
+
if (cache?.state === AiGenerationState.CANCELLED) {
|
|
11
|
+
return cache;
|
|
12
|
+
}
|
|
13
|
+
if (TERMINAL_FSM.includes(clarkState)) {
|
|
14
|
+
if (cache && ACTIVE_CACHE.includes(cache.state)) {
|
|
15
|
+
return { state: AiGenerationState.IDLE };
|
|
16
|
+
}
|
|
17
|
+
return cache;
|
|
18
|
+
}
|
|
19
|
+
// Non-terminal FSM: always mirror the cache. We deliberately do not infer
|
|
20
|
+
// GENERATING from an active FSM state alone — an active FSM with no active
|
|
21
|
+
// cache can be a stale transition window and would falsely block the UI
|
|
22
|
+
// backup migration RPC (which gates on isAiLoading).
|
|
23
|
+
return cache;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=resolve-generation-state-for-ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-generation-state-for-ui.js","sourceRoot":"","sources":["../../src/ai-service/resolve-generation-state-for-ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAO1E,MAAM,YAAY,GAAiB,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;AACpE,MAAM,YAAY,GAAwB;IACxC,iBAAiB,CAAC,UAAU;IAC5B,iBAAiB,CAAC,SAAS;IAC3B,iBAAiB,CAAC,WAAW;CAC9B,CAAC;AAEF,MAAM,UAAU,2BAA2B,CAAC,KAG3C;IACC,MAAM,EAAE,UAAU,EAAE,mBAAmB,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAEzD,IAAI,KAAK,EAAE,KAAK,KAAK,iBAAiB,CAAC,SAAS,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACtC,IAAI,KAAK,IAAI,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAChD,OAAO,EAAE,KAAK,EAAE,iBAAiB,CAAC,IAAI,EAAE,CAAC;QAC3C,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,0EAA0E;IAC1E,2EAA2E;IAC3E,wEAAwE;IACxE,qDAAqD;IACrD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const content = "---\nname: superblocks-migration\ndescription: |\n Convert legacy Superblocks 2.0 YAML APIs (\"block-chain\" format) to the new 3.0 sdk-api TypeScript format.\n Load when executing a v2\u2192v3 migration turn \u2014 the runtime prompt will tell you to.\nreadOnly: true\nmetadata:\n author: superblocks\n version: \"1.0\"\n---\n\n# v2 \u2192 v3 API Translation\n\nYou are converting **legacy Superblocks \"block-chain\" YAML APIs** into the **new code-mode `@superblocksteam/sdk-api` TypeScript format**. Each YAML file under `scratch/v2-backup/apis/<ApiName>/api.yaml` must be emitted as a single TypeScript file at `server/apis/<ApiName>/api.ts` that compiles, typechecks, and preserves behavior exactly.\n\n## Meta-rule: ZERO judgment calls\n\nIf any situation below is not resolved deterministically by this document, **STOP** for that API. Do **not** pick a default. Do **not** guess a factory, a shape, or an import. Skip it, continue with other APIs, and mark the checklist item as `failed` via `build_manageChecklist` with a short `failureReason` describing the exact ambiguity (failing rule, block name if any, what would be needed to proceed). This rule overrides everything else.\n\nCorollary: do not add `// TODO` comments that silently ship. Unresolved items live only as `failed` checklist entries.\n\nCorollary for `migration_page_route_verification_*`: see the _Page route verification_ section below \u2014 screenshot timeout/error \u2192 `failed`, never `completed`, never \"verified via router/source inspection.\" The full rule (including the hard-rule restatements) lives there to avoid drift.\n\n## Inputs and outputs\n\n- **Source tree:** `scratch/v2-backup/apis/<ApiName>/api.yaml`. Discover the actual set by listing the directory \u2014 do not hardcode a count or list.\n- **Target tree:** `server/apis/<ApiName>/api.ts`. Do not create scaffolding trees that do not already exist (see \"Registry registration\" below).\n- **Checklist:** the migration checklist has already been seeded with one item per API (id `api_<ApiName>`, origin `2.0-upgrade`, status `pending`, `clearOnFinalize: false`). Legacy in-flight runs may still have `origin: \"seed_api\"` for these API items. Pull the live set by calling `build_manageChecklist` with `action: \"get\"` and filtering to `status: \"pending\"` plus API-migration origins (`origin: \"2.0-upgrade\"` or legacy `origin: \"seed_api\"`) \u2014 that is your authoritative API list and count for this turn.\n\n## Required reading (read these BEFORE writing any output)\n\nAuthoritative. If a rule here conflicts with your priors, these win.\n\n1. `node_modules/@superblocksteam/sdk-api/README.md` \u2014 whole thing (api() contract, execution model, `ctx.*`, exports, error classes, performance best practices, `useApi` frontend hook, integration method table).\n2. `node_modules/@superblocksteam/sdk-api/src/index.ts` (the **barrel**) \u2014 the authoritative list of exported factory names. Integration factory names are whatever this file exports, not whatever the directory name is. Never invent or case-fold a factory name without confirming it here.\n3. The README for **every integration** referenced by the YAMLs you convert:\n - `node_modules/@superblocksteam/sdk-api/src/integrations/<kind>/README.md`\n - If a vendor-specific factory exists for the target service (e.g., a dedicated one for a given LLM provider), prefer it over a generic HTTP one.\n4. `skills/system/superblocks-migration/references/yaml-block-mapping.md` \u2014 full YAML \u2192 TS mapping for each legacy block type.\n\nThere is **no `javascript` integration** in sdk-api \u2014 inline JS/TS lives directly inside `run(ctx, input)`. Any block whose YAML key is `javascript:` becomes plain TypeScript in `run()`. The same applies to **`python:` blocks**: there is no `python` integration in sdk-api, so port the body to inline TypeScript inside `run(ctx, input)` (see \"Substituting unsupported integrations\" below and the Python section in `yaml-block-mapping.md`).\n\n## Substituting unsupported integrations\n\nThe pre-migration UI warns the user when an app references integrations whose v2 plugin is not present in sdk-api. The migration is **not** aborted on those APIs \u2014 they are still in your `seed_api` checklist and you are expected to make a best-effort port rather than immediately marking them `failed`.\n\nSubstitution rules (apply in order; first match wins):\n\n1. **`python:` step \u2192 inline TypeScript.** Re-write the Python body as equivalent TypeScript inside `run(ctx, input)`, exactly the way `javascript:` blocks are inlined. Translate Python idioms to JS/TS (e.g. `requests.get(...)` \u2192 `fetch(...)`, list comprehensions \u2192 `array.map`/`filter`, `len(x)` \u2192 `x.length`, dict access \u2192 object property access, `os.environ[...]` \u2192 `process.env[...]`, raise/except \u2192 `throw`/`try\u2026catch`). If the Python relied on a third-party PyPI package with no obvious JS equivalent, mark that one API `failed` with a `failureReason` naming the package \u2014 do not ship a guess.\n2. **HTTP-shaped vendor plugin \u2192 REST.** If an unsupported integration was effectively making REST calls (e.g. a thin wrapper around an HTTP API) and you can read the request shape from the YAML, port it to the `restApi` factory from sdk-api (or the dedicated vendor factory if one exists in the barrel \u2014 check `node_modules/@superblocksteam/sdk-api/src/index.ts`).\n3. **Otherwise, mark `failed`.** Per the meta-rule, do not invent a factory or fabricate behavior. Use `build_manageChecklist` with `status: \"failed\"` and a concrete `failureReason` (e.g. `\"unsupported integration <pluginId> with no JS-equivalent path\"`).\n\nDo **not** silently skip a step or replace it with a `// TODO` \u2014 every API still needs a deterministic outcome (`completed` or `failed`) on the checklist.\n\n## Preflight gate (MUST pass before any file edits)\n\nComplete this orientation sequence before writing or modifying any API file:\n\n0. **Install recommended user dependencies (before API work).** The platform restructure already computed exactly which v2 user-added packages the migrated client/server code imports, and persisted them at `scratch/migration-state.json` \u2192 `recommendedUserDeps` (each entry has `name`, `version`, and `dev`). Your job is to install that list \u2014 not to recompute it.\n - Mark `migration_dependency_verification` as `in_progress` via `build_manageChecklist`.\n - Read `scratch/migration-state.json` and extract `recommendedUserDeps`.\n - If `recommendedUserDeps` is missing or empty, mark `migration_dependency_verification` as `completed` and continue to step 1.\n - Otherwise, call `build_installPackages` **once** with every entry from `recommendedUserDeps` (passing `name`, `version`, and `dev` through unchanged). Do **not** skip because `node_modules` exists on disk; the platform never wrote these packages into `package.json`.\n - **Failure semantics (covers every non-success outcome \u2014 no judgment calls):**\n - On full success \u2192 mark `migration_dependency_verification` as `completed`.\n - On **any** failure \u2014 full, partial (some packages installed, others did not), structured registry error (`not_in_registry`, `registry_auth_failed`, `registry_unreachable`), or unstructured error \u2014 mark `migration_dependency_verification` as `failed` with a `failureReason` that lists the affected package names and the tool's verbatim error code or message. Treat partial success the same as full failure for checklist purposes; do not split into multiple checklist items. Then continue to step 1 so API translation can still proceed. The user/operator will repair the registry/packages and re-trigger the migration turn.\n - If `scratch/migration-state.json` also contains `recommendedUserDepsPinnedToLatest` (a string array of package names), include those names in the `failureReason` of `migration_dependency_verification` even on full success \u2014 phrased as \"pinned to latest, may need user confirmation: <names>\" \u2014 so the user can downgrade them before runtime if the latest major is incompatible. Use status `completed` in this case (the install succeeded), but the surfaced reason gives the user a checkpoint to act on.\n - Do **not** scan imports yourself, edit `package.json`, or add packages outside `recommendedUserDeps`. If you believe a package is missing from the list, that is a platform bug: mark `migration_dependency_verification` as `failed` with `failureReason: \"platform bug: <pkg> imported by <file> but absent from recommendedUserDeps\"` and continue with API work using the packages that did install. (`build_manageChecklist` has no `note` action \u2014 `failed` with a structured `failureReason` is the only way to record this.)\n1. Call `build_manageChecklist` with `action: \"get\"` and filter to `status: \"pending\"` and API-migration origins (`origin: \"2.0-upgrade\"` or legacy `origin: \"seed_api\"`) \u2014 this is your authoritative API list and count for this turn.\n2. Read `node_modules/@superblocksteam/sdk-api/src/index.ts` and treat it as the **only** source of truth for sdk-api export/factory names.\n3. Read `node_modules/@superblocksteam/sdk-api/README.md`.\n4. For each API, read only the integration README(s) needed for that API right before migrating it (just-in-time). Do **not** preload every integration README for the entire app.\n\nHard constraints:\n\n- Do **not** rely on prior conversation memory, \"knowledge\" summaries, or inferred export names.\n- Do **not** start editing API files until preflight steps 0\u20133 are complete.\n- If a required file cannot be read, mark that API's checklist item `failed` with a concrete `failureReason` that names the missing path.\n\n## File layout & exports\n\n- One API per file, default export: `export default api({ ... });`.\n- Use ESM-style relative `.js` specifiers in imports.\n- File path: `server/apis/<ApiName>/api.ts` where `<ApiName>` is the YAML `metadata.name` (for example, `GetFloors` \u2192 `server/apis/GetFloors/api.ts`).\n- The `api({ name })` string and the registry key must both equal the YAML `metadata.name` verbatim \u2014 frontends call `useApi(\"<metadata.name>\")`.\n\n### Registry registration (conditional)\n\n- If `server/apis/index.ts` exists in the target tree: add an import + entry for each new module. Do not reorder existing entries.\n- If it does **not** exist: do **not** create it, do not create scaffolding. Mark the checklist item `failed` with a `failureReason` noting the missing registry.\n\n## Critical rules\n\n1. **Integration IDs are opaque per-YAML.** Extract each distinct `step.integration` UUID to a named `const` at the top of the file. Never carry UUIDs across files.\n2. **SQL: parameterize always.** Zero `${\u2026}` interpolations may remain inside any SQL string. Dynamic lists use `= ANY($N::<type>[])` \u2014 never string-building `IN (\u2026)`.\n3. **`query` vs `execute`.** Rows returned \u2192 `query` with Zod schema. Nothing actionable \u2192 `execute`.\n4. **Output shape preservation.** Mirror the legacy API's externally-visible response exactly \u2014 shape, nullability, cardinality. Do not wrap in envelopes.\n5. **Default is sequential.** `TYPE_FOREACH` \u2192 `for ... of` with sequential `await`. `Promise.all` only when YAML explicitly used a `parallel:` block.\n6. **Determinism, no slop.** No retries, no caching, no extra logging beyond a single `ctx.log.info(\"<ApiName> start\", {...})` at the top of `run`. No narrative code comments.\n7. **Never invent client methods.** If the integration README only documents `apiRequest`, use `apiRequest`.\n\n## Security / user identity\n\n- `authorization.type: AUTHORIZATION_TYPE_APP_USERS` is enforced by the server; rely on `ctx.user` in TS.\n- If the YAML accepts `userId` / `email` / etc. as API input, remove that input and read from `ctx.user` instead.\n\n## Observability\n\n- One `ctx.log.info(\"<ApiName> start\", { <safe-ids> })` at the top of `run` is allowed. Never log secrets, tokens, or PII.\n\n## Verification before you hand off\n\nRuntime verification (required):\n\n1. `build_debug` passing is required but not sufficient. Do not treat compile/typecheck success as proof that runtime behavior is correct.\n2. Use risk-based runtime checks: run `testApi` for APIs with integrations (REST/vendor/SQL), multi-step control flow, transformed outputs, or any uncertainty. For obviously simple APIs, you may skip `testApi`.\n3. If `testApi` output appears stale or mismatched, run `build_reloadFile` once and re-test. If runtime still fails after documented-method verification + one reload/retest cycle, record a concrete `failureReason` and continue.\n\nPage route verification (required once per migration run):\n\n**Hard rule:** A route is verified only with **runtime visual evidence on that exact path**. Reading `client/router.tsx`, page source, or backup artifacts is orientation only \u2014 it **never** satisfies verification.\n\n**Hard rule:** `build_debug` passing and `get_runtime_errors` returning `count: 0` are **not sufficient** for route verification. Do not mark routes `completed` because \"only APIs changed\" or \"the frontend files are unchanged.\"\n\n**Hard rule:** If `build_captureScreenshot` errors or times out for a route, mark that `migration_page_route_verification_*` item `failed` with `failureReason` naming the path and outcome (prefix `page_route_screenshot_timeout:` or `page_route_screenshot_error:`). Do **not** mark `completed`. Do **not** substitute router/source inspection.\n\n### Evidence required per route\n\nMark `completed` only when **all** are true:\n\n1. The app preview is on **that route's path** (not merely the default route).\n2. `build_captureScreenshot` **succeeds** and returns an image you inspect.\n3. You **describe** what you see and confirm it is not a loading-only view (follow the screenshot tool's skeleton/spinner retry procedure first).\n4. Any route-specific runtime errors are resolved (re-check after fixes).\n\n### Procedure (one route at a time)\n\n1. Enumerate checklist items whose IDs start with `migration_page_route_verification_`.\n2. Enumerate paths from `scratch/v2-backup/router.tsx` (fallback: `scratch/v2-backup/pages/**/index.tsx` confirmed against `client/router.tsx`).\n3. For each route: set the matching item `in_progress` \u2192 `build_navigatePreview` with that path \u2192 `build_captureScreenshot` \u2192 on success, `completed`.\n4. If the preview looks stale, `build_reloadFile` **once**, then retry screenshot. If capture still fails, `failed` with `failureReason` as above.\n5. Fix import/lazy-load/runtime failures, then repeat from step 3 for that route.\n\n### Forbidden shortcuts\n\n- Marking `completed` because `client/router.tsx` lists the path\n- Marking `completed` because the page module exists under `client/pages/`\n- Marking `completed` after screenshot timeout/error\n- Batch-marking all route items without per-route screenshot evidence\n\nFor each converted API, self-check:\n\n1. File default-exports exactly one `api({...})`; `name` matches `metadata.name`.\n2. Zero `${\u2026}` interpolations remain in any SQL string.\n3. No SQL `IN (\u2026)` built by concatenation; dynamic lists use `= ANY($N::<type>[])`.\n4. Every prior block's `.output` read is replaced by an actual result `const`.\n5. Input is the minimal union of identifiers the YAML references that are not produced by earlier blocks or `Variables`.\n6. Output shape exactly mirrors the legacy API's external response.\n7. If `server/apis/index.ts` exists, it registers the new module under `metadata.name`.\n8. **sdk-api integration wiring:** declare each integration in an `integrations: { \u2026 }` block and call it via `ctx.integrations.<key>` \u2014 never call `postgres(ID)` / `github(ID)` / etc. inside `run()` as if they were clients.\n9. **`input` / `output` schemas:** both are Zod schemas (`input: z.object({\u2026})`, `output: z.\u2026`). Do not use plain `{ field: { type: \"string\" } }` objects.\n10. **`run` signature:** `async run(ctx, input)` (or destructured input fields as the second argument). Never import `ctx` from the module scope.\n\n## Parallelization policy\n\nCount pending APIs from the checklist (`build_manageChecklist` `action: \"get\"`, filter `status: \"pending\"` and API-migration origins: `origin: \"2.0-upgrade\"` or legacy `origin: \"seed_api\"`).\n\n- **If the pending count is `< 8`:** migrate the APIs yourself, sequentially. Do NOT call `spawnCodingSubagents`. Work through each API using the per-API procedure below.\n- **If the pending count is `>= 8`:** you **MUST spawn sub-agents** to migrate these APIs in parallel. There are too many APIs to migrate sequentially yourself. Do NOT attempt to migrate APIs yourself in this run \u2014 use `spawnCodingSubagents`.\n - Split the APIs into batches of ~5 (aim for 4\u20136 per batch), with a hard cap of **5 sub-agents total**. If more than 25 APIs remain, give later batches larger shares rather than spawning more than 5 workers.\n - For each batch, craft an `instructions` string that:\n - Names the exact `<ApiName>` values that sub-agent owns, verbatim, as a bulleted list.\n - **Directs the sub-agent to `build_readFile` `skills/system/superblocks-migration/SKILL.md` (and the integration README(s) for the APIs it owns) before writing any files.** Do not inline a shortened sdk-api contract \u2014 keep a single source of truth.\n - Restates the per-API procedure below so the sub-agent is self-contained.\n - Reminds the sub-agent to update the shared checklist (id `api_<ApiName>`) for every item it owns.\n - **Also pass `apiNames: [\"<ApiName1>\", \"<ApiName2>\", \u2026]` for every sub-agent**, listing the same names that appear in its `instructions`. The spawn tool stamps each `api_<ApiName>` checklist item with that sub-agent's `id` as `workerId` BEFORE fan-out, which lets the migration UI render one batch row per sub-agent in the chat sidebar. Forgetting `apiNames` is non-fatal (the sub-agents still run) but the sidebar checklist will fall back to one row per API instead of one per batch.\n - **Call `spawnCodingSubagents` as the ONLY tool call in that turn.** Do not emit any other tool calls alongside it \u2014 no reads, no writes, no checklist updates. The tool blocks until every sub-agent finishes; you cannot do migration work \"while waiting\" because there is no waiting from your perspective \u2014 your next turn only begins after the tool returns. If you emit other tool calls in the same turn, you and the sub-agents will race on the shared checklist and corrupt state.\n - **After `spawnCodingSubagents` returns** \u2014 only in a subsequent turn \u2014 read the checklist via `build_manageChecklist` with `action: \"get\"`. For any `failed` items, review the `failureReason`. Retry small numbers of recoverable failures yourself (sequentially, using the per-API procedure below). Leave deterministic failures as `failed`.\n\n## Per-API procedure\n\nFor APIs you migrate yourself, or that you embed in a sub-agent's `instructions`:\n\n1. Call `build_manageChecklist` with `action: \"update\"`, `itemId: \"api_<ApiName>\"`, `status: \"in_progress\"`.\n2. Read `scratch/v2-backup/apis/<ApiName>/api.yaml` and any sibling files the blocks reference.\n3. Produce the TypeScript module at `server/apis/<ApiName>/api.ts`, overwriting the stub. Use the YAML block \u2192 TS mapping in `skills/system/superblocks-migration/references/yaml-block-mapping.md`.\n4. If `server/apis/index.ts` exists, update it to register the new module.\n5. Call `build_debug`. If it fails, fix and repeat until it passes. Do not proceed to step 6 until `build_debug` succeeds.\n6. **Call `runMigrationVerification({ apiName: \"<ApiName>\", inputs: <inputs> })` and resolve every divergence in this same chat.** The tool's response includes `attempt` and `maxAttempts` so you don't need to track an attempt counter yourself \u2014 the server reads it from on-disk history per API.\n\n Your job is to make v3 produce the same response as v2 \u2014 not to \"try a few times and punt to the user\". The user already lived with this API working on v2 with their real data; if v3 doesn't match, that's a regression you introduced, and you fix it here. NEVER leave a `diverged` API for the user to \"Accept divergence\" or \"Try one more attempt\" via the API calls panel \u2014 those buttons exist as escape hatches for situations the policy gate requires (mutations, denied integrations), not as a way for you to skip work.\n\n Synthesize `inputs` the same way you would for `testApi`. Inspect the v2 YAML from step 2 (`apiInputs` / externally-declared parameters) and the v3 TS from step 3 (`input` schema on `run(ctx, input)`). Every name the caller must supply must appear as a top-level key in `inputs` with a realistic mock value matching its expected type. This includes two categories \u2014 do not conflate them:\n - **API parameters** \u2014 names declared in `apiInputs` (v2) or the v3 `input` shape (e.g. `sourceContext`, `currentDocument`, `messages`). Pass each parameter name directly as a key in `inputs`. These are what the frontend passes when it invokes the API; they are not unavailable \"runtime bindings.\"\n - **UI bindings and caller context** \u2014 values the API reads from the app that are not API parameters (component values like `Input1.value`/`Select1.selectedItem.id`, table selections like `Table1.selectedRow`, state variables, workflow `body`/`params` not declared as `apiInputs`). Mock each binding the API references that isn't produced by an earlier block.\n\n Both v2 and v3 receive the same `inputs`, so this is what makes the diff meaningful \u2014 `{}` for an API that expects parameters or bindings produces a vacuous `both_failed` that tells you nothing. Errors like `'sourceContext' is not defined` (v2) or v3 input-validation failures for missing required fields mean you omitted keys from `inputs`; synthesize mocks and retry. That is not an environmental failure.\n\n Outcomes and how to resolve them:\n - **`passed`**: call `build_manageChecklist` with `status: \"completed\"`. Done.\n\n **Platform gate:** the checklist store rejects `status: \"completed\"` on `api_<ApiName>` items until verification has run at least once (`lastVerificationAt` is set \u2014 normally via this tool). You cannot bulk-mark APIs complete without calling `runMigrationVerification` per API.\n - **`skipped_mutation`**: this is a policy gate, not a deterministic pass. Do **NOT** mark the checklist item `completed` yet. Leave it unresolved (keep `in_progress`), continue processing other APIs, and resolve all skipped items in one grouped decision at the end of the run (see \"Mutation policy follow-up\" below).\n\n - **`v2_unrunnable`**: the v2 backup itself couldn't execute, so there is no baseline to match. Call `build_manageChecklist` with `status: \"completed\"` and continue.\n\n - **`both_failed`**:\n - If you passed `inputs: {}` or omitted declared API parameters / bindings: synthesize real `inputs` (per the bullet above) and retry. Do NOT mark completed here \u2014 missing inputs caused this, not a real failure.\n - If the error names a symbol that appears in `apiInputs` or the v3 `input` schema: add that key to `inputs` with a realistic mock and retry. Do NOT classify this as environmental \u2014 the parameter is available; you did not supply it.\n - If you passed real inputs and v2 still failed: read v2's error. If it is environmental (auth/credentials/integration-unavailable: \"no integration configured\", \"401\", \"ECONNREFUSED\", \"missing API key\"), v2 cannot run in this verification context regardless of what you do \u2014 call `build_manageChecklist` with `status: \"completed\"` and continue; the user will verify manually. If it's a v2 runtime error that v3 also reproduces, treat as `diverged` (your inputs are wrong, or the API expects state that isn't reproducible here \u2014 revise inputs and retry).\n\n - **`error`**: a system error in the verification flow itself (cannot read v3 source, etc.). Fix what you can; if it persists across one retry, mark the item `failed` with `failureReason: \"<error detail>\"` and continue.\n\n- **`diverged`**: the API ran on both sides and the outputs differ. **Iterate until v3 matches v2 byte-for-byte (modulo the normalizations api-comparator already applies: identical ISO timestamps, near-now ISO timestamps within \u00B160s of each other and \u00B15min of \"now\", UUIDs, monotonic integer IDs differing by \u22641 on fields whose leaf ends with \"id\", floats within 1e-9 relative tolerance, and per-request opaque identifiers at leaves named `requestId`/`traceId`/`spanId`/`correlationId`/`sessionId`/`nonce`/`csrfToken`/`_id` \u2014 note: a bare leaf named `token` is intentionally NOT normalized, since auth/access-token divergence is a security-relevant signal we want to surface).**\n\n There is one bounded judgment exception: if both v2 and v3 executions succeeded, the output shape/types are equivalent, and the remaining diffs are value-level fields you reasonably infer are inherently non-deterministic outputs for this API, treat the migration as semantically complete for this run. In that case, mark the checklist item `completed` and continue.\n\n Use this exception only when all of the following are true:\n - The divergence is not structural (no missing/extra fields, no type mismatch, no changed nesting/cardinality, no changed error/status behavior).\n - The differing fields are expected to vary per invocation and do not change control flow decisions.\n - The API's functional contract remains intact for downstream consumers.\n\n If any of those conditions are not met, the divergence is semantic and must be fixed \u2014 do NOT add code purely to mask values the comparator already tolerates.\n\n For each `summaryForAgent` entry \u2014 every entry names the JSON path that diverged and the v2/v3 values \u2014 find the block in `server/apis/<ApiName>/api.ts` that produces that path and fix the discrepancy. Common causes, in rough order of frequency:\n - wrong column projection or missing field in a SELECT\n - missing transform / output shape mismatch (array vs object wrapper, single vs list)\n - off-by-one or wrong placeholder in a SQL parameter\n - mistyped binding key (case, plural, dotted path)\n - type coercion (string vs number, null vs undefined, boolean vs \"true\")\n - missing default value when the binding is undefined\n - wrong join order or implicit ordering of rows\n - filter/where condition different from v2\n - missing `LIMIT`, `OFFSET`, or pagination handling\n\n If a divergence stems from the `inputs` you passed (e.g. v2 echoes the input one way and v3 a different way because they normalize it differently), revise the inputs alongside the source.\n\n Then call `build_debug` (fix any failures), then `runMigrationVerification` again with the revised source/inputs.\n\n **There is no fixed retry budget \u2014 iterate until `passed` or until you have firm structural evidence that no v3 source change can reconcile v2 and v3.** Acceptable evidence for stopping: v2 references a YAML construct with no v3 SDK equivalent and the divergence is in that construct; v2 derives a value from runtime state v3 cannot observe (e.g. an env var that differs by environment). When you stop on structural grounds, mark the item `failed` with `failureReason: \"verification_diverged_irreconcilable: <one-paragraph reason naming the specific summaryForAgent entry and the structural reason> | summary: <JSON.stringify(summaryForAgent)>\"`.\n\n Guardrail against infinite loops (NOT a retry budget): if you have iterated 8 times on the same API and the set of divergences has not materially changed across the last 3 attempts (i.e. you are flailing, not converging), stop and mark `failed` with the same `failureReason` shape. If you ARE converging \u2014 fewer divergences each attempt, or the remaining ones look smaller \u2014 keep going past 8.\n\n## Run-level rules\n\n- Do NOT emit a free-text UNRESOLVED report \u2014 every unresolved item must be a `failed` checklist entry with a `failureReason`.\n- Do NOT stop the run because one API failed. Only stop once every API is either `completed` or `failed`.\n\n## Mutation policy follow-up (required once per run if any API returned `skipped_mutation`)\n\nAfter you've done everything deterministic (all non-skipped APIs settled), if one or more APIs ended with `skipped_mutation`, call **one** grouped `askMultiChoice` with exactly these options:\n\n- `Mark all untested APIs as complete`\n- `Test them, and you'll be prompted for permission`\n\nThen:\n\n1. If user picks **`Mark all untested APIs as complete`**:\n - For each skipped API checklist item, call `build_manageChecklist` update \u2192 `status: \"completed\"`.\n2. If user picks **`Test them, and you'll be prompted for permission`**:\n - Clear persisted write-policy first so `deny`/`ask` modal state does not keep forcing `skipped_mutation`:\n - read `scratch/migration-state.json`\n - remove the `integrationWritePolicy` field\n - write the file back\n - Then run `testApi` for each skipped API so the runtime can prompt the user for write approval in-context.\n - After user approvals and tests settle, update checklist status accordingly (`completed` on success, `failed` with concrete `failureReason` on deterministic blockers).\n\n## Post-batch re-verification\n\nAfter `spawnCodingSubagents` returns (or after all sequential APIs are settled), before updating the checklist overall status:\n\n1. Call `build_manageChecklist` with `action: \"get\"` and read all items.\n2. For any item where `verificationOutcome === \"auto_passed\"` and `lastVerificationAt` is older than any sibling item's `updatedAt` minus 60 seconds: this item may have drifted due to registry edits made by later sub-agents. Re-run `runMigrationVerification({ apiName, inputs: <inputs> })` for each such item \u2014 synthesize `inputs` the same way as in step 6 of the per-API procedure.\n3. If any re-verification produces `diverged`, apply the normal per-API diverge\u2192retry loop (no fixed retry budget; iterate until `passed` or firm structural-irreconcilability evidence, with the anti-flail guardrail at 8 iterations without convergence).\n4. Proceed to mark overall checklist completed/failed only after all re-verifications settle.\n";
|
|
1
|
+
export declare const content = "---\nname: superblocks-migration\ndescription: |\n Convert legacy Superblocks 2.0 YAML APIs (\"block-chain\" format) to the new 3.0 sdk-api TypeScript format.\n Load when executing a v2\u2192v3 migration turn \u2014 the runtime prompt will tell you to.\nreadOnly: true\nmetadata:\n author: superblocks\n version: \"1.0\"\n---\n\n# v2 \u2192 v3 API Translation\n\nYou are converting **legacy Superblocks \"block-chain\" YAML APIs** into the **new code-mode `@superblocksteam/sdk-api` TypeScript format**. Each YAML file under `scratch/v2-backup/apis/<ApiName>/api.yaml` must be emitted as a single TypeScript file at `server/apis/<ApiName>/api.ts` that compiles, typechecks, and preserves behavior exactly.\n\n## Meta-rule: ZERO judgment calls\n\nIf any situation below is not resolved deterministically by this document, **STOP** for that API. Do **not** pick a default. Do **not** guess a factory, a shape, or an import. Skip it, continue with other APIs, and mark the checklist item as `failed` via `build_manageChecklist` with a short `failureReason` describing the exact ambiguity (failing rule, block name if any, what would be needed to proceed). This rule overrides everything else.\n\nCorollary: do not add `// TODO` comments that silently ship. Unresolved items live only as `failed` checklist entries.\n\nCorollary for `migration_page_route_verification_*`: see the _Page route verification_ section below \u2014 screenshot timeout/error \u2192 `failed`, never `completed`, never \"verified via router/source inspection.\" The full rule (including the hard-rule restatements) lives there to avoid drift.\n\n## Inputs and outputs\n\n- **Source tree:** `scratch/v2-backup/apis/<ApiName>/api.yaml`. Discover the actual set by listing the directory \u2014 do not hardcode a count or list.\n- **Target tree:** `server/apis/<ApiName>/api.ts`. Do not create scaffolding trees that do not already exist (see \"Registry registration\" below).\n- **Checklist:** the migration checklist has already been seeded with one item per API (id `api_<ApiName>`, origin `2.0-upgrade`, status `pending`, `clearOnFinalize: false`). Legacy in-flight runs may still have `origin: \"seed_api\"` for these API items. Pull the live set by calling `build_manageChecklist` with `action: \"get\"` and filtering to `status: \"pending\"` plus API-migration origins (`origin: \"2.0-upgrade\"` or legacy `origin: \"seed_api\"`) \u2014 that is your authoritative API list and count for this turn.\n\n## Required reading (read these BEFORE writing any output)\n\nAuthoritative. If a rule here conflicts with your priors, these win.\n\n1. `node_modules/@superblocksteam/sdk-api/README.md` \u2014 whole thing (api() contract, execution model, `ctx.*`, exports, error classes, performance best practices, `useApi` frontend hook, integration method table).\n2. `node_modules/@superblocksteam/sdk-api/src/index.ts` (the **barrel**) \u2014 the authoritative list of exported factory names. Integration factory names are whatever this file exports, not whatever the directory name is. Never invent or case-fold a factory name without confirming it here.\n3. The README for **every integration** referenced by the YAMLs you convert:\n - `node_modules/@superblocksteam/sdk-api/src/integrations/<kind>/README.md`\n - If a vendor-specific factory exists for the target service (e.g., a dedicated one for a given LLM provider), prefer it over a generic HTTP one.\n4. `skills/system/superblocks-migration/references/yaml-block-mapping.md` \u2014 full YAML \u2192 TS mapping for each legacy block type.\n\nThere is **no `javascript` integration** in sdk-api \u2014 inline JS/TS lives directly inside `run(ctx, input)`. Any block whose YAML key is `javascript:` becomes plain TypeScript in `run()`. The same applies to **`python:` blocks**: there is no `python` integration in sdk-api, so port the body to inline TypeScript inside `run(ctx, input)` (see \"Substituting unsupported integrations\" below and the Python section in `yaml-block-mapping.md`).\n\n## Substituting unsupported integrations\n\nThe pre-migration UI warns the user when an app references integrations whose v2 plugin is not present in sdk-api. The migration is **not** aborted on those APIs \u2014 they are still in your `seed_api` checklist and you are expected to make a best-effort port rather than immediately marking them `failed`.\n\nSubstitution rules (apply in order; first match wins):\n\n1. **`python:` step \u2192 inline TypeScript.** Re-write the Python body as equivalent TypeScript inside `run(ctx, input)`, exactly the way `javascript:` blocks are inlined. Translate Python idioms to JS/TS (e.g. `requests.get(...)` \u2192 `fetch(...)`, list comprehensions \u2192 `array.map`/`filter`, `len(x)` \u2192 `x.length`, dict access \u2192 object property access, `os.environ[...]` \u2192 `process.env[...]`, raise/except \u2192 `throw`/`try\u2026catch`). If the Python relied on a third-party PyPI package with no obvious JS equivalent, mark that one API `failed` with a `failureReason` naming the package \u2014 do not ship a guess.\n2. **HTTP-shaped vendor plugin \u2192 REST.** If an unsupported integration was effectively making REST calls (e.g. a thin wrapper around an HTTP API) and you can read the request shape from the YAML, port it to the `restApi` factory from sdk-api (or the dedicated vendor factory if one exists in the barrel \u2014 check `node_modules/@superblocksteam/sdk-api/src/index.ts`).\n3. **Otherwise, mark `failed`.** Per the meta-rule, do not invent a factory or fabricate behavior. Use `build_manageChecklist` with `status: \"failed\"` and a concrete `failureReason` (e.g. `\"unsupported integration <pluginId> with no JS-equivalent path\"`).\n\nDo **not** silently skip a step or replace it with a `// TODO` \u2014 every API still needs a deterministic outcome (`completed` or `failed`) on the checklist.\n\n## Preflight gate (MUST pass before any file edits)\n\nComplete this orientation sequence before writing or modifying any API file:\n\n0. **Install recommended user dependencies (before API work).** The platform restructure already computed exactly which v2 user-added packages the migrated client/server code imports, and persisted them at `scratch/migration-state.json` \u2192 `recommendedUserDeps` (each entry has `name`, `version`, and `dev`). Your job is to install that list \u2014 not to recompute it.\n - Mark `migration_dependency_verification` as `in_progress` via `build_manageChecklist`.\n - Read `scratch/migration-state.json` and extract `recommendedUserDeps`.\n - If `recommendedUserDeps` is missing or empty, mark `migration_dependency_verification` as `completed` and continue to step 1.\n - Otherwise, call `build_installPackages` **once** with every entry from `recommendedUserDeps` (passing `name`, `version`, and `dev` through unchanged). Do **not** skip because `node_modules` exists on disk; the platform never wrote these packages into `package.json`.\n - **Failure semantics (covers every non-success outcome \u2014 no judgment calls):**\n - On full success \u2192 mark `migration_dependency_verification` as `completed`.\n - On **any** failure \u2014 full, partial (some packages installed, others did not), structured registry error (`not_in_registry`, `registry_auth_failed`, `registry_unreachable`), or unstructured error \u2014 mark `migration_dependency_verification` as `failed` with a `failureReason` that lists the affected package names and the tool's verbatim error code or message. Treat partial success the same as full failure for checklist purposes; do not split into multiple checklist items. Then continue to step 1 so API translation can still proceed. The user/operator will repair the registry/packages and re-trigger the migration turn.\n - If `scratch/migration-state.json` also contains `recommendedUserDepsPinnedToLatest` (a string array of package names), include those names in the `failureReason` of `migration_dependency_verification` even on full success \u2014 phrased as \"pinned to latest, may need user confirmation: <names>\" \u2014 so the user can downgrade them before runtime if the latest major is incompatible. Use status `completed` in this case (the install succeeded), but the surfaced reason gives the user a checkpoint to act on.\n - Do **not** scan imports yourself, edit `package.json`, or add packages outside `recommendedUserDeps`. If you believe a package is missing from the list, that is a platform bug: mark `migration_dependency_verification` as `failed` with `failureReason: \"platform bug: <pkg> imported by <file> but absent from recommendedUserDeps\"` and continue with API work using the packages that did install. (`build_manageChecklist` has no `note` action \u2014 `failed` with a structured `failureReason` is the only way to record this.)\n1. Call `build_manageChecklist` with `action: \"get\"` and filter to `status: \"pending\"` and API-migration origins (`origin: \"2.0-upgrade\"` or legacy `origin: \"seed_api\"`) \u2014 this is your authoritative API list and count for this turn.\n2. Read `node_modules/@superblocksteam/sdk-api/src/index.ts` and treat it as the **only** source of truth for sdk-api export/factory names.\n3. Read `node_modules/@superblocksteam/sdk-api/README.md`.\n4. For each API, read only the integration README(s) needed for that API right before migrating it (just-in-time). Do **not** preload every integration README for the entire app.\n\nHard constraints:\n\n- Do **not** rely on prior conversation memory, \"knowledge\" summaries, or inferred export names.\n- Do **not** start editing API files until preflight steps 0\u20133 are complete.\n- If a required file cannot be read, mark that API's checklist item `failed` with a concrete `failureReason` that names the missing path.\n\n## File layout & exports\n\n- One API per file, default export: `export default api({ ... });`.\n- Use ESM-style relative `.js` specifiers in imports.\n- File path: `server/apis/<ApiName>/api.ts` where `<ApiName>` is the YAML `metadata.name` (for example, `GetFloors` \u2192 `server/apis/GetFloors/api.ts`).\n- The `api({ name })` string and the registry key must both equal the YAML `metadata.name` verbatim \u2014 frontends call `useApi(\"<metadata.name>\")`.\n\n### Registry registration (conditional)\n\n- If `server/apis/index.ts` exists in the target tree: add an import + entry for each new module. Do not reorder existing entries.\n- If it does **not** exist: do **not** create it, do not create scaffolding. Mark the checklist item `failed` with a `failureReason` noting the missing registry.\n\n## Critical rules\n\n1. **Integration IDs are opaque per-YAML.** Extract each distinct `step.integration` UUID to a named `const` at the top of the file. Never carry UUIDs across files.\n2. **SQL: parameterize always.** Zero `${\u2026}` interpolations may remain inside any SQL string. Dynamic lists use `= ANY($N::<type>[])` \u2014 never string-building `IN (\u2026)`.\n3. **`query` vs `execute`.** Rows returned \u2192 `query` with Zod schema. Nothing actionable \u2192 `execute`.\n4. **Output shape preservation.** Mirror the legacy API's externally-visible response exactly \u2014 shape, nullability, cardinality. Do not wrap in envelopes.\n5. **Default is sequential.** `TYPE_FOREACH` \u2192 `for ... of` with sequential `await`. `Promise.all` only when YAML explicitly used a `parallel:` block.\n6. **Determinism, no slop.** No retries, no caching, no extra logging beyond a single `ctx.log.info(\"<ApiName> start\", {...})` at the top of `run`. No narrative code comments.\n7. **Never invent client methods.** If the integration README only documents `apiRequest`, use `apiRequest`.\n\n## Security / user identity\n\n- `authorization.type: AUTHORIZATION_TYPE_APP_USERS` is enforced by the server; rely on `ctx.user` in TS.\n- If the YAML accepts `userId` / `email` / etc. as API input, remove that input and read from `ctx.user` instead.\n\n## Observability\n\n- One `ctx.log.info(\"<ApiName> start\", { <safe-ids> })` at the top of `run` is allowed. Never log secrets, tokens, or PII.\n\n## Verification before you hand off\n\nRuntime verification (required):\n\n1. `build_debug` passing is required but not sufficient. Do not treat compile/typecheck success as proof that runtime behavior is correct.\n2. Use risk-based runtime checks: run `testApi` for APIs with integrations (REST/vendor/SQL), multi-step control flow, transformed outputs, or any uncertainty. For obviously simple APIs, you may skip `testApi`.\n3. If `testApi` output appears stale or mismatched, run `build_reloadFile` once and re-test. If runtime still fails after documented-method verification + one reload/retest cycle, record a concrete `failureReason` and continue.\n\nPage route verification (required once per migration run):\n\n**Hard rule:** A route is verified only with **runtime visual evidence on that exact path**. Reading `client/router.tsx`, page source, or backup artifacts is orientation only \u2014 it **never** satisfies verification.\n\n**Hard rule:** `build_debug` passing and `get_runtime_errors` returning `count: 0` are **not sufficient** for route verification. Do not mark routes `completed` because \"only APIs changed\" or \"the frontend files are unchanged.\"\n\n**Hard rule:** If `build_captureScreenshot` errors or times out for a route, mark that `migration_page_route_verification_*` item `failed` with `failureReason` naming the path and outcome (prefix `page_route_screenshot_timeout:` or `page_route_screenshot_error:`). Do **not** mark `completed`. Do **not** substitute router/source inspection.\n\n### Evidence required per route\n\nMark `completed` only when **all** are true:\n\n1. The app preview is on **that route's path** (not merely the default route).\n2. `build_captureScreenshot` **succeeds** and returns an image you inspect.\n3. You **describe** what you see and confirm it is not a loading-only view (follow the screenshot tool's skeleton/spinner retry procedure first).\n4. Any route-specific runtime errors are resolved (re-check after fixes).\n\n### Procedure (one route at a time)\n\n1. Enumerate checklist items whose IDs start with `migration_page_route_verification_`.\n2. Enumerate paths from `scratch/v2-backup/router.tsx` (fallback: `scratch/v2-backup/pages/**/index.tsx` confirmed against `client/router.tsx`).\n3. For each route: set the matching item `in_progress` \u2192 `build_navigatePreview` with that path \u2192 `build_captureScreenshot` \u2192 on success, `completed`.\n4. If the preview looks stale, `build_reloadFile` **once**, then retry screenshot. If capture still fails, `failed` with `failureReason` as above.\n5. Fix import/lazy-load/runtime failures, then repeat from step 3 for that route.\n\n### Forbidden shortcuts\n\n- Marking `completed` because `client/router.tsx` lists the path\n- Marking `completed` because the page module exists under `client/pages/`\n- Marking `completed` after screenshot timeout/error\n- Batch-marking all route items without per-route screenshot evidence\n\nFor each converted API, self-check:\n\n1. File default-exports exactly one `api({...})`; `name` matches `metadata.name`.\n2. Zero `${\u2026}` interpolations remain in any SQL string.\n3. No SQL `IN (\u2026)` built by concatenation; dynamic lists use `= ANY($N::<type>[])`.\n4. Every prior block's `.output` read is replaced by an actual result `const`.\n5. Input is the minimal union of identifiers the YAML references that are not produced by earlier blocks or `Variables`.\n6. Output shape exactly mirrors the legacy API's external response.\n7. If `server/apis/index.ts` exists, it registers the new module under `metadata.name`.\n8. **sdk-api integration wiring:** declare each integration in an `integrations: { \u2026 }` block and call it via `ctx.integrations.<key>` \u2014 never call `postgres(ID)` / `github(ID)` / etc. inside `run()` as if they were clients.\n9. **`input` / `output` schemas:** both are Zod schemas (`input: z.object({\u2026})`, `output: z.\u2026`). Do not use plain `{ field: { type: \"string\" } }` objects.\n10. **`run` signature:** `async run(ctx, input)` (or destructured input fields as the second argument). Never import `ctx` from the module scope.\n\n## Parallelization policy\n\nCount pending APIs from the checklist (`build_manageChecklist` `action: \"get\"`, filter `status: \"pending\"` and API-migration origins: `origin: \"2.0-upgrade\"` or legacy `origin: \"seed_api\"`).\n\n- **If the pending count is `< 8`:** migrate the APIs yourself, sequentially. Do NOT call `spawnCodingSubagents`. Work through each API using the per-API procedure below.\n- **If the pending count is `>= 8`:** you **MUST spawn sub-agents** to migrate these APIs in parallel. There are too many APIs to migrate sequentially yourself. Do NOT attempt to migrate APIs yourself in this run \u2014 use `spawnCodingSubagents`.\n - Split the APIs into batches of ~5 (aim for 4\u20136 per batch), with a hard cap of **5 sub-agents total**. If more than 25 APIs remain, give later batches larger shares rather than spawning more than 5 workers.\n - For each batch, craft an `instructions` string that:\n - Names the exact `<ApiName>` values that sub-agent owns, verbatim, as a bulleted list.\n - **Directs the sub-agent to `build_readFile` `skills/system/superblocks-migration/SKILL.md` (and the integration README(s) for the APIs it owns) before writing any files.** Do not inline a shortened sdk-api contract \u2014 keep a single source of truth.\n - Restates the per-API procedure below so the sub-agent is self-contained.\n - Reminds the sub-agent to update the shared checklist (id `api_<ApiName>`) for every item it owns.\n - **Also pass `apiNames: [\"<ApiName1>\", \"<ApiName2>\", \u2026]` for every sub-agent**, listing the same names that appear in its `instructions`. The spawn tool stamps each `api_<ApiName>` checklist item with that sub-agent's `id` as `workerId` BEFORE fan-out, which lets the migration UI render one batch row per sub-agent in the chat sidebar. Forgetting `apiNames` is non-fatal (the sub-agents still run) but the sidebar checklist will fall back to one row per API instead of one per batch.\n - **Call `spawnCodingSubagents` as the ONLY tool call in that turn.** Do not emit any other tool calls alongside it \u2014 no reads, no writes, no checklist updates. The tool blocks until every sub-agent finishes; you cannot do migration work \"while waiting\" because there is no waiting from your perspective \u2014 your next turn only begins after the tool returns. If you emit other tool calls in the same turn, you and the sub-agents will race on the shared checklist and corrupt state.\n - **After `spawnCodingSubagents` returns** \u2014 only in a subsequent turn \u2014 read the checklist via `build_manageChecklist` with `action: \"get\"`. For any `failed` items, review the `failureReason`. Retry small numbers of recoverable failures yourself (sequentially, using the per-API procedure below). Leave deterministic failures as `failed`.\n\n## Per-API procedure\n\nFor APIs you migrate yourself, or that you embed in a sub-agent's `instructions`:\n\n1. Call `build_manageChecklist` with `action: \"update\"`, `itemId: \"api_<ApiName>\"`, `status: \"in_progress\"`.\n2. Read `scratch/v2-backup/apis/<ApiName>/api.yaml` and any sibling files the blocks reference.\n3. Produce the TypeScript module at `server/apis/<ApiName>/api.ts`, overwriting the stub. Use the YAML block \u2192 TS mapping in `skills/system/superblocks-migration/references/yaml-block-mapping.md`.\n4. If `server/apis/index.ts` exists, update it to register the new module.\n5. Call `build_debug`. If it fails, fix and repeat until it passes. Do not proceed to step 6 until `build_debug` succeeds.\n6. **Call `runMigrationVerification({ apiName: \"<ApiName>\", inputs: <inputs> })` and resolve every divergence in this same chat.** The tool's response includes `attempt` and `maxAttempts` so you don't need to track an attempt counter yourself \u2014 the server reads it from on-disk history per API.\n\n Your job is to make v3 produce the same response as v2 \u2014 not to \"try a few times and punt to the user\". The user already lived with this API working on v2 with their real data; if v3 doesn't match, that's a regression you introduced, and you fix it here. NEVER leave a `diverged` API for the user to \"Accept divergence\" or \"Try one more attempt\" via the API calls panel \u2014 those buttons exist as escape hatches for situations the policy gate requires (mutations, denied integrations), not as a way for you to skip work.\n\n Synthesize `inputs` the same way you would for `testApi`. Inspect the v2 YAML from step 2 (`apiInputs` / externally-declared parameters) and the v3 TS from step 3 (`input` schema on `run(ctx, input)`). Every name the caller must supply must appear as a top-level key in `inputs` with a realistic mock value matching its expected type. This includes two categories \u2014 do not conflate them:\n - **API parameters** \u2014 names declared in `apiInputs` (v2) or the v3 `input` shape (e.g. `sourceContext`, `currentDocument`, `messages`). Pass each parameter name directly as a key in `inputs`. These are what the frontend passes when it invokes the API; they are not unavailable \"runtime bindings.\"\n - **UI bindings and caller context** \u2014 values the API reads from the app that are not API parameters (component values like `Input1.value`/`Select1.selectedItem.id`, table selections like `Table1.selectedRow`, state variables, workflow `body`/`params` not declared as `apiInputs`). Mock each binding the API references that isn't produced by an earlier block.\n\n Both v2 and v3 receive the same `inputs`, so this is what makes the diff meaningful \u2014 `{}` for an API that expects parameters or bindings produces a vacuous `both_failed` that tells you nothing. Errors like `'sourceContext' is not defined` (v2) or v3 input-validation failures for missing required fields mean you omitted keys from `inputs`; synthesize mocks and retry. That is not an environmental failure.\n\n Outcomes and how to resolve them:\n - **`passed`**: call `build_manageChecklist` with `status: \"completed\"`. Done.\n\n **Platform gate:** the checklist store rejects `status: \"completed\"` on `api_<ApiName>` items until verification has run at least once (`lastVerificationAt` is set \u2014 normally via this tool). You cannot bulk-mark APIs complete without calling `runMigrationVerification` per API.\n - **`skipped_mutation`**: this is a policy gate, not a deterministic pass. Do **NOT** mark the checklist item `completed` yet. Leave it unresolved (keep `in_progress`), continue processing other APIs, and resolve all skipped items in one grouped decision at the end of the run (see \"Mutation policy follow-up\" below).\n\n - **`v2_unrunnable`**: the v2 backup itself couldn't execute, so there is no baseline to match. Call `build_manageChecklist` with `status: \"completed\"` and continue.\n\n - **`timeout`**: a pipeline stalled past the reporting timeout (`side` says which one). This is transient environment noise \u2014 a dropped editor connection or a backgrounded browser tab \u2014 NOT evidence about the API. Do **NOT** mark the item `completed`. Retry `runMigrationVerification` after finishing your current API. If it times out repeatedly, tell the user verification is stalling (likely tab backgrounded / connection dropped), ask them to keep the app tab focused, and retry \u2014 never convert repeated timeouts into `completed`.\n\n - **`disconnected`**: the editor connection was down when the pipeline tried to run (`side` says which one) \u2014 the app tab is closed, backgrounded, or reconnecting. Unlike `timeout` this diagnosis is certain, and it says nothing about the API. Do **NOT** mark the item `completed`. Tell the user the app tab must stay open and focused during verification, then retry `runMigrationVerification` \u2014 never convert `disconnected` into `completed`.\n\n - **`both_failed`**:\n - If you passed `inputs: {}` or omitted declared API parameters / bindings: synthesize real `inputs` (per the bullet above) and retry. Do NOT mark completed here \u2014 missing inputs caused this, not a real failure.\n - If the error names a symbol that appears in `apiInputs` or the v3 `input` schema: add that key to `inputs` with a realistic mock and retry. Do NOT classify this as environmental \u2014 the parameter is available; you did not supply it.\n - If you passed real inputs and v2 still failed: read v2's error. If it is environmental (auth/credentials/integration-unavailable: \"no integration configured\", \"401\", \"ECONNREFUSED\", \"missing API key\"), v2 cannot run in this verification context regardless of what you do \u2014 call `build_manageChecklist` with `status: \"completed\"` and continue; the user will verify manually. If it's a v2 runtime error that v3 also reproduces, treat as `diverged` (your inputs are wrong, or the API expects state that isn't reproducible here \u2014 revise inputs and retry).\n\n - **`error`**: a system error in the verification flow itself (cannot read v3 source, etc.). Fix what you can; if it persists across one retry, mark the item `failed` with `failureReason: \"<error detail>\"` and continue.\n\n- **`diverged`**: the API ran on both sides and the outputs differ. **Iterate until v3 matches v2 byte-for-byte (modulo the normalizations api-comparator already applies: identical ISO timestamps, near-now ISO timestamps within \u00B160s of each other and \u00B15min of \"now\", UUIDs, monotonic integer IDs differing by \u22641 on fields whose leaf ends with \"id\", floats within 1e-9 relative tolerance, and per-request opaque identifiers at leaves named `requestId`/`traceId`/`spanId`/`correlationId`/`sessionId`/`nonce`/`csrfToken`/`_id` \u2014 note: a bare leaf named `token` is intentionally NOT normalized, since auth/access-token divergence is a security-relevant signal we want to surface).**\n\n There is one bounded judgment exception: if both v2 and v3 executions succeeded, the output shape/types are equivalent, and the remaining diffs are value-level fields you reasonably infer are inherently non-deterministic outputs for this API, treat the migration as semantically complete for this run. In that case, mark the checklist item `completed` and continue.\n\n Use this exception only when all of the following are true:\n - The divergence is not structural (no missing/extra fields, no type mismatch, no changed nesting/cardinality, no changed error/status behavior).\n - The differing fields are expected to vary per invocation and do not change control flow decisions.\n - The API's functional contract remains intact for downstream consumers.\n\n If any of those conditions are not met, the divergence is semantic and must be fixed \u2014 do NOT add code purely to mask values the comparator already tolerates.\n\n For each `summaryForAgent` entry \u2014 every entry names the JSON path that diverged and the v2/v3 values \u2014 find the block in `server/apis/<ApiName>/api.ts` that produces that path and fix the discrepancy. Common causes, in rough order of frequency:\n - wrong column projection or missing field in a SELECT\n - missing transform / output shape mismatch (array vs object wrapper, single vs list)\n - off-by-one or wrong placeholder in a SQL parameter\n - mistyped binding key (case, plural, dotted path)\n - type coercion (string vs number, null vs undefined, boolean vs \"true\")\n - missing default value when the binding is undefined\n - wrong join order or implicit ordering of rows\n - filter/where condition different from v2\n - missing `LIMIT`, `OFFSET`, or pagination handling\n\n If a divergence stems from the `inputs` you passed (e.g. v2 echoes the input one way and v3 a different way because they normalize it differently), revise the inputs alongside the source.\n\n Then call `build_debug` (fix any failures), then `runMigrationVerification` again with the revised source/inputs.\n\n **There is no fixed retry budget \u2014 iterate until `passed` or until you have firm structural evidence that no v3 source change can reconcile v2 and v3.** Acceptable evidence for stopping: v2 references a YAML construct with no v3 SDK equivalent and the divergence is in that construct; v2 derives a value from runtime state v3 cannot observe (e.g. an env var that differs by environment). When you stop on structural grounds, mark the item `failed` with `failureReason: \"verification_diverged_irreconcilable: <one-paragraph reason naming the specific summaryForAgent entry and the structural reason> | summary: <JSON.stringify(summaryForAgent)>\"`.\n\n Guardrail against infinite loops (NOT a retry budget): if you have iterated 8 times on the same API and the set of divergences has not materially changed across the last 3 attempts (i.e. you are flailing, not converging), stop and mark `failed` with the same `failureReason` shape. If you ARE converging \u2014 fewer divergences each attempt, or the remaining ones look smaller \u2014 keep going past 8.\n\n## Run-level rules\n\n- Do NOT emit a free-text UNRESOLVED report \u2014 every unresolved item must be a `failed` checklist entry with a `failureReason`.\n- Do NOT stop the run because one API failed. Only stop once every API is either `completed` or `failed`.\n\n## Mutation policy follow-up (required once per run if any API returned `skipped_mutation`)\n\nAfter you've done everything deterministic (all non-skipped APIs settled), if one or more APIs ended with `skipped_mutation`, call **one** grouped `askMultiChoice` with exactly these options:\n\n- `Mark all untested APIs as complete`\n- `Test them, and you'll be prompted for permission`\n\nThen:\n\n1. If user picks **`Mark all untested APIs as complete`**:\n - For each skipped API checklist item, call `build_manageChecklist` update \u2192 `status: \"completed\"`.\n2. If user picks **`Test them, and you'll be prompted for permission`**:\n - Clear persisted write-policy first so a `deny` modal choice does not keep forcing `skipped_mutation`:\n - read `scratch/migration-state.json`\n - remove the `integrationWritePolicy` field\n - write the file back\n - Then run `testApi` for each skipped API so the runtime can prompt the user for write approval in-context.\n - After user approvals and tests settle, update checklist status accordingly (`completed` on success, `failed` with concrete `failureReason` on deterministic blockers).\n\n## Post-batch re-verification\n\nAfter `spawnCodingSubagents` returns (or after all sequential APIs are settled), before updating the checklist overall status:\n\n1. Call `build_manageChecklist` with `action: \"get\"` and read all items.\n2. For any item where `verificationOutcome === \"auto_passed\"` and `lastVerificationAt` is older than any sibling item's `updatedAt` minus 60 seconds: this item may have drifted due to registry edits made by later sub-agents. Re-run `runMigrationVerification({ apiName, inputs: <inputs> })` for each such item \u2014 synthesize `inputs` the same way as in step 6 of the per-API procedure.\n3. If any re-verification produces `diverged`, apply the normal per-API diverge\u2192retry loop (no fixed retry budget; iterate until `passed` or firm structural-irreconcilability evidence, with the anti-flail guardrail at 8 iterations without convergence).\n4. Proceed to mark overall checklist completed/failed only after all re-verifications settle.\n";
|
|
2
2
|
//# sourceMappingURL=skill.generated.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill.generated.d.ts","sourceRoot":"","sources":["../../../../../src/ai-service/skills/system/superblocks-migration/skill.generated.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"skill.generated.d.ts","sourceRoot":"","sources":["../../../../../src/ai-service/skills/system/superblocks-migration/skill.generated.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,g39BAuRnB,CAAC"}
|
|
@@ -206,6 +206,10 @@ For APIs you migrate yourself, or that you embed in a sub-agent's \`instructions
|
|
|
206
206
|
|
|
207
207
|
- **\`v2_unrunnable\`**: the v2 backup itself couldn't execute, so there is no baseline to match. Call \`build_manageChecklist\` with \`status: "completed"\` and continue.
|
|
208
208
|
|
|
209
|
+
- **\`timeout\`**: a pipeline stalled past the reporting timeout (\`side\` says which one). This is transient environment noise — a dropped editor connection or a backgrounded browser tab — NOT evidence about the API. Do **NOT** mark the item \`completed\`. Retry \`runMigrationVerification\` after finishing your current API. If it times out repeatedly, tell the user verification is stalling (likely tab backgrounded / connection dropped), ask them to keep the app tab focused, and retry — never convert repeated timeouts into \`completed\`.
|
|
210
|
+
|
|
211
|
+
- **\`disconnected\`**: the editor connection was down when the pipeline tried to run (\`side\` says which one) — the app tab is closed, backgrounded, or reconnecting. Unlike \`timeout\` this diagnosis is certain, and it says nothing about the API. Do **NOT** mark the item \`completed\`. Tell the user the app tab must stay open and focused during verification, then retry \`runMigrationVerification\` — never convert \`disconnected\` into \`completed\`.
|
|
212
|
+
|
|
209
213
|
- **\`both_failed\`**:
|
|
210
214
|
- If you passed \`inputs: {}\` or omitted declared API parameters / bindings: synthesize real \`inputs\` (per the bullet above) and retry. Do NOT mark completed here — missing inputs caused this, not a real failure.
|
|
211
215
|
- If the error names a symbol that appears in \`apiInputs\` or the v3 \`input\` schema: add that key to \`inputs\` with a realistic mock and retry. Do NOT classify this as environmental — the parameter is available; you did not supply it.
|
|
@@ -260,7 +264,7 @@ Then:
|
|
|
260
264
|
1. If user picks **\`Mark all untested APIs as complete\`**:
|
|
261
265
|
- For each skipped API checklist item, call \`build_manageChecklist\` update → \`status: "completed"\`.
|
|
262
266
|
2. If user picks **\`Test them, and you'll be prompted for permission\`**:
|
|
263
|
-
- Clear persisted write-policy first so \`deny
|
|
267
|
+
- Clear persisted write-policy first so a \`deny\` modal choice does not keep forcing \`skipped_mutation\`:
|
|
264
268
|
- read \`scratch/migration-state.json\`
|
|
265
269
|
- remove the \`integrationWritePolicy\` field
|
|
266
270
|
- write the file back
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill.generated.js","sourceRoot":"","sources":["../../../../../src/ai-service/skills/system/superblocks-migration/skill.generated.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,mDAAmD;AAEnD,MAAM,CAAC,MAAM,OAAO,GAAG
|
|
1
|
+
{"version":3,"file":"skill.generated.js","sourceRoot":"","sources":["../../../../../src/ai-service/skills/system/superblocks-migration/skill.generated.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,mDAAmD;AAEnD,MAAM,CAAC,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuRtB,CAAC"}
|
|
@@ -55,7 +55,25 @@ export declare const flushDeferredInteractiveMessage: (clark: Clark, chatSession
|
|
|
55
55
|
export type SendUserMessageOptions = {
|
|
56
56
|
persistBeforeDeliver?: boolean;
|
|
57
57
|
};
|
|
58
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Result of {@link sendUserMessageChannel}.
|
|
60
|
+
*
|
|
61
|
+
* - `success: true` — payload was delivered to the peer within the push
|
|
62
|
+
* bound ({@link PEER_PUSH_TIMEOUT_MS}).
|
|
63
|
+
* - `success: false` with `peerDisconnected: true` — there was no peer, the
|
|
64
|
+
* peer's transport closed mid-push, or the push exceeded the bound (a
|
|
65
|
+
* half-open peer that never acks). Callers must not await this channel
|
|
66
|
+
* unbounded; the bound is enforced here so a half-open peer cannot hang
|
|
67
|
+
* the caller.
|
|
68
|
+
*/
|
|
69
|
+
export type SendUserMessageResult = {
|
|
70
|
+
success: true;
|
|
71
|
+
} | {
|
|
72
|
+
success: false;
|
|
73
|
+
peerDisconnected: true;
|
|
74
|
+
message: string;
|
|
75
|
+
};
|
|
76
|
+
export declare const sendUserMessageChannel: (clark: Clark, chatSessionStore: ChatSessionStore) => (payload: AiChatMessage, delay?: number, immediate?: boolean, { persistBeforeDeliver }?: SendUserMessageOptions) => Promise<SendUserMessageResult>;
|
|
59
77
|
export declare const sendUserGenerationStateChannel: (clark: Clark) => (payload: Parameters<EditorClientMethods["aiSetGenerationState"]>[0]) => Promise<void>;
|
|
60
78
|
/**
|
|
61
79
|
* Clears the pendingToolPermissionRequest from the FSM context and notifies the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"peer.d.ts","sourceRoot":"","sources":["../../../../src/ai-service/state-machine/helpers/peer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACpB,MAAM,uCAAuC,CAAC;AAI/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"peer.d.ts","sourceRoot":"","sources":["../../../../src/ai-service/state-machine/helpers/peer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACpB,MAAM,uCAAuC,CAAC;AAI/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAwH7C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,4BAA4B,GACpC;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GACjE;IACE,OAAO,EAAE,KAAK,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN,eAAO,MAAM,6BAA6B,GACxC,OAAO,KAAK,EACZ,kBAAkB,gBAAgB,MAIhC,SAAS,aAAa,EACtB,cAAS,EACT,mBAAiB,EACjB,UAAS;IACP,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE;QACjB,OAAO,EAAE,CAAC,MAAM,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,aAAa,CAAA;SAAE,KAAK,OAAO,CAAC;KACtE,CAAC;CACE,KACL,OAAO,CAAC,4BAA4B,CA0FxC,CAAC;AAEF,eAAO,MAAM,+BAA+B,GAC1C,OAAO,KAAK,EACZ,kBAAkB,gBAAgB,KACjC,OAAO,CAAC,OAAO,CAcjB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,qBAAqB,GAC7B;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,gBAAgB,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAWhE,eAAO,MAAM,sBAAsB,GACjC,OAAO,KAAK,EACZ,kBAAkB,gBAAgB,MAIhC,SAAS,aAAa,EACtB,cAAS,EACT,mBAAiB,EACjB,2BAAkC,sBAA2B,KAC5D,OAAO,CAAC,qBAAqB,CAwDjC,CAAC;AAEF,eAAO,MAAM,8BAA8B,GAAI,OAAO,KAAK,MAEvD,SAAS,UAAU,CAAC,mBAAmB,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,kBAgCtE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iCAAiC,GAC5C,OAAO,KAAK,EACZ,eAAsB,SAmCvB,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,OAAO,KAAK,EACZ,kBAAkB,gBAAgB,MAGpB,SAAS,gBAAgB,EAAE,cAAS,kBAgBnD,CAAC"}
|
|
@@ -1,7 +1,50 @@
|
|
|
1
1
|
import { getLogger } from "../../../util/logger.js";
|
|
2
2
|
import { OperationQueue } from "../../../util/operation-queue.js";
|
|
3
3
|
import { sanitizeAiProviderResponse } from "../../chat/utils.js";
|
|
4
|
-
import { catchBackgroundPeerDisconnect,
|
|
4
|
+
import { catchBackgroundPeerDisconnect, isTransportCloseError, } from "./stable-peer.js";
|
|
5
|
+
const PEER_PUSH_TIMEOUT_MS = 10_000;
|
|
6
|
+
class PeerPushTimeoutError extends Error {
|
|
7
|
+
}
|
|
8
|
+
function withPeerPushTimeout(promise) {
|
|
9
|
+
return new Promise((resolve, reject) => {
|
|
10
|
+
const timer = setTimeout(() => reject(new PeerPushTimeoutError("peer push timed out")), PEER_PUSH_TIMEOUT_MS);
|
|
11
|
+
// Wrap with Promise.resolve: some callers (and test doubles) hand back a
|
|
12
|
+
// non-promise value synchronously; calling `.then` directly on that would
|
|
13
|
+
// throw instead of settling.
|
|
14
|
+
Promise.resolve(promise).then((v) => {
|
|
15
|
+
clearTimeout(timer);
|
|
16
|
+
resolve(v);
|
|
17
|
+
}, (e) => {
|
|
18
|
+
clearTimeout(timer);
|
|
19
|
+
reject(e);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Bounds a fire-and-forget peer push to {@link PEER_PUSH_TIMEOUT_MS} and
|
|
25
|
+
* classifies the outcome. Returns `true` when the push acked, `false` when the
|
|
26
|
+
* peer was disconnected or half-open (transport close, or the bound fired
|
|
27
|
+
* because the peer never acked). Re-throws genuine RPC-layer failures.
|
|
28
|
+
*
|
|
29
|
+
* Every push that shares the FSM's single `peerChannelQueue` MUST go through a
|
|
30
|
+
* bound like this: `OperationQueue` chains each op on the previous one, so an
|
|
31
|
+
* unbounded push wedged on a half-open peer would block every later queued op
|
|
32
|
+
* from starting — including a plan-delta whose own 10s bound then never arms,
|
|
33
|
+
* re-opening the 180s tool-timeout hang this fixes.
|
|
34
|
+
*/
|
|
35
|
+
async function deliverBoundedPush(promise, description) {
|
|
36
|
+
try {
|
|
37
|
+
await withPeerPushTimeout(promise);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
if (err instanceof PeerPushTimeoutError || isTransportCloseError(err)) {
|
|
42
|
+
getLogger().warn(`[ai-service] ${description} not delivered: peer disconnected/half-open`);
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
5
48
|
const peerQueue = (clark) => {
|
|
6
49
|
const queue = clark.context.peerChannelQueue ?? new OperationQueue();
|
|
7
50
|
clark.updateContext({
|
|
@@ -28,10 +71,14 @@ async function pushInteractiveMessage(clark, payload) {
|
|
|
28
71
|
return INTERACTIVE_PEER_PUSH_DROPPED;
|
|
29
72
|
}
|
|
30
73
|
try {
|
|
31
|
-
|
|
74
|
+
// Bound the push like the plan-delta channel: a half-open peer at the
|
|
75
|
+
// first (interactive plan-card) push would otherwise await aiPushMessage
|
|
76
|
+
// indefinitely and ride the 180s tool timeout. A timeout is treated as a
|
|
77
|
+
// drop, so the caller's peerDisconnected handling kicks in.
|
|
78
|
+
await withPeerPushTimeout(peer.call.aiPushMessage(payload));
|
|
32
79
|
}
|
|
33
80
|
catch (err) {
|
|
34
|
-
if (isTransportCloseError(err)) {
|
|
81
|
+
if (err instanceof PeerPushTimeoutError || isTransportCloseError(err)) {
|
|
35
82
|
getLogger().info(`[ai-service] Interactive message push type=${payload.type} dropped because the editor peer disconnected`);
|
|
36
83
|
return INTERACTIVE_PEER_PUSH_DROPPED;
|
|
37
84
|
}
|
|
@@ -134,6 +181,13 @@ export const flushDeferredInteractiveMessage = async (clark, chatSessionStore) =
|
|
|
134
181
|
const result = await sendInteractiveMessage(deferred.payload);
|
|
135
182
|
return result.success;
|
|
136
183
|
};
|
|
184
|
+
// Frozen: this single instance is returned from every disconnect path, so a
|
|
185
|
+
// caller must never mutate it (doing so would corrupt every other caller).
|
|
186
|
+
const PEER_DISCONNECTED_RESULT = Object.freeze({
|
|
187
|
+
success: false,
|
|
188
|
+
peerDisconnected: true,
|
|
189
|
+
message: "Message could not be delivered because the editor peer disconnected.",
|
|
190
|
+
});
|
|
137
191
|
export const sendUserMessageChannel = (clark, chatSessionStore) => {
|
|
138
192
|
const queue = peerQueue(clark);
|
|
139
193
|
return async (payload, delay = 0, immediate = false, { persistBeforeDeliver = false } = {}) => {
|
|
@@ -158,9 +212,24 @@ export const sendUserMessageChannel = (clark, chatSessionStore) => {
|
|
|
158
212
|
}
|
|
159
213
|
if (!clark.context.peer) {
|
|
160
214
|
getLogger().warn(`[ai-service] Cannot send message: no peer. type=${payloadWithId.type}, state=${clark.state}`);
|
|
161
|
-
return;
|
|
215
|
+
return PEER_DISCONNECTED_RESULT;
|
|
216
|
+
}
|
|
217
|
+
try {
|
|
218
|
+
await withPeerPushTimeout(clark.context.peer.call.aiPushMessage(payloadWithId));
|
|
219
|
+
return { success: true };
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
if (err instanceof PeerPushTimeoutError || isTransportCloseError(err)) {
|
|
223
|
+
getLogger().warn(`[ai-service] message push type=${payloadWithId.type} not delivered: peer disconnected/half-open`);
|
|
224
|
+
return PEER_DISCONNECTED_RESULT;
|
|
225
|
+
}
|
|
226
|
+
// Genuine RPC-layer failure (not a disconnect). Most call sites void
|
|
227
|
+
// this channel, so a bare rethrow would surface as a contextless
|
|
228
|
+
// unhandled rejection — log the payload type before propagating, the
|
|
229
|
+
// same way pushInteractiveMessage does.
|
|
230
|
+
getLogger().warn(`[ai-service] message push type=${payloadWithId.type} failed`, err);
|
|
231
|
+
throw err;
|
|
162
232
|
}
|
|
163
|
-
return catchExpectedPeerDisconnect(clark.context.peer.call.aiPushMessage(payloadWithId), `message push type=${payloadWithId.type}`);
|
|
164
233
|
};
|
|
165
234
|
return immediate ? deliver() : queue(deliver, delay);
|
|
166
235
|
};
|
|
@@ -187,7 +256,9 @@ export const sendUserGenerationStateChannel = (clark) => {
|
|
|
187
256
|
getLogger().warn(`[ai-service] Cannot send generation state: no peer. state=${payload.state}`);
|
|
188
257
|
return;
|
|
189
258
|
}
|
|
190
|
-
|
|
259
|
+
// Bounded: a half-open peer would otherwise hang this await indefinitely
|
|
260
|
+
// and, since callers void it, leak a run that never settles.
|
|
261
|
+
await deliverBoundedPush(peer.call.aiSetGenerationState(payload), `generation state push state=${payload.state}`);
|
|
191
262
|
};
|
|
192
263
|
};
|
|
193
264
|
/**
|
|
@@ -228,7 +299,10 @@ export const sendChangeInfoChannel = (clark, chatSessionStore) => {
|
|
|
228
299
|
getLogger().warn(`[ai-service] Cannot send change info: no peer`);
|
|
229
300
|
return;
|
|
230
301
|
}
|
|
231
|
-
|
|
302
|
+
// Bounded: this push shares the FSM's peerChannelQueue with plan-delta
|
|
303
|
+
// sends, so an unbounded await here on a half-open peer would wedge the
|
|
304
|
+
// queue and starve every later push.
|
|
305
|
+
await deliverBoundedPush(clark.context.peer.call.aiPushChangeInfo(payload), `change info push type=${payload.type}`);
|
|
232
306
|
}, delay);
|
|
233
307
|
};
|
|
234
308
|
};
|