sliccy 6.110.0 → 6.110.2
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/node-server/_cloud_core/src/operations/start.d.ts.map +1 -1
- package/dist/node-server/_cloud_core/src/operations/start.js +152 -132
- package/dist/ui/.vite/manifest.json +132 -132
- package/dist/ui/assets/{account-store-DmTUzOwD.js → account-store-8sKKUZ8J.js} +1 -1
- package/dist/ui/assets/{account-store-C3hpxUnj.js → account-store-Bg1KKHOx.js} +1 -1
- package/dist/ui/assets/{adobe-C6blUXjx.js → adobe-0CWIpyju.js} +1 -1
- package/dist/ui/assets/{adobe-CeRHOrV3.js → adobe-ChXsF6gw.js} +1 -1
- package/dist/ui/assets/{agent-bridge-BytMhrHG.js → agent-bridge-B43SVYcu.js} +1 -1
- package/dist/ui/assets/{agent-panels-CW3VQhe5.js → agent-panels-9uCI5yeM.js} +1 -1
- package/dist/ui/assets/{apply-layout-C9oYfek3.js → apply-layout-Bz-0rXhV.js} +1 -1
- package/dist/ui/assets/{apps-buLjOZpb.js → apps-C16RztyU.js} +1 -1
- package/dist/ui/assets/{azure-openai-BQJFNoBY.js → azure-openai-BCKGDF-y.js} +1 -1
- package/dist/ui/assets/{azure-openai-BvVWJJJ0.js → azure-openai-DoQszniP.js} +1 -1
- package/dist/ui/assets/cdp-ws-page-bridge-CtHmog_w.js +1 -0
- package/dist/ui/assets/{cerebras-CokNYO8b.js → cerebras-CQwhL4Ig.js} +1 -1
- package/dist/ui/assets/{cerebras-BjJmr6-W.js → cerebras-kH_bQsg2.js} +1 -1
- package/dist/ui/assets/{connect-surface-BHqqK_uZ.js → connect-surface-BMrb-EnN.js} +1 -1
- package/dist/ui/assets/{directed-approval-CGapNvBZ.js → directed-approval-zeD_orXz.js} +1 -1
- package/dist/ui/assets/{dist-DhiPJE96.js → dist-BKQr3WRb.js} +1 -1
- package/dist/ui/assets/{dist-CIyvNQb4.js → dist-CBELmDjr.js} +1 -1
- package/dist/ui/assets/dist-DHO9E-gl.js +2 -0
- package/dist/ui/assets/dist-iMxkf8fm.js +2 -0
- package/dist/ui/assets/{fs-D9DlVz0g.js → fs-BsqtoiKD.js} +2 -2
- package/dist/ui/assets/{fs-b7tPDGDe.js → fs-DKRiXKHo.js} +1 -1
- package/dist/ui/assets/{github-rMrWcSVm.js → github-DGUqMidV.js} +1 -1
- package/dist/ui/assets/{github-CAYwnl-b.js → github-DqsEulTB.js} +2 -2
- package/dist/ui/assets/{github-copilot-BaohZB3G.js → github-copilot-DJf8cE1K.js} +1 -1
- package/dist/ui/assets/{github-copilot-BaEPoc2l.js → github-copilot-Xp2l1YxD.js} +1 -1
- package/dist/ui/assets/{github-install-9ynDwgiQ.js → github-install-DRa8AaBY.js} +1 -1
- package/dist/ui/assets/{github-zip-nBMk_5yk.js → github-zip-BpPiUirA.js} +1 -1
- package/dist/ui/assets/{js-realm-worker-adzmez5_.js → js-realm-worker-D6DSLfXh.js} +10 -10
- package/dist/ui/assets/{kernel-worker-DqzdssFu.js → kernel-worker-DQDT4Cud.js} +530 -530
- package/dist/ui/assets/{local-llm--yLtHAZU.js → local-llm-Cjzjpqa1.js} +1 -1
- package/dist/ui/assets/{local-llm-CiMne0-B.js → local-llm-OBHKAcNH.js} +1 -1
- package/dist/ui/assets/{main-CfZo7HyV.js → main-BK-7ArIz.js} +3 -3
- package/dist/ui/assets/{mount-CC0djJXQ.js → mount-BrQpW9eO.js} +1 -1
- package/dist/ui/assets/{mount-rYO-8m8f.js → mount-Rb9VVKip.js} +2 -2
- package/dist/ui/assets/{mount-recovery-CvuTQnTL.js → mount-recovery-Cb-AXW35.js} +1 -1
- package/dist/ui/assets/{new-session-BS3W0s9e.js → new-session-CF4YpiQ9.js} +2 -2
- package/dist/ui/assets/{oauth-bootstrap-DpG29VCH.js → oauth-bootstrap-YFOy1SIX.js} +2 -2
- package/dist/ui/assets/{onboarding-orchestrator-BI0_TR0Z.js → onboarding-orchestrator-Dmh6rOJl.js} +1 -1
- package/dist/ui/assets/{openai-codex-BJ4JLVfo.js → openai-codex-84EHUcAD.js} +1 -1
- package/dist/ui/assets/{openai-codex-C8aOD0t8.js → openai-codex-DY_L0KSA.js} +1 -1
- package/dist/ui/assets/{openrouter-DHg1gMnT.js → openrouter-meLV8ehE.js} +1 -1
- package/dist/ui/assets/{openrouter-oauth-DukR2YjX.js → openrouter-oauth-CblQ27-K.js} +1 -1
- package/dist/ui/assets/{openrouter-oauth-CRVMrh7E.js → openrouter-oauth-DudFNSW4.js} +1 -1
- package/dist/ui/assets/{openrouter-LCca2Pyd.js → openrouter-z7GGvxCM.js} +1 -1
- package/dist/ui/assets/{panel-rpc-handlers-p0z9KK9s.js → panel-rpc-handlers-DmiAyTiy.js} +2 -2
- package/dist/ui/assets/{panelize-shell-DRCqD-hf.js → panelize-shell-65i9Hq7n.js} +1 -1
- package/dist/ui/assets/{provider-8X1TXGOz.js → provider-BE0mTIGf.js} +1 -1
- package/dist/ui/assets/{provider-CMYr90tG.js → provider-BLbTGk-_.js} +2 -2
- package/dist/ui/assets/{provider-settings-BbKZBkmj.js → provider-settings-Dq-yRgMh.js} +1 -1
- package/dist/ui/assets/provider-store-access-CJdYrcvf.js +1 -0
- package/dist/ui/assets/provider-store-access-NHOQWINx.js +1 -0
- package/dist/ui/assets/{providers-B3XsxeEV.js → providers-B3OPYf2o.js} +2 -2
- package/dist/ui/assets/{providers-DuNEVEmM.js → providers-BlPz5ou6.js} +1 -1
- package/dist/ui/assets/{quick-llm-BQeXAXhA.js → quick-llm-CcFoANd_.js} +1 -1
- package/dist/ui/assets/{recovery-screen-Dg10xiZK.js → recovery-screen-44Uu5Cgy.js} +1 -1
- package/dist/ui/assets/{run-74Dp3xqK.js → run-BQu73khp.js} +1 -1
- package/dist/ui/assets/{setup-feature-flags-remote-BDXotdTe.js → setup-feature-flags-remote-ITlSmr_i.js} +1 -1
- package/dist/ui/assets/sidecar-repair-Ddcz9Mvv.js +1 -0
- package/dist/ui/assets/{skills-fw01LxeE.js → skills-B0o8gPTv.js} +1 -1
- package/dist/ui/assets/slicc-version-BrPYMXS9.js +1 -0
- package/dist/ui/assets/{state-YABVHFPR.js → state-BSTmV4yO.js} +1 -1
- package/dist/ui/assets/{store-DuMDTOYq.js → store-C3RMRz9d.js} +1 -1
- package/dist/ui/assets/{store--DLIZTf_.js → store-CzQ9Fvfr.js} +1 -1
- package/dist/ui/assets/{sudo-Lv8DoXxd.js → sudo-CPH7ANoV.js} +1 -1
- package/dist/ui/assets/{sync-dialog-B8ssqjz4.js → sync-dialog-vSEl3KxP.js} +1 -1
- package/dist/ui/assets/{tray-sidecar-B1xCDlFe.js → tray-sidecar-BIcoXTJN.js} +1 -1
- package/dist/ui/assets/{upgrade-detection-TlqXRH1-.js → upgrade-detection-TsOPChOa.js} +1 -1
- package/dist/ui/assets/{voice-reply-CGJnZqW1.js → voice-reply-O_Z2C0eg.js} +1 -1
- package/dist/ui/assets/{wc-attach-DANq4_X7.js → wc-attach-DM5yRZRS.js} +2 -2
- package/dist/ui/assets/{wc-extension-BRZxL5Z1.js → wc-extension-Dg5dOqTK.js} +2 -2
- package/dist/ui/assets/{wc-float-label-KQOIpgnm.js → wc-float-label-Bmp3gmHN.js} +1 -1
- package/dist/ui/assets/{wc-floatbar-online-D1LOCURF.js → wc-floatbar-online-B8ug4UwE.js} +1 -1
- package/dist/ui/assets/{wc-follower-D7D0OBf3.js → wc-follower-G03aUmAn.js} +3 -3
- package/dist/ui/assets/{wc-follower-oauth-DZllVzrT.js → wc-follower-oauth-D15d_vbh.js} +1 -1
- package/dist/ui/assets/{wc-live-RnON2Ugk.js → wc-live-CiwhsK8i.js} +7 -7
- package/dist/ui/assets/{wc-nav-Clor2VFZ.js → wc-nav-D8Bi3zRA.js} +2 -2
- package/dist/ui/assets/{wc-onboarding-BUmFCg_U.js → wc-onboarding-DUBWYyMl.js} +2 -2
- package/dist/ui/assets/{wc-placeholder-8Judy9cG.js → wc-placeholder-CPMV2eO3.js} +3 -3
- package/dist/ui/assets/{wc-settings-Bvx2BLQv.js → wc-settings-M8e_JWQh.js} +3 -3
- package/dist/ui/assets/{wc-shell-CsfCsd9q.js → wc-shell-WlrdsROD.js} +2 -2
- package/dist/ui/assets/{wc-shortcut-config-BK4O1f_G.js → wc-shortcut-config-BftmZXGf.js} +1 -1
- package/dist/ui/assets/{wc-sprinkles-D65r5HD-.js → wc-sprinkles-DhXJLTUO.js} +2 -2
- package/dist/ui/assets/{wc-transcript-export-UUnE-lk6.js → wc-transcript-export-DjpmBvLP.js} +2 -2
- package/dist/ui/assets/{wc-tray-CPQsc5Us.js → wc-tray-BdgbNPhM.js} +4 -4
- package/dist/ui/assets/welcome-detection-0SaDZUV0.js +1 -0
- package/dist/ui/assets/{xai-grok-DoYWlKs_.js → xai-grok-CVEtAfJK.js} +1 -1
- package/dist/ui/assets/{xai-grok-IHkw5Jqa.js → xai-grok-DH1oX2E5.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/ui/packages/webapp/index.html +3 -3
- package/package.json +2 -2
- package/dist/ui/assets/cdp-ws-page-bridge-DI26JBMr.js +0 -1
- package/dist/ui/assets/dist-CLbkZ_1_.js +0 -2
- package/dist/ui/assets/dist-ChNj9ewx.js +0 -2
- package/dist/ui/assets/provider-store-access-D5VrJP0f.js +0 -1
- package/dist/ui/assets/provider-store-access-DxHrtPBD.js +0 -1
- package/dist/ui/assets/sidecar-repair-Mh9rQVbp.js +0 -1
- package/dist/ui/assets/slicc-version-DF86HAGG.js +0 -1
- package/dist/ui/assets/welcome-detection-D7QFjBKz.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/operations/start.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,WAAW,aAAa;IAC5B;wEACoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB;iEAC6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC;qEACiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;2DACuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;0DACsD;IACtD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,oDAAoD;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,GAAG,CAAC,EAAE;QACJ,gBAAgB,EAAE,MAAM,CAAC;QACzB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;IACF;;;2CAGuC;IACvC,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC;CAC/B;
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/operations/start.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,WAAW,aAAa;IAC5B;wEACoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB;iEAC6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC;qEACiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;2DACuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;0DACsD;IACtD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,oDAAoD;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,GAAG,CAAC,EAAE;QACJ,gBAAgB,EAAE,MAAM,CAAC;QACzB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;IACF;;;2CAGuC;IACvC,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC;CAC/B;AA2DD;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,CAmCpC;AA6ID,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CA0D9F"}
|
|
@@ -26,6 +26,34 @@ function parseCapLimit(name, raw) {
|
|
|
26
26
|
}
|
|
27
27
|
return n;
|
|
28
28
|
}
|
|
29
|
+
function errMessage(err) {
|
|
30
|
+
return err instanceof Error ? err.message : String(err);
|
|
31
|
+
}
|
|
32
|
+
/** Enforce running/paused caps when env caps are provided. */
|
|
33
|
+
function enforceCaps(existing, env) {
|
|
34
|
+
const running = existing.filter((e) => e.state === 'running' || e.state === 'reserved').length;
|
|
35
|
+
const paused = existing.filter((e) => e.state === 'paused').length;
|
|
36
|
+
const runningCap = parseCapLimit('CONE_CAP_RUNNING', env.CONE_CAP_RUNNING);
|
|
37
|
+
const pausedCap = parseCapLimit('CONE_CAP_PAUSED', env.CONE_CAP_PAUSED);
|
|
38
|
+
if (running >= runningCap) {
|
|
39
|
+
throw new CloudError('CAP_EXCEEDED', `at running cap (${running}/${runningCap})`, {
|
|
40
|
+
running,
|
|
41
|
+
cap: runningCap,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (paused >= pausedCap) {
|
|
45
|
+
throw new CloudError('CAP_EXCEEDED', `at paused cap (${paused}/${pausedCap})`, {
|
|
46
|
+
paused,
|
|
47
|
+
cap: pausedCap,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function loadExistingCones(deps, opts) {
|
|
52
|
+
if (opts.reconciledCones)
|
|
53
|
+
return opts.reconciledCones;
|
|
54
|
+
const { listCones } = await import('./list.js');
|
|
55
|
+
return listCones(deps, opts.userId ? { metadata: { userId: opts.userId } } : {});
|
|
56
|
+
}
|
|
29
57
|
/**
|
|
30
58
|
* Reserve a slot in the registry atomically under DO lock, BEFORE substrate.create.
|
|
31
59
|
* Returns a synthetic reservationId (pending-<uuid>) that counts toward the cap.
|
|
@@ -40,32 +68,10 @@ export async function reserveSlot(deps, opts) {
|
|
|
40
68
|
// Read existing entries to enforce caps + name conflicts.
|
|
41
69
|
// If caller provided a pre-reconciled list (worker DO path), use it directly.
|
|
42
70
|
// Otherwise (CLI path), do a full reconciliation via listCones.
|
|
43
|
-
|
|
44
|
-
if (opts.reconciledCones) {
|
|
45
|
-
existing = opts.reconciledCones;
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
const { listCones } = await import('./list.js');
|
|
49
|
-
existing = await listCones(deps, opts.userId ? { metadata: { userId: opts.userId } } : {});
|
|
50
|
-
}
|
|
71
|
+
const existing = await loadExistingCones(deps, opts);
|
|
51
72
|
// Cap check: count both running and reserved entries (reservations count as running)
|
|
52
73
|
if (opts.env) {
|
|
53
|
-
|
|
54
|
-
const paused = existing.filter((e) => e.state === 'paused').length;
|
|
55
|
-
const runningCap = parseCapLimit('CONE_CAP_RUNNING', opts.env.CONE_CAP_RUNNING);
|
|
56
|
-
const pausedCap = parseCapLimit('CONE_CAP_PAUSED', opts.env.CONE_CAP_PAUSED);
|
|
57
|
-
if (running >= runningCap) {
|
|
58
|
-
throw new CloudError('CAP_EXCEEDED', `at running cap (${running}/${runningCap})`, {
|
|
59
|
-
running,
|
|
60
|
-
cap: runningCap,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
if (paused >= pausedCap) {
|
|
64
|
-
throw new CloudError('CAP_EXCEEDED', `at paused cap (${paused}/${pausedCap})`, {
|
|
65
|
-
paused,
|
|
66
|
-
cap: pausedCap,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
74
|
+
enforceCaps(existing, opts.env);
|
|
69
75
|
}
|
|
70
76
|
// Name conflict check
|
|
71
77
|
const requestedName = opts.name?.trim();
|
|
@@ -87,6 +93,121 @@ export async function reserveSlot(deps, opts) {
|
|
|
87
93
|
await deps.registry.append(placeholder);
|
|
88
94
|
return { reservationId };
|
|
89
95
|
}
|
|
96
|
+
function buildCreateEnvVars(opts, safeSecrets) {
|
|
97
|
+
return {
|
|
98
|
+
SLICC_TRAY_WORKER_BASE_URL: opts.workerBaseUrl,
|
|
99
|
+
SLICC_SECRETS_ENV_B64: encodeBundleEnv(safeSecrets),
|
|
100
|
+
...(opts.coneConfigJson ? { SLICC_CONE_CONFIG_B64: encodeBundleEnv(opts.coneConfigJson) } : {}),
|
|
101
|
+
...(opts.envs ?? {}),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function buildCreateMetadata(opts) {
|
|
105
|
+
return {
|
|
106
|
+
sliccVersion: opts.sliccVersion,
|
|
107
|
+
...(opts.name ? { name: opts.name } : {}),
|
|
108
|
+
...(opts.metadata ?? {}),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Swap a reservation for the real sandbox entry, or append a legacy placeholder.
|
|
113
|
+
* Returns the registry key that is now active (the real sandboxId).
|
|
114
|
+
*
|
|
115
|
+
* The placeholder ensures concurrent /list-cones calls see the cone in the registry
|
|
116
|
+
* (pass 1) instead of treating it as an orphan (pass 2). The empty joinUrl
|
|
117
|
+
* means the dashboard hides the Open button until pollCloudStatus completes
|
|
118
|
+
* and the entry is updated below. State is 'reserved' until poll completes.
|
|
119
|
+
*/
|
|
120
|
+
async function registerStartPlaceholder(registry, substrateId, handle, opts, createdAt) {
|
|
121
|
+
if (opts.reservationId) {
|
|
122
|
+
// Remove the reservation entry and append the real one
|
|
123
|
+
await registry.remove(opts.reservationId);
|
|
124
|
+
const placeholder = {
|
|
125
|
+
substrate: substrateId,
|
|
126
|
+
sandboxId: handle.sandboxId,
|
|
127
|
+
name: opts.name,
|
|
128
|
+
createdAt,
|
|
129
|
+
lastSeen: createdAt,
|
|
130
|
+
state: 'reserved',
|
|
131
|
+
joinUrl: '',
|
|
132
|
+
metadata: opts.metadata,
|
|
133
|
+
};
|
|
134
|
+
await registry.append(placeholder);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
// Legacy path: no reservation, append directly
|
|
138
|
+
const placeholder = {
|
|
139
|
+
substrate: substrateId,
|
|
140
|
+
sandboxId: handle.sandboxId,
|
|
141
|
+
name: opts.name,
|
|
142
|
+
createdAt,
|
|
143
|
+
lastSeen: createdAt,
|
|
144
|
+
state: 'reserved',
|
|
145
|
+
joinUrl: '',
|
|
146
|
+
};
|
|
147
|
+
await registry.append(placeholder);
|
|
148
|
+
}
|
|
149
|
+
return handle.sandboxId;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Two-layer secrets bootstrap (see Plan B):
|
|
153
|
+
* 1. start.sh writes /slicc/secrets.env from $ADOBE_IMS_TOKEN if the file
|
|
154
|
+
* doesn't already exist (fallback for race-free worker path where env-vars
|
|
155
|
+
* arrive before this writeFile lands).
|
|
156
|
+
* 2. THIS writeFile uploads the full filtered secrets.env. Worker overwrites
|
|
157
|
+
* with Adobe-only content (effectively a no-op since start.sh already wrote
|
|
158
|
+
* the same token). CLI overwrites with non-Adobe secrets (GitHub PATs, S3
|
|
159
|
+
* keys, etc.), load-bearing for CLI-launched cones. The CLI race is benign
|
|
160
|
+
* because the page-side bootstrap polls /api/hosted-bootstrap after a 5s
|
|
161
|
+
* delay, by which time this writeFile has landed.
|
|
162
|
+
*/
|
|
163
|
+
async function writeBootstrapFiles(handle, safeSecrets, coneConfigJson) {
|
|
164
|
+
await handle.writeFile('/slicc/secrets.env', safeSecrets);
|
|
165
|
+
if (coneConfigJson) {
|
|
166
|
+
await handle.writeFile('/slicc/cone-config.json', coneConfigJson);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async function pollStatusOrThrow(handle, opts, minUpdatedAt) {
|
|
170
|
+
try {
|
|
171
|
+
return await pollCloudStatus(handle, {
|
|
172
|
+
timeoutMs: opts.pollTimeoutMs ?? 60_000,
|
|
173
|
+
intervalMs: opts.pollIntervalMs ?? 500,
|
|
174
|
+
minUpdatedAt,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
catch (pollErr) {
|
|
178
|
+
// Surface boot diagnostics before tearing down. Spec failure mode #7.
|
|
179
|
+
const stderr = await tailStderr(handle, 50);
|
|
180
|
+
throw new CloudError('SANDBOX_NOT_READY', `${errMessage(pollErr)}\n` + `--- last 50 lines of /tmp/slicc-stderr.log ---\n${stderr}`, { sandboxId: handle.sandboxId });
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
async function bestEffortCleanup(registry, activeRegistryId, handle) {
|
|
184
|
+
// Best-effort cleanup: remove whichever registry entry is currently active.
|
|
185
|
+
if (activeRegistryId) {
|
|
186
|
+
try {
|
|
187
|
+
await registry.remove(activeRegistryId);
|
|
188
|
+
}
|
|
189
|
+
catch (cleanupErr) {
|
|
190
|
+
console.warn('[cloud-core] start cleanup', {
|
|
191
|
+
phase: 'registry-remove',
|
|
192
|
+
sandboxId: activeRegistryId,
|
|
193
|
+
err: errMessage(cleanupErr),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Always kill the real sandbox if it was created (handle exists at this point)
|
|
198
|
+
if (handle) {
|
|
199
|
+
try {
|
|
200
|
+
await handle.kill();
|
|
201
|
+
}
|
|
202
|
+
catch (cleanupErr) {
|
|
203
|
+
console.warn('[cloud-core] start cleanup', {
|
|
204
|
+
phase: 'handle-kill',
|
|
205
|
+
sandboxId: handle.sandboxId,
|
|
206
|
+
err: errMessage(cleanupErr),
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
90
211
|
export async function startCone(deps, opts) {
|
|
91
212
|
const safeSecrets = filterSecretsEnv(opts.envContents);
|
|
92
213
|
// Track whichever registry entry is currently live, for cleanup on failure.
|
|
@@ -97,19 +218,8 @@ export async function startCone(deps, opts) {
|
|
|
97
218
|
handle = await deps.substrate.create({
|
|
98
219
|
template: opts.template ?? 'slicc',
|
|
99
220
|
autoPauseOnCap: opts.autoPauseOnCap ?? true,
|
|
100
|
-
envVars:
|
|
101
|
-
|
|
102
|
-
SLICC_SECRETS_ENV_B64: encodeBundleEnv(safeSecrets),
|
|
103
|
-
...(opts.coneConfigJson
|
|
104
|
-
? { SLICC_CONE_CONFIG_B64: encodeBundleEnv(opts.coneConfigJson) }
|
|
105
|
-
: {}),
|
|
106
|
-
...(opts.envs ?? {}),
|
|
107
|
-
},
|
|
108
|
-
metadata: {
|
|
109
|
-
sliccVersion: opts.sliccVersion,
|
|
110
|
-
...(opts.name ? { name: opts.name } : {}),
|
|
111
|
-
...(opts.metadata ?? {}),
|
|
112
|
-
},
|
|
221
|
+
envVars: buildCreateEnvVars(opts, safeSecrets),
|
|
222
|
+
metadata: buildCreateMetadata(opts),
|
|
113
223
|
name: opts.name,
|
|
114
224
|
});
|
|
115
225
|
// Capture freshness baseline AFTER sandbox creation: any /tmp/slicc-join.json
|
|
@@ -121,73 +231,10 @@ export async function startCone(deps, opts) {
|
|
|
121
231
|
const minUpdatedAt = new Date(Date.now() - 5_000).toISOString();
|
|
122
232
|
const createdAt = new Date().toISOString();
|
|
123
233
|
// Update or append placeholder depending on whether we have a reservation.
|
|
124
|
-
//
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
// (pass 1) instead of treating it as an orphan (pass 2). The empty joinUrl
|
|
129
|
-
// means the dashboard hides the Open button until pollCloudStatus completes
|
|
130
|
-
// and the entry is updated below. State is 'reserved' until poll completes.
|
|
131
|
-
if (opts.reservationId) {
|
|
132
|
-
// Remove the reservation entry and append the real one
|
|
133
|
-
await deps.registry.remove(opts.reservationId);
|
|
134
|
-
const placeholder = {
|
|
135
|
-
substrate: deps.substrate.id,
|
|
136
|
-
sandboxId: handle.sandboxId,
|
|
137
|
-
name: opts.name,
|
|
138
|
-
createdAt,
|
|
139
|
-
lastSeen: createdAt,
|
|
140
|
-
state: 'reserved',
|
|
141
|
-
joinUrl: '',
|
|
142
|
-
metadata: opts.metadata,
|
|
143
|
-
};
|
|
144
|
-
await deps.registry.append(placeholder);
|
|
145
|
-
// After swapping, the real sandboxId is the active registry key.
|
|
146
|
-
activeRegistryId = handle.sandboxId;
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
// Legacy path: no reservation, append directly
|
|
150
|
-
const placeholder = {
|
|
151
|
-
substrate: deps.substrate.id,
|
|
152
|
-
sandboxId: handle.sandboxId,
|
|
153
|
-
name: opts.name,
|
|
154
|
-
createdAt,
|
|
155
|
-
lastSeen: createdAt,
|
|
156
|
-
state: 'reserved',
|
|
157
|
-
joinUrl: '',
|
|
158
|
-
};
|
|
159
|
-
await deps.registry.append(placeholder);
|
|
160
|
-
// The newly-appended sandboxId is the active registry key.
|
|
161
|
-
activeRegistryId = handle.sandboxId;
|
|
162
|
-
}
|
|
163
|
-
// Two-layer secrets bootstrap (see Plan B):
|
|
164
|
-
// 1. start.sh writes /slicc/secrets.env from $ADOBE_IMS_TOKEN if the file
|
|
165
|
-
// doesn't already exist (fallback for race-free worker path where env-vars
|
|
166
|
-
// arrive before this writeFile lands).
|
|
167
|
-
// 2. THIS writeFile uploads the full filtered secrets.env. Worker overwrites
|
|
168
|
-
// with Adobe-only content (effectively a no-op since start.sh already wrote
|
|
169
|
-
// the same token). CLI overwrites with non-Adobe secrets (GitHub PATs, S3
|
|
170
|
-
// keys, etc.), load-bearing for CLI-launched cones. The CLI race is benign
|
|
171
|
-
// because the page-side bootstrap polls /api/hosted-bootstrap after a 5s
|
|
172
|
-
// delay, by which time this writeFile has landed.
|
|
173
|
-
await handle.writeFile('/slicc/secrets.env', safeSecrets);
|
|
174
|
-
if (opts.coneConfigJson) {
|
|
175
|
-
await handle.writeFile('/slicc/cone-config.json', opts.coneConfigJson);
|
|
176
|
-
}
|
|
177
|
-
let status;
|
|
178
|
-
try {
|
|
179
|
-
status = await pollCloudStatus(handle, {
|
|
180
|
-
timeoutMs: opts.pollTimeoutMs ?? 60_000,
|
|
181
|
-
intervalMs: opts.pollIntervalMs ?? 500,
|
|
182
|
-
minUpdatedAt,
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
catch (pollErr) {
|
|
186
|
-
// Surface boot diagnostics before tearing down. Spec failure mode #7.
|
|
187
|
-
const stderr = await tailStderr(handle, 50);
|
|
188
|
-
throw new CloudError('SANDBOX_NOT_READY', `${pollErr instanceof Error ? pollErr.message : String(pollErr)}\n` +
|
|
189
|
-
`--- last 50 lines of /tmp/slicc-stderr.log ---\n${stderr}`, { sandboxId: handle.sandboxId });
|
|
190
|
-
}
|
|
234
|
+
// After swapping/appending, the real sandboxId is the active registry key.
|
|
235
|
+
activeRegistryId = await registerStartPlaceholder(deps.registry, deps.substrate.id, handle, opts, createdAt);
|
|
236
|
+
await writeBootstrapFiles(handle, safeSecrets, opts.coneConfigJson);
|
|
237
|
+
const status = await pollStatusOrThrow(handle, opts, minUpdatedAt);
|
|
191
238
|
// Promote the placeholder to a fully-populated running entry.
|
|
192
239
|
await deps.registry.update(handle.sandboxId, {
|
|
193
240
|
state: 'running',
|
|
@@ -203,34 +250,7 @@ export async function startCone(deps, opts) {
|
|
|
203
250
|
};
|
|
204
251
|
}
|
|
205
252
|
catch (err) {
|
|
206
|
-
|
|
207
|
-
if (activeRegistryId) {
|
|
208
|
-
try {
|
|
209
|
-
await deps.registry.remove(activeRegistryId);
|
|
210
|
-
}
|
|
211
|
-
catch (cleanupErr) {
|
|
212
|
-
const msg = cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr);
|
|
213
|
-
console.warn('[cloud-core] start cleanup', {
|
|
214
|
-
phase: 'registry-remove',
|
|
215
|
-
sandboxId: activeRegistryId,
|
|
216
|
-
err: msg,
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
// Always kill the real sandbox if it was created (handle exists at this point)
|
|
221
|
-
if (handle) {
|
|
222
|
-
try {
|
|
223
|
-
await handle.kill();
|
|
224
|
-
}
|
|
225
|
-
catch (cleanupErr) {
|
|
226
|
-
const msg = cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr);
|
|
227
|
-
console.warn('[cloud-core] start cleanup', {
|
|
228
|
-
phase: 'handle-kill',
|
|
229
|
-
sandboxId: handle.sandboxId,
|
|
230
|
-
err: msg,
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
}
|
|
253
|
+
await bestEffortCleanup(deps.registry, activeRegistryId, handle);
|
|
234
254
|
throw err;
|
|
235
255
|
}
|
|
236
256
|
}
|