deepline 0.1.26 → 0.1.28
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/README.md +6 -1
- package/dist/cli/index.js +171 -47
- package/dist/cli/index.mjs +169 -45
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +360 -41
- package/dist/repo/apps/play-runner-workers/src/entry.ts +101 -42
- package/dist/repo/sdk/src/plays/harness-stub.ts +2 -20
- package/dist/repo/sdk/src/version.ts +1 -1
- package/package.json +1 -1
|
@@ -106,7 +106,6 @@ import {
|
|
|
106
106
|
// re-bundle harness internals into per-play. Keep that in mind.
|
|
107
107
|
import {
|
|
108
108
|
harnessPersistCompletedSheetRows,
|
|
109
|
-
harnessPrewarmPostgresSessions,
|
|
110
109
|
harnessReadSheetDatasetRows,
|
|
111
110
|
harnessReadStagedFileChunk,
|
|
112
111
|
harnessStartSheetDataset,
|
|
@@ -568,7 +567,11 @@ async function postRuntimeApi<T>(
|
|
|
568
567
|
// hits the same handler with the same auth — only the transport changes.
|
|
569
568
|
const serializedBody = JSON.stringify(body);
|
|
570
569
|
let lastError: unknown = null;
|
|
571
|
-
for (
|
|
570
|
+
for (
|
|
571
|
+
let attempt = 0;
|
|
572
|
+
attempt <= RUNTIME_API_RETRY_DELAYS_MS.length;
|
|
573
|
+
attempt += 1
|
|
574
|
+
) {
|
|
572
575
|
let res: Response;
|
|
573
576
|
try {
|
|
574
577
|
res = await fetchRuntimeApi(baseUrl, '/api/v2/plays/internal/runtime', {
|
|
@@ -618,7 +621,13 @@ function isRetryableRuntimeApiError(error: unknown): boolean {
|
|
|
618
621
|
}
|
|
619
622
|
|
|
620
623
|
function isRetryableRuntimeApiResponse(status: number, body: string): boolean {
|
|
621
|
-
if (
|
|
624
|
+
if (
|
|
625
|
+
status === 408 ||
|
|
626
|
+
status === 429 ||
|
|
627
|
+
status === 502 ||
|
|
628
|
+
status === 503 ||
|
|
629
|
+
status === 504
|
|
630
|
+
) {
|
|
622
631
|
return true;
|
|
623
632
|
}
|
|
624
633
|
return (
|
|
@@ -2465,7 +2474,10 @@ function readHarnessStagedFileChunks(input: {
|
|
|
2465
2474
|
}
|
|
2466
2475
|
|
|
2467
2476
|
const requiredBytes = expectedBytes ?? objectSize;
|
|
2468
|
-
if (
|
|
2477
|
+
if (
|
|
2478
|
+
typeof requiredBytes === 'number' &&
|
|
2479
|
+
observedBytes !== requiredBytes
|
|
2480
|
+
) {
|
|
2469
2481
|
recordRunnerPerfTrace({
|
|
2470
2482
|
req: input.req,
|
|
2471
2483
|
phase: 'csv.read_mismatch',
|
|
@@ -2761,6 +2773,28 @@ async function prepareMapRows(input: {
|
|
|
2761
2773
|
userEmail: input.req.userEmail,
|
|
2762
2774
|
preloadedDbSessions: input.req.preloadedDbSessions ?? null,
|
|
2763
2775
|
});
|
|
2776
|
+
for (const timing of result.timings ?? []) {
|
|
2777
|
+
const phase =
|
|
2778
|
+
typeof timing.phase === 'string' && timing.phase.trim()
|
|
2779
|
+
? timing.phase.trim()
|
|
2780
|
+
: 'unknown';
|
|
2781
|
+
const ms =
|
|
2782
|
+
typeof timing.ms === 'number' && Number.isFinite(timing.ms)
|
|
2783
|
+
? timing.ms
|
|
2784
|
+
: 0;
|
|
2785
|
+
const { phase: _phase, ms: _ms, ...extra } = timing;
|
|
2786
|
+
void _phase;
|
|
2787
|
+
void _ms;
|
|
2788
|
+
recordRunnerPerfTrace({
|
|
2789
|
+
req: input.req,
|
|
2790
|
+
phase: `sheet_start.${phase}`,
|
|
2791
|
+
ms,
|
|
2792
|
+
extra: {
|
|
2793
|
+
tableNamespace: input.tableNamespace,
|
|
2794
|
+
...extra,
|
|
2795
|
+
},
|
|
2796
|
+
});
|
|
2797
|
+
}
|
|
2764
2798
|
return {
|
|
2765
2799
|
inserted: result.inserted,
|
|
2766
2800
|
skipped: result.skipped,
|
|
@@ -3717,7 +3751,8 @@ function createMinimalWorkerCtx(
|
|
|
3717
3751
|
if (matchByPath) {
|
|
3718
3752
|
file = {
|
|
3719
3753
|
logicalPath: matchByPath.playPath,
|
|
3720
|
-
fileName:
|
|
3754
|
+
fileName:
|
|
3755
|
+
matchByPath.playPath.split('/').pop() ?? matchByPath.playPath,
|
|
3721
3756
|
storageKey: matchByPath.storageKey,
|
|
3722
3757
|
contentType: matchByPath.contentType,
|
|
3723
3758
|
bytes: matchByPath.bytes,
|
|
@@ -4245,19 +4280,6 @@ async function executeRunRequest(
|
|
|
4245
4280
|
});
|
|
4246
4281
|
const abortController = options?.abortController ?? new AbortController();
|
|
4247
4282
|
const abortSignal = abortController.signal;
|
|
4248
|
-
const postgresPrewarmStartedAt = nowMs();
|
|
4249
|
-
await harnessPrewarmPostgresSessions({
|
|
4250
|
-
executorToken: req.executorToken,
|
|
4251
|
-
sessions: req.preloadedDbSessions ?? [],
|
|
4252
|
-
});
|
|
4253
|
-
recordRunnerPerfTrace({
|
|
4254
|
-
req,
|
|
4255
|
-
phase: 'runner.prewarm_postgres',
|
|
4256
|
-
ms: nowMs() - postgresPrewarmStartedAt,
|
|
4257
|
-
extra: {
|
|
4258
|
-
sessions: req.preloadedDbSessions?.length ?? 0,
|
|
4259
|
-
},
|
|
4260
|
-
});
|
|
4261
4283
|
let runLogBuffer: string[] = [];
|
|
4262
4284
|
let pendingRunLogLines: string[] = [];
|
|
4263
4285
|
let stepProgressByNodeId: LiveNodeProgressMap = {};
|
|
@@ -4427,6 +4449,11 @@ async function executeRunRequest(
|
|
|
4427
4449
|
if (!options?.persistResultDatasets) return;
|
|
4428
4450
|
await ledgerFlushInFlight.catch(() => undefined);
|
|
4429
4451
|
const now = nowMs();
|
|
4452
|
+
pendingRunLogLines = runLogBuffer;
|
|
4453
|
+
dirtyProgressNodeIds = new Set([
|
|
4454
|
+
...dirtyProgressNodeIds,
|
|
4455
|
+
...Object.keys(stepProgressByNodeId),
|
|
4456
|
+
]);
|
|
4430
4457
|
pendingLedgerEvents = [...pendingLedgerEvents, terminalEvent];
|
|
4431
4458
|
const events = drainPendingLedgerEvents(now);
|
|
4432
4459
|
if (events.length === 0) return;
|
|
@@ -4510,12 +4537,12 @@ async function executeRunRequest(
|
|
|
4510
4537
|
ms: nowMs() - serializeStartedAt,
|
|
4511
4538
|
});
|
|
4512
4539
|
if (options?.persistResultDatasets) {
|
|
4513
|
-
const
|
|
4540
|
+
const ledgerFlushWaitStartedAt = nowMs();
|
|
4514
4541
|
await ledgerFlushInFlight.catch(() => undefined);
|
|
4515
4542
|
recordRunnerPerfTrace({
|
|
4516
4543
|
req,
|
|
4517
4544
|
phase: 'runner.run_ledger_flush_wait',
|
|
4518
|
-
ms: nowMs() -
|
|
4545
|
+
ms: nowMs() - ledgerFlushWaitStartedAt,
|
|
4519
4546
|
});
|
|
4520
4547
|
const resultDatasetStartedAt = nowMs();
|
|
4521
4548
|
await persistResultDatasets(req, result, serializedResult);
|
|
@@ -4526,31 +4553,58 @@ async function executeRunRequest(
|
|
|
4526
4553
|
});
|
|
4527
4554
|
const terminalResult = trimResultForStatus(serializedResult);
|
|
4528
4555
|
const terminalOccurredAt = nowMs();
|
|
4556
|
+
const terminalLedgerPromise = (async () => {
|
|
4557
|
+
const terminalUpdateStartedAt = nowMs();
|
|
4558
|
+
await flushTerminalLedgerEvents({
|
|
4559
|
+
type: 'run.completed',
|
|
4560
|
+
runId: req.runId,
|
|
4561
|
+
source: 'worker',
|
|
4562
|
+
occurredAt: terminalOccurredAt,
|
|
4563
|
+
result: terminalResult,
|
|
4564
|
+
});
|
|
4565
|
+
recordRunnerPerfTrace({
|
|
4566
|
+
req,
|
|
4567
|
+
phase: 'runner.terminal_ledger_append',
|
|
4568
|
+
ms: nowMs() - terminalUpdateStartedAt,
|
|
4569
|
+
});
|
|
4570
|
+
})().catch((error) => {
|
|
4571
|
+
console.error(
|
|
4572
|
+
`[play-harness] non-fatal terminal ledger append failed runId=${req.runId}: ${
|
|
4573
|
+
error instanceof Error ? error.message : String(error)
|
|
4574
|
+
}`,
|
|
4575
|
+
);
|
|
4576
|
+
});
|
|
4577
|
+
|
|
4578
|
+
await terminalLedgerPromise;
|
|
4579
|
+
|
|
4529
4580
|
const billingStartedAt = nowMs();
|
|
4530
|
-
|
|
4581
|
+
const billingPromise = finalizeWorkerComputeBilling({
|
|
4531
4582
|
req,
|
|
4532
4583
|
success: true,
|
|
4533
4584
|
actionEstimate: 4,
|
|
4585
|
+
}).then(() => {
|
|
4586
|
+
recordRunnerPerfTrace({
|
|
4587
|
+
req,
|
|
4588
|
+
phase: 'runner.compute_billing_finalize',
|
|
4589
|
+
ms: nowMs() - billingStartedAt,
|
|
4590
|
+
});
|
|
4534
4591
|
});
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
phase: 'runner.terminal_ledger_append',
|
|
4552
|
-
ms: nowMs() - terminalUpdateStartedAt,
|
|
4553
|
-
});
|
|
4592
|
+
if (extractMaxCreditsPerRun(req.contractSnapshot) !== null) {
|
|
4593
|
+
await billingPromise;
|
|
4594
|
+
} else {
|
|
4595
|
+
const nonBlockingBillingPromise = billingPromise.catch((error) => {
|
|
4596
|
+
console.error(
|
|
4597
|
+
`[play-harness] non-fatal compute billing finalize failed runId=${req.runId}: ${
|
|
4598
|
+
error instanceof Error ? error.message : String(error)
|
|
4599
|
+
}`,
|
|
4600
|
+
);
|
|
4601
|
+
});
|
|
4602
|
+
if (options?.waitUntil) {
|
|
4603
|
+
options.waitUntil(nonBlockingBillingPromise);
|
|
4604
|
+
} else {
|
|
4605
|
+
await nonBlockingBillingPromise;
|
|
4606
|
+
}
|
|
4607
|
+
}
|
|
4554
4608
|
}
|
|
4555
4609
|
const parentSignalStartedAt = nowMs();
|
|
4556
4610
|
await signalParentPlayTerminal({
|
|
@@ -4713,7 +4767,9 @@ function runRequestFromWorkflowParams(
|
|
|
4713
4767
|
inputFile && inputStorageKey
|
|
4714
4768
|
? {
|
|
4715
4769
|
[fileName]: {
|
|
4716
|
-
logicalPath: String(
|
|
4770
|
+
logicalPath: String(
|
|
4771
|
+
inputFile.logicalPath ?? inputFile.path ?? fileName,
|
|
4772
|
+
),
|
|
4717
4773
|
fileName,
|
|
4718
4774
|
storageKey: inputStorageKey,
|
|
4719
4775
|
contentType:
|
|
@@ -5255,7 +5311,10 @@ function inferOutputRows(result: unknown): number {
|
|
|
5255
5311
|
}
|
|
5256
5312
|
if (typeof value !== 'object') return;
|
|
5257
5313
|
const record = value as Record<string, unknown>;
|
|
5258
|
-
if (
|
|
5314
|
+
if (
|
|
5315
|
+
typeof record.tableNamespace === 'string' &&
|
|
5316
|
+
typeof record.count === 'number'
|
|
5317
|
+
) {
|
|
5259
5318
|
datasets.push(record.count);
|
|
5260
5319
|
}
|
|
5261
5320
|
for (const [key, child] of Object.entries(record)) {
|
|
@@ -8,13 +8,11 @@
|
|
|
8
8
|
*
|
|
9
9
|
* What it does:
|
|
10
10
|
* - Exposes thin functions that look like the in-bundle implementations
|
|
11
|
-
* they're replacing (
|
|
11
|
+
* they're replacing (runtime-api call, staged dataset IO, …).
|
|
12
12
|
* - Each function calls `env.HARNESS.<method>(...)` — the typed RPC
|
|
13
13
|
* stub provided by the Cloudflare service binding.
|
|
14
14
|
*
|
|
15
15
|
* What it does NOT do:
|
|
16
|
-
* - Does NOT import zod (that's the whole point — zod stays in the
|
|
17
|
-
* harness Worker).
|
|
18
16
|
* - Does NOT import the harness Worker's `PlayHarness` class (that
|
|
19
17
|
* would re-bundle the whole harness; only TYPES are imported).
|
|
20
18
|
* - Does NOT cache RPC results across plays — caching belongs to
|
|
@@ -36,12 +34,10 @@ import type {
|
|
|
36
34
|
PreloadedRuntimeDbSessionInput,
|
|
37
35
|
RuntimeApiCallInput,
|
|
38
36
|
RuntimeApiCallResult,
|
|
39
|
-
RuntimePayloadSchemaId,
|
|
40
37
|
SheetDatasetRowsInput,
|
|
41
38
|
SheetDatasetRowsResult,
|
|
42
39
|
StagedFileChunkInput,
|
|
43
40
|
StagedFileChunkResult,
|
|
44
|
-
ValidatePayloadResult,
|
|
45
41
|
} from '../../../apps/play-harness-worker/src/rpc-types';
|
|
46
42
|
|
|
47
43
|
/**
|
|
@@ -173,6 +169,7 @@ export async function harnessStartSheetDataset(input: {
|
|
|
173
169
|
pendingRows: Array<Record<string, unknown>>;
|
|
174
170
|
completedRows: Array<Record<string, unknown>>;
|
|
175
171
|
tableNamespace: string;
|
|
172
|
+
timings?: Array<Record<string, unknown>>;
|
|
176
173
|
}> {
|
|
177
174
|
return requireBinding().startSheetDataset(input);
|
|
178
175
|
}
|
|
@@ -195,18 +192,3 @@ export async function harnessPersistCompletedSheetRows(input: {
|
|
|
195
192
|
}): Promise<{ ok: true; rowsWritten: number; tableNamespace: string }> {
|
|
196
193
|
return requireBinding().persistCompletedMapRows(input);
|
|
197
194
|
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Validate a payload against a named schema. The schema definitions
|
|
201
|
-
* (and zod itself) live in the harness Worker — see
|
|
202
|
-
* `apps/play-harness-worker/src/leaves/validate.ts → KNOWN_SCHEMAS`.
|
|
203
|
-
*
|
|
204
|
-
* Use a schema id of the form `tool:<provider>:<operation>` for tool
|
|
205
|
-
* inputs, or `runtime-api:<action>` for runtime-api request bodies.
|
|
206
|
-
*/
|
|
207
|
-
export async function harnessValidatePayload(
|
|
208
|
-
schemaId: RuntimePayloadSchemaId,
|
|
209
|
-
payload: unknown,
|
|
210
|
-
): Promise<ValidatePayloadResult> {
|
|
211
|
-
return requireBinding().validatePayload({ schemaId, payload });
|
|
212
|
-
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const SDK_VERSION = "0.1.
|
|
1
|
+
export const SDK_VERSION = "0.1.28";
|
|
2
2
|
export const SDK_API_CONTRACT = "2026-05-runs-v2";
|