sliccy 4.26.0 → 4.27.1
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/cone-config/index.d.ts +21 -0
- package/dist/node-server/_cloud_core/src/cone-config/index.d.ts.map +1 -1
- package/dist/node-server/_cloud_core/src/cone-config/index.js +91 -40
- package/dist/node-server/_cloud_core/src/index.d.ts +1 -1
- package/dist/node-server/_cloud_core/src/index.d.ts.map +1 -1
- package/dist/node-server/_cloud_core/src/index.js +1 -1
- package/dist/node-server/_cloud_core/src/substrates/e2b.d.ts +9 -0
- package/dist/node-server/_cloud_core/src/substrates/e2b.d.ts.map +1 -1
- package/dist/node-server/_cloud_core/src/substrates/e2b.js +14 -2
- package/dist/node-server/_cloud_core/tests/cone-config/cone-config.test.js +34 -1
- package/dist/node-server/_cloud_core/tests/e2b-substrate.test.d.ts +2 -0
- package/dist/node-server/_cloud_core/tests/e2b-substrate.test.d.ts.map +1 -0
- package/dist/node-server/_cloud_core/tests/e2b-substrate.test.js +18 -0
- package/dist/node-server/cloud/dispatch.d.ts +1 -0
- package/dist/node-server/cloud/dispatch.js +47 -29
- package/dist/node-server/cloud/start.d.ts +14 -0
- package/dist/node-server/cloud/start.js +15 -1
- package/dist/node-server/hosted-bootstrap.d.ts +2 -1
- package/dist/node-server/hosted-bootstrap.js +17 -1
- package/dist/node-server/index.js +1 -0
- package/dist/ui/assets/{account-store-C_cA3i6g.js → account-store-BLxY-a1I.js} +2 -2
- package/dist/ui/assets/{account-store-QleYDKnG.js → account-store-DlrAEcf8.js} +2 -2
- package/dist/ui/assets/{adobe-Buv0zDrc.js → adobe-8U6ockuy.js} +1 -1
- package/dist/ui/assets/{adobe-_MN845Fw.js → adobe-DQz0wHip.js} +1 -1
- package/dist/ui/assets/{agent-message-to-chat-BISoOCaW.js → agent-message-to-chat-D1qFGa0H.js} +1 -1
- package/dist/ui/assets/{apps-C28amp1i.js → apps-Clsar6I4.js} +1 -1
- package/dist/ui/assets/{azure-openai-CGn8k87V.js → azure-openai-CKI3J0pL.js} +1 -1
- package/dist/ui/assets/{azure-openai-BUhRZLl1.js → azure-openai-FFvXbd9e.js} +1 -1
- package/dist/ui/assets/{bsh-watchdog-DQkgs5b2.js → bsh-watchdog-RV9EwAEl.js} +1 -1
- package/dist/ui/assets/{connect-surface-CsN-fRzW.js → connect-surface-BDz_Jbtn.js} +1 -1
- package/dist/ui/assets/dip-B2piWft1.js +1 -0
- package/dist/ui/assets/{dist-Ud2wprp1.js → dist-BramTh3k.js} +1 -1
- package/dist/ui/assets/{dist-Q6Ijgx42.js → dist-qMFg53E9.js} +1 -1
- package/dist/ui/assets/{es-ykMvrvgd.js → es-D1SJDD--.js} +1 -1
- package/dist/ui/assets/{fs-BYPY106y.js → fs-B2-HQOUo.js} +1 -1
- package/dist/ui/assets/{fs-DoZH1t2b.js → fs-Df-Hc8KP.js} +2 -2
- package/dist/ui/assets/{github-C9PTf7-p.js → github-BRGlvnq3.js} +2 -2
- package/dist/ui/assets/{github-CeXLHUEm.js → github-DjsOp-K7.js} +1 -1
- package/dist/ui/assets/{github-copilot--a7qwxPo.js → github-copilot-Cyx_KiQV.js} +1 -1
- package/dist/ui/assets/{github-copilot-BfaeGhAx.js → github-copilot-DyaoHWUW.js} +1 -1
- package/dist/ui/assets/{hear-CHDQfguT.js → hear-CYJlpYDZ.js} +1 -1
- package/dist/ui/assets/{kernel-worker-JEGL1H9y.js → kernel-worker-Bu123P9s.js} +20 -20
- package/dist/ui/assets/{kokoro-engine-kv1GOKX7.js → kokoro-engine-CpRjXbAb.js} +1 -1
- package/dist/ui/assets/{lick-ws-bridge-CYeKRx-9.js → lick-ws-bridge-CVqku5t6.js} +1 -1
- package/dist/ui/assets/{local-llm-BD11kv77.js → local-llm-q2LIMuy-.js} +1 -1
- package/dist/ui/assets/{main-CE5zQ7n8.js → main-DmMCSYcC.js} +3 -3
- package/dist/ui/assets/{mount-B2wqIfs8.js → mount-CI10hvjc.js} +2 -2
- package/dist/ui/assets/{mount-D8Dafwe1.js → mount-DOUb_feL.js} +1 -1
- package/dist/ui/assets/{new-session-CoPL13pP.js → new-session-C9LAN5Hd.js} +2 -2
- package/dist/ui/assets/{oauth-bootstrap-Bok5Qb_f.js → oauth-bootstrap-DbxcP6Sh.js} +2 -2
- package/dist/ui/assets/{oauth-service-DMG4VUb6.js → oauth-service-C05rMMVl.js} +1 -1
- package/dist/ui/assets/{openai-codex-9Wve47FT.js → openai-codex-CRBhrEBc.js} +1 -1
- package/dist/ui/assets/{openai-codex-2S-Cwbop.js → openai-codex-ChnTS79X.js} +1 -1
- package/dist/ui/assets/{panel-rpc-handlers-CpmURTlO.js → panel-rpc-handlers-DNPwL0jj.js} +1 -1
- package/dist/ui/assets/{provider-CMmXdeLg.js → provider-BvnOU_Pd.js} +1 -1
- package/dist/ui/assets/{provider-BZXGxqbT.js → provider-Dg_nVqWt.js} +2 -2
- package/dist/ui/assets/provider-store-access-B7FRxI4Y.js +1 -0
- package/dist/ui/assets/provider-store-access-BIowizns.js +1 -0
- package/dist/ui/assets/{providers-B9f6qRKl.js → providers-Duc0oO9P.js} +1 -1
- package/dist/ui/assets/{quick-llm-BtUr0Fuw.js → quick-llm-C1JqX7L6.js} +1 -1
- package/dist/ui/assets/session-freezer-C9D4TMQN.js +1 -0
- package/dist/ui/assets/setup-sudo-BhQ2Wc_x.js +1 -0
- package/dist/ui/assets/{speak-CSf0rHKy.js → speak-ChGyltW6.js} +1 -1
- package/dist/ui/assets/{sprinkle-manager-CStXC4E3.js → sprinkle-manager-DP_96pVo.js} +1 -1
- package/dist/ui/assets/{store-CcQt0JbT.js → store-Bf6RiNFb.js} +1 -1
- package/dist/ui/assets/{sudo-DFtdMkBt.js → sudo-C9cKVFZG.js} +1 -1
- package/dist/ui/assets/{transformers-env-CL1k8Gl_.js → transformers-env-DnluHRSF.js} +1 -1
- package/dist/ui/assets/{tray-leave-runtime-qp-hFu3c.js → tray-leave-runtime-B41WhRx6.js} +1 -1
- package/dist/ui/assets/{upgrade-detection-Dtv8Fgtu.js → upgrade-detection-DgkuUQy4.js} +1 -1
- package/dist/ui/assets/{wc-attach-D35Mcmik.js → wc-attach-Bp4HbqWU.js} +2 -2
- package/dist/ui/assets/{wc-detached-ecJY40A0.js → wc-detached-IkSYcZmW.js} +1 -1
- package/dist/ui/assets/{wc-extension-B91PNRXx.js → wc-extension-CvCoUpxB.js} +2 -2
- package/dist/ui/assets/{wc-live-C_FXEKPs.js → wc-live-BM77caIc.js} +5 -5
- package/dist/ui/assets/{wc-nav-CQvxC63l.js → wc-nav-BRozp7W6.js} +2 -2
- package/dist/ui/assets/{wc-onboarding-DmXUKxBT.js → wc-onboarding-BT494emk.js} +2 -2
- package/dist/ui/assets/{wc-placeholder-B_loirHI.js → wc-placeholder-zgsjJZEf.js} +3 -3
- package/dist/ui/assets/{wc-settings-D_hfd5HZ.js → wc-settings-hKIoyp6i.js} +2 -2
- package/dist/ui/assets/{wc-shell-Hz6gftb-.js → wc-shell-CqewO6sV.js} +5 -5
- package/dist/ui/assets/{wc-sprinkles-CwjG2x5f.js → wc-sprinkles-BmbfRkwi.js} +2 -2
- package/dist/ui/assets/{wc-tray-C8EBociY.js → wc-tray-Dr8JSlyW.js} +3 -3
- package/dist/ui/assets/{xai-grok-Bcs5PCv3.js → xai-grok-C1e47-Eh.js} +1 -1
- package/dist/ui/assets/{xai-grok-DZtMI_Qj.js → xai-grok-DYvGZxFo.js} +1 -1
- package/dist/ui/index.html +2 -2
- package/dist/ui/packages/webapp/index.html +2 -2
- package/package.json +1 -1
- package/dist/ui/assets/dip-D8nk4YNm.js +0 -1
- package/dist/ui/assets/provider-store-access-BtyEXL2H.js +0 -1
- package/dist/ui/assets/provider-store-access-CW7DcuPJ.js +0 -1
- package/dist/ui/assets/session-freezer-DroVbUe6.js +0 -1
- package/dist/ui/assets/setup-sudo-DFOwnLKI.js +0 -1
|
@@ -74,4 +74,25 @@ export declare function bundleIndex(cfg: ConeConfig): ConeConfigIndex;
|
|
|
74
74
|
/** Portable base64 of a UTF-8 string (worker/browser/node all have btoa+TextEncoder). */
|
|
75
75
|
export declare function encodeBundleEnv(json: string): string;
|
|
76
76
|
export declare function decodeBundleEnv(b64: string): string;
|
|
77
|
+
/**
|
|
78
|
+
* Best-effort expiry (epoch ms) of an Adobe IMS access token, for stamping
|
|
79
|
+
* onto a synthesized Adobe `OAuthAccount.tokenExpiresAt`.
|
|
80
|
+
*
|
|
81
|
+
* Why it matters: a window-less kernel-worker cone must not treat a still-valid
|
|
82
|
+
* token as expired. The webapp's `getValidAccessToken` (providers/adobe.ts)
|
|
83
|
+
* returns the token only while `tokenExpiresAt` is in the future; otherwise it
|
|
84
|
+
* attempts a silent renewal that ALWAYS returns null in a worker (no `window`)
|
|
85
|
+
* and then throws "Adobe session expired". Without an expiry the account
|
|
86
|
+
* defaults to `tokenExpiresAt ?? 0`, so the very first turn fails. Every site
|
|
87
|
+
* that synthesizes an Adobe oauth account from a bare IMS bearer — node-server's
|
|
88
|
+
* legacy-token branch and the worker's back-compat + resume paths — must stamp
|
|
89
|
+
* this or reintroduce that failure mode.
|
|
90
|
+
*
|
|
91
|
+
* IMS access tokens are JWTs whose payload carries `created_at` + `expires_in`
|
|
92
|
+
* (both epoch ms). Returns `created_at + expires_in`, or `undefined` for opaque
|
|
93
|
+
* / unparseable tokens (callers then leave `tokenExpiresAt` unset — prior
|
|
94
|
+
* behavior). Side-effect- and dependency-free (`atob`, not `node:Buffer`) so it
|
|
95
|
+
* is safe to call from the CF Worker and the browser as well as node-server.
|
|
96
|
+
*/
|
|
97
|
+
export declare function imsTokenExpiry(token: string): number | undefined;
|
|
77
98
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cone-config/index.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,MAAM,OAAO,GAAG,YAAY,GAAG,aAAa,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,WAAW,EAAE,CAAA;KAAE,CAAC;IAC3D,MAAM,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC7D;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,WAAW,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3F,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,4EAA4E;AAC5E,eAAO,MAAM,qBAAqB,QAAa,CAAC;AAMhD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAS7D;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cone-config/index.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,MAAM,OAAO,GAAG,YAAY,GAAG,aAAa,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,WAAW,EAAE,CAAA;KAAE,CAAC;IAC3D,MAAM,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC7D;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,WAAW,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3F,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,4EAA4E;AAC5E,eAAO,MAAM,qBAAqB,QAAa,CAAC;AAMhD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAS7D;AAyGD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAWvE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,eAAe,GAAG,UAAU,CAYpF;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAOlE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAM7F;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,GAAG,eAAe,CAW5D;AAED,yFAAyF;AACzF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQpD;AACD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAInD;AAWD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAiBhE"}
|
|
@@ -83,6 +83,48 @@ function validateSecret(s) {
|
|
|
83
83
|
}
|
|
84
84
|
return { name: sec.name, value: sec.value, domains: sec.domains };
|
|
85
85
|
}
|
|
86
|
+
/** Validate the `upsert` arm of a resume delta (accounts/secrets reuse the full-bundle validators). */
|
|
87
|
+
function validateDeltaUpsert(input) {
|
|
88
|
+
if (!input || typeof input !== 'object') {
|
|
89
|
+
throw new Error('cone-config: delta.upsert must be an object');
|
|
90
|
+
}
|
|
91
|
+
const up = input;
|
|
92
|
+
const upsert = {};
|
|
93
|
+
if (up.accounts !== undefined) {
|
|
94
|
+
if (!Array.isArray(up.accounts)) {
|
|
95
|
+
throw new Error('cone-config: delta.upsert.accounts must be an array');
|
|
96
|
+
}
|
|
97
|
+
upsert.accounts = up.accounts.map((a) => validateAccount(a));
|
|
98
|
+
}
|
|
99
|
+
if (up.secrets !== undefined) {
|
|
100
|
+
if (!Array.isArray(up.secrets)) {
|
|
101
|
+
throw new Error('cone-config: delta.upsert.secrets must be an array');
|
|
102
|
+
}
|
|
103
|
+
upsert.secrets = up.secrets.map((s) => validateSecret(s));
|
|
104
|
+
}
|
|
105
|
+
return upsert;
|
|
106
|
+
}
|
|
107
|
+
/** Validate the `delete` arm of a resume delta (provider-id / secret-name string lists). */
|
|
108
|
+
function validateDeltaDelete(input) {
|
|
109
|
+
if (!input || typeof input !== 'object') {
|
|
110
|
+
throw new Error('cone-config: delta.delete must be an object');
|
|
111
|
+
}
|
|
112
|
+
const del = input;
|
|
113
|
+
const deletion = {};
|
|
114
|
+
if (del.providerIds !== undefined) {
|
|
115
|
+
if (!Array.isArray(del.providerIds) || !del.providerIds.every(isStr)) {
|
|
116
|
+
throw new Error('cone-config: delta.delete.providerIds must be string[]');
|
|
117
|
+
}
|
|
118
|
+
deletion.providerIds = del.providerIds;
|
|
119
|
+
}
|
|
120
|
+
if (del.secretNames !== undefined) {
|
|
121
|
+
if (!Array.isArray(del.secretNames) || !del.secretNames.every(isStr)) {
|
|
122
|
+
throw new Error('cone-config: delta.delete.secretNames must be string[]');
|
|
123
|
+
}
|
|
124
|
+
deletion.secretNames = del.secretNames;
|
|
125
|
+
}
|
|
126
|
+
return deletion;
|
|
127
|
+
}
|
|
86
128
|
/**
|
|
87
129
|
* Validate an untrusted resume delta (the worker receives it as `unknown`).
|
|
88
130
|
* Nested accounts/secrets go through the same validators as a full bundle, so a
|
|
@@ -99,46 +141,10 @@ export function validateConeConfigDelta(input) {
|
|
|
99
141
|
throw new Error('cone-config: delta.model must be a string');
|
|
100
142
|
out.model = d.model;
|
|
101
143
|
}
|
|
102
|
-
if (d.upsert !== undefined)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const up = d.upsert;
|
|
107
|
-
const upsert = {};
|
|
108
|
-
if (up.accounts !== undefined) {
|
|
109
|
-
if (!Array.isArray(up.accounts)) {
|
|
110
|
-
throw new Error('cone-config: delta.upsert.accounts must be an array');
|
|
111
|
-
}
|
|
112
|
-
upsert.accounts = up.accounts.map((a) => validateAccount(a));
|
|
113
|
-
}
|
|
114
|
-
if (up.secrets !== undefined) {
|
|
115
|
-
if (!Array.isArray(up.secrets)) {
|
|
116
|
-
throw new Error('cone-config: delta.upsert.secrets must be an array');
|
|
117
|
-
}
|
|
118
|
-
upsert.secrets = up.secrets.map((s) => validateSecret(s));
|
|
119
|
-
}
|
|
120
|
-
out.upsert = upsert;
|
|
121
|
-
}
|
|
122
|
-
if (d.delete !== undefined) {
|
|
123
|
-
if (!d.delete || typeof d.delete !== 'object') {
|
|
124
|
-
throw new Error('cone-config: delta.delete must be an object');
|
|
125
|
-
}
|
|
126
|
-
const del = d.delete;
|
|
127
|
-
const deletion = {};
|
|
128
|
-
if (del.providerIds !== undefined) {
|
|
129
|
-
if (!Array.isArray(del.providerIds) || !del.providerIds.every(isStr)) {
|
|
130
|
-
throw new Error('cone-config: delta.delete.providerIds must be string[]');
|
|
131
|
-
}
|
|
132
|
-
deletion.providerIds = del.providerIds;
|
|
133
|
-
}
|
|
134
|
-
if (del.secretNames !== undefined) {
|
|
135
|
-
if (!Array.isArray(del.secretNames) || !del.secretNames.every(isStr)) {
|
|
136
|
-
throw new Error('cone-config: delta.delete.secretNames must be string[]');
|
|
137
|
-
}
|
|
138
|
-
deletion.secretNames = del.secretNames;
|
|
139
|
-
}
|
|
140
|
-
out.delete = deletion;
|
|
141
|
-
}
|
|
144
|
+
if (d.upsert !== undefined)
|
|
145
|
+
out.upsert = validateDeltaUpsert(d.upsert);
|
|
146
|
+
if (d.delete !== undefined)
|
|
147
|
+
out.delete = validateDeltaDelete(d.delete);
|
|
142
148
|
return out;
|
|
143
149
|
}
|
|
144
150
|
export function mergeConeConfig(base, delta) {
|
|
@@ -207,3 +213,48 @@ export function decodeBundleEnv(b64) {
|
|
|
207
213
|
const bytes = Uint8Array.from(bin, (c) => c.charCodeAt(0));
|
|
208
214
|
return new TextDecoder().decode(bytes);
|
|
209
215
|
}
|
|
216
|
+
/** Decode a base64url segment (JWT alphabet) to a UTF-8 string. */
|
|
217
|
+
function decodeBase64Url(seg) {
|
|
218
|
+
// base64url → base64; atob (forgiving-base64) tolerates the missing padding.
|
|
219
|
+
const b64 = seg.replace(/-/g, '+').replace(/_/g, '/');
|
|
220
|
+
const bin = atob(b64);
|
|
221
|
+
const bytes = Uint8Array.from(bin, (c) => c.charCodeAt(0));
|
|
222
|
+
return new TextDecoder().decode(bytes);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Best-effort expiry (epoch ms) of an Adobe IMS access token, for stamping
|
|
226
|
+
* onto a synthesized Adobe `OAuthAccount.tokenExpiresAt`.
|
|
227
|
+
*
|
|
228
|
+
* Why it matters: a window-less kernel-worker cone must not treat a still-valid
|
|
229
|
+
* token as expired. The webapp's `getValidAccessToken` (providers/adobe.ts)
|
|
230
|
+
* returns the token only while `tokenExpiresAt` is in the future; otherwise it
|
|
231
|
+
* attempts a silent renewal that ALWAYS returns null in a worker (no `window`)
|
|
232
|
+
* and then throws "Adobe session expired". Without an expiry the account
|
|
233
|
+
* defaults to `tokenExpiresAt ?? 0`, so the very first turn fails. Every site
|
|
234
|
+
* that synthesizes an Adobe oauth account from a bare IMS bearer — node-server's
|
|
235
|
+
* legacy-token branch and the worker's back-compat + resume paths — must stamp
|
|
236
|
+
* this or reintroduce that failure mode.
|
|
237
|
+
*
|
|
238
|
+
* IMS access tokens are JWTs whose payload carries `created_at` + `expires_in`
|
|
239
|
+
* (both epoch ms). Returns `created_at + expires_in`, or `undefined` for opaque
|
|
240
|
+
* / unparseable tokens (callers then leave `tokenExpiresAt` unset — prior
|
|
241
|
+
* behavior). Side-effect- and dependency-free (`atob`, not `node:Buffer`) so it
|
|
242
|
+
* is safe to call from the CF Worker and the browser as well as node-server.
|
|
243
|
+
*/
|
|
244
|
+
export function imsTokenExpiry(token) {
|
|
245
|
+
const parts = token.split('.');
|
|
246
|
+
if (parts.length !== 3)
|
|
247
|
+
return undefined;
|
|
248
|
+
try {
|
|
249
|
+
const payload = JSON.parse(decodeBase64Url(parts[1]));
|
|
250
|
+
const created = Number(payload.created_at);
|
|
251
|
+
const ttl = Number(payload.expires_in);
|
|
252
|
+
if (Number.isFinite(created) && created > 0 && Number.isFinite(ttl) && ttl > 0) {
|
|
253
|
+
return created + ttl;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
// opaque / malformed token — leave expiry unset
|
|
258
|
+
}
|
|
259
|
+
return undefined;
|
|
260
|
+
}
|
|
@@ -15,6 +15,6 @@ export type { Registry } from './registry.js';
|
|
|
15
15
|
export { filterSecretsEnv } from './secrets-filter.js';
|
|
16
16
|
export * from './substrate.js';
|
|
17
17
|
export * from './substrate-factory.js';
|
|
18
|
-
export { createE2bSubstrate } from './substrates/e2b.js';
|
|
18
|
+
export { createE2bSubstrate, isSliccTemplate } from './substrates/e2b.js';
|
|
19
19
|
export * from './types.js';
|
|
20
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAQA,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC;AAC5B,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC/D,cAAc,cAAc,CAAC;AAC7B,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAQA,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC;AAC5B,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC/D,cAAc,cAAc,CAAC;AAC7B,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC1E,cAAc,YAAY,CAAC"}
|
|
@@ -16,5 +16,5 @@ export * from './polling.js';
|
|
|
16
16
|
export { filterSecretsEnv } from './secrets-filter.js';
|
|
17
17
|
export * from './substrate.js';
|
|
18
18
|
export * from './substrate-factory.js';
|
|
19
|
-
export { createE2bSubstrate } from './substrates/e2b.js';
|
|
19
|
+
export { createE2bSubstrate, isSliccTemplate } from './substrates/e2b.js';
|
|
20
20
|
export * from './types.js';
|
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
import type { SandboxSubstrate, SubstrateConfig } from '../substrate.js';
|
|
2
|
+
/**
|
|
3
|
+
* Does an e2b template alias belong to SLICC? `Sandbox.list` returns every
|
|
4
|
+
* sandbox on the team, so we filter by template alias (`info.name`) to ignore
|
|
5
|
+
* unrelated sandboxes. We match the `slicc` PREFIX, not exact `slicc`, so cones
|
|
6
|
+
* booted from an isolated test alias (e.g. `slicc-test`, built via
|
|
7
|
+
* SLICC_E2B_TEMPLATE_NAME) still appear in `--cloud list` instead of showing as
|
|
8
|
+
* `dead`. The undefined guard keeps a nameless sandbox from throwing.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isSliccTemplate(name: string | undefined): boolean;
|
|
2
11
|
export declare function createE2bSubstrate(cfg: SubstrateConfig): SandboxSubstrate;
|
|
3
12
|
//# sourceMappingURL=e2b.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"e2b.d.ts","sourceRoot":"","sources":["../../../src/substrates/e2b.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAKV,gBAAgB,EAChB,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAKzB,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,eAAe,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"e2b.d.ts","sourceRoot":"","sources":["../../../src/substrates/e2b.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAKV,gBAAgB,EAChB,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAKzB;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEjE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,eAAe,GAAG,gBAAgB,CA8DzE"}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { Sandbox } from 'e2b';
|
|
2
2
|
const DEFAULT_TTL_MS = 60 * 60 * 1000; // 1 hour
|
|
3
|
+
/**
|
|
4
|
+
* Does an e2b template alias belong to SLICC? `Sandbox.list` returns every
|
|
5
|
+
* sandbox on the team, so we filter by template alias (`info.name`) to ignore
|
|
6
|
+
* unrelated sandboxes. We match the `slicc` PREFIX, not exact `slicc`, so cones
|
|
7
|
+
* booted from an isolated test alias (e.g. `slicc-test`, built via
|
|
8
|
+
* SLICC_E2B_TEMPLATE_NAME) still appear in `--cloud list` instead of showing as
|
|
9
|
+
* `dead`. The undefined guard keeps a nameless sandbox from throwing.
|
|
10
|
+
*/
|
|
11
|
+
export function isSliccTemplate(name) {
|
|
12
|
+
return name?.startsWith('slicc') ?? false;
|
|
13
|
+
}
|
|
3
14
|
export function createE2bSubstrate(cfg) {
|
|
4
15
|
// Capture apiKey locally to pass explicitly to every SDK call (worker-safe).
|
|
5
16
|
const apiKey = cfg.apiKey;
|
|
@@ -40,8 +51,9 @@ export function createE2bSubstrate(cfg) {
|
|
|
40
51
|
const page = await paginator.nextItems();
|
|
41
52
|
for (const info of page) {
|
|
42
53
|
// The SDK's `templateId` is the immutable hash (e.g. cjd0k6foq…);
|
|
43
|
-
// the alias
|
|
44
|
-
|
|
54
|
+
// the alias (`slicc`, `slicc-test`, …) is on `info.name`. Filter on
|
|
55
|
+
// the alias prefix so isolated test-template cones list too.
|
|
56
|
+
if (isSliccTemplate(info.name)) {
|
|
45
57
|
items.push({
|
|
46
58
|
sandboxId: info.sandboxId,
|
|
47
59
|
// Sandbox name (user-supplied `--name`) lives in metadata.
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { bundleIndex, bundleToFiles, decodeBundleEnv, encodeBundleEnv, MAX_CONE_CONFIG_BYTES, mergeConeConfig, serializeSecretsEnv, validateConeConfig, validateConeConfigDelta, } from '../../src/cone-config/index.js';
|
|
2
|
+
import { bundleIndex, bundleToFiles, decodeBundleEnv, encodeBundleEnv, imsTokenExpiry, MAX_CONE_CONFIG_BYTES, mergeConeConfig, serializeSecretsEnv, validateConeConfig, validateConeConfigDelta, } from '../../src/cone-config/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Build a fake Adobe IMS access token (JWT) with the given timing claims,
|
|
5
|
+
* using the portable base64url encoding that `imsTokenExpiry` decodes via
|
|
6
|
+
* `atob` (no node:Buffer — this helper runs in the CF Worker too).
|
|
7
|
+
*/
|
|
8
|
+
function fakeImsJwt(createdAt, expiresIn) {
|
|
9
|
+
const b64url = (o) => btoa(JSON.stringify(o)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
10
|
+
return [
|
|
11
|
+
b64url({ alg: 'RS256', typ: 'JWT' }),
|
|
12
|
+
b64url({ created_at: String(createdAt), expires_in: String(expiresIn), type: 'access_token' }),
|
|
13
|
+
'sig',
|
|
14
|
+
].join('.');
|
|
15
|
+
}
|
|
3
16
|
const base = {
|
|
4
17
|
model: 'anthropic:claude-opus-4-6',
|
|
5
18
|
accounts: [
|
|
@@ -117,3 +130,23 @@ describe('base64 env round-trip', () => {
|
|
|
117
130
|
expect(MAX_CONE_CONFIG_BYTES).toBeGreaterThan(0);
|
|
118
131
|
});
|
|
119
132
|
});
|
|
133
|
+
describe('imsTokenExpiry', () => {
|
|
134
|
+
it('returns created_at + expires_in for a JWT IMS token', () => {
|
|
135
|
+
expect(imsTokenExpiry(fakeImsJwt(1_780_000_000_000, 86_400_000))).toBe(1_780_000_000_000 + 86_400_000);
|
|
136
|
+
});
|
|
137
|
+
it('returns undefined for an opaque (non-JWT) token', () => {
|
|
138
|
+
expect(imsTokenExpiry('opaque-token')).toBeUndefined();
|
|
139
|
+
});
|
|
140
|
+
it('returns undefined when the JWT payload lacks timing claims', () => {
|
|
141
|
+
const b64url = (o) => btoa(JSON.stringify(o)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
142
|
+
const token = [b64url({ alg: 'RS256' }), b64url({ sub: 'x' }), 'sig'].join('.');
|
|
143
|
+
expect(imsTokenExpiry(token)).toBeUndefined();
|
|
144
|
+
});
|
|
145
|
+
it('returns undefined when timing claims are non-positive', () => {
|
|
146
|
+
expect(imsTokenExpiry(fakeImsJwt(0, 86_400_000))).toBeUndefined();
|
|
147
|
+
expect(imsTokenExpiry(fakeImsJwt(1_780_000_000_000, 0))).toBeUndefined();
|
|
148
|
+
});
|
|
149
|
+
it('returns undefined for a malformed base64 payload', () => {
|
|
150
|
+
expect(imsTokenExpiry('a.!!!notbase64!!!.c')).toBeUndefined();
|
|
151
|
+
});
|
|
152
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2b-substrate.test.d.ts","sourceRoot":"","sources":["../../tests/e2b-substrate.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { isSliccTemplate } from '../src/substrates/e2b.js';
|
|
3
|
+
describe('isSliccTemplate (e2b list alias filter)', () => {
|
|
4
|
+
it('matches the production slicc alias', () => {
|
|
5
|
+
expect(isSliccTemplate('slicc')).toBe(true);
|
|
6
|
+
});
|
|
7
|
+
it('matches isolated test aliases (slicc-test) so they list instead of showing dead', () => {
|
|
8
|
+
expect(isSliccTemplate('slicc-test')).toBe(true);
|
|
9
|
+
expect(isSliccTemplate('slicc-pr-1108')).toBe(true);
|
|
10
|
+
});
|
|
11
|
+
it('rejects unrelated team templates', () => {
|
|
12
|
+
expect(isSliccTemplate('base')).toBe(false);
|
|
13
|
+
expect(isSliccTemplate('not-slicc')).toBe(false);
|
|
14
|
+
});
|
|
15
|
+
it('rejects a nameless sandbox without throwing', () => {
|
|
16
|
+
expect(isSliccTemplate(undefined)).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
const VALID_SUBCOMMANDS = ['start', 'list', 'pause', 'resume', 'kill'];
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
const baseArgs = {
|
|
15
|
-
substrate: 'e2b',
|
|
16
|
-
};
|
|
2
|
+
/** Subcommands that accept a positional query (sandbox ID or name). */
|
|
3
|
+
function takesQuery(sub) {
|
|
4
|
+
return sub === 'pause' || sub === 'resume' || sub === 'kill';
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Parse the flag list that follows `--cloud <subcommand>` into a flat
|
|
8
|
+
* `BaseArgs` bag. The discriminated union is assembled later in
|
|
9
|
+
* `buildParsedArgs`; keeping the two phases separate holds each function's
|
|
10
|
+
* cognitive complexity under the biome cap.
|
|
11
|
+
*/
|
|
12
|
+
function parseBaseArgs(rest, sub) {
|
|
13
|
+
const baseArgs = { substrate: 'e2b' };
|
|
17
14
|
let i = 0;
|
|
18
15
|
while (i < rest.length) {
|
|
19
16
|
const a = rest[i];
|
|
@@ -23,15 +20,19 @@ export function parseCloudArgs(argv) {
|
|
|
23
20
|
else if (a === '--env-file') {
|
|
24
21
|
baseArgs.envFile = rest[++i];
|
|
25
22
|
}
|
|
23
|
+
else if (a === '--template') {
|
|
24
|
+
// Substrate template alias to launch from (default 'slicc'). Lets
|
|
25
|
+
// `--cloud start` boot an isolated test template (e.g. 'slicc-test')
|
|
26
|
+
// built via SLICC_E2B_TEMPLATE_NAME without touching production.
|
|
27
|
+
baseArgs.template = rest[++i];
|
|
28
|
+
}
|
|
26
29
|
else if (a === '--substrate') {
|
|
27
30
|
const v = rest[++i];
|
|
28
31
|
if (v !== 'e2b')
|
|
29
32
|
throw new Error(`unsupported substrate: ${v} (MVP only supports 'e2b')`);
|
|
30
33
|
baseArgs.substrate = v;
|
|
31
34
|
}
|
|
32
|
-
else if (!a.startsWith('--') &&
|
|
33
|
-
!baseArgs.query &&
|
|
34
|
-
(sub === 'pause' || sub === 'resume' || sub === 'kill')) {
|
|
35
|
+
else if (!a.startsWith('--') && !baseArgs.query && takesQuery(sub)) {
|
|
35
36
|
baseArgs.query = a;
|
|
36
37
|
}
|
|
37
38
|
else {
|
|
@@ -39,7 +40,17 @@ export function parseCloudArgs(argv) {
|
|
|
39
40
|
}
|
|
40
41
|
i++;
|
|
41
42
|
}
|
|
42
|
-
|
|
43
|
+
return baseArgs;
|
|
44
|
+
}
|
|
45
|
+
/** Require and return the positional query for the query-taking subcommands. */
|
|
46
|
+
function requireQuery(sub, query) {
|
|
47
|
+
if (!query) {
|
|
48
|
+
throw new Error(`${sub} requires a query argument (sandbox ID or name)`);
|
|
49
|
+
}
|
|
50
|
+
return query;
|
|
51
|
+
}
|
|
52
|
+
/** Assemble the discriminated union from the parsed flag bag. */
|
|
53
|
+
function buildParsedArgs(sub, baseArgs) {
|
|
43
54
|
switch (sub) {
|
|
44
55
|
case 'start':
|
|
45
56
|
return {
|
|
@@ -48,32 +59,39 @@ export function parseCloudArgs(argv) {
|
|
|
48
59
|
substrate: baseArgs.substrate,
|
|
49
60
|
name: baseArgs.name,
|
|
50
61
|
envFile: baseArgs.envFile,
|
|
62
|
+
template: baseArgs.template,
|
|
51
63
|
},
|
|
52
64
|
};
|
|
53
65
|
case 'list':
|
|
54
66
|
return { subcommand: 'list', args: { substrate: baseArgs.substrate } };
|
|
55
67
|
case 'pause':
|
|
56
68
|
case 'kill':
|
|
57
|
-
if (!baseArgs.query) {
|
|
58
|
-
throw new Error(`${sub} requires a query argument (sandbox ID or name)`);
|
|
59
|
-
}
|
|
60
69
|
return {
|
|
61
70
|
subcommand: sub,
|
|
62
|
-
args: { substrate: baseArgs.substrate, query: baseArgs.query },
|
|
71
|
+
args: { substrate: baseArgs.substrate, query: requireQuery(sub, baseArgs.query) },
|
|
63
72
|
};
|
|
64
73
|
case 'resume':
|
|
65
|
-
if (!baseArgs.query) {
|
|
66
|
-
throw new Error(`${sub} requires a query argument (sandbox ID or name)`);
|
|
67
|
-
}
|
|
68
74
|
return {
|
|
69
75
|
subcommand: 'resume',
|
|
70
76
|
args: {
|
|
71
77
|
substrate: baseArgs.substrate,
|
|
72
|
-
query: baseArgs.query,
|
|
78
|
+
query: requireQuery(sub, baseArgs.query),
|
|
73
79
|
envFile: baseArgs.envFile,
|
|
74
80
|
},
|
|
75
81
|
};
|
|
76
|
-
default:
|
|
77
|
-
throw new Error(`unknown subcommand: ${sub}`);
|
|
78
82
|
}
|
|
79
83
|
}
|
|
84
|
+
export function parseCloudArgs(argv) {
|
|
85
|
+
if (argv.includes('--hosted') && argv.includes('--cloud')) {
|
|
86
|
+
throw new Error('--cloud and --hosted are mutually exclusive');
|
|
87
|
+
}
|
|
88
|
+
const cloudIdx = argv.indexOf('--cloud');
|
|
89
|
+
if (cloudIdx === -1)
|
|
90
|
+
return null;
|
|
91
|
+
const sub = argv[cloudIdx + 1];
|
|
92
|
+
if (!sub || !VALID_SUBCOMMANDS.includes(sub)) {
|
|
93
|
+
throw new Error(`unknown subcommand: ${sub ?? '(none)'} (expected one of: ${VALID_SUBCOMMANDS.join(', ')})`);
|
|
94
|
+
}
|
|
95
|
+
const baseArgs = parseBaseArgs(argv.slice(cloudIdx + 2), sub);
|
|
96
|
+
return buildParsedArgs(sub, baseArgs);
|
|
97
|
+
}
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import type { SandboxSubstrate } from '../_cloud_core/src/index.js';
|
|
2
2
|
import { type SandboxHandle, type StartResult } from '../_cloud_core/src/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* CLI poll budget for `/tmp/slicc-join.json` to appear after sandbox create.
|
|
5
|
+
*
|
|
6
|
+
* cloud-core defaults this to 60s, which is too tight for a COLD boot of the
|
|
7
|
+
* hosted-leader image: start.sh budgets chromium cold-start alone at 60s
|
|
8
|
+
* (SLICC_CDP_LAUNCH_TIMEOUT_MS), and node boot + tray registration push the
|
|
9
|
+
* observed first-boot time to ~50-70s. The 60s default loses that race on the
|
|
10
|
+
* coldest (first-after-build) boot, surfacing as a spurious SANDBOX_NOT_READY.
|
|
11
|
+
*
|
|
12
|
+
* The worker path deliberately keeps the tighter 60s default (its request is
|
|
13
|
+
* wall-clock-constrained by the dashboard fetch / CF edge), but a laptop CLI
|
|
14
|
+
* can afford to wait — so we give it generous headroom here.
|
|
15
|
+
*/
|
|
16
|
+
export declare const CLI_START_POLL_TIMEOUT_MS = 180000;
|
|
3
17
|
export interface RunStartOpts {
|
|
4
18
|
substrate: SandboxSubstrate;
|
|
5
19
|
envFilePath: string;
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs';
|
|
2
2
|
import { startCone } from '../_cloud_core/src/index.js';
|
|
3
3
|
import { FileRegistry } from './registry-file.js';
|
|
4
|
+
/**
|
|
5
|
+
* CLI poll budget for `/tmp/slicc-join.json` to appear after sandbox create.
|
|
6
|
+
*
|
|
7
|
+
* cloud-core defaults this to 60s, which is too tight for a COLD boot of the
|
|
8
|
+
* hosted-leader image: start.sh budgets chromium cold-start alone at 60s
|
|
9
|
+
* (SLICC_CDP_LAUNCH_TIMEOUT_MS), and node boot + tray registration push the
|
|
10
|
+
* observed first-boot time to ~50-70s. The 60s default loses that race on the
|
|
11
|
+
* coldest (first-after-build) boot, surfacing as a spurious SANDBOX_NOT_READY.
|
|
12
|
+
*
|
|
13
|
+
* The worker path deliberately keeps the tighter 60s default (its request is
|
|
14
|
+
* wall-clock-constrained by the dashboard fetch / CF edge), but a laptop CLI
|
|
15
|
+
* can afford to wait — so we give it generous headroom here.
|
|
16
|
+
*/
|
|
17
|
+
export const CLI_START_POLL_TIMEOUT_MS = 180_000;
|
|
4
18
|
/**
|
|
5
19
|
* Extract ADOBE_IMS_TOKEN (+ DOMAINS) from an env-file body so they can be
|
|
6
20
|
* injected as sandbox env vars at Sandbox.create. start.sh writes them to
|
|
@@ -40,7 +54,7 @@ export async function runStart(opts) {
|
|
|
40
54
|
template: opts.template,
|
|
41
55
|
name: opts.name,
|
|
42
56
|
sliccVersion: opts.sliccVersion,
|
|
43
|
-
pollTimeoutMs: opts.pollTimeoutMs,
|
|
57
|
+
pollTimeoutMs: opts.pollTimeoutMs ?? CLI_START_POLL_TIMEOUT_MS,
|
|
44
58
|
pollIntervalMs: opts.pollIntervalMs,
|
|
45
59
|
metadata: {
|
|
46
60
|
createdBy: process.env['USER'] ?? 'unknown',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Account, imsTokenExpiry } from './_cloud_core/src/index.js';
|
|
2
2
|
import type { Express } from 'express';
|
|
3
3
|
import type { SecretStore } from './secrets/types.js';
|
|
4
|
+
export { imsTokenExpiry };
|
|
4
5
|
export interface HostedBootstrapPayload {
|
|
5
6
|
model?: string;
|
|
6
7
|
accounts?: Account[];
|
|
@@ -14,7 +14,15 @@
|
|
|
14
14
|
* orchestrator talks to the leader through the tray-worker tunnel, not http.
|
|
15
15
|
*/
|
|
16
16
|
import { readFileSync } from 'node:fs';
|
|
17
|
+
// Import from the package root (not the './cone-config' subpath): node-server's
|
|
18
|
+
// inline-workspaces packaging only rewrites the bare '@slicc/cloud-core'
|
|
19
|
+
// specifier, so a subpath import leaks an un-inlined workspace reference.
|
|
20
|
+
import { imsTokenExpiry } from './_cloud_core/src/index.js';
|
|
17
21
|
import { requireLoopback } from './cloud-status.js';
|
|
22
|
+
// Re-export so existing callers/tests can keep importing it from here. The
|
|
23
|
+
// implementation now lives in @slicc/cloud-core/cone-config (side-effect-free,
|
|
24
|
+
// Buffer-free) so the worker's back-compat + resume paths reuse the same logic.
|
|
25
|
+
export { imsTokenExpiry };
|
|
18
26
|
const CONE_CONFIG_PATH = '/slicc/cone-config.json';
|
|
19
27
|
const DEFAULT_MODEL = 'adobe:claude-opus-4-6';
|
|
20
28
|
export function buildHostedBootstrapPayload(sources) {
|
|
@@ -25,9 +33,17 @@ export function buildHostedBootstrapPayload(sources) {
|
|
|
25
33
|
}
|
|
26
34
|
const legacy = sources.getLegacyAdobeToken();
|
|
27
35
|
if (legacy) {
|
|
36
|
+
const expiresAt = imsTokenExpiry(legacy);
|
|
28
37
|
return {
|
|
29
38
|
model: DEFAULT_MODEL,
|
|
30
|
-
accounts: [
|
|
39
|
+
accounts: [
|
|
40
|
+
{
|
|
41
|
+
providerId: 'adobe',
|
|
42
|
+
kind: 'oauth',
|
|
43
|
+
accessToken: legacy,
|
|
44
|
+
...(expiresAt !== undefined ? { tokenExpiresAt: expiresAt } : {}),
|
|
45
|
+
},
|
|
46
|
+
],
|
|
31
47
|
adobeImsToken: legacy,
|
|
32
48
|
};
|
|
33
49
|
}
|
|
@@ -1360,6 +1360,7 @@ async function runCloudSubcommand(parsed) {
|
|
|
1360
1360
|
workerBaseUrl: process.env['SLICC_TRAY_WORKER_BASE_URL']?.trim() || 'https://www.sliccy.ai',
|
|
1361
1361
|
sliccVersion: localSliccVersion,
|
|
1362
1362
|
name: parsed.args.name,
|
|
1363
|
+
template: parsed.args.template,
|
|
1363
1364
|
});
|
|
1364
1365
|
console.log(`Sandbox ${result.sandboxId} ready.`);
|
|
1365
1366
|
console.log(`Open: ${result.joinUrl}`);
|