deepline 0.3.409 → 0.3.411
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/bundling-sources/sdk/src/agent-runtime.ts +18 -1
- package/dist/bundling-sources/sdk/src/client.ts +206 -333
- package/dist/bundling-sources/sdk/src/compat.ts +45 -2
- package/dist/bundling-sources/sdk/src/db/query.ts +9 -10
- package/dist/bundling-sources/sdk/src/http.ts +38 -20
- package/dist/bundling-sources/sdk/src/index.ts +4 -5
- package/dist/bundling-sources/sdk/src/play.ts +10 -10
- package/dist/bundling-sources/sdk/src/plays/bundle-play-file.ts +6 -4
- package/dist/bundling-sources/sdk/src/plays/check-local-play-graph.ts +114 -0
- package/dist/bundling-sources/sdk/src/plays/client.ts +431 -0
- package/dist/bundling-sources/sdk/src/plays/local-play-execution.ts +2 -2
- package/dist/bundling-sources/sdk/src/plays/run-request.ts +106 -16
- package/dist/bundling-sources/sdk/src/release.ts +13 -7
- package/dist/bundling-sources/sdk/src/runs/read-errors.ts +8 -0
- package/dist/bundling-sources/sdk/src/runs/watch-polling.ts +124 -13
- package/dist/bundling-sources/sdk/src/tool-calls.ts +108 -19
- package/dist/bundling-sources/sdk/src/types.ts +18 -0
- package/dist/bundling-sources/shared_libs/integration-contracts/execute-retry-contract.ts +37 -0
- package/dist/bundling-sources/shared_libs/integration-contracts/package.json +3 -0
- package/dist/bundling-sources/shared_libs/monitors/package.json +1 -1
- package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +3 -1
- package/dist/bundling-sources/shared_libs/play-runtime/async-operation.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +277 -76
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/dataset-row-input.ts +124 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +6 -62
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durable-tool-identity.ts +67 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execute-server-timing.ts +64 -6
- package/dist/bundling-sources/shared_libs/play-runtime/freshness-receipt-execution.ts +1 -5
- package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-artifact-runtime-contract.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-http-request.ts +10 -0
- package/dist/bundling-sources/shared_libs/play-runtime/query-result-dataset.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/egress-probe.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +26 -16
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-heartbeat.ts +36 -11
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-terminal-push.ts +35 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +21 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +21 -6
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +11 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +85 -20
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +71 -13
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-execution-queries.ts +100 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-pool.ts +9 -5
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +337 -146
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +26 -12
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +3 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +425 -102
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-dispatch-authority.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +181 -124
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-worker-wake.ts +152 -0
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +5 -3
- package/dist/bundling-sources/shared_libs/play-runtime/tool-cache-policy.ts +31 -0
- package/dist/bundling-sources/shared_libs/play-runtime/transient-service-error.ts +10 -0
- package/dist/bundling-sources/shared_libs/plays/ambiguous-write-error.ts +25 -0
- package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +4 -0
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +63 -68
- package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +129 -63
- package/dist/bundling-sources/shared_libs/plays/contracts.ts +14 -0
- package/dist/bundling-sources/shared_libs/plays/enrich-play-compiler.ts +58 -16
- package/dist/bundling-sources/shared_libs/plays/fetch-http-error.ts +50 -0
- package/dist/bundling-sources/shared_libs/plays/source-authoring-edition.ts +351 -0
- package/dist/bundling-sources/shared_libs/plays/tool-list-getter-mode.ts +9 -0
- package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +1 -1
- package/dist/cli/auth-M7TBLW55.js +40 -0
- package/dist/cli/{auth-5HIIACF7.mjs → auth-YD6ZTMB2.mjs} +6 -6
- package/dist/cli/{billing-4275N7FL.js → billing-2L3MOB42.js} +84 -84
- package/dist/cli/{billing-EVZ3ZWKC.mjs → billing-ZT46GV4C.mjs} +8 -8
- package/dist/cli/{chunk-ZAAKSJAS.js → chunk-27GJKC5Q.js} +17 -10
- package/dist/cli/{chunk-UHNDVD3P.js → chunk-2H4EY7KH.js} +100 -41
- package/dist/cli/{chunk-GAICVLKL.js → chunk-2NI6DHN7.js} +2 -2
- package/dist/cli/{chunk-JGHG4NBA.js → chunk-2WUY3VNK.js} +19 -4
- package/dist/cli/{chunk-FHPCKULR.mjs → chunk-4BA6ATHA.mjs} +2 -2
- package/dist/cli/{chunk-RTCDW2GU.js → chunk-4O4WNFFC.js} +170 -49
- package/dist/cli/{chunk-OSDXE27V.mjs → chunk-4PG4ARL2.mjs} +17 -10
- package/dist/cli/{chunk-AU4OFDFX.js → chunk-5IGDNBG7.js} +26 -26
- package/dist/cli/{chunk-WYQO2CBS.mjs → chunk-5LRWWMRV.mjs} +149 -28
- package/dist/cli/{chunk-PMVFAYL7.mjs → chunk-63ILLN5H.mjs} +2 -2
- package/dist/cli/chunk-6AUE6JXY.js +35 -0
- package/dist/cli/chunk-7DSMMCXP.js +501 -0
- package/dist/cli/{chunk-6BJK4EJ3.mjs → chunk-AARWVK4C.mjs} +2132 -65
- package/dist/cli/{chunk-FERRDNMO.js → chunk-AD47BXN2.js} +5 -5
- package/dist/cli/{chunk-J6DCKJNM.mjs → chunk-BJV3VSKE.mjs} +16 -1
- package/dist/cli/{chunk-S6R3OX7B.js → chunk-E4CABWXL.js} +25 -2
- package/dist/cli/{chunk-NXGCO4JB.mjs → chunk-E4IXDAZI.mjs} +5 -0
- package/dist/cli/{chunk-BEVLCKXG.mjs → chunk-E4KBNNNB.mjs} +1 -1
- package/dist/cli/{chunk-2PRO2JTX.mjs → chunk-E52TKKVI.mjs} +36 -284
- package/dist/cli/chunk-FR2ILQ4G.mjs +8 -0
- package/dist/cli/{chunk-2GI3QD3L.js → chunk-FRVPOXGB.js} +644 -330
- package/dist/cli/chunk-G43JLBDE.mjs +501 -0
- package/dist/cli/{chunk-BZAMOCPA.mjs → chunk-IMZ56EOH.mjs} +3 -3
- package/dist/cli/chunk-IPGV6VFA.mjs +6084 -0
- package/dist/cli/{chunk-IT3XBJQR.mjs → chunk-IR3AKJAY.mjs} +330 -625
- package/dist/cli/chunk-J33TSWO5.js +8 -0
- package/dist/cli/chunk-JQMZUWNM.mjs +35 -0
- package/dist/cli/chunk-JYHSEGRM.js +6084 -0
- package/dist/cli/{chunk-JI2B4RZP.mjs → chunk-KCC3FKIW.mjs} +71 -12
- package/dist/cli/{chunk-6IKARAYD.mjs → chunk-L2VKAASU.mjs} +23 -0
- package/dist/cli/{chunk-O3VSXP2F.js → chunk-LWBM5FFL.js} +50 -50
- package/dist/cli/{chunk-VWBTTJYQ.mjs → chunk-M6OASCVL.mjs} +6 -3
- package/dist/cli/{chunk-YHPYUZZX.mjs → chunk-MAMVGOSC.mjs} +1 -1
- package/dist/cli/{chunk-Q2E4E4FJ.js → chunk-NPBJI7RE.js} +8 -8
- package/dist/cli/chunk-NQWIZ5PZ.js +313 -0
- package/dist/cli/{chunk-HQXL5526.mjs → chunk-NUX2QHNC.mjs} +1 -1
- package/dist/cli/{chunk-TQNHMWUR.mjs → chunk-OGSXENOF.mjs} +5 -2
- package/dist/cli/{chunk-SEFMGO3Z.js → chunk-OQQOXSYA.js} +2184 -117
- package/dist/cli/{chunk-FJCIUF34.js → chunk-OZSC6CEW.js} +128 -376
- package/dist/cli/{chunk-NZSF57UO.mjs → chunk-PO2VU6WV.mjs} +2 -2
- package/dist/cli/{chunk-7P5AA3SN.js → chunk-PPDBRJRW.js} +6 -1
- package/dist/cli/{chunk-ILHRA7AD.js → chunk-QADCFSGH.js} +7 -7
- package/dist/cli/{chunk-N44JHMKY.mjs → chunk-RFES6Q2J.mjs} +452 -138
- package/dist/cli/{chunk-DEC3JECC.js → chunk-RMINBDYY.js} +5 -2
- package/dist/cli/{chunk-WLOCMJWV.js → chunk-TPFD4F5S.js} +426 -721
- package/dist/cli/{chunk-V76R6HMV.js → chunk-U5AQKE3T.js} +1029 -806
- package/dist/cli/{chunk-PBZYY7VZ.mjs → chunk-UAEVKAUR.mjs} +734 -511
- package/dist/cli/{chunk-WHG43Z67.js → chunk-VGHWJL4W.js} +11 -8
- package/dist/cli/chunk-VKKVSFRD.js +62 -0
- package/dist/cli/{chunk-GSK6NHVM.js → chunk-WU4U6VSB.js} +5 -5
- package/dist/cli/chunk-XAB47ZRV.mjs +313 -0
- package/dist/cli/{chunk-JRAVVJ3T.mjs → chunk-XJD6LZCO.mjs} +2 -2
- package/dist/cli/chunk-ZCALLYF6.mjs +62 -0
- package/dist/cli/{chunk-YD7B53RW.js → chunk-ZHWBU36H.js} +12 -12
- package/dist/cli/{csv-A2MP6EFV.mjs → csv-BKNRRW7D.mjs} +5 -5
- package/dist/cli/{csv-BBOTCGQY.js → csv-SVDP2EU7.js} +14 -14
- package/dist/cli/{db-3W5DMTUX.mjs → db-LU4KLRM6.mjs} +15 -20
- package/dist/cli/{db-G4CODDCA.js → db-OQ6S7TTZ.js} +42 -47
- package/dist/cli/{describe-PQTQ5B6F.js → describe-45TGETKR.js} +27 -22
- package/dist/cli/{describe-XYJ2ZT4M.mjs → describe-U4KOGDRA.mjs} +20 -15
- package/dist/cli/describe-core.d.mts +2 -2
- package/dist/cli/describe-core.d.ts +2 -2
- package/dist/cli/describe-core.js +6 -6
- package/dist/cli/describe-core.mjs +5 -5
- package/dist/cli/{executions-UR67CA5H.mjs → executions-2GAAUXLA.mjs} +8 -8
- package/dist/cli/{executions-TLANVR7Y.js → executions-VZN56VRC.js} +10 -10
- package/dist/cli/{feedback-6C2YTRJL.js → feedback-NS76B5GU.js} +13 -9
- package/dist/cli/{feedback-WHCMGEIL.mjs → feedback-XW5IWA5R.mjs} +11 -7
- package/dist/cli/{git-GWLB6VSA.mjs → git-CLI66XP6.mjs} +6 -6
- package/dist/cli/git-VGYRGFEN.js +24 -0
- package/dist/cli/index.js +236 -348
- package/dist/cli/index.mjs +162 -274
- package/dist/cli/{legacy-noops-ZUFA7RWI.js → legacy-noops-HCFB3ZOV.js} +9 -9
- package/dist/cli/{legacy-noops-KF4XIFEF.mjs → legacy-noops-ODDOMLBL.mjs} +6 -6
- package/dist/cli/{monitors-TB3K2IVE.js → monitors-7WXQ7JFT.js} +94 -94
- package/dist/cli/{monitors-6UOIDIMB.mjs → monitors-ZXX456TE.mjs} +8 -8
- package/dist/cli/{org-CKWMBPIR.js → org-YLX5PHBQ.js} +68 -68
- package/dist/cli/{org-WGHHMVDZ.mjs → org-YUN3TLNP.mjs} +8 -8
- package/dist/cli/{play-LYPAXCLD.mjs → play-LL73A7EP.mjs} +533 -98
- package/dist/cli/{play-N2B3KAVS.js → play-YGOXL52D.js} +1067 -632
- package/dist/cli/{providers-6DI5BVZJ.mjs → providers-35QSAUHL.mjs} +8 -8
- package/dist/cli/{providers-UR42MD6Z.js → providers-RHCIU2PX.js} +11 -11
- package/dist/cli/{quickstart-MNA2S6PO.mjs → quickstart-6BN3LCZH.mjs} +5 -5
- package/dist/cli/{quickstart-FCJG4XGB.js → quickstart-ORMM4NRK.js} +7 -7
- package/dist/cli/search-EWDMUPHR.js +30 -0
- package/dist/cli/{search-VPPYUJ2M.mjs → search-GAERWLSE.mjs} +9 -9
- package/dist/cli/{secrets-QOSMVO36.js → secrets-3AFCTGT7.js} +17 -17
- package/dist/cli/{secrets-DRI4W7Z5.mjs → secrets-FCL5PALY.mjs} +8 -8
- package/dist/cli/sessions-3OEHEQG7.js +16 -0
- package/dist/cli/{sessions-DQNUKP43.mjs → sessions-RSSL7I7O.mjs} +6 -6
- package/dist/cli/{settings-DWDK3Y2R.mjs → settings-GE4NRE7Y.mjs} +12 -12
- package/dist/cli/{settings-JUGGCOPS.js → settings-RX5K4I7H.js} +79 -79
- package/dist/cli/{setup-AWBHNYXK.js → setup-N3ZNAEL5.js} +45 -44
- package/dist/cli/{setup-D5DWVNY4.mjs → setup-X3RXGG4F.mjs} +11 -10
- package/dist/cli/{skills-YV2XR35J.mjs → skills-5JEAJBDE.mjs} +7 -7
- package/dist/cli/skills-VAAQVEQC.js +29 -0
- package/dist/cli/tools-BYYOT2DU.js +44 -0
- package/dist/cli/{tools-VFJYHNV2.mjs → tools-JOKUWEBZ.mjs} +19 -14
- package/dist/cli/update-36G4ZD7B.js +31 -0
- package/dist/cli/{update-IM6VOTGL.mjs → update-UBHEVFR3.mjs} +11 -9
- package/dist/cli/{workflow-26URBWPV.mjs → workflow-FR6EXAXF.mjs} +44 -20
- package/dist/cli/{workflow-3BS6U6SL.js → workflow-SZAVOHN6.js} +54 -30
- package/dist/{client-BfInrZPB.d.mts → client-74k4IPh6.d.mts} +135 -54
- package/dist/{client-BMjJFpan.d.ts → client-C1IK1f8c.d.ts} +135 -54
- package/dist/{compiler-manifest-Ycx-hoAr.d.mts → compiler-manifest-lzWpbV3w.d.mts} +83 -66
- package/dist/{compiler-manifest-Ycx-hoAr.d.ts → compiler-manifest-lzWpbV3w.d.ts} +83 -66
- package/dist/{index-CZXgiN3E.d.mts → index-C8Cy-YTm.d.ts} +5 -1
- package/dist/{index-NPG5pqxQ.d.ts → index-CtNK-0nI.d.mts} +5 -1
- package/dist/index.d.mts +47 -9
- package/dist/index.d.ts +47 -9
- package/dist/index.js +17 -14
- package/dist/index.mjs +13 -10
- package/dist/install-integrity.json +118 -102
- package/dist/plays/bundle-play-file.d.mts +3 -3
- package/dist/plays/bundle-play-file.d.ts +3 -3
- package/dist/plays/bundle-play-file.mjs +5 -4
- package/dist/plays/csv-data-input.js +3 -3
- package/dist/plays/csv-data-input.mjs +2 -2
- package/dist/plays/play-description.d.mts +2 -2
- package/dist/plays/play-description.d.ts +2 -2
- package/dist/plays/run-request.d.mts +2 -2
- package/dist/plays/run-request.d.ts +2 -2
- package/dist/plays/run-request.js +11 -3
- package/dist/plays/run-request.mjs +10 -2
- package/dist/release.d.mts +15 -6
- package/dist/release.d.ts +15 -6
- package/dist/release.js +2 -2
- package/dist/release.mjs +1 -1
- package/package.json +2 -2
- package/dist/cli/auth-F6BX32XZ.js +0 -40
- package/dist/cli/chunk-264PC2RN.mjs +0 -83
- package/dist/cli/chunk-44ZTYHMQ.mjs +0 -155
- package/dist/cli/chunk-53HN7WZN.js +0 -392
- package/dist/cli/chunk-7AALNGTA.mjs +0 -392
- package/dist/cli/chunk-ALD4COBH.js +0 -155
- package/dist/cli/chunk-CLJGSOVM.mjs +0 -1716
- package/dist/cli/chunk-WNUR6VP5.js +0 -83
- package/dist/cli/chunk-Z4VNJOF7.js +0 -1716
- package/dist/cli/git-VQFF6D7C.js +0 -24
- package/dist/cli/search-NCEEONMQ.js +0 -30
- package/dist/cli/sessions-3WYKQABW.js +0 -16
- package/dist/cli/skills-AKPAJVSO.js +0 -29
- package/dist/cli/tools-RBKEK6PM.js +0 -39
- package/dist/cli/update-VFNUBLDA.js +0 -29
|
@@ -76,6 +76,7 @@ export type SdkCompatibilitySkillsUpdate = {
|
|
|
76
76
|
};
|
|
77
77
|
|
|
78
78
|
const CHECK_TIMEOUT_MS = 2_000;
|
|
79
|
+
const SDK_CLI_AUTO_UPDATE_CAPABILITY = 'safe-continuation-v1';
|
|
79
80
|
/**
|
|
80
81
|
* A cached clean policy younger than this is trusted outright: the command
|
|
81
82
|
* runs without a live request. Policy floors move on a release cadence; the
|
|
@@ -132,12 +133,14 @@ function shouldSkipCompatibilityCheck(): boolean {
|
|
|
132
133
|
|
|
133
134
|
export function sdkCompatibilityCachePath(
|
|
134
135
|
baseUrl: string,
|
|
135
|
-
homeDir = homedir(),
|
|
136
|
+
homeDir = process.env.HOME?.trim() || homedir(),
|
|
136
137
|
): string {
|
|
137
138
|
return join(sdkCliStateDirPath(baseUrl, homeDir), 'compat-cache.json');
|
|
138
139
|
}
|
|
139
140
|
|
|
140
|
-
function legacySdkCompatibilityCachePath(
|
|
141
|
+
function legacySdkCompatibilityCachePath(
|
|
142
|
+
homeDir = process.env.HOME?.trim() || homedir(),
|
|
143
|
+
): string {
|
|
141
144
|
return join(homeDir, '.cache', 'deepline', 'sdk-compat-cache.json');
|
|
142
145
|
}
|
|
143
146
|
|
|
@@ -229,6 +232,36 @@ function isSavedWithin(savedAt: unknown, windowMs: number, now: number) {
|
|
|
229
232
|
return Number.isFinite(age) && age >= 0 && age <= windowMs;
|
|
230
233
|
}
|
|
231
234
|
|
|
235
|
+
const UPDATE_ADVISORY_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* True when the optional "update available" / "deprecated" notice is due for
|
|
239
|
+
* this host: at most once a day, so a loop of commands prints it once rather
|
|
240
|
+
* than once per iteration. A state directory that cannot be written repeats
|
|
241
|
+
* the notice instead of hiding it.
|
|
242
|
+
*/
|
|
243
|
+
export function claimUpdateAdvisory(
|
|
244
|
+
baseUrl: string,
|
|
245
|
+
now = Date.now(),
|
|
246
|
+
): boolean {
|
|
247
|
+
const path = join(sdkCliStateDirPath(baseUrl), 'update-advisory.json');
|
|
248
|
+
try {
|
|
249
|
+
const { shownAt } = JSON.parse(readFileSync(path, 'utf8')) as {
|
|
250
|
+
shownAt?: unknown;
|
|
251
|
+
};
|
|
252
|
+
if (isSavedWithin(shownAt, UPDATE_ADVISORY_INTERVAL_MS, now)) return false;
|
|
253
|
+
} catch {
|
|
254
|
+
// No marker yet, or an unreadable one: the notice is due.
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
258
|
+
writeFileSync(path, `${JSON.stringify({ shownAt: now })}\n`);
|
|
259
|
+
} catch {
|
|
260
|
+
// Read-only state directory.
|
|
261
|
+
}
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
|
|
232
265
|
function readCachedCompatibility(
|
|
233
266
|
baseUrl: string,
|
|
234
267
|
command: string | null | undefined,
|
|
@@ -348,6 +381,8 @@ export async function checkSdkCompatibility(
|
|
|
348
381
|
/** Optional read-only catalog result carried by the same live check. */
|
|
349
382
|
catalog?: {
|
|
350
383
|
toolId: string;
|
|
384
|
+
cliInvocationId?: string;
|
|
385
|
+
purpose?: 'execution_warnings';
|
|
351
386
|
acceptMetadata: (metadata: unknown) => void;
|
|
352
387
|
};
|
|
353
388
|
} = {},
|
|
@@ -378,6 +413,9 @@ export async function checkSdkCompatibility(
|
|
|
378
413
|
}
|
|
379
414
|
if (options.catalog) {
|
|
380
415
|
url.searchParams.set('catalog_tool_id', options.catalog.toolId);
|
|
416
|
+
if (options.catalog.purpose) {
|
|
417
|
+
url.searchParams.set('catalog_purpose', options.catalog.purpose);
|
|
418
|
+
}
|
|
381
419
|
}
|
|
382
420
|
const response = await fetch(url, {
|
|
383
421
|
method: 'GET',
|
|
@@ -388,9 +426,13 @@ export async function checkSdkCompatibility(
|
|
|
388
426
|
'X-Deepline-API-Major': String(SDK_API_MAJOR),
|
|
389
427
|
'X-Deepline-API-Contract': SDK_API_CONTRACT,
|
|
390
428
|
'X-Deepline-CLI-Update-Preferences': '1',
|
|
429
|
+
'X-Deepline-CLI-Auto-Update-Capability': SDK_CLI_AUTO_UPDATE_CAPABILITY,
|
|
391
430
|
...(options.catalog
|
|
392
431
|
? { Authorization: `Bearer ${resolveApiKeyForBaseUrl(baseUrl)}` }
|
|
393
432
|
: {}),
|
|
433
|
+
...(options.catalog?.cliInvocationId
|
|
434
|
+
? { 'X-Deepline-CLI-Invocation-ID': options.catalog.cliInvocationId }
|
|
435
|
+
: {}),
|
|
394
436
|
},
|
|
395
437
|
signal: controller.signal,
|
|
396
438
|
});
|
|
@@ -416,6 +458,7 @@ export async function checkSdkCompatibility(
|
|
|
416
458
|
);
|
|
417
459
|
}
|
|
418
460
|
if (
|
|
461
|
+
data.ok &&
|
|
419
462
|
options.catalog &&
|
|
420
463
|
catalogMetadata &&
|
|
421
464
|
typeof catalogMetadata === 'object' &&
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from '../errors';
|
|
5
|
-
import type { HttpClient } from '../http';
|
|
6
|
-
import type { CustomerDbQueryResult } from '../types';
|
|
1
|
+
import { CustomerDbQueryOutcomeUnknownError, DeeplineError } from '../errors';
|
|
2
|
+
import type { HttpClient } from '../http.js';
|
|
3
|
+
import type { CustomerDbQueryResult } from '../types.js';
|
|
7
4
|
|
|
8
5
|
export type CustomerDbQueryOptions = {
|
|
9
6
|
sql: string;
|
|
@@ -24,12 +21,13 @@ export type CustomerDbQueryPlan = {
|
|
|
24
21
|
creditSpending: 'none';
|
|
25
22
|
recovery: 'original_operation_key' | 'unkeyed_unknown_outcome';
|
|
26
23
|
};
|
|
27
|
-
transport: { maxRetries:
|
|
24
|
+
transport: { maxRetries: number; urlFailover: 'disabled' | 'loopback_only' };
|
|
28
25
|
};
|
|
29
26
|
|
|
30
27
|
/** Validate and describe SQL execution without sending it. */
|
|
31
28
|
export function planCustomerDbQuery(
|
|
32
29
|
input: CustomerDbQueryOptions,
|
|
30
|
+
maxRetries = 3,
|
|
33
31
|
): CustomerDbQueryPlan {
|
|
34
32
|
if (typeof input.sql !== 'string' || !input.sql.trim())
|
|
35
33
|
throw new DeeplineError('sql must not be empty.', 400, 'INVALID_SQL');
|
|
@@ -87,8 +85,8 @@ export function planCustomerDbQuery(
|
|
|
87
85
|
: 'original_operation_key',
|
|
88
86
|
},
|
|
89
87
|
transport: {
|
|
90
|
-
maxRetries: 0,
|
|
91
|
-
urlFailover: 'disabled',
|
|
88
|
+
maxRetries: operationKey === undefined ? 0 : maxRetries,
|
|
89
|
+
urlFailover: operationKey === undefined ? 'disabled' : 'loopback_only',
|
|
92
90
|
},
|
|
93
91
|
};
|
|
94
92
|
}
|
|
@@ -96,8 +94,9 @@ export function planCustomerDbQuery(
|
|
|
96
94
|
export async function queryCustomerDatabase(
|
|
97
95
|
http: HttpClient,
|
|
98
96
|
input: CustomerDbQueryOptions,
|
|
97
|
+
maxRetries: number,
|
|
99
98
|
): Promise<CustomerDbQueryResult> {
|
|
100
|
-
const plan = planCustomerDbQuery(input);
|
|
99
|
+
const plan = planCustomerDbQuery(input, maxRetries);
|
|
101
100
|
let result: CustomerDbQueryResult;
|
|
102
101
|
try {
|
|
103
102
|
result = await http.post<CustomerDbQueryResult>(
|
|
@@ -54,6 +54,10 @@ import {
|
|
|
54
54
|
WORKER_CALLBACK_URL_OVERRIDE_HEADER,
|
|
55
55
|
} from '../../shared_libs/play-runtime/coordinator-headers.js';
|
|
56
56
|
import { PLAY_RUNTIME_TEST_FAULT_HEADER } from '../../shared_libs/play-runtime/test-runtime-seams.js';
|
|
57
|
+
import {
|
|
58
|
+
EXECUTE_RETRY_POLICY_HEADER,
|
|
59
|
+
parseExecuteRetryPolicy,
|
|
60
|
+
} from '../../shared_libs/integration-contracts/execute-retry-contract.js';
|
|
57
61
|
|
|
58
62
|
const MAX_DIAGNOSTIC_HEADER_LENGTH = 120;
|
|
59
63
|
const COWORK_NETWORK_HINT =
|
|
@@ -76,6 +80,10 @@ interface RequestOptions {
|
|
|
76
80
|
* most mutating API calls must fail loudly after the first server response.
|
|
77
81
|
*/
|
|
78
82
|
retryApiErrors?: boolean;
|
|
83
|
+
/** Only explicit server-authorized responses may retry; transport failures never retry. */
|
|
84
|
+
retryFromExecutePolicy?: boolean;
|
|
85
|
+
/** Retry budget enabled only by an explicit safe execute-policy response. */
|
|
86
|
+
executePolicyMaxRetries?: number;
|
|
79
87
|
/** Per-request retry override. Use 0 for possibly delivered mutating calls. */
|
|
80
88
|
maxRetries?: number;
|
|
81
89
|
/** Disable localhost/127.0.0.1 failover for non-idempotent requests. */
|
|
@@ -101,10 +109,11 @@ interface RequestOptions {
|
|
|
101
109
|
|
|
102
110
|
interface StreamOptions {
|
|
103
111
|
method?: 'GET' | 'POST';
|
|
112
|
+
/** An unkeyed mutation must not try another URL after a lost response. */
|
|
113
|
+
exactUrlOnly?: boolean;
|
|
104
114
|
body?: unknown;
|
|
105
115
|
headers?: Record<string, string>;
|
|
106
116
|
signal?: AbortSignal;
|
|
107
|
-
exactUrlOnly?: boolean;
|
|
108
117
|
}
|
|
109
118
|
|
|
110
119
|
type RequestAbortTaggedError = Error & {
|
|
@@ -314,29 +323,23 @@ export class HttpClient {
|
|
|
314
323
|
if (agentSessionId) {
|
|
315
324
|
headers['X-Deepline-Agent-Session-Id'] = agentSessionId;
|
|
316
325
|
}
|
|
317
|
-
const playArtifactR2Prefix =
|
|
318
|
-
env.DEEPLINE_PLAY_ARTIFACT_R2_PREFIX;
|
|
326
|
+
const playArtifactR2Prefix = env.DEEPLINE_PLAY_ARTIFACT_R2_PREFIX;
|
|
319
327
|
if (playArtifactR2Prefix) {
|
|
320
328
|
headers['x-deepline-play-artifact-r2-prefix'] = playArtifactR2Prefix;
|
|
321
329
|
}
|
|
322
|
-
const coordinatorUrl =
|
|
323
|
-
|
|
324
|
-
const
|
|
325
|
-
env.DEEPLINE_INTERNAL_TOKEN;
|
|
326
|
-
const absurdReleaseOverride =
|
|
327
|
-
env.DEEPLINE_ABSURD_RELEASE;
|
|
330
|
+
const coordinatorUrl = env.DEEPLINE_COORDINATOR_URL;
|
|
331
|
+
const coordinatorInternalToken = env.DEEPLINE_INTERNAL_TOKEN;
|
|
332
|
+
const absurdReleaseOverride = env.DEEPLINE_ABSURD_RELEASE;
|
|
328
333
|
const preferredReceiptGatewayMachineId =
|
|
329
334
|
env.DEEPLINE_PREFERRED_RECEIPT_GATEWAY_MACHINE_ID;
|
|
330
335
|
if (coordinatorUrl?.trim()) {
|
|
331
336
|
headers[COORDINATOR_URL_OVERRIDE_HEADER] = coordinatorUrl.trim();
|
|
332
337
|
}
|
|
333
|
-
const workerCallbackUrl =
|
|
334
|
-
env.DEEPLINE_WORKER_CALLBACK_URL;
|
|
338
|
+
const workerCallbackUrl = env.DEEPLINE_WORKER_CALLBACK_URL;
|
|
335
339
|
if (workerCallbackUrl?.trim()) {
|
|
336
340
|
headers[WORKER_CALLBACK_URL_OVERRIDE_HEADER] = workerCallbackUrl.trim();
|
|
337
341
|
}
|
|
338
|
-
const runtimeSchedulerSchema =
|
|
339
|
-
env.DEEPLINE_RUNTIME_SCHEDULER_SCHEMA;
|
|
342
|
+
const runtimeSchedulerSchema = env.DEEPLINE_RUNTIME_SCHEDULER_SCHEMA;
|
|
340
343
|
if (runtimeSchedulerSchema?.trim()) {
|
|
341
344
|
headers[RUNTIME_SCHEDULER_SCHEMA_OVERRIDE_HEADER] =
|
|
342
345
|
runtimeSchedulerSchema.trim();
|
|
@@ -344,15 +347,13 @@ export class HttpClient {
|
|
|
344
347
|
// Automated test harnesses (e.g. tests/gauntlet-e2e-tests) set DEEPLINE_SYNTHETIC_RUN
|
|
345
348
|
// so their intentionally failing plays do not page the SDK CLI error
|
|
346
349
|
// channel. Honored server-side only in non-prod (see plays/run route).
|
|
347
|
-
const syntheticRun =
|
|
348
|
-
env.DEEPLINE_SYNTHETIC_RUN;
|
|
350
|
+
const syntheticRun = env.DEEPLINE_SYNTHETIC_RUN;
|
|
349
351
|
if (syntheticRun && syntheticRun.trim() && syntheticRun.trim() !== '0') {
|
|
350
352
|
headers[SYNTHETIC_RUN_HEADER] = '1';
|
|
351
353
|
}
|
|
352
354
|
// Test-only runtime seam. The server validates both environment and value
|
|
353
355
|
// before honoring this header.
|
|
354
|
-
const runtimeTestFault =
|
|
355
|
-
env.DEEPLINE_TEST_RUNTIME_FAULT;
|
|
356
|
+
const runtimeTestFault = env.DEEPLINE_TEST_RUNTIME_FAULT;
|
|
356
357
|
if (runtimeTestFault?.trim()) {
|
|
357
358
|
headers[PLAY_RUNTIME_TEST_FAULT_HEADER] = runtimeTestFault.trim();
|
|
358
359
|
}
|
|
@@ -441,7 +442,7 @@ export class HttpClient {
|
|
|
441
442
|
let retryAfterDelayMs: number | null = null;
|
|
442
443
|
let totalRetryWaitMs = 0;
|
|
443
444
|
|
|
444
|
-
|
|
445
|
+
let maxRetries = options?.maxRetries ?? this.config.maxRetries;
|
|
445
446
|
|
|
446
447
|
requestAttempts: for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
447
448
|
if (options?.signal?.aborted) {
|
|
@@ -529,6 +530,18 @@ export class HttpClient {
|
|
|
529
530
|
httpStatus: response.status,
|
|
530
531
|
body: parsed,
|
|
531
532
|
});
|
|
533
|
+
const responseRetryAllowed =
|
|
534
|
+
options?.retryFromExecutePolicy !== true ||
|
|
535
|
+
parseExecuteRetryPolicy(
|
|
536
|
+
response.headers.get(EXECUTE_RETRY_POLICY_HEADER),
|
|
537
|
+
) === 'transient-http-safe';
|
|
538
|
+
if (
|
|
539
|
+
options?.retryFromExecutePolicy === true &&
|
|
540
|
+
responseRetryAllowed &&
|
|
541
|
+
options.executePolicyMaxRetries !== undefined
|
|
542
|
+
) {
|
|
543
|
+
maxRetries = options.executePolicyMaxRetries;
|
|
544
|
+
}
|
|
532
545
|
|
|
533
546
|
const structuredToolError =
|
|
534
547
|
options?.toolId && !response.ok
|
|
@@ -553,7 +566,7 @@ export class HttpClient {
|
|
|
553
566
|
retryAfterMs:
|
|
554
567
|
failure.retryAfterMs ?? Math.max(0, retryAfter),
|
|
555
568
|
});
|
|
556
|
-
if (attempt < maxRetries) {
|
|
569
|
+
if (responseRetryAllowed && attempt < maxRetries) {
|
|
557
570
|
retryAfterDelayMs = retryAfter;
|
|
558
571
|
break;
|
|
559
572
|
}
|
|
@@ -576,7 +589,7 @@ export class HttpClient {
|
|
|
576
589
|
}
|
|
577
590
|
const retryAfter = parseRetryAfter(response);
|
|
578
591
|
lastError = new RateLimitError(retryAfter);
|
|
579
|
-
if (attempt < maxRetries) {
|
|
592
|
+
if (responseRetryAllowed && attempt < maxRetries) {
|
|
580
593
|
retryAfterDelayMs = retryAfter;
|
|
581
594
|
break;
|
|
582
595
|
}
|
|
@@ -592,6 +605,7 @@ export class HttpClient {
|
|
|
592
605
|
if (!response.ok) {
|
|
593
606
|
const retryableApiError =
|
|
594
607
|
options?.retryApiErrors === true &&
|
|
608
|
+
responseRetryAllowed &&
|
|
595
609
|
isRetryableApiErrorResponse(response.status);
|
|
596
610
|
// A 5xx that escaped a Worker can return Cloudflare's default HTML
|
|
597
611
|
// error page. Never surface raw HTML to CLI users: replace the
|
|
@@ -693,6 +707,7 @@ export class HttpClient {
|
|
|
693
707
|
timeoutMs,
|
|
694
708
|
timedOut: requestTimedOut,
|
|
695
709
|
});
|
|
710
|
+
if (options?.retryFromExecutePolicy) break requestAttempts;
|
|
696
711
|
} finally {
|
|
697
712
|
clearTimeout(timeoutId);
|
|
698
713
|
options?.signal?.removeEventListener('abort', abortRequest);
|
|
@@ -918,7 +933,10 @@ export class HttpClient {
|
|
|
918
933
|
options?: Pick<
|
|
919
934
|
RequestOptions,
|
|
920
935
|
| 'retryApiErrors'
|
|
936
|
+
| 'retryFromExecutePolicy'
|
|
937
|
+
| 'executePolicyMaxRetries'
|
|
921
938
|
| 'timeout'
|
|
939
|
+
| 'signal'
|
|
922
940
|
| 'maxRetries'
|
|
923
941
|
| 'exactUrlOnly'
|
|
924
942
|
| 'toolId'
|
|
@@ -78,10 +78,7 @@ export {
|
|
|
78
78
|
MONITOR_JOB_RECONCILIATION_STATES,
|
|
79
79
|
MONITOR_JOB_STATES,
|
|
80
80
|
} from './client';
|
|
81
|
-
export type {
|
|
82
|
-
CustomerDbQueryOptions,
|
|
83
|
-
CustomerDbQueryPlan,
|
|
84
|
-
} from './db/query';
|
|
81
|
+
export type { CustomerDbQueryOptions, CustomerDbQueryPlan } from './db/query';
|
|
85
82
|
export { planCustomerDbQuery } from './db/query';
|
|
86
83
|
export type { DeeplineToolCallOptions } from './play';
|
|
87
84
|
export {
|
|
@@ -90,7 +87,7 @@ export {
|
|
|
90
87
|
} from './plays/local-play-execution';
|
|
91
88
|
export type { LocalPlayGraph } from './plays/local-play-execution';
|
|
92
89
|
export type { PlayDescriptionOptions } from './plays/play-description';
|
|
93
|
-
export { CtxFetchHttpError } from './play';
|
|
90
|
+
export { CtxFetchHttpError, CtxFetchAmbiguousWriteError } from './play';
|
|
94
91
|
export { RunObserveTransportUnavailableError } from './runs/observe-transport';
|
|
95
92
|
export { RunEventQueryInputError } from '../../shared_libs/play-runtime/run-event-query';
|
|
96
93
|
export type {
|
|
@@ -316,6 +313,8 @@ export type {
|
|
|
316
313
|
DeeplineClientOptions,
|
|
317
314
|
ResolvedConfig,
|
|
318
315
|
ToolDefinition,
|
|
316
|
+
ToolCategorySummary,
|
|
317
|
+
ToolCategoryListing,
|
|
319
318
|
ToolMetadata,
|
|
320
319
|
ToolRequestCondition,
|
|
321
320
|
ToolRequestWarningRule,
|
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
* @module
|
|
76
76
|
*/
|
|
77
77
|
import { DeeplineClient } from './client';
|
|
78
|
+
import { createPlayClient, type PlayClientOperations } from './plays/client';
|
|
78
79
|
import { DeeplineError } from './errors';
|
|
79
80
|
import {
|
|
80
81
|
attachToolResultListDataset,
|
|
@@ -83,7 +84,8 @@ import {
|
|
|
83
84
|
} from '../../shared_libs/play-runtime/tool-result.js';
|
|
84
85
|
export { readValue, readList } from '../../shared_libs/play-runtime/tool-result.js';
|
|
85
86
|
import { createDeferredPlayDataset } from '../../shared_libs/plays/dataset.js';
|
|
86
|
-
export { CtxFetchHttpError } from '../../shared_libs/plays/
|
|
87
|
+
export { CtxFetchHttpError } from '../../shared_libs/plays/fetch-http-error.js';
|
|
88
|
+
export { CtxFetchAmbiguousWriteError } from '../../shared_libs/plays/ambiguous-write-error.js';
|
|
87
89
|
import {
|
|
88
90
|
QUERY_RESULT_DATASET_PAGE_SIZE,
|
|
89
91
|
isCustomerDbDatasetTool,
|
|
@@ -955,7 +957,7 @@ class DeeplinePlayJobImpl<TOutput = unknown> implements PlayJob<TOutput> {
|
|
|
955
957
|
readonly id: string;
|
|
956
958
|
|
|
957
959
|
constructor(
|
|
958
|
-
private readonly client:
|
|
960
|
+
private readonly client: PlayClientOperations,
|
|
959
961
|
runId: string,
|
|
960
962
|
) {
|
|
961
963
|
this.id = runId;
|
|
@@ -1006,10 +1008,10 @@ class DeeplinePlayJobImpl<TOutput = unknown> implements PlayJob<TOutput> {
|
|
|
1006
1008
|
if (status.package) {
|
|
1007
1009
|
return status.package as TOutput;
|
|
1008
1010
|
}
|
|
1009
|
-
const payload = status.result
|
|
1010
|
-
return ((payload && 'output' in payload
|
|
1011
|
+
const payload = status.result;
|
|
1012
|
+
return ((payload && typeof payload === 'object' && 'output' in payload
|
|
1011
1013
|
? payload.output
|
|
1012
|
-
:
|
|
1014
|
+
: payload) ?? null) as TOutput;
|
|
1013
1015
|
}
|
|
1014
1016
|
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
1015
1017
|
}
|
|
@@ -1028,7 +1030,7 @@ function createNamedPlayHandle<
|
|
|
1028
1030
|
TInput = Record<string, unknown>,
|
|
1029
1031
|
TOutput = unknown,
|
|
1030
1032
|
>(
|
|
1031
|
-
clientFactory: () =>
|
|
1033
|
+
clientFactory: () => PlayClientOperations,
|
|
1032
1034
|
name: string,
|
|
1033
1035
|
): DeeplineNamedPlay<TInput, TOutput> {
|
|
1034
1036
|
return {
|
|
@@ -1062,9 +1064,7 @@ function createNamedPlayHandle<
|
|
|
1062
1064
|
}
|
|
1063
1065
|
|
|
1064
1066
|
/**
|
|
1065
|
-
*
|
|
1066
|
-
*
|
|
1067
|
-
* Created by {@link Deepline.connect}. Wraps a {@link DeeplineClient} with a friendlier API for common operations.
|
|
1067
|
+
* SDK context with tool shortcuts and play handles, created by {@link Deepline.connect}. Wraps a {@link DeeplineClient} for common operations.
|
|
1068
1068
|
*
|
|
1069
1069
|
* @example
|
|
1070
1070
|
* ```typescript
|
|
@@ -1872,7 +1872,7 @@ export function definePlay<TInput, TOutput extends PlayReturnObject>(
|
|
|
1872
1872
|
});
|
|
1873
1873
|
|
|
1874
1874
|
const handle = createNamedPlayHandle<TInput, TOutput>(
|
|
1875
|
-
() =>
|
|
1875
|
+
() => createPlayClient(),
|
|
1876
1876
|
name,
|
|
1877
1877
|
);
|
|
1878
1878
|
for (const key of [
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { dirname, join, resolve } from 'node:path';
|
|
1
|
+
import { dirname, resolve } from 'node:path';
|
|
3
2
|
import { fileURLToPath } from 'node:url';
|
|
4
3
|
import { existsSync } from 'node:fs';
|
|
5
4
|
import { realpath } from 'node:fs/promises';
|
|
6
5
|
import {
|
|
7
6
|
bundlePlayFile as bundlePlayFileCore,
|
|
8
|
-
PLAY_BUNDLE_CACHE_NAMESPACE,
|
|
9
7
|
type BundlePlayFileOptions,
|
|
10
8
|
type BundledPlayFileSuccess,
|
|
11
9
|
type BundledPlayFileResult,
|
|
@@ -126,7 +124,10 @@ export function createSdkPlayBundlingAdapter(): PlayBundlingAdapter {
|
|
|
126
124
|
nodeModulesDir: HAS_PACKAGED_BUNDLING_SOURCES
|
|
127
125
|
? resolve(SDK_PACKAGE_ROOT, 'node_modules')
|
|
128
126
|
: resolve(PROJECT_ROOT, 'node_modules'),
|
|
129
|
-
|
|
127
|
+
// Emit the current SDK/compiler implementation on every invocation. The
|
|
128
|
+
// customer graph hash does not include SDK/compiler source bytes, so reusing an
|
|
129
|
+
// artifact can silently retain an older compiler or SDK implementation.
|
|
130
|
+
cacheDir: null,
|
|
130
131
|
sdkSourceRoot: SDK_SOURCE_ROOT,
|
|
131
132
|
sdkPackageJson: SDK_PACKAGE_JSON,
|
|
132
133
|
sdkEntryFile: SDK_ENTRY_FILE,
|
|
@@ -156,6 +157,7 @@ export async function bundlePlayFile(
|
|
|
156
157
|
const result = await bundlePlayFileCore(filePath, {
|
|
157
158
|
target: options.target ?? defaultPlayBundleTarget(),
|
|
158
159
|
exportName: options.exportName,
|
|
160
|
+
compatibility: options.compatibility,
|
|
159
161
|
adapter: {
|
|
160
162
|
...createSdkPlayBundlingAdapter(),
|
|
161
163
|
sourceIdentityRoot,
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { BundledPlayFileSuccess } from '../../../shared_libs/plays/bundling/index.js';
|
|
2
|
+
import type { DeeplineClient } from '../client.js';
|
|
3
|
+
import { playAuthoringGraphPath } from './authoring-graph-path.js';
|
|
4
|
+
|
|
5
|
+
type CheckRequest = Parameters<DeeplineClient['checkPlayArtifact']>[0];
|
|
6
|
+
type CheckResult = Awaited<ReturnType<DeeplineClient['checkPlayArtifact']>>;
|
|
7
|
+
type LocalPlayGraph = {
|
|
8
|
+
root: BundledPlayFileSuccess;
|
|
9
|
+
nodes: ReadonlyMap<string, BundledPlayFileSuccess>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/** Source validation changes no customer resources and is safe to repeat. */
|
|
13
|
+
export const LOCAL_PLAY_CHECK_EFFECTS = {
|
|
14
|
+
cloudMutations: [] as readonly string[],
|
|
15
|
+
localWrites: [] as readonly string[],
|
|
16
|
+
creditSpending: 'none',
|
|
17
|
+
recovery: 'repeat_validation',
|
|
18
|
+
} as const;
|
|
19
|
+
|
|
20
|
+
/** Check each future-authored composition under its own artifact and source policy. */
|
|
21
|
+
export async function checkLocalPlayGraph(input: {
|
|
22
|
+
client: Pick<DeeplineClient, 'checkPlayArtifact'>;
|
|
23
|
+
graph: LocalPlayGraph;
|
|
24
|
+
rootPlayName: string;
|
|
25
|
+
exportName: string;
|
|
26
|
+
integrationMode?: CheckRequest['integrationMode'];
|
|
27
|
+
prepareArtifact?: (
|
|
28
|
+
artifact: BundledPlayFileSuccess['artifact'],
|
|
29
|
+
) => BundledPlayFileSuccess['artifact'];
|
|
30
|
+
}): Promise<{ result: CheckResult; failedChild?: BundledPlayFileSuccess }> {
|
|
31
|
+
const { client, graph } = input;
|
|
32
|
+
const nodesByPath = new Map(
|
|
33
|
+
[...graph.nodes.values()].map((node) => [node.filePath, node]),
|
|
34
|
+
);
|
|
35
|
+
const importedPlaysFor = (node: BundledPlayFileSuccess) => {
|
|
36
|
+
const imported = new Set<string>();
|
|
37
|
+
const collect = (parent: BundledPlayFileSuccess) => {
|
|
38
|
+
for (const dependency of parent.importedPlayDependencies) {
|
|
39
|
+
if (imported.has(dependency.filePath)) continue;
|
|
40
|
+
const child = nodesByPath.get(dependency.filePath);
|
|
41
|
+
if (!child)
|
|
42
|
+
throw new Error(
|
|
43
|
+
`Missing bundled Play dependency ${dependency.filePath}.`,
|
|
44
|
+
);
|
|
45
|
+
imported.add(dependency.filePath);
|
|
46
|
+
collect(child);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
collect(node);
|
|
50
|
+
return [...imported].map((filePath) => {
|
|
51
|
+
const child = nodesByPath.get(filePath)!;
|
|
52
|
+
return {
|
|
53
|
+
playName: child.playName,
|
|
54
|
+
sourceCode: child.sourceCode,
|
|
55
|
+
sourcePath: playAuthoringGraphPath(node, child.filePath),
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
const checkNode = (node: BundledPlayFileSuccess) => {
|
|
60
|
+
const name =
|
|
61
|
+
node.playName ?? (node === graph.root ? input.rootPlayName : null);
|
|
62
|
+
if (!name)
|
|
63
|
+
throw new Error(`Bundled Play ${node.filePath} has no declared name.`);
|
|
64
|
+
const importedPlays = importedPlaysFor(node);
|
|
65
|
+
const exportName =
|
|
66
|
+
node === graph.root
|
|
67
|
+
? input.exportName
|
|
68
|
+
: (node.artifact.exportName ?? 'default');
|
|
69
|
+
return client.checkPlayArtifact({
|
|
70
|
+
name,
|
|
71
|
+
sourceCode: node.sourceCode,
|
|
72
|
+
sourceFiles: node.sourceFiles,
|
|
73
|
+
description: node.playDescription ?? undefined,
|
|
74
|
+
artifact: input.prepareArtifact?.(node.artifact) ?? node.artifact,
|
|
75
|
+
...(exportName === 'default' ? {} : { exportName }),
|
|
76
|
+
...(importedPlays.length ? { importedPlays } : {}),
|
|
77
|
+
...(input.integrationMode
|
|
78
|
+
? { integrationMode: input.integrationMode }
|
|
79
|
+
: {}),
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
if (
|
|
83
|
+
[...graph.nodes.values()].some(
|
|
84
|
+
(node) =>
|
|
85
|
+
(node.artifact.compatibility.authoringContractEdition ?? 1) >= 10,
|
|
86
|
+
)
|
|
87
|
+
) {
|
|
88
|
+
const checked = new Set<string>();
|
|
89
|
+
const checkChildren = async (
|
|
90
|
+
node: BundledPlayFileSuccess,
|
|
91
|
+
): Promise<{
|
|
92
|
+
result: CheckResult;
|
|
93
|
+
failedChild: BundledPlayFileSuccess;
|
|
94
|
+
} | null> => {
|
|
95
|
+
if (checked.has(node.filePath)) return null;
|
|
96
|
+
checked.add(node.filePath);
|
|
97
|
+
for (const dependency of node.importedPlayDependencies) {
|
|
98
|
+
const child = nodesByPath.get(dependency.filePath);
|
|
99
|
+
if (!child)
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Missing bundled Play dependency ${dependency.filePath}.`,
|
|
102
|
+
);
|
|
103
|
+
const failure = await checkChildren(child);
|
|
104
|
+
if (failure) return failure;
|
|
105
|
+
}
|
|
106
|
+
if (node === graph.root) return null;
|
|
107
|
+
const result = await checkNode(node);
|
|
108
|
+
return result.valid ? null : { result, failedChild: node };
|
|
109
|
+
};
|
|
110
|
+
const failure = await checkChildren(graph.root);
|
|
111
|
+
if (failure) return failure;
|
|
112
|
+
}
|
|
113
|
+
return { result: await checkNode(graph.root) };
|
|
114
|
+
}
|