deepline 0.1.110 → 0.1.112
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/cli/index.js +476 -314
- package/dist/cli/index.mjs +383 -220
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +179 -130
- package/dist/repo/apps/play-runner-workers/src/entry.ts +119 -20
- package/dist/repo/sdk/src/release.ts +2 -2
- package/dist/repo/shared_libs/play-runtime/run-ledger.ts +40 -14
- package/dist/repo/shared_libs/play-runtime/scheduler-backend.ts +2 -0
- package/dist/repo/shared_libs/plays/bundling/index.ts +124 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -274,10 +274,10 @@ var SDK_RELEASE = {
|
|
|
274
274
|
// skill on the sdk sync surface, and the people-search-to-email prebuilt.
|
|
275
275
|
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
276
276
|
// the SDK enrich generator's one-second stale policy.
|
|
277
|
-
version: "0.1.
|
|
277
|
+
version: "0.1.112",
|
|
278
278
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
279
279
|
supportPolicy: {
|
|
280
|
-
latest: "0.1.
|
|
280
|
+
latest: "0.1.112",
|
|
281
281
|
minimumSupported: "0.1.53",
|
|
282
282
|
deprecatedBelow: "0.1.53",
|
|
283
283
|
commandMinimumSupported: [
|
package/dist/index.mjs
CHANGED
|
@@ -196,10 +196,10 @@ var SDK_RELEASE = {
|
|
|
196
196
|
// skill on the sdk sync surface, and the people-search-to-email prebuilt.
|
|
197
197
|
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
198
198
|
// the SDK enrich generator's one-second stale policy.
|
|
199
|
-
version: "0.1.
|
|
199
|
+
version: "0.1.112",
|
|
200
200
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
201
201
|
supportPolicy: {
|
|
202
|
-
latest: "0.1.
|
|
202
|
+
latest: "0.1.112",
|
|
203
203
|
minimumSupported: "0.1.53",
|
|
204
204
|
deprecatedBelow: "0.1.53",
|
|
205
205
|
commandMinimumSupported: [
|
|
@@ -2898,150 +2898,181 @@ export class DynamicWorkflow extends WorkflowEntrypoint<
|
|
|
2898
2898
|
},
|
|
2899
2899
|
});
|
|
2900
2900
|
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
metadata,
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
ms: 0,
|
|
2920
|
-
graphHash,
|
|
2921
|
-
extra: { artifactStorageKey },
|
|
2922
|
-
});
|
|
2923
|
-
const stub = loadDynamicPlayWorkerSync(
|
|
2924
|
-
env,
|
|
2925
|
-
{
|
|
2901
|
+
const dispatchWorkflowStartedAt = Date.now();
|
|
2902
|
+
try {
|
|
2903
|
+
return await dispatchWorkflow(
|
|
2904
|
+
{ env: this.env, ctx: this.ctx },
|
|
2905
|
+
dispatchedEvent as Parameters<typeof dispatchWorkflow>[1],
|
|
2906
|
+
step as Parameters<typeof dispatchWorkflow>[2],
|
|
2907
|
+
async ({ metadata, env }) => {
|
|
2908
|
+
const graphHash = readMetadataString(metadata, 'graphHash');
|
|
2909
|
+
const artifactStorageKey = readMetadataString(
|
|
2910
|
+
metadata,
|
|
2911
|
+
'artifactStorageKey',
|
|
2912
|
+
);
|
|
2913
|
+
const runIdForTrace =
|
|
2914
|
+
typeof (metadata as Record<string, unknown>).runId === 'string'
|
|
2915
|
+
? ((metadata as Record<string, unknown>).runId as string)
|
|
2916
|
+
: graphHash;
|
|
2917
|
+
const loaderStartedAt = Date.now();
|
|
2918
|
+
trace({
|
|
2926
2919
|
runId: runIdForTrace,
|
|
2920
|
+
phase: 'coordinator.loader_callback_entry',
|
|
2921
|
+
ms: 0,
|
|
2927
2922
|
graphHash,
|
|
2928
|
-
artifactStorageKey,
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
dynamicWorkerCode:
|
|
2934
|
-
typeof metadata.dynamicWorkerCode === 'string'
|
|
2935
|
-
? metadata.dynamicWorkerCode
|
|
2936
|
-
: null,
|
|
2937
|
-
packagedFiles: normalizePackagedFiles(metadata.packagedFiles),
|
|
2938
|
-
},
|
|
2939
|
-
trace,
|
|
2940
|
-
);
|
|
2941
|
-
const entrypoint = stub.getEntrypoint(
|
|
2942
|
-
'TenantWorkflow',
|
|
2943
|
-
) as unknown as WorkflowRunner;
|
|
2944
|
-
trace({
|
|
2945
|
-
runId: runIdForTrace,
|
|
2946
|
-
phase: 'coordinator.loader_compile',
|
|
2947
|
-
ms: Date.now() - loaderStartedAt,
|
|
2948
|
-
graphHash,
|
|
2949
|
-
});
|
|
2950
|
-
// Wrap the entrypoint so its run() failure surfaces here rather
|
|
2951
|
-
// than disappearing into the framework's silent rpcMethod=run
|
|
2952
|
-
// exception path.
|
|
2953
|
-
return {
|
|
2954
|
-
run: async (innerEvent: unknown, innerStep: unknown) => {
|
|
2955
|
-
const innerStartedAt = Date.now();
|
|
2956
|
-
trace({
|
|
2923
|
+
extra: { artifactStorageKey },
|
|
2924
|
+
});
|
|
2925
|
+
const stub = loadDynamicPlayWorkerSync(
|
|
2926
|
+
env,
|
|
2927
|
+
{
|
|
2957
2928
|
runId: runIdForTrace,
|
|
2958
|
-
phase: 'coordinator.runner_run_start',
|
|
2959
|
-
ms: 0,
|
|
2960
2929
|
graphHash,
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2930
|
+
artifactStorageKey,
|
|
2931
|
+
artifactHash:
|
|
2932
|
+
typeof metadata.artifactHash === 'string'
|
|
2933
|
+
? metadata.artifactHash
|
|
2934
|
+
: null,
|
|
2935
|
+
dynamicWorkerCode:
|
|
2936
|
+
typeof metadata.dynamicWorkerCode === 'string'
|
|
2937
|
+
? metadata.dynamicWorkerCode
|
|
2938
|
+
: null,
|
|
2939
|
+
packagedFiles: normalizePackagedFiles(metadata.packagedFiles),
|
|
2940
|
+
},
|
|
2941
|
+
trace,
|
|
2942
|
+
);
|
|
2943
|
+
const entrypointStartedAt = Date.now();
|
|
2944
|
+
const entrypoint = stub.getEntrypoint(
|
|
2945
|
+
'TenantWorkflow',
|
|
2946
|
+
) as unknown as WorkflowRunner;
|
|
2947
|
+
trace({
|
|
2948
|
+
runId: runIdForTrace,
|
|
2949
|
+
phase: 'coordinator.loader_get_entrypoint',
|
|
2950
|
+
ms: Date.now() - entrypointStartedAt,
|
|
2951
|
+
graphHash,
|
|
2952
|
+
});
|
|
2953
|
+
trace({
|
|
2954
|
+
runId: runIdForTrace,
|
|
2955
|
+
phase: 'coordinator.loader_compile',
|
|
2956
|
+
ms: Date.now() - loaderStartedAt,
|
|
2957
|
+
graphHash,
|
|
2958
|
+
});
|
|
2959
|
+
// Wrap the entrypoint so its run() failure surfaces here rather
|
|
2960
|
+
// than disappearing into the framework's silent rpcMethod=run
|
|
2961
|
+
// exception path.
|
|
2962
|
+
return {
|
|
2963
|
+
run: async (innerEvent: unknown, innerStep: unknown) => {
|
|
2964
|
+
const innerStartedAt = Date.now();
|
|
2996
2965
|
trace({
|
|
2997
2966
|
runId: runIdForTrace,
|
|
2998
|
-
phase: 'coordinator.
|
|
2999
|
-
ms:
|
|
2967
|
+
phase: 'coordinator.runner_run_start',
|
|
2968
|
+
ms: 0,
|
|
3000
2969
|
graphHash,
|
|
3001
2970
|
});
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
: null,
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
2971
|
+
try {
|
|
2972
|
+
const result = await (
|
|
2973
|
+
entrypoint as unknown as {
|
|
2974
|
+
run(e: unknown, s: unknown): Promise<unknown>;
|
|
2975
|
+
}
|
|
2976
|
+
).run(innerEvent, innerStep);
|
|
2977
|
+
const output = isRecord(result) ? result : null;
|
|
2978
|
+
const terminalStartedAt = Date.now();
|
|
2979
|
+
try {
|
|
2980
|
+
await writeCoordinatorTerminalState(env, {
|
|
2981
|
+
runId: runIdForTrace,
|
|
2982
|
+
status: 'completed',
|
|
2983
|
+
result: output?.result ?? result,
|
|
2984
|
+
totalRows: output?.totalRows ?? output?.outputRows ?? null,
|
|
2985
|
+
durationMs: output?.durationMs ?? null,
|
|
2986
|
+
playName:
|
|
2987
|
+
typeof output?.playName === 'string'
|
|
2988
|
+
? output.playName
|
|
2989
|
+
: null,
|
|
2990
|
+
liveLogs: sanitizeLiveLogLines(output?.liveLogs),
|
|
2991
|
+
liveNodeProgress: output?.liveNodeProgress ?? null,
|
|
2992
|
+
});
|
|
2993
|
+
trace({
|
|
2994
|
+
runId: runIdForTrace,
|
|
2995
|
+
phase: 'coordinator.terminal_state_write',
|
|
2996
|
+
ms: Date.now() - terminalStartedAt,
|
|
2997
|
+
graphHash,
|
|
2998
|
+
extra: { status: 'completed' },
|
|
2999
|
+
});
|
|
3000
|
+
} catch (terminalError) {
|
|
3001
|
+
console.warn(
|
|
3002
|
+
'[coordinator] completed terminal cache write failed; preserving completed run',
|
|
3003
|
+
{
|
|
3004
|
+
graphHash,
|
|
3005
|
+
runId: runIdForTrace,
|
|
3006
|
+
message:
|
|
3007
|
+
terminalError instanceof Error
|
|
3008
|
+
? terminalError.message
|
|
3009
|
+
: String(terminalError),
|
|
3010
|
+
},
|
|
3011
|
+
);
|
|
3012
|
+
}
|
|
3013
|
+
trace({
|
|
3014
|
+
runId: runIdForTrace,
|
|
3015
|
+
phase: 'coordinator.runner_run',
|
|
3016
|
+
ms: Date.now() - innerStartedAt,
|
|
3017
|
+
graphHash,
|
|
3018
|
+
});
|
|
3019
|
+
return result;
|
|
3020
|
+
} catch (innerError) {
|
|
3021
|
+
const failure = normalizePlayRunFailure(innerError);
|
|
3023
3022
|
console.error(
|
|
3024
|
-
'[coordinator]
|
|
3023
|
+
'[coordinator] DynamicWorkflow runner.run threw',
|
|
3025
3024
|
{
|
|
3026
3025
|
graphHash,
|
|
3027
3026
|
message:
|
|
3028
|
-
|
|
3029
|
-
?
|
|
3030
|
-
: String(
|
|
3027
|
+
innerError instanceof Error
|
|
3028
|
+
? innerError.message
|
|
3029
|
+
: String(innerError),
|
|
3030
|
+
name: innerError instanceof Error ? innerError.name : null,
|
|
3031
|
+
stack:
|
|
3032
|
+
innerError instanceof Error &&
|
|
3033
|
+
typeof innerError.stack === 'string'
|
|
3034
|
+
? innerError.stack.split('\n').slice(0, 12).join('\n')
|
|
3035
|
+
: null,
|
|
3031
3036
|
},
|
|
3032
3037
|
);
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3038
|
+
await markWorkflowRuntimeFailure({
|
|
3039
|
+
env,
|
|
3040
|
+
event: innerEvent,
|
|
3041
|
+
error: innerError,
|
|
3042
|
+
}).catch((markError) => {
|
|
3043
|
+
console.error(
|
|
3044
|
+
'[coordinator] failed to forward DynamicWorkflow runner error',
|
|
3045
|
+
{
|
|
3046
|
+
graphHash,
|
|
3047
|
+
message:
|
|
3048
|
+
markError instanceof Error
|
|
3049
|
+
? markError.message
|
|
3050
|
+
: String(markError),
|
|
3051
|
+
},
|
|
3052
|
+
);
|
|
3053
|
+
});
|
|
3054
|
+
await writeCoordinatorTerminalState(env, {
|
|
3055
|
+
runId: runIdForTrace,
|
|
3056
|
+
status: 'failed',
|
|
3057
|
+
error: failure.message,
|
|
3058
|
+
}).catch(() => undefined);
|
|
3059
|
+
throw innerError;
|
|
3060
|
+
}
|
|
3061
|
+
},
|
|
3062
|
+
};
|
|
3063
|
+
},
|
|
3064
|
+
);
|
|
3065
|
+
} finally {
|
|
3066
|
+
trace({
|
|
3067
|
+
runId: dispatchTrace.runId,
|
|
3068
|
+
phase: 'coordinator.dispatch_workflow_total',
|
|
3069
|
+
ms: Date.now() - dispatchWorkflowStartedAt,
|
|
3070
|
+
graphHash: dispatchTrace.graphHash,
|
|
3071
|
+
extra: {
|
|
3072
|
+
instanceId: dispatchTrace.instanceId,
|
|
3073
|
+
},
|
|
3074
|
+
});
|
|
3075
|
+
}
|
|
3045
3076
|
}
|
|
3046
3077
|
}
|
|
3047
3078
|
|
|
@@ -3426,6 +3457,18 @@ async function handleWorkflowRoute(input: {
|
|
|
3426
3457
|
const parseStartedAt = Date.now();
|
|
3427
3458
|
const params = (await request.json()) as PlayWorkflowParams;
|
|
3428
3459
|
submittedRunId = params.runId ?? runId;
|
|
3460
|
+
recordSubmitTiming({
|
|
3461
|
+
phase: 'coordinator.submit_received',
|
|
3462
|
+
ms: Date.now() - submitStartedAt,
|
|
3463
|
+
graphHash: params.graphHash ?? null,
|
|
3464
|
+
extra: {
|
|
3465
|
+
hasDynamicWorkerCode: Boolean(params.dynamicWorkerCode),
|
|
3466
|
+
dynamicWorkerBytes:
|
|
3467
|
+
typeof params.dynamicWorkerCode === 'string'
|
|
3468
|
+
? params.dynamicWorkerCode.length
|
|
3469
|
+
: 0,
|
|
3470
|
+
},
|
|
3471
|
+
});
|
|
3429
3472
|
recordSubmitTiming({
|
|
3430
3473
|
phase: 'coordinator.submit_parse_body',
|
|
3431
3474
|
ms: Date.now() - parseStartedAt,
|
|
@@ -3555,6 +3598,12 @@ async function handleWorkflowRoute(input: {
|
|
|
3555
3598
|
try {
|
|
3556
3599
|
const dispatchStartedAt = Date.now();
|
|
3557
3600
|
const createStartedAt = Date.now();
|
|
3601
|
+
recordSubmitTiming({
|
|
3602
|
+
phase: 'coordinator.workflow_create_start',
|
|
3603
|
+
ms: 0,
|
|
3604
|
+
graphHash: params.graphHash ?? null,
|
|
3605
|
+
extra: { instanceId: defaultInstanceId },
|
|
3606
|
+
});
|
|
3558
3607
|
const createResult = await createOrAttachWorkflowInstance({
|
|
3559
3608
|
create: () =>
|
|
3560
3609
|
createDynamicWorkflowInstance({
|
|
@@ -401,6 +401,9 @@ function captureRuntimeApiBinding(env: WorkerEnv): void {
|
|
|
401
401
|
}
|
|
402
402
|
|
|
403
403
|
let cachedCoordinatorBinding: WorkerEnv['COORDINATOR'] | null = null;
|
|
404
|
+
const TRACE_FLUSH_MS = 1_000;
|
|
405
|
+
const pendingTraceForwardsByRun = new Map<string, Promise<void>>();
|
|
406
|
+
|
|
404
407
|
function captureCoordinatorBinding(env: WorkerEnv): void {
|
|
405
408
|
cachedCoordinatorBinding = env.COORDINATOR ?? null;
|
|
406
409
|
}
|
|
@@ -685,32 +688,58 @@ function recordRunnerPerfTrace(input: {
|
|
|
685
688
|
ms?: number;
|
|
686
689
|
extra?: Record<string, unknown>;
|
|
687
690
|
}): void {
|
|
691
|
+
// Benchmark note: these runner spans decompose the server watch's terminal
|
|
692
|
+
// wait. They are logged locally and forwarded to the coordinator so
|
|
693
|
+
// `/api/v2/plays/run --watch` benchmark exports can join them with
|
|
694
|
+
// `server.stream_scheduler_terminal_event` by runId.
|
|
688
695
|
if (!input.req.runId || !input.phase) return;
|
|
696
|
+
const phase = input.phase.startsWith('runner.')
|
|
697
|
+
? input.phase
|
|
698
|
+
: `runner.${input.phase}`;
|
|
689
699
|
// Tool-level traces can fire once per row/provider step. Forwarding each one
|
|
690
700
|
// through the coordinator binding can consume Cloudflare's subrequest budget
|
|
691
701
|
// before large batched maps finish.
|
|
692
|
-
if (
|
|
702
|
+
if (phase.startsWith('runner.tool.')) {
|
|
693
703
|
return;
|
|
694
704
|
}
|
|
695
705
|
const payload = {
|
|
696
706
|
ts: Date.now(),
|
|
697
707
|
source: 'dynamic_worker' as const,
|
|
698
708
|
runId: input.req.runId,
|
|
699
|
-
phase
|
|
709
|
+
phase,
|
|
700
710
|
ms: input.ms ?? 0,
|
|
701
711
|
...(input.extra ?? {}),
|
|
702
712
|
};
|
|
703
713
|
console.log(
|
|
704
714
|
`[deepline-run:${input.req.runId}] [perf-trace] ${JSON.stringify(payload)}`,
|
|
705
715
|
);
|
|
706
|
-
cachedCoordinatorBinding
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
716
|
+
const binding = cachedCoordinatorBinding;
|
|
717
|
+
if (!binding) return;
|
|
718
|
+
const forward = binding
|
|
719
|
+
.recordPerfTrace(input.req.runId, payload)
|
|
720
|
+
.catch(() => undefined);
|
|
721
|
+
const previous = pendingTraceForwardsByRun.get(input.req.runId);
|
|
722
|
+
const pending = previous
|
|
723
|
+
? previous.then(
|
|
724
|
+
() => forward,
|
|
725
|
+
() => forward,
|
|
726
|
+
)
|
|
727
|
+
: forward;
|
|
728
|
+
pendingTraceForwardsByRun.set(input.req.runId, pending);
|
|
729
|
+
void pending.finally(() => {
|
|
730
|
+
if (pendingTraceForwardsByRun.get(input.req.runId) === pending) {
|
|
731
|
+
pendingTraceForwardsByRun.delete(input.req.runId);
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
async function drainRunnerPerfTraces(req: RunRequest): Promise<void> {
|
|
737
|
+
const pending = pendingTraceForwardsByRun.get(req.runId);
|
|
738
|
+
if (!pending) return;
|
|
739
|
+
await Promise.race([
|
|
740
|
+
pending,
|
|
741
|
+
new Promise((resolve) => setTimeout(resolve, TRACE_FLUSH_MS)),
|
|
742
|
+
]);
|
|
714
743
|
}
|
|
715
744
|
|
|
716
745
|
function makeRequestId(): string {
|
|
@@ -5962,7 +5991,17 @@ async function executeRunRequest(
|
|
|
5962
5991
|
onToolFailed: (toolId, at) => stepLifecycle?.onToolFailed(toolId, at),
|
|
5963
5992
|
};
|
|
5964
5993
|
|
|
5994
|
+
let hasEmittedRunnerEvent = false;
|
|
5965
5995
|
const wrappedEmit = (event: RunnerEvent) => {
|
|
5996
|
+
if (!hasEmittedRunnerEvent) {
|
|
5997
|
+
hasEmittedRunnerEvent = true;
|
|
5998
|
+
recordRunnerPerfTrace({
|
|
5999
|
+
req,
|
|
6000
|
+
phase: 'first_event',
|
|
6001
|
+
ms: nowMs() - startedAt,
|
|
6002
|
+
extra: { eventType: event.type },
|
|
6003
|
+
});
|
|
6004
|
+
}
|
|
5966
6005
|
if (event.type === 'log') {
|
|
5967
6006
|
appendRunLogLine(event.message);
|
|
5968
6007
|
flushLedgerEvents(false);
|
|
@@ -6133,6 +6172,14 @@ async function executeRunRequest(
|
|
|
6133
6172
|
phase: 'runner.execute_total',
|
|
6134
6173
|
ms: nowMs() - startedAt,
|
|
6135
6174
|
});
|
|
6175
|
+
// The server-side watch path reads coordinator-buffered perf traces from
|
|
6176
|
+
// the same tail response that carries the terminal event. Runner traces are
|
|
6177
|
+
// forwarded asynchronously during execution so normal play latency is not
|
|
6178
|
+
// gated on observability writes; before returning terminal output, wait a
|
|
6179
|
+
// bounded interval for those writes to land. This keeps benchmark exports
|
|
6180
|
+
// able to decompose "terminal wait" into runner/dataset/ledger phases
|
|
6181
|
+
// without turning trace delivery into a correctness dependency.
|
|
6182
|
+
await drainRunnerPerfTraces(req);
|
|
6136
6183
|
return {
|
|
6137
6184
|
playName: req.playName,
|
|
6138
6185
|
result: serializedResult,
|
|
@@ -6160,6 +6207,7 @@ async function executeRunRequest(
|
|
|
6160
6207
|
appendRunLogLine(
|
|
6161
6208
|
`${aborted ? '[cancelled]' : '[error]'} ${redactSecretsFromLogString(message)}`,
|
|
6162
6209
|
);
|
|
6210
|
+
const terminalUpdateStartedAt = nowMs();
|
|
6163
6211
|
await flushTerminalLedgerEvents({
|
|
6164
6212
|
type: aborted ? 'run.cancelled' : 'run.failed',
|
|
6165
6213
|
runId: req.runId,
|
|
@@ -6184,25 +6232,55 @@ async function executeRunRequest(
|
|
|
6184
6232
|
],
|
|
6185
6233
|
},
|
|
6186
6234
|
});
|
|
6235
|
+
recordRunnerPerfTrace({
|
|
6236
|
+
req,
|
|
6237
|
+
phase: aborted
|
|
6238
|
+
? 'runner.terminal_ledger_append_cancelled'
|
|
6239
|
+
: 'runner.terminal_ledger_append_failed',
|
|
6240
|
+
ms: nowMs() - terminalUpdateStartedAt,
|
|
6241
|
+
extra: {
|
|
6242
|
+
errorCode: failure.code,
|
|
6243
|
+
errorPhase: failure.phase,
|
|
6244
|
+
},
|
|
6245
|
+
});
|
|
6246
|
+
const billingStartedAt = nowMs();
|
|
6187
6247
|
await finalizeWorkerComputeBilling({
|
|
6188
6248
|
req,
|
|
6189
6249
|
success: false,
|
|
6190
6250
|
actionEstimate: 4,
|
|
6191
|
-
})
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6251
|
+
})
|
|
6252
|
+
.catch((finalizeError) => {
|
|
6253
|
+
console.error(
|
|
6254
|
+
`[play-harness] non-fatal compute billing finalize failed runId=${req.runId}: ${
|
|
6255
|
+
finalizeError instanceof Error
|
|
6256
|
+
? finalizeError.message
|
|
6257
|
+
: String(finalizeError)
|
|
6258
|
+
}`,
|
|
6259
|
+
);
|
|
6260
|
+
})
|
|
6261
|
+
.finally(() => {
|
|
6262
|
+
recordRunnerPerfTrace({
|
|
6263
|
+
req,
|
|
6264
|
+
phase: 'runner.compute_billing_finalize_failed',
|
|
6265
|
+
ms: nowMs() - billingStartedAt,
|
|
6266
|
+
});
|
|
6267
|
+
});
|
|
6200
6268
|
}
|
|
6201
6269
|
await signalParentPlayTerminal({
|
|
6202
6270
|
req,
|
|
6203
6271
|
status: aborted ? 'cancelled' : 'failed',
|
|
6204
6272
|
error: message,
|
|
6205
6273
|
}).catch(() => null);
|
|
6274
|
+
recordRunnerPerfTrace({
|
|
6275
|
+
req,
|
|
6276
|
+
phase: aborted ? 'runner.execute_cancelled' : 'runner.execute_failed',
|
|
6277
|
+
ms: nowMs() - startedAt,
|
|
6278
|
+
extra: {
|
|
6279
|
+
errorCode: failure.code,
|
|
6280
|
+
errorPhase: failure.phase,
|
|
6281
|
+
},
|
|
6282
|
+
});
|
|
6283
|
+
await drainRunnerPerfTraces(req);
|
|
6206
6284
|
throw error;
|
|
6207
6285
|
} finally {
|
|
6208
6286
|
clearTimeout(runtimeDeadlineTimer);
|
|
@@ -6631,14 +6709,29 @@ export class TenantWorkflow extends WorkflowEntrypoint<
|
|
|
6631
6709
|
// Must run BEFORE any SDK call site that would reach into HARNESS,
|
|
6632
6710
|
// i.e. before user play code is invoked. Idempotent within a run.
|
|
6633
6711
|
captureHarnessBinding(this.env);
|
|
6712
|
+
recordRunnerPerfTrace({
|
|
6713
|
+
req,
|
|
6714
|
+
phase: 'tenant_workflow_entry',
|
|
6715
|
+
ms: 0,
|
|
6716
|
+
extra: {
|
|
6717
|
+
hasWorkflowStep: true,
|
|
6718
|
+
},
|
|
6719
|
+
});
|
|
6634
6720
|
// Fire the one-time wiring probe (deduplicated across runs in the
|
|
6635
6721
|
// same isolate). Awaited so the result is in the log before user code
|
|
6636
6722
|
// begins. A missing or unhealthy HARNESS fails the run before user code
|
|
6637
6723
|
// can accidentally take a slower fallback path.
|
|
6724
|
+
const probeStartedAt = nowMs();
|
|
6638
6725
|
await probeHarnessOnce(this.env, runPrefix);
|
|
6726
|
+
recordRunnerPerfTrace({
|
|
6727
|
+
req,
|
|
6728
|
+
phase: 'tenant_workflow_probe_harness',
|
|
6729
|
+
ms: nowMs() - probeStartedAt,
|
|
6730
|
+
});
|
|
6639
6731
|
const abortController = new AbortController();
|
|
6640
6732
|
try {
|
|
6641
|
-
|
|
6733
|
+
const executeStartedAt = nowMs();
|
|
6734
|
+
const output = (await executeRunRequest(
|
|
6642
6735
|
req,
|
|
6643
6736
|
this.env,
|
|
6644
6737
|
(runnerEvent) => {
|
|
@@ -6669,6 +6762,12 @@ export class TenantWorkflow extends WorkflowEntrypoint<
|
|
|
6669
6762
|
waitUntil: (promise) => this.ctx.waitUntil(promise),
|
|
6670
6763
|
},
|
|
6671
6764
|
)) as Record<string, unknown>;
|
|
6765
|
+
recordRunnerPerfTrace({
|
|
6766
|
+
req,
|
|
6767
|
+
phase: 'tenant_workflow_execute_request',
|
|
6768
|
+
ms: nowMs() - executeStartedAt,
|
|
6769
|
+
});
|
|
6770
|
+
return output;
|
|
6672
6771
|
} catch (error) {
|
|
6673
6772
|
// CF Workflows + the dynamic-workflows framework swallow the error
|
|
6674
6773
|
// message and surface only "internal error; reference = <id>" via
|
|
@@ -99,10 +99,10 @@ export const SDK_RELEASE = {
|
|
|
99
99
|
// skill on the sdk sync surface, and the people-search-to-email prebuilt.
|
|
100
100
|
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
101
101
|
// the SDK enrich generator's one-second stale policy.
|
|
102
|
-
version: '0.1.
|
|
102
|
+
version: '0.1.112',
|
|
103
103
|
apiContract: '2026-06-dataset-column-cell-stale-hard-cutover',
|
|
104
104
|
supportPolicy: {
|
|
105
|
-
latest: '0.1.
|
|
105
|
+
latest: '0.1.112',
|
|
106
106
|
minimumSupported: '0.1.53',
|
|
107
107
|
deprecatedBelow: '0.1.53',
|
|
108
108
|
commandMinimumSupported: [
|