deepline 0.3.448 → 0.3.450
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/play.ts +1 -1
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +3 -3
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-capability.ts +1 -1
- package/dist/bundling-sources/shared_libs/observability/telemetry.ts +2 -1
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-execution-relay.ts +2 -13
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-receipt-gateway.ts +2 -16
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/runtime-topology.ts +23 -1
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-topology.ts +52 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +80 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +16 -3
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +34 -10
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +14 -11
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +54 -6
- package/dist/bundling-sources/shared_libs/product-notifications/catalog.ts +10 -6
- package/dist/bundling-sources/shared_libs/product-notifications/default-policy.ts +1 -1
- package/dist/cli/auth-3LOZKBPO.js +40 -0
- package/dist/cli/{auth-HAJKEPAE.mjs → auth-CHYW6BU3.mjs} +4 -4
- package/dist/cli/{billing-ZGQY3GVK.js → billing-NCV2CBLH.js} +73 -73
- package/dist/cli/{billing-CMA2G5Y4.mjs → billing-YADYH5P7.mjs} +4 -4
- package/dist/cli/{chunk-TKOVC3AP.js → chunk-2SASGLVN.js} +6 -6
- package/dist/cli/{chunk-2GVRS7UB.mjs → chunk-2UNTSLTR.mjs} +3 -3
- package/dist/cli/{chunk-TBTIA6U4.js → chunk-2VKDHJU3.js} +81 -81
- package/dist/cli/{chunk-K5M6UG3D.mjs → chunk-3JEMYGIR.mjs} +1 -1
- package/dist/cli/{chunk-5XOPYIT6.mjs → chunk-3SRJO6H4.mjs} +3 -3
- package/dist/cli/{chunk-PGE4JW7C.js → chunk-47GRLLV2.js} +6 -6
- package/dist/cli/{chunk-XM6A4V77.mjs → chunk-4Z356NPN.mjs} +1 -1
- package/dist/cli/{chunk-2BKTT44A.mjs → chunk-5R7YPB5X.mjs} +1 -1
- package/dist/cli/{chunk-TEPZMKN7.js → chunk-6TABNDCB.js} +4 -4
- package/dist/cli/{chunk-LNBSMAUK.js → chunk-7IUG4STX.js} +50 -50
- package/dist/cli/{chunk-YTWQ4G4P.mjs → chunk-AJUNUE32.mjs} +1 -1
- package/dist/cli/{chunk-XXHLFL3J.mjs → chunk-B2V2F3KV.mjs} +1 -1
- package/dist/cli/{chunk-TOLQMV5C.mjs → chunk-B4T7EFBZ.mjs} +4 -4
- package/dist/cli/{chunk-33KZX7WI.mjs → chunk-CA3NM3W4.mjs} +3 -3
- package/dist/cli/{chunk-ZNEU3KF2.js → chunk-CBM27PDJ.js} +8 -8
- package/dist/cli/{chunk-QS5BY6FO.mjs → chunk-EKVOSR3S.mjs} +5 -5
- package/dist/cli/{chunk-HOLESVLX.mjs → chunk-HRRVDDFH.mjs} +8 -8
- package/dist/cli/{chunk-7XUVB46D.js → chunk-IESQOIOE.js} +8 -8
- package/dist/cli/{chunk-DCQP53KU.js → chunk-IGMBTEF7.js} +26 -26
- package/dist/cli/{chunk-CB3Y7THP.js → chunk-IYBC6WON.js} +1 -1
- package/dist/cli/{chunk-DP6CINW2.js → chunk-JWZIZH2C.js} +10 -10
- package/dist/cli/{chunk-6X5G45GR.js → chunk-LTQCEQOZ.js} +20 -20
- package/dist/cli/{chunk-PVG52FJA.mjs → chunk-N42KCXPD.mjs} +2 -2
- package/dist/cli/{chunk-PVNPEQCM.js → chunk-NSIOVSNZ.js} +52 -52
- package/dist/cli/{chunk-WYU4UYJN.js → chunk-OZ5ME7BP.js} +2 -2
- package/dist/cli/{chunk-R76RSTHC.mjs → chunk-QROZFMGC.mjs} +1 -1
- package/dist/cli/{chunk-H54AY3OO.mjs → chunk-UJHJXWM4.mjs} +2 -2
- package/dist/cli/{chunk-DBNTO3T4.js → chunk-UMA7425N.js} +2 -2
- package/dist/cli/{chunk-Z6SRBSI2.js → chunk-VYMLYV2K.js} +16 -16
- package/dist/cli/{chunk-JYZVM2VV.js → chunk-XUD5AOQY.js} +35 -35
- package/dist/cli/{chunk-JETVD7NN.mjs → chunk-ZEVUPOF6.mjs} +2 -2
- package/dist/cli/{chunk-SXPQ4ZSU.mjs → chunk-ZYORWYLP.mjs} +2 -2
- package/dist/cli/{csv-64TF4NDO.mjs → csv-7PXCJKYS.mjs} +3 -3
- package/dist/cli/{csv-FTRQZV3H.js → csv-VQLS5D7H.js} +12 -12
- package/dist/cli/{db-RZUHE4GB.mjs → db-JYLMLQQO.mjs} +4 -4
- package/dist/cli/{db-REW2BPP6.js → db-XDUC3MFP.js} +25 -25
- package/dist/cli/{describe-3X7HQ3JN.js → describe-G6SRQQHS.js} +16 -16
- package/dist/cli/{describe-XU7JL4VM.mjs → describe-LDHY5HTB.mjs} +12 -12
- package/dist/cli/describe-core.d.mts +1 -1
- package/dist/cli/describe-core.d.ts +1 -1
- package/dist/cli/{executions-Y42LOK2X.js → executions-HPI65XBL.js} +6 -6
- package/dist/cli/{executions-LFDOGILB.mjs → executions-M7MDBFHA.mjs} +4 -4
- package/dist/cli/{feedback-LRF3UIQM.mjs → feedback-6V4DDJVD.mjs} +3 -3
- package/dist/cli/{feedback-LIKR4GUV.js → feedback-Y66JKRPN.js} +7 -7
- package/dist/cli/{git-GGJXLHN2.mjs → git-BTKGTTGF.mjs} +4 -4
- package/dist/cli/git-VVC5BRCG.js +24 -0
- package/dist/cli/index.js +131 -131
- package/dist/cli/index.mjs +36 -36
- package/dist/cli/{legacy-noops-SJMC6NR5.js → legacy-noops-DEVCEE64.js} +7 -7
- package/dist/cli/{legacy-noops-QW3P53AG.mjs → legacy-noops-MUBHYOEG.mjs} +4 -4
- package/dist/cli/{monitors-VRM5AA7T.js → monitors-2DJFA7XX.js} +90 -91
- package/dist/cli/{monitors-Q2UZTDFC.mjs → monitors-SOGDSYPL.mjs} +10 -11
- package/dist/cli/{org-BIUKWUM4.mjs → org-D6ZFFG4D.mjs} +4 -4
- package/dist/cli/{org-F7OCO7BT.js → org-UWMWVV73.js} +66 -66
- package/dist/cli/{play-3WJID2EB.js → play-P423OXCU.js} +283 -283
- package/dist/cli/{play-HK6V5JO5.mjs → play-TIR2S6IA.mjs} +10 -10
- package/dist/cli/{providers-X3KZO4PN.js → providers-6F5F6D4O.js} +7 -7
- package/dist/cli/{providers-RM2PBFPD.mjs → providers-HRDAG3UX.mjs} +4 -4
- package/dist/cli/{quickstart-TKNR4AHF.js → quickstart-SOWZOPAS.js} +5 -5
- package/dist/cli/{quickstart-L7CAMJUL.mjs → quickstart-UMZS7HBY.mjs} +3 -3
- package/dist/cli/{search-XRVV24KN.mjs → search-5FGZVQSP.mjs} +5 -5
- package/dist/cli/search-BDIO4BBH.js +30 -0
- package/dist/cli/{secrets-K3BXJVSB.js → secrets-7E2TOVYP.js} +13 -13
- package/dist/cli/{secrets-W6IACZAX.mjs → secrets-SACNVEWL.mjs} +4 -4
- package/dist/cli/{sessions-CITACQM6.mjs → sessions-5VCX7MYU.mjs} +4 -4
- package/dist/cli/{sessions-WX6DSVSN.js → sessions-FNON33JD.js} +5 -5
- package/dist/cli/{settings-MQTTUMWY.js → settings-6MYQGDQX.js} +75 -75
- package/dist/cli/{settings-W7JDSM35.mjs → settings-EJACNJR4.mjs} +8 -8
- package/dist/cli/{setup-EQ64XDNX.mjs → setup-KJ7IADVC.mjs} +7 -7
- package/dist/cli/{setup-OWHEIGVW.js → setup-QVEIV4R4.js} +42 -42
- package/dist/cli/{skills-5JBRC5OR.mjs → skills-SUV3DJEU.mjs} +5 -5
- package/dist/cli/skills-YPH2KNH6.js +29 -0
- package/dist/cli/{tools-DIXBDNAX.mjs → tools-H4ZL5QDZ.mjs} +12 -12
- package/dist/cli/tools-X23MQMNE.js +44 -0
- package/dist/cli/{update-EYIS2XVV.mjs → update-5UGF4334.mjs} +7 -7
- package/dist/cli/update-GZOPNTGJ.js +31 -0
- package/dist/cli/{workflow-YKFU3E2C.mjs → workflow-RABLQNGO.mjs} +6 -6
- package/dist/cli/{workflow-OEKRLGWT.js → workflow-THIBJ3VE.js} +16 -16
- package/dist/{client-CBitBZpr.d.ts → client-CPRaigLC.d.ts} +1 -0
- package/dist/{client-CTUbBRgg.d.mts → client-DstDI5TV.d.mts} +1 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +6 -6
- package/dist/index.mjs +3 -3
- package/dist/install-integrity.json +80 -80
- package/dist/plays/play-description.d.mts +1 -1
- package/dist/plays/play-description.d.ts +1 -1
- package/dist/plays/run-request.d.mts +1 -1
- package/dist/plays/run-request.d.ts +1 -1
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +2 -2
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
- package/dist/cli/auth-HUJ3DIQI.js +0 -40
- package/dist/cli/git-BH7ZZPCT.js +0 -24
- package/dist/cli/search-65KJJGHQ.js +0 -30
- package/dist/cli/skills-5AXKZGMJ.js +0 -29
- package/dist/cli/tools-EXCJ2QMK.js +0 -44
- package/dist/cli/update-KSIVBEIH.js +0 -31
|
@@ -181,7 +181,7 @@ export type PlayFetchResponse = PlayAuthoringFetchResponse;
|
|
|
181
181
|
* row to its output stream. This is how you build a play "on top of" a monitor
|
|
182
182
|
* (e.g. run enrichment every time a watched company posts a new job). Each
|
|
183
183
|
* listener binds to a monitor tool id + one of its output stream keys (see
|
|
184
|
-
* `deepline
|
|
184
|
+
* `deepline describe <id>` for a tool's streams and row columns).
|
|
185
185
|
* The changed row is delivered as the listener event's `after` in the play function's input.
|
|
186
186
|
*
|
|
187
187
|
* The default Play runtime is 30 minutes. For bounded long-running batches, add
|
|
@@ -205,7 +205,7 @@ export const SDK_RELEASE = {
|
|
|
205
205
|
// getters keep their established compatibility behavior.
|
|
206
206
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
207
207
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
208
|
-
version: '0.3.
|
|
208
|
+
version: '0.3.450',
|
|
209
209
|
updateSummary: {
|
|
210
210
|
introducedIn: '0.3.90',
|
|
211
211
|
summary:
|
|
@@ -127,10 +127,10 @@ export function monitorErrorNextAction(payload: MonitorErrorPayload): string {
|
|
|
127
127
|
return 'Stop monitor work and contact the Deepline team to request access; then rerun `deepline monitors status`.';
|
|
128
128
|
}
|
|
129
129
|
if (code === 'monitor_tool_not_found' || code === 'unknown_monitor_tool') {
|
|
130
|
-
return 'Run `deepline monitors
|
|
130
|
+
return 'Run `deepline tools list --categories monitors`, choose a returned tool id, then retry with that exact id.';
|
|
131
131
|
}
|
|
132
132
|
if (code === 'monitor_provider_not_offered') {
|
|
133
|
-
return 'This provider monitor is retired for new deployments. Run `deepline monitors
|
|
133
|
+
return 'This provider monitor is retired for new deployments. Run `deepline tools list --categories monitors` to choose a supported monitor. Existing retired-provider monitors can still be inspected and deleted.';
|
|
134
134
|
}
|
|
135
135
|
if (code === 'deployed_monitor_not_found' || code === 'monitor_not_found') {
|
|
136
136
|
return 'Run `deepline monitors list --status all`, choose a returned public monitor key, then retry with that key.';
|
|
@@ -183,7 +183,7 @@ export function monitorErrorNextAction(payload: MonitorErrorPayload): string {
|
|
|
183
183
|
return 'Fix every returned issue using its path and suggestion. Rerun `deepline monitors check` for definitions or the relevant dry-run for delete/reactivate; do not mutate until validation passes.';
|
|
184
184
|
}
|
|
185
185
|
if (code === 'monitor_tool_unavailable') {
|
|
186
|
-
return 'Run `deepline monitors
|
|
186
|
+
return 'Run `deepline tools list --categories monitors`; choose a tool returned for this workspace, or stop and request access to the unavailable capability.';
|
|
187
187
|
}
|
|
188
188
|
if (code === 'monitor_entitlement_limit_exceeded') {
|
|
189
189
|
return 'Run `deepline monitors list --status all`; reuse or disable an existing monitor, or ask the user to change entitlement before retrying.';
|
|
@@ -447,7 +447,7 @@ export function defineProviderMonitorCapability(input: {
|
|
|
447
447
|
fields,
|
|
448
448
|
pricing: {
|
|
449
449
|
presentation:
|
|
450
|
-
'Use the Deepline pricing returned by describe,
|
|
450
|
+
'Use the Deepline pricing returned by describe, check, or deploy --dry-run. Provider spend is not exposed.',
|
|
451
451
|
},
|
|
452
452
|
identity: {
|
|
453
453
|
semantics: input.upstreamCollision
|
|
@@ -332,9 +332,10 @@ function errorFields(
|
|
|
332
332
|
export function createConsoleTelemetryAdapter(input?: {
|
|
333
333
|
console?: Pick<Console, 'debug' | 'info' | 'warn' | 'error'>;
|
|
334
334
|
}): TelemetryAdapter {
|
|
335
|
-
const target = input?.console ?? console;
|
|
336
335
|
return {
|
|
337
336
|
emit(event) {
|
|
337
|
+
// Convex Node actions replace console for each invocation in a warm process.
|
|
338
|
+
const target = input?.console ?? console;
|
|
338
339
|
const line = JSON.stringify(event);
|
|
339
340
|
if (event.telemetryKind === 'log' || event.telemetryKind === 'span')
|
|
340
341
|
target[event.telemetryLevel](line);
|
package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-execution-relay.ts
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
} from '../fly-gateway-route-probe';
|
|
25
25
|
import {
|
|
26
26
|
gatewayMachineConfig,
|
|
27
|
+
productionGatewayImageEnsureArgs,
|
|
27
28
|
productionGatewayTopology,
|
|
28
29
|
RUNTIME_GATEWAY_AUTOSCALED_METADATA_KEY,
|
|
29
30
|
RUNTIME_TOPOLOGY,
|
|
@@ -307,19 +308,7 @@ async function assertExactReady(machineId: string): Promise<void> {
|
|
|
307
308
|
});
|
|
308
309
|
}
|
|
309
310
|
async function prepare(sha: string): Promise<void> {
|
|
310
|
-
run('bun',
|
|
311
|
-
'scripts/ensure-runtime-image.ts',
|
|
312
|
-
'--kind',
|
|
313
|
-
'gateway',
|
|
314
|
-
'--app',
|
|
315
|
-
app,
|
|
316
|
-
'--config',
|
|
317
|
-
RUNTIME_TOPOLOGY.production.components.executionRelay.image.config,
|
|
318
|
-
'--dockerfile',
|
|
319
|
-
RUNTIME_TOPOLOGY.production.components.executionRelay.image.dockerfile,
|
|
320
|
-
'--sha',
|
|
321
|
-
sha,
|
|
322
|
-
]);
|
|
311
|
+
run('bun', productionGatewayImageEnsureArgs('executionRelay', sha));
|
|
323
312
|
const client = new FlyMachinesClient(app, requireFlyToken(), fetch);
|
|
324
313
|
const initial = await inventory(client);
|
|
325
314
|
const existing = candidates(initial, sha);
|
package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-receipt-gateway.ts
CHANGED
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
import { reconcileGatewaySourceDrain } from '../../deployment/runtime-gateway-drain';
|
|
36
36
|
import {
|
|
37
37
|
gatewayMachineConfig,
|
|
38
|
+
productionGatewayImageEnsureArgs,
|
|
38
39
|
productionGatewayTopology,
|
|
39
40
|
RUNTIME_TOPOLOGY,
|
|
40
41
|
} from '../../deployment/runtime-topology';
|
|
@@ -42,9 +43,6 @@ import {
|
|
|
42
43
|
const topology = productionGatewayTopology('receipt');
|
|
43
44
|
const fleet = {
|
|
44
45
|
app: RUNTIME_TOPOLOGY.production.components.receiptGateway.app,
|
|
45
|
-
config: RUNTIME_TOPOLOGY.production.components.receiptGateway.image.config,
|
|
46
|
-
dockerfile:
|
|
47
|
-
RUNTIME_TOPOLOGY.production.components.receiptGateway.image.dockerfile,
|
|
48
46
|
minimumMachines: topology.minimumMachines,
|
|
49
47
|
primaryRegion: topology.region,
|
|
50
48
|
processGroup: topology.processGroup,
|
|
@@ -886,19 +884,7 @@ async function prepare(operationId: string): Promise<void> {
|
|
|
886
884
|
return;
|
|
887
885
|
}
|
|
888
886
|
}
|
|
889
|
-
run('bun',
|
|
890
|
-
'scripts/ensure-runtime-image.ts',
|
|
891
|
-
'--kind',
|
|
892
|
-
'gateway',
|
|
893
|
-
'--app',
|
|
894
|
-
fleet.app,
|
|
895
|
-
'--config',
|
|
896
|
-
fleet.config,
|
|
897
|
-
'--dockerfile',
|
|
898
|
-
fleet.dockerfile,
|
|
899
|
-
'--sha',
|
|
900
|
-
operationId,
|
|
901
|
-
]);
|
|
887
|
+
run('bun', productionGatewayImageEnsureArgs('receiptGateway', operationId));
|
|
902
888
|
const blue = serving();
|
|
903
889
|
if (existing.length > 0) {
|
|
904
890
|
assertCandidateSourceGeneration({ candidates: existing, serving: blue });
|
package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/runtime-topology.ts
CHANGED
|
@@ -20,7 +20,12 @@ import {
|
|
|
20
20
|
readFileSync,
|
|
21
21
|
writeFileSync,
|
|
22
22
|
} from 'node:fs';
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
productionGatewayImageEnsureArgs,
|
|
25
|
+
productionGatewayTopology,
|
|
26
|
+
RUNTIME_TOPOLOGY,
|
|
27
|
+
type ProductionGatewayComponent,
|
|
28
|
+
} from '../../deployment/runtime-topology';
|
|
24
29
|
import {
|
|
25
30
|
shouldCreateDetachedProcessGroup,
|
|
26
31
|
terminateChildProcessTree,
|
|
@@ -499,6 +504,23 @@ export async function prepareProductionTopologyPlan(
|
|
|
499
504
|
description: 'Reconcile declared Fly apps',
|
|
500
505
|
});
|
|
501
506
|
await stageSecrets({ ...input, environment, command: input.command });
|
|
507
|
+
// One sequential publish, so the parallel prepares below find their
|
|
508
|
+
// release tags and never push the same image concurrently.
|
|
509
|
+
const gatewayImageComponents: ProductionGatewayComponent[] = [
|
|
510
|
+
'receiptGateway',
|
|
511
|
+
'executionRelay',
|
|
512
|
+
];
|
|
513
|
+
for (const component of gatewayImageComponents) {
|
|
514
|
+
await input.command({
|
|
515
|
+
command: 'bun',
|
|
516
|
+
args: productionGatewayImageEnsureArgs(
|
|
517
|
+
component,
|
|
518
|
+
input.plan.releaseSha,
|
|
519
|
+
),
|
|
520
|
+
environment,
|
|
521
|
+
description: `Ensure runtime gateway image for ${RUNTIME_TOPOLOGY.production.components[component].app}`,
|
|
522
|
+
});
|
|
523
|
+
}
|
|
502
524
|
const executionRelayArgs = [
|
|
503
525
|
'scripts/roll-execution-relay.ts',
|
|
504
526
|
'prepare',
|
|
@@ -144,6 +144,11 @@ const previewGateways: Record<RuntimeGatewayRole, GatewayTopology> = {
|
|
|
144
144
|
},
|
|
145
145
|
};
|
|
146
146
|
|
|
147
|
+
// Both gateways run the same image. Concurrent pushes of one Depot build to
|
|
148
|
+
// two repos left a shared blob upload hanging (2026-10-27 releases), so the
|
|
149
|
+
// image is built once into this repo and re-tagged into the other.
|
|
150
|
+
const productionGatewayImageCacheApp = productionGateways.receipt.app;
|
|
151
|
+
|
|
147
152
|
export const RUNTIME_TOPOLOGY = {
|
|
148
153
|
production: {
|
|
149
154
|
components: {
|
|
@@ -153,6 +158,7 @@ export const RUNTIME_TOPOLOGY = {
|
|
|
153
158
|
publicIngress: true,
|
|
154
159
|
image: {
|
|
155
160
|
kind: 'gateway',
|
|
161
|
+
cacheApp: productionGatewayImageCacheApp,
|
|
156
162
|
config: 'deploy/fly/runtime-worker/receipt-gateway.toml',
|
|
157
163
|
dockerfile: 'deploy/fly/runtime-worker/receipt-gateway.Dockerfile',
|
|
158
164
|
},
|
|
@@ -163,6 +169,7 @@ export const RUNTIME_TOPOLOGY = {
|
|
|
163
169
|
publicIngress: true,
|
|
164
170
|
image: {
|
|
165
171
|
kind: 'gateway',
|
|
172
|
+
cacheApp: productionGatewayImageCacheApp,
|
|
166
173
|
config: 'deploy/fly/runtime-worker/execution-relay.toml',
|
|
167
174
|
dockerfile: 'deploy/fly/runtime-worker/receipt-gateway.Dockerfile',
|
|
168
175
|
},
|
|
@@ -253,16 +260,33 @@ export function productionSingletonComponents(): SingletonComponent[] {
|
|
|
253
260
|
);
|
|
254
261
|
}
|
|
255
262
|
|
|
256
|
-
export function assertRuntimeTopologyInvariants(
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
) as Array<{
|
|
263
|
+
export function assertRuntimeTopologyInvariants(
|
|
264
|
+
declared: Record<string, unknown> = RUNTIME_TOPOLOGY.production.components,
|
|
265
|
+
): void {
|
|
266
|
+
const components = Object.values(declared) as Array<{
|
|
267
|
+
app: string;
|
|
268
|
+
release: string;
|
|
269
|
+
publicIngress: boolean;
|
|
270
|
+
image?: { kind: string; cacheApp?: string };
|
|
271
|
+
}>;
|
|
260
272
|
const apps = components.map((component) => component.app);
|
|
261
273
|
if (new Set(apps).size !== apps.length) {
|
|
262
274
|
throw new Error(
|
|
263
275
|
'Every production runtime component requires a unique app.',
|
|
264
276
|
);
|
|
265
277
|
}
|
|
278
|
+
const imageRepos = new Map<string, string>();
|
|
279
|
+
for (const { app, image } of components) {
|
|
280
|
+
if (!image) continue;
|
|
281
|
+
const repo = image.cacheApp ?? app;
|
|
282
|
+
const declaredRepo = imageRepos.get(image.kind);
|
|
283
|
+
if (declaredRepo !== undefined && declaredRepo !== repo) {
|
|
284
|
+
throw new Error(
|
|
285
|
+
`Production components with image kind ${image.kind} must share one cacheApp so the image is built once; found ${declaredRepo} and ${repo}.`,
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
imageRepos.set(image.kind, repo);
|
|
289
|
+
}
|
|
266
290
|
for (const component of components) {
|
|
267
291
|
if (component.release === 'machine-set' && !component.publicIngress) {
|
|
268
292
|
throw new Error(
|
|
@@ -279,6 +303,30 @@ export function assertRuntimeTopologyInvariants(): void {
|
|
|
279
303
|
|
|
280
304
|
assertRuntimeTopologyInvariants();
|
|
281
305
|
|
|
306
|
+
export type ProductionGatewayComponent = 'receiptGateway' | 'executionRelay';
|
|
307
|
+
|
|
308
|
+
export function productionGatewayImageEnsureArgs(
|
|
309
|
+
component: ProductionGatewayComponent,
|
|
310
|
+
sha: string,
|
|
311
|
+
): string[] {
|
|
312
|
+
const { app, image } = RUNTIME_TOPOLOGY.production.components[component];
|
|
313
|
+
return [
|
|
314
|
+
'scripts/ensure-runtime-image.ts',
|
|
315
|
+
'--kind',
|
|
316
|
+
image.kind,
|
|
317
|
+
'--app',
|
|
318
|
+
app,
|
|
319
|
+
'--cache-app',
|
|
320
|
+
image.cacheApp,
|
|
321
|
+
'--config',
|
|
322
|
+
image.config,
|
|
323
|
+
'--dockerfile',
|
|
324
|
+
image.dockerfile,
|
|
325
|
+
'--sha',
|
|
326
|
+
sha,
|
|
327
|
+
];
|
|
328
|
+
}
|
|
329
|
+
|
|
282
330
|
export function runtimeGatewayTopology(
|
|
283
331
|
profile: RuntimeGatewayTopologyProfile,
|
|
284
332
|
role: RuntimeGatewayRole,
|
|
@@ -62,6 +62,27 @@ const DAYTONA_LOGGED_ERROR_NAMES: ReadonlySet<string> = new Set([
|
|
|
62
62
|
'Error',
|
|
63
63
|
]);
|
|
64
64
|
const DAYTONA_LOGGED_PROVIDER_TEXT_MAX_CHARS = 160;
|
|
65
|
+
// Deliberately unanchored: `insufficient_credits` and `billingError` must match,
|
|
66
|
+
// and withholding an innocent word costs only one message. `suspended` is a
|
|
67
|
+
// sandbox state and `load balancer` is infrastructure, so they stay readable.
|
|
68
|
+
const DAYTONA_PROVIDER_ACCOUNT_TEXT_PATTERN =
|
|
69
|
+
/\$\s*\d|credit|billing|invoice|payment|(?<!su)spen[dt]|charge|cost|\busd\b|balance(?!r)|fund|wallet|top.?up|subscription|upgrade your/i;
|
|
70
|
+
const DAYTONA_PROVIDER_PAYMENT_REQUIRED_STATUS = 402;
|
|
71
|
+
// By name: the SDK ships CJS and ESM builds, and `instanceof` fails across them.
|
|
72
|
+
// Deepline's own `Daytona*` errors carry diagnostics classifiers read in full.
|
|
73
|
+
const DAYTONA_SDK_ERROR_NAMES: ReadonlySet<string> = new Set([
|
|
74
|
+
'DaytonaError',
|
|
75
|
+
'DaytonaNotFoundError',
|
|
76
|
+
'DaytonaRateLimitError',
|
|
77
|
+
'DaytonaAuthenticationError',
|
|
78
|
+
'DaytonaAuthorizationError',
|
|
79
|
+
'DaytonaConflictError',
|
|
80
|
+
'DaytonaValidationError',
|
|
81
|
+
'DaytonaTimeoutError',
|
|
82
|
+
'DaytonaConnectionError',
|
|
83
|
+
]);
|
|
84
|
+
const DAYTONA_PROVIDER_ERROR_CODE_PATTERN = /^[A-Za-z][A-Za-z0-9_.-]{1,63}$/;
|
|
85
|
+
const DAYTONA_PROVIDER_DETAIL_PATTERN = / \[provider [^\]]*\]/g;
|
|
65
86
|
|
|
66
87
|
/** A provider state from Daytona's published enum, or `unrecognized`. */
|
|
67
88
|
export function daytonaSandboxStateForLog(state: unknown): string | null {
|
|
@@ -167,6 +188,60 @@ export function boundedDaytonaProviderTextForLog(
|
|
|
167
188
|
return bounded || null;
|
|
168
189
|
}
|
|
169
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Provider text for a run's error, which customers read. Same bounds as the
|
|
193
|
+
* log form, and text about the provider account is withheld so provider spend
|
|
194
|
+
* never reaches a customer. Status and code still identify the failure.
|
|
195
|
+
*/
|
|
196
|
+
export function daytonaProviderTextForRunError(value: string): string | null {
|
|
197
|
+
return DAYTONA_PROVIDER_ACCOUNT_TEXT_PATTERN.test(value)
|
|
198
|
+
? 'provider account detail withheld'
|
|
199
|
+
: boundedDaytonaProviderTextForLog(value);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** A provider-authored error, with or without an HTTP status. */
|
|
203
|
+
export function isDaytonaProviderError(error: unknown): error is DaytonaError {
|
|
204
|
+
return error instanceof Error && DAYTONA_SDK_ERROR_NAMES.has(error.name);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** A provider error's message as a run's error states it. */
|
|
208
|
+
export function daytonaProviderMessageForRunError(
|
|
209
|
+
error: DaytonaError,
|
|
210
|
+
): string | null {
|
|
211
|
+
return daytonaErrorStatusForLog(error) ===
|
|
212
|
+
DAYTONA_PROVIDER_PAYMENT_REQUIRED_STATUS
|
|
213
|
+
? 'provider account detail withheld'
|
|
214
|
+
: daytonaProviderTextForRunError(error.message);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* The provider's status and code as a suffix for a run's error text. The key is
|
|
219
|
+
* `errorCode=` because failure taxonomies read a bare `code=` as Deepline's own.
|
|
220
|
+
*/
|
|
221
|
+
export function daytonaProviderDetailForRunError(error: unknown): string {
|
|
222
|
+
const status = daytonaErrorStatusForLog(error);
|
|
223
|
+
const errorCode = (error as { errorCode?: unknown } | null)?.errorCode;
|
|
224
|
+
const fields = [
|
|
225
|
+
...(status === null ? [] : [`status=${status}`]),
|
|
226
|
+
...(typeof errorCode === 'string' &&
|
|
227
|
+
status !== DAYTONA_PROVIDER_PAYMENT_REQUIRED_STATUS &&
|
|
228
|
+
DAYTONA_PROVIDER_ERROR_CODE_PATTERN.test(errorCode) &&
|
|
229
|
+
!DAYTONA_PROVIDER_ACCOUNT_TEXT_PATTERN.test(errorCode)
|
|
230
|
+
? [`errorCode=${errorCode}`]
|
|
231
|
+
: []),
|
|
232
|
+
];
|
|
233
|
+
return fields.length > 0 ? ` [provider ${fields.join(' ')}]` : '';
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* The run error as retry classification reads it. A diagnostic must not choose
|
|
238
|
+
* a retry: `errorCode=ETIMEDOUT` here would re-run a start whose outcome is
|
|
239
|
+
* unknown.
|
|
240
|
+
*/
|
|
241
|
+
export function withoutDaytonaProviderDetail(error: string): string {
|
|
242
|
+
return error.replace(DAYTONA_PROVIDER_DETAIL_PATTERN, '');
|
|
243
|
+
}
|
|
244
|
+
|
|
170
245
|
/** What this client knew when a sent create ended without a verdict. */
|
|
171
246
|
export type DaytonaLaunchOutcomeDiagnostic = {
|
|
172
247
|
/** Whether the create request returned a response before the deadline. */
|
|
@@ -239,12 +314,16 @@ function providerError(error: unknown): unknown {
|
|
|
239
314
|
if (!axios.isAxiosError(error)) return error;
|
|
240
315
|
const status = error.response?.status;
|
|
241
316
|
const data = error.response?.data;
|
|
242
|
-
const
|
|
317
|
+
const providerMessage =
|
|
243
318
|
typeof data === 'string'
|
|
244
319
|
? data
|
|
245
320
|
: typeof data?.message === 'string'
|
|
246
321
|
? data.message
|
|
247
322
|
: error.message;
|
|
323
|
+
// Not axios's "Request failed with status code" wording: retry classification
|
|
324
|
+
// matches that text, and this change only explains the failure.
|
|
325
|
+
const message =
|
|
326
|
+
providerMessage.trim() || 'Daytona returned an empty response body';
|
|
248
327
|
const errorClasses: Record<number, typeof DaytonaError> = {
|
|
249
328
|
400: DaytonaValidationError,
|
|
250
329
|
401: DaytonaAuthenticationError,
|
package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts
CHANGED
|
@@ -6,7 +6,11 @@ import {
|
|
|
6
6
|
daytonaErrorClassForLog,
|
|
7
7
|
daytonaErrorCodeForLog,
|
|
8
8
|
daytonaErrorStatusForLog,
|
|
9
|
+
daytonaProviderDetailForRunError,
|
|
10
|
+
daytonaProviderMessageForRunError,
|
|
11
|
+
daytonaProviderTextForRunError,
|
|
9
12
|
daytonaSandboxStateForLog,
|
|
13
|
+
isDaytonaProviderError,
|
|
10
14
|
} from './daytona-launch-transport';
|
|
11
15
|
import type {
|
|
12
16
|
PlayRunnerExecutionConfig,
|
|
@@ -349,7 +353,9 @@ async function rejectAcquiredSandbox(
|
|
|
349
353
|
try {
|
|
350
354
|
await deleteSandbox();
|
|
351
355
|
} catch (error) {
|
|
352
|
-
const cleanupError =
|
|
356
|
+
const cleanupError = daytonaProviderTextForRunError(
|
|
357
|
+
error instanceof Error ? error.message : String(error),
|
|
358
|
+
);
|
|
353
359
|
throw new Error(
|
|
354
360
|
`${reason} Defensive deletion of Daytona sandbox ${sandbox.id} also failed: ${cleanupError}`,
|
|
355
361
|
{ cause: error },
|
|
@@ -672,6 +678,8 @@ async function createRetriedOneShotDaytonaSandbox(input: {
|
|
|
672
678
|
cancellationSignal?: AbortSignal;
|
|
673
679
|
}): Promise<DaytonaCreateResult> {
|
|
674
680
|
const errors: string[] = [];
|
|
681
|
+
// Customers read these; acquisition classification reads the raw `errors`.
|
|
682
|
+
const runErrors: string[] = [];
|
|
675
683
|
for (const [index, delayMs] of DAYTONA_CREATE_RETRY_DELAYS_MS.entries()) {
|
|
676
684
|
input.cancellationSignal?.throwIfAborted();
|
|
677
685
|
const attempt = input.nextProviderAttempt();
|
|
@@ -767,6 +775,11 @@ async function createRetriedOneShotDaytonaSandbox(input: {
|
|
|
767
775
|
errorClass: daytonaCreateErrorClass(error),
|
|
768
776
|
});
|
|
769
777
|
errors.push(message);
|
|
778
|
+
runErrors.push(
|
|
779
|
+
isDaytonaProviderError(error)
|
|
780
|
+
? `${daytonaProviderMessageForRunError(error) ?? ''}${daytonaProviderDetailForRunError(error)}`.trim()
|
|
781
|
+
: (daytonaProviderTextForRunError(message) ?? ''),
|
|
782
|
+
);
|
|
770
783
|
// Log-only: whether the create request returned before the deadline and
|
|
771
784
|
// what Daytona last reported, so an unknown outcome is attributable.
|
|
772
785
|
const launchOutcome =
|
|
@@ -878,7 +891,7 @@ async function createRetriedOneShotDaytonaSandbox(input: {
|
|
|
878
891
|
throw reconcilePending();
|
|
879
892
|
}
|
|
880
893
|
throw new Error(
|
|
881
|
-
`${message} Daytona did not return a cleanup-addressable sandbox identity; Modal fallback suppressed. The named ephemeral sandbox retains Daytona's auto-delete-on-stop backstop.`,
|
|
894
|
+
`${daytonaProviderTextForRunError(message)} Daytona did not return a cleanup-addressable sandbox identity; Modal fallback suppressed. The named ephemeral sandbox retains Daytona's auto-delete-on-stop backstop.`,
|
|
882
895
|
{ cause: error },
|
|
883
896
|
);
|
|
884
897
|
}
|
|
@@ -926,7 +939,7 @@ async function createRetriedOneShotDaytonaSandbox(input: {
|
|
|
926
939
|
...(reservation ? { sandboxCapacityLeaseId: reservation.leaseId } : {}),
|
|
927
940
|
};
|
|
928
941
|
}
|
|
929
|
-
const message = `Daytona sandbox create failed across ${errors.length} bounded attempts: ${
|
|
942
|
+
const message = `Daytona sandbox create failed across ${errors.length} bounded attempts: ${runErrors.join('; ')}`;
|
|
930
943
|
const fallbackReason =
|
|
931
944
|
resolveDaytonaSandboxAcquisitionUnavailableReason(errors);
|
|
932
945
|
if (fallbackReason) {
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
+
boundedDaytonaProviderTextForLog,
|
|
2
3
|
createDaytonaLaunchClient,
|
|
4
|
+
daytonaErrorCodeForLog,
|
|
5
|
+
daytonaErrorStatusForLog,
|
|
6
|
+
daytonaProviderDetailForRunError,
|
|
7
|
+
daytonaProviderMessageForRunError,
|
|
8
|
+
isDaytonaProviderError,
|
|
3
9
|
redactDaytonaErrorDetail,
|
|
10
|
+
withoutDaytonaProviderDetail,
|
|
4
11
|
} from './daytona-launch-transport';
|
|
5
12
|
import type { DaytonaClientOptions } from '../../daytona-runtime-config';
|
|
6
13
|
import {
|
|
@@ -1112,7 +1119,7 @@ export async function deleteDaytonaSandboxById(input: {
|
|
|
1112
1119
|
return outcome.kind === 'deleted' || outcome.kind === 'already_absent';
|
|
1113
1120
|
}
|
|
1114
1121
|
|
|
1115
|
-
function formatDaytonaError(error: unknown): string {
|
|
1122
|
+
export function formatDaytonaError(error: unknown): string {
|
|
1116
1123
|
if (!(error instanceof Error)) {
|
|
1117
1124
|
return String(error);
|
|
1118
1125
|
}
|
|
@@ -1122,11 +1129,20 @@ function formatDaytonaError(error: unknown): string {
|
|
|
1122
1129
|
error.cause && error.cause !== error
|
|
1123
1130
|
? ` cause=${formatDaytonaError(error.cause)}`
|
|
1124
1131
|
: '';
|
|
1132
|
+
const message = isDaytonaProviderError(error)
|
|
1133
|
+
? daytonaProviderMessageForRunError(error)
|
|
1134
|
+
: error.message;
|
|
1125
1135
|
const details =
|
|
1126
1136
|
error.name && error.name !== 'Error'
|
|
1127
|
-
? [error.name,
|
|
1128
|
-
:
|
|
1129
|
-
return `${details || 'Error'}${code}${cause}`;
|
|
1137
|
+
? [error.name, message].filter(Boolean).join(': ')
|
|
1138
|
+
: message || error.name || 'Error';
|
|
1139
|
+
return `${details || 'Error'}${code}${daytonaProviderDetailForRunError(error)}${cause}`;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/** A thrown error's message for a run error, keeping provider text bounded. */
|
|
1143
|
+
export function runErrorMessage(error: unknown): string {
|
|
1144
|
+
if (isDaytonaProviderError(error)) return formatDaytonaError(error);
|
|
1145
|
+
return error instanceof Error ? error.message : String(error);
|
|
1130
1146
|
}
|
|
1131
1147
|
|
|
1132
1148
|
function sleep(ms: number): Promise<void> {
|
|
@@ -1264,38 +1280,39 @@ export function retryableRuntimeInitializationFailureReason(
|
|
|
1264
1280
|
| 'daytona_infrastructure'
|
|
1265
1281
|
| null {
|
|
1266
1282
|
if (result.status !== 'failed') return null;
|
|
1267
|
-
|
|
1283
|
+
const error = withoutDaytonaProviderDetail(result.error);
|
|
1284
|
+
if (RUNTIME_POSTGRES_CONNECT_RETRY_PATTERN.test(error)) {
|
|
1268
1285
|
return 'runtime_postgres_connect';
|
|
1269
1286
|
}
|
|
1270
|
-
if (RUNTIME_RECEIPT_GATEWAY_TRANSPORT_RETRY_PATTERN.test(
|
|
1287
|
+
if (RUNTIME_RECEIPT_GATEWAY_TRANSPORT_RETRY_PATTERN.test(error)) {
|
|
1271
1288
|
return 'runtime_receipt_gateway_transport';
|
|
1272
1289
|
}
|
|
1273
1290
|
const rowsProcessed = Number(result.stats?.rowsProcessed ?? 0);
|
|
1274
1291
|
if (
|
|
1275
1292
|
rowsProcessed === 0 &&
|
|
1276
1293
|
result.steps.length === 0 &&
|
|
1277
|
-
DAYTONA_RUNNER_STARTUP_TRANSPORT_RETRY_PATTERN.test(
|
|
1294
|
+
DAYTONA_RUNNER_STARTUP_TRANSPORT_RETRY_PATTERN.test(error)
|
|
1278
1295
|
) {
|
|
1279
1296
|
return 'daytona_runner_startup_transport';
|
|
1280
1297
|
}
|
|
1281
1298
|
if (
|
|
1282
1299
|
rowsProcessed === 0 &&
|
|
1283
1300
|
result.steps.length === 0 &&
|
|
1284
|
-
DAYTONA_PUBLIC_STATUS_TRANSIENT_RETRY_PATTERN.test(
|
|
1301
|
+
DAYTONA_PUBLIC_STATUS_TRANSIENT_RETRY_PATTERN.test(error)
|
|
1285
1302
|
) {
|
|
1286
1303
|
return 'daytona_public_status';
|
|
1287
1304
|
}
|
|
1288
1305
|
if (
|
|
1289
1306
|
rowsProcessed === 0 &&
|
|
1290
1307
|
result.steps.length === 0 &&
|
|
1291
|
-
RUNTIME_API_TRANSPORT_RETRY_PATTERN.test(
|
|
1308
|
+
RUNTIME_API_TRANSPORT_RETRY_PATTERN.test(error)
|
|
1292
1309
|
) {
|
|
1293
1310
|
return 'runtime_api_transport';
|
|
1294
1311
|
}
|
|
1295
1312
|
if (
|
|
1296
1313
|
rowsProcessed === 0 &&
|
|
1297
1314
|
result.steps.length === 0 &&
|
|
1298
|
-
DAYTONA_INFRASTRUCTURE_RETRY_PATTERN.test(
|
|
1315
|
+
DAYTONA_INFRASTRUCTURE_RETRY_PATTERN.test(error)
|
|
1299
1316
|
) {
|
|
1300
1317
|
return 'daytona_infrastructure';
|
|
1301
1318
|
}
|
|
@@ -1916,6 +1933,13 @@ export const daytonaPlayRunnerBackend: PlayRunnerBackend = {
|
|
|
1916
1933
|
runnerAttempt: Math.max(0, Math.floor(config.context.runAttempt ?? 0)),
|
|
1917
1934
|
error: formatDaytonaError(error),
|
|
1918
1935
|
operation: 'runner_backend',
|
|
1936
|
+
// Operator evidence: the run error withholds some of this from customers.
|
|
1937
|
+
providerStatus: daytonaErrorStatusForLog(error),
|
|
1938
|
+
providerCode: daytonaErrorCodeForLog(error),
|
|
1939
|
+
providerText:
|
|
1940
|
+
error instanceof Error
|
|
1941
|
+
? boundedDaytonaProviderTextForLog(error.message)
|
|
1942
|
+
: null,
|
|
1919
1943
|
elapsedMs: Date.now() - startedAt,
|
|
1920
1944
|
});
|
|
1921
1945
|
return withCleanup(
|
package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts
CHANGED
|
@@ -92,7 +92,10 @@ import {
|
|
|
92
92
|
resolveRuntimeSandboxPlacementBackend,
|
|
93
93
|
type PlayRunnerBackend,
|
|
94
94
|
} from '../runner-backends';
|
|
95
|
-
import {
|
|
95
|
+
import {
|
|
96
|
+
retryableRuntimeInitializationFailureReason,
|
|
97
|
+
runErrorMessage,
|
|
98
|
+
} from '../runner-backends/backends/daytona';
|
|
96
99
|
import {
|
|
97
100
|
isRuntimeSandboxCanaryProduction,
|
|
98
101
|
resolveLaunchRuntimeSandboxPlacementPolicy,
|
|
@@ -2321,12 +2324,10 @@ async function terminalizeSandboxCapacityRejection(input: {
|
|
|
2321
2324
|
limit: input.error.limit,
|
|
2322
2325
|
});
|
|
2323
2326
|
const terminal = await input.deps.runWithClient((client) =>
|
|
2324
|
-
executePostgresSchedulerClaim(
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
input.options,
|
|
2329
|
-
),
|
|
2327
|
+
executePostgresSchedulerClaim(client, claim, async () => failedResult, {
|
|
2328
|
+
...input.options,
|
|
2329
|
+
terminalLogOutbox: 'failure_reason',
|
|
2330
|
+
}),
|
|
2330
2331
|
);
|
|
2331
2332
|
if (terminal.status === 'failed') {
|
|
2332
2333
|
const reporter = input.deps.createProgressReporter(
|
|
@@ -3261,7 +3262,9 @@ async function executeAssignedAbsurdAttempt(input: {
|
|
|
3261
3262
|
async () => runnerResult,
|
|
3262
3263
|
{
|
|
3263
3264
|
...options,
|
|
3264
|
-
terminalLogOutbox: input.fromDetachedRunner
|
|
3265
|
+
terminalLogOutbox: input.fromDetachedRunner
|
|
3266
|
+
? 'ctx_log_tail'
|
|
3267
|
+
: 'failure_reason',
|
|
3265
3268
|
sandboxCrashDiagnostic,
|
|
3266
3269
|
...(observedTerminalProgressEvents.length > 0 ||
|
|
3267
3270
|
failedTerminalProgressEvents.length > 0
|
|
@@ -5686,8 +5689,7 @@ async function salvageAbsurdFinalAttemptTerminal(input: {
|
|
|
5686
5689
|
);
|
|
5687
5690
|
}
|
|
5688
5691
|
if (!input.force && attempt < maxAttempts) return;
|
|
5689
|
-
const message =
|
|
5690
|
-
input.error instanceof Error ? input.error.message : String(input.error);
|
|
5692
|
+
const message = runErrorMessage(input.error);
|
|
5691
5693
|
const failedResult: PlayRunnerResult = {
|
|
5692
5694
|
status: 'failed',
|
|
5693
5695
|
error:
|
|
@@ -5757,10 +5759,11 @@ async function salvageAbsurdFinalAttemptTerminal(input: {
|
|
|
5757
5759
|
input.detachedRecovery
|
|
5758
5760
|
? {
|
|
5759
5761
|
...input.options,
|
|
5762
|
+
terminalLogOutbox: 'failure_reason',
|
|
5760
5763
|
preserveRunnerTerminal: true,
|
|
5761
5764
|
protectWaitingSuspensionFailure,
|
|
5762
5765
|
}
|
|
5763
|
-
: input.options,
|
|
5766
|
+
: { ...input.options, terminalLogOutbox: 'failure_reason' },
|
|
5764
5767
|
);
|
|
5765
5768
|
});
|
|
5766
5769
|
break;
|