deepline 0.1.119 → 0.1.121
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 +4 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/README.md +21 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/batching.ts +185 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-batch.ts +107 -0
- package/dist/{repo → bundling-sources}/sdk/src/client.ts +116 -12
- package/dist/bundling-sources/sdk/src/compat.ts +191 -0
- package/dist/bundling-sources/sdk/src/gtm.ts +146 -0
- package/dist/bundling-sources/sdk/src/helpers.ts +12 -0
- package/dist/{repo → bundling-sources}/sdk/src/index.ts +2 -1
- package/dist/{repo → bundling-sources}/sdk/src/play.ts +3 -1
- package/dist/{repo → bundling-sources}/sdk/src/plays/bundle-play-file.ts +17 -5
- package/dist/{repo → bundling-sources}/sdk/src/release.ts +2 -2
- package/dist/{repo → bundling-sources}/sdk/src/runs/observe-transport.ts +2 -3
- package/dist/bundling-sources/shared_libs/play-data-plane/index.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +838 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +5510 -0
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-contract.ts +261 -0
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +828 -0
- package/dist/bundling-sources/shared_libs/play-runtime/dataset-id.ts +10 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-runtime-config.ts +50 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durability-store.ts +20 -0
- package/dist/bundling-sources/shared_libs/play-runtime/event-wait-tools.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +171 -0
- package/dist/bundling-sources/shared_libs/play-runtime/hatchet-cold-execution-diagnosis.ts +321 -0
- package/dist/bundling-sources/shared_libs/play-runtime/hatchet-cold-execution-target.ts +158 -0
- package/dist/bundling-sources/shared_libs/play-runtime/internal-step-ids.ts +34 -0
- package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +34 -0
- package/dist/bundling-sources/shared_libs/play-runtime/live-state-contract.ts +50 -0
- package/dist/bundling-sources/shared_libs/play-runtime/map-execution-frame.ts +119 -0
- package/dist/{repo → bundling-sources}/shared_libs/play-runtime/map-row-identity.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-latency-trace.ts +636 -0
- package/dist/bundling-sources/shared_libs/play-runtime/postgres-json.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-runtime/progress-emitter.ts +197 -0
- package/dist/bundling-sources/shared_libs/play-runtime/projection.ts +262 -0
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +143 -0
- package/dist/bundling-sources/shared_libs/play-runtime/public-play-contract.ts +42 -0
- package/dist/bundling-sources/shared_libs/play-runtime/receipt-status.ts +40 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +178 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +4015 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-constraints.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-neon-serverless.ts +238 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-pg.ts +53 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver.ts +149 -0
- package/dist/bundling-sources/shared_libs/play-runtime/suspension.ts +68 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-batch-executor.ts +149 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result-types.ts +159 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tracing.ts +33 -0
- package/dist/bundling-sources/shared_libs/play-runtime/waterfall-replay.ts +79 -0
- package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +139 -0
- package/dist/bundling-sources/shared_libs/plays/artifact-transport.ts +14 -0
- package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +49 -0
- package/dist/bundling-sources/shared_libs/plays/compiler-manifest.ts +41 -0
- package/dist/bundling-sources/shared_libs/plays/dataset-summary.ts +163 -0
- package/dist/bundling-sources/shared_libs/plays/definition.ts +267 -0
- package/dist/bundling-sources/shared_libs/plays/file-refs.ts +11 -0
- package/dist/bundling-sources/shared_libs/plays/input-contract.ts +146 -0
- package/dist/bundling-sources/shared_libs/plays/resolve-static-pipeline.ts +190 -0
- package/dist/bundling-sources/shared_libs/plays/runtime-validation.ts +417 -0
- package/dist/bundling-sources/shared_libs/plays/tool-codegen.ts +142 -0
- package/dist/bundling-sources/shared_libs/security/safe-outbound-fetch.ts +274 -0
- package/dist/bundling-sources/shared_libs/temporal/preview-config.ts +150 -0
- package/dist/cli/index.js +811 -2207
- package/dist/cli/index.mjs +847 -2258
- package/dist/compiler-manifest-BjoRENv9.d.mts +227 -0
- package/dist/compiler-manifest-BjoRENv9.d.ts +227 -0
- package/dist/index.d.mts +8 -231
- package/dist/index.d.ts +8 -231
- package/dist/index.js +101 -15
- package/dist/index.mjs +101 -15
- package/dist/plays/bundle-play-file.d.mts +120 -0
- package/dist/plays/bundle-play-file.d.ts +120 -0
- package/dist/plays/bundle-play-file.mjs +1830 -0
- package/package.json +4 -9
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/child-play-await.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/child-play-submit.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/coordinator-entry.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/dedup-do.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/entry.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/csv-rows.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/dataset-handles.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/harness-receipt-store.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/live-progress.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/map-chunk-plan.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/receipts.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/row-isolation.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/tool-http-errors.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/workflow-instance-create.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/workflow-retry-state.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/workflow-retry.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/agent-runtime.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/config.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/errors.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/http.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/plays/harness-stub.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/plays/local-file-discovery.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/stream-reconnect.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/tool-output.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/types.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/version.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/worker-play-entry.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-data-plane/cell-policy.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-data-plane/column-names.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-data-plane/sheet-contract.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/backend.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/batch-runtime.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/batching-types.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/cell-staleness.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/coordinator-headers.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/csv-rename.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/db-session-crypto.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/db-session-plan.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/db-session.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/dedup-backend.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/default-batch-strategies.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/email-status.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/execution-plan.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/extractor-targets.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/fullenrich-batching.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/coordinator-rate-state-backend.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/governor.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/policy.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/rate-state-backend.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/live-events.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/play-runtime-batching-registry.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/profiles.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/providers.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/run-failure.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/run-ledger.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/run-snapshot-stream.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/scheduler-backend.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/secret-capability.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/secret-redaction.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/step-lifecycle-tracker.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/step-program-dataset-builder.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/submit-limits.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/tool-result.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/work-receipts.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/bootstrap-routes.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/bundling/index.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/bundling/limits.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/contracts.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/dataset.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/row-identity.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/secret-guardrails.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/static-pipeline.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/security/outbound-url-policy.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/security/safe-fetch.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/temporal/constants.ts +0 -0
|
@@ -0,0 +1,838 @@
|
|
|
1
|
+
import { createWriteStream } from 'node:fs';
|
|
2
|
+
import { stat } from 'node:fs/promises';
|
|
3
|
+
import { Readable } from 'node:stream';
|
|
4
|
+
import { pipeline } from 'node:stream/promises';
|
|
5
|
+
import type { PlaySheetContract } from '@shared_libs/plays/static-pipeline';
|
|
6
|
+
import type { PlayRowUpdate } from '@shared_libs/play-runtime/ctx-types';
|
|
7
|
+
import type { PlayRunTimelineEntry } from '@shared_libs/play-runtime/live-events';
|
|
8
|
+
import {
|
|
9
|
+
buildPlayRunLedgerEventsFromStatusPatch,
|
|
10
|
+
buildTerminalLogReplayEvents,
|
|
11
|
+
createEmptyPlayRunLedgerSnapshot,
|
|
12
|
+
reducePlayRunLedgerEvents,
|
|
13
|
+
slicePositionalLogLines,
|
|
14
|
+
type PlayRunLedgerEvent,
|
|
15
|
+
type PlayRunLedgerSnapshot,
|
|
16
|
+
} from '@shared_libs/play-runtime/run-ledger';
|
|
17
|
+
import type {
|
|
18
|
+
ComputeBillingItem,
|
|
19
|
+
PlayStagedFileRef,
|
|
20
|
+
PlayVisualNodeProgressMap,
|
|
21
|
+
} from '@shared_libs/play-runtime/worker-api-types';
|
|
22
|
+
import type { RuntimeStepReceipt } from '@shared_libs/play-runtime/ctx-types';
|
|
23
|
+
import type {
|
|
24
|
+
CreateDbSessionRequest,
|
|
25
|
+
CreateDbSessionResponse,
|
|
26
|
+
} from '@shared_libs/play-runtime/db-session';
|
|
27
|
+
import type { PlayBundleArtifact } from '@shared_libs/plays/artifact-types';
|
|
28
|
+
|
|
29
|
+
export type StoredPlayArtifactPayload = {
|
|
30
|
+
sourceCode: string;
|
|
31
|
+
codeFormat: 'function' | 'cjs_module' | 'esm_module';
|
|
32
|
+
artifact: PlayBundleArtifact;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export type RuntimeStatusUpdate = {
|
|
36
|
+
playId: string;
|
|
37
|
+
status: string;
|
|
38
|
+
error?: string;
|
|
39
|
+
runtimeBackend?: string | null;
|
|
40
|
+
artifactHash?: string | null;
|
|
41
|
+
graphHash?: string | null;
|
|
42
|
+
waitKind?: string | null;
|
|
43
|
+
waitUntil?: number | null;
|
|
44
|
+
activeBoundaryId?: string | null;
|
|
45
|
+
lastCheckpointAt?: number | null;
|
|
46
|
+
liveLogs?: string[];
|
|
47
|
+
/**
|
|
48
|
+
* Monotonic count of log lines the producer ever emitted on this run's
|
|
49
|
+
* channel. `liveLogs` is a rotating tail of those lines; the total lets the
|
|
50
|
+
* positional cursor stay correct once the buffer has rotated.
|
|
51
|
+
*/
|
|
52
|
+
liveLogTotalCount?: number;
|
|
53
|
+
/**
|
|
54
|
+
* Explicit terminal-output replay for final runner logs when the caller must
|
|
55
|
+
* keep `status` nonterminal. Hatchet/Postgres progress finalizers do this so
|
|
56
|
+
* scheduler projection remains the only terminal run writer, while the Run
|
|
57
|
+
* Log Stream still gets terminal transport recovery semantics.
|
|
58
|
+
*/
|
|
59
|
+
terminalLogReplay?: {
|
|
60
|
+
lines: string[];
|
|
61
|
+
totalCount?: number;
|
|
62
|
+
} | null;
|
|
63
|
+
liveTimeline?: PlayRunTimelineEntry[];
|
|
64
|
+
liveNodeProgress?: PlayVisualNodeProgressMap;
|
|
65
|
+
result?: Record<string, unknown> | null;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type RuntimeSaveResults = {
|
|
69
|
+
playId: string;
|
|
70
|
+
result: {
|
|
71
|
+
success: boolean;
|
|
72
|
+
error?: string;
|
|
73
|
+
publicResult?: Record<string, unknown> | null;
|
|
74
|
+
maxCreditsPerRun?: number | null;
|
|
75
|
+
temporalActionEstimate?: {
|
|
76
|
+
totalActions?: number;
|
|
77
|
+
[key: string]: unknown;
|
|
78
|
+
} | null;
|
|
79
|
+
};
|
|
80
|
+
userId?: string | null;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
type RuntimeApiRequest =
|
|
84
|
+
| {
|
|
85
|
+
action: 'create_signed_artifact_url';
|
|
86
|
+
storageKey: string;
|
|
87
|
+
}
|
|
88
|
+
| {
|
|
89
|
+
action: 'create_signed_staged_file_url';
|
|
90
|
+
file: Pick<PlayStagedFileRef, 'storageKey'>;
|
|
91
|
+
}
|
|
92
|
+
| ({
|
|
93
|
+
action: 'create_db_session';
|
|
94
|
+
} & CreateDbSessionRequest)
|
|
95
|
+
| {
|
|
96
|
+
action: 'append_run_events';
|
|
97
|
+
playId: string;
|
|
98
|
+
events: PlayRunLedgerEvent[];
|
|
99
|
+
}
|
|
100
|
+
| {
|
|
101
|
+
action: 'start_inline_child_run';
|
|
102
|
+
playName: string;
|
|
103
|
+
runId: string;
|
|
104
|
+
workflowFamilyKey?: string | null;
|
|
105
|
+
artifactStorageKey?: string | null;
|
|
106
|
+
artifactHash?: string | null;
|
|
107
|
+
graphHash?: string | null;
|
|
108
|
+
runtimeBackend?: string | null;
|
|
109
|
+
schedulerBackend?: string | null;
|
|
110
|
+
schedulerSchema?: string | null;
|
|
111
|
+
executionProfile?: string | null;
|
|
112
|
+
maxCreditsPerRun?: number | null;
|
|
113
|
+
staticPipeline?: unknown;
|
|
114
|
+
source?: 'published' | 'ad_hoc' | 'draft';
|
|
115
|
+
activeRunLimit?: number | null;
|
|
116
|
+
}
|
|
117
|
+
| ({
|
|
118
|
+
action: 'save_results';
|
|
119
|
+
} & RuntimeSaveResults)
|
|
120
|
+
| {
|
|
121
|
+
action: 'apply_row_updates';
|
|
122
|
+
playName: string;
|
|
123
|
+
tableNamespace: string;
|
|
124
|
+
sheetContract: PlaySheetContract;
|
|
125
|
+
runId: string;
|
|
126
|
+
userEmail: string;
|
|
127
|
+
updates: Array<Omit<PlayRowUpdate, 'rowId'> & { runId?: string }>;
|
|
128
|
+
}
|
|
129
|
+
| {
|
|
130
|
+
action: 'compute_billing_upsert';
|
|
131
|
+
sessionId: string;
|
|
132
|
+
orgId: string;
|
|
133
|
+
userId?: string | null;
|
|
134
|
+
operation: string;
|
|
135
|
+
workflowId?: string;
|
|
136
|
+
runId?: string;
|
|
137
|
+
}
|
|
138
|
+
| {
|
|
139
|
+
action: 'compute_billing_record_item';
|
|
140
|
+
sessionId: string;
|
|
141
|
+
orgId: string;
|
|
142
|
+
userId?: string | null;
|
|
143
|
+
operation: string;
|
|
144
|
+
item: ComputeBillingItem;
|
|
145
|
+
}
|
|
146
|
+
| {
|
|
147
|
+
action: 'compute_billing_finalize';
|
|
148
|
+
sessionId: string;
|
|
149
|
+
orgId: string;
|
|
150
|
+
userId?: string | null;
|
|
151
|
+
operation: string;
|
|
152
|
+
status: 'completed' | 'error';
|
|
153
|
+
workflowId?: string;
|
|
154
|
+
runId?: string;
|
|
155
|
+
maxCreditsPerRun?: number | null;
|
|
156
|
+
finalItem: ComputeBillingItem;
|
|
157
|
+
}
|
|
158
|
+
| {
|
|
159
|
+
action: 'get_runtime_step_receipt';
|
|
160
|
+
playName: string;
|
|
161
|
+
runId: string;
|
|
162
|
+
key: string;
|
|
163
|
+
}
|
|
164
|
+
| {
|
|
165
|
+
action: 'claim_runtime_step_receipt';
|
|
166
|
+
playName: string;
|
|
167
|
+
runId: string;
|
|
168
|
+
key: string;
|
|
169
|
+
reclaimRunning?: boolean;
|
|
170
|
+
}
|
|
171
|
+
| {
|
|
172
|
+
action: 'complete_runtime_step_receipt';
|
|
173
|
+
playName: string;
|
|
174
|
+
runId: string;
|
|
175
|
+
key: string;
|
|
176
|
+
output: unknown;
|
|
177
|
+
}
|
|
178
|
+
| {
|
|
179
|
+
action: 'fail_runtime_step_receipt';
|
|
180
|
+
playName: string;
|
|
181
|
+
runId: string;
|
|
182
|
+
key: string;
|
|
183
|
+
error: string;
|
|
184
|
+
}
|
|
185
|
+
| {
|
|
186
|
+
action: 'skip_runtime_step_receipt';
|
|
187
|
+
playName: string;
|
|
188
|
+
runId: string;
|
|
189
|
+
key: string;
|
|
190
|
+
output?: unknown;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export type WorkerRuntimeApiContext = {
|
|
194
|
+
baseUrl: string;
|
|
195
|
+
executorToken: string;
|
|
196
|
+
vercelProtectionBypassToken?: string | null;
|
|
197
|
+
fetch?: typeof fetch;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const APP_RUNTIME_API_RETRY_DELAYS_MS = [100, 250, 500, 1_000] as const;
|
|
201
|
+
const APP_RUNTIME_API_APPEND_RETRY_DELAYS_MS = [
|
|
202
|
+
100, 250, 500, 1_000, 2_000, 4_000, 8_000,
|
|
203
|
+
] as const;
|
|
204
|
+
const RUN_STATUS_LEDGER_SNAPSHOT_CACHE_LIMIT = 1_000;
|
|
205
|
+
const runStatusLedgerSnapshots = new Map<string, PlayRunLedgerSnapshot>();
|
|
206
|
+
// Positional log cursor per run: count of liveLogs lines already forwarded to
|
|
207
|
+
// the ledger from this process. Process-local on purpose — a fresh process
|
|
208
|
+
// re-sends from offset 0 and Run Log Stream ingestion skips the overlap
|
|
209
|
+
// positionally (exactly-once on the channel, repeated identical lines kept).
|
|
210
|
+
const runLogChannelSentCounts = new Map<string, number>();
|
|
211
|
+
const runStatusUpdateChains = new Map<string, Promise<void>>();
|
|
212
|
+
const vercelProtectionCookieCache = new Map<string, Promise<string | null>>();
|
|
213
|
+
|
|
214
|
+
function isTerminalRuntimeStatus(status: string): boolean {
|
|
215
|
+
return (
|
|
216
|
+
status === 'completed' ||
|
|
217
|
+
status === 'failed' ||
|
|
218
|
+
status === 'cancelled' ||
|
|
219
|
+
status === 'terminated' ||
|
|
220
|
+
status === 'timed_out'
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function rememberRunStatusLedgerSnapshot(
|
|
225
|
+
runId: string,
|
|
226
|
+
snapshot: PlayRunLedgerSnapshot,
|
|
227
|
+
) {
|
|
228
|
+
runStatusLedgerSnapshots.delete(runId);
|
|
229
|
+
runStatusLedgerSnapshots.set(runId, snapshot);
|
|
230
|
+
while (
|
|
231
|
+
runStatusLedgerSnapshots.size > RUN_STATUS_LEDGER_SNAPSHOT_CACHE_LIMIT
|
|
232
|
+
) {
|
|
233
|
+
const oldestRunId = runStatusLedgerSnapshots.keys().next().value;
|
|
234
|
+
if (!oldestRunId) break;
|
|
235
|
+
runStatusLedgerSnapshots.delete(oldestRunId);
|
|
236
|
+
runLogChannelSentCounts.delete(oldestRunId);
|
|
237
|
+
runStatusUpdateChains.delete(oldestRunId);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function isRetryableAppRuntimeResponse(input: {
|
|
242
|
+
action: RuntimeApiRequest['action'];
|
|
243
|
+
status: number;
|
|
244
|
+
body: string;
|
|
245
|
+
}): boolean {
|
|
246
|
+
if (!isRetryableAppRuntimeAction(input.action)) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
if (
|
|
250
|
+
input.action === 'append_run_events' &&
|
|
251
|
+
input.status === 500 &&
|
|
252
|
+
/Play run .+ not found/i.test(input.body)
|
|
253
|
+
) {
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
if (input.status === 500 && isTransientAppRuntimeFailureBody(input.body)) {
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
return (
|
|
260
|
+
input.status === 429 ||
|
|
261
|
+
input.status === 502 ||
|
|
262
|
+
input.status === 503 ||
|
|
263
|
+
input.status === 504
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function isTransientAppRuntimeFailureBody(body: string): boolean {
|
|
268
|
+
return /WorkerOverloaded|"\s*code\s*"\s*:\s*"\s*InternalServerError\s*"|Your request couldn't be completed\. Try again later\.|timeout exceeded when trying to connect|timed out|fetch failed|ECONNRESET|ECONNREFUSED|UND_ERR_CONNECT_TIMEOUT/i.test(
|
|
269
|
+
body,
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function isRetryableAppRuntimeFetchError(input: {
|
|
274
|
+
action: RuntimeApiRequest['action'];
|
|
275
|
+
error: unknown;
|
|
276
|
+
}): boolean {
|
|
277
|
+
if (!isRetryableAppRuntimeAction(input.action)) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
const message =
|
|
281
|
+
input.error instanceof Error ? input.error.message : String(input.error);
|
|
282
|
+
return /fetch failed|connection (terminated|timeout|timed out|closed|reset)|econnreset|etimedout|econnrefused/i.test(
|
|
283
|
+
message,
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function isRetryableAppRuntimeAction(
|
|
288
|
+
action: RuntimeApiRequest['action'],
|
|
289
|
+
): boolean {
|
|
290
|
+
return (
|
|
291
|
+
action === 'append_run_events' ||
|
|
292
|
+
action === 'create_db_session' ||
|
|
293
|
+
action === 'create_signed_artifact_url' ||
|
|
294
|
+
action === 'create_signed_staged_file_url'
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function appRuntimeRetryDelaysForAction(
|
|
299
|
+
action: RuntimeApiRequest['action'],
|
|
300
|
+
): readonly number[] {
|
|
301
|
+
return action === 'append_run_events'
|
|
302
|
+
? APP_RUNTIME_API_APPEND_RETRY_DELAYS_MS
|
|
303
|
+
: APP_RUNTIME_API_RETRY_DELAYS_MS;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function appRuntimeMaxAttempts(action: RuntimeApiRequest['action']): number {
|
|
307
|
+
return appRuntimeRetryDelaysForAction(action).length + 1;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function appRuntimeRetryDelayMs(
|
|
311
|
+
action: RuntimeApiRequest['action'],
|
|
312
|
+
attempt: number,
|
|
313
|
+
): number {
|
|
314
|
+
return appRuntimeRetryDelaysForAction(action)[attempt - 1] ?? 1_000;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function sleep(ms: number): Promise<void> {
|
|
318
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function resolveAppRuntimeApiUrl(context: WorkerRuntimeApiContext): string {
|
|
322
|
+
const baseUrl = context.baseUrl.trim().replace(/\/$/, '');
|
|
323
|
+
const url = new URL(`${baseUrl}/api/v2/plays/internal/runtime`);
|
|
324
|
+
const bypassToken = context.vercelProtectionBypassToken?.trim();
|
|
325
|
+
if (bypassToken) {
|
|
326
|
+
url.searchParams.set('x-vercel-set-bypass-cookie', 'true');
|
|
327
|
+
url.searchParams.set('x-vercel-protection-bypass', bypassToken);
|
|
328
|
+
}
|
|
329
|
+
return url.toString();
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function setCookieHeaders(headers: Headers): string[] {
|
|
333
|
+
const getter = (headers as Headers & { getSetCookie?: () => string[] })
|
|
334
|
+
.getSetCookie;
|
|
335
|
+
if (typeof getter === 'function') {
|
|
336
|
+
return getter.call(headers);
|
|
337
|
+
}
|
|
338
|
+
const single = headers.get('set-cookie');
|
|
339
|
+
return single ? [single] : [];
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function cookieHeaderFromSetCookie(headers: Headers): string | null {
|
|
343
|
+
const cookies = setCookieHeaders(headers)
|
|
344
|
+
.flatMap((header) => header.split(/,(?=\s*[^;,=]+=[^;,]+)/g))
|
|
345
|
+
.map((header) => header.split(';', 1)[0]?.trim() ?? '')
|
|
346
|
+
.filter(Boolean);
|
|
347
|
+
return cookies.length > 0 ? cookies.join('; ') : null;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function resolveVercelProtectionCookie(
|
|
351
|
+
context: WorkerRuntimeApiContext,
|
|
352
|
+
): Promise<string | null> {
|
|
353
|
+
const bypassToken = context.vercelProtectionBypassToken?.trim();
|
|
354
|
+
if (!bypassToken) return Promise.resolve(null);
|
|
355
|
+
|
|
356
|
+
const baseUrl = context.baseUrl.trim().replace(/\/$/, '');
|
|
357
|
+
const cacheKey = `${baseUrl}\n${bypassToken}`;
|
|
358
|
+
const cached = vercelProtectionCookieCache.get(cacheKey);
|
|
359
|
+
if (cached) return cached;
|
|
360
|
+
|
|
361
|
+
const promise = (async () => {
|
|
362
|
+
const url = new URL(`${baseUrl}/api/v2/health`);
|
|
363
|
+
url.searchParams.set('x-vercel-set-bypass-cookie', 'true');
|
|
364
|
+
url.searchParams.set('x-vercel-protection-bypass', bypassToken);
|
|
365
|
+
const runtimeFetch = context.fetch ?? fetch;
|
|
366
|
+
const response = await runtimeFetch(url.toString(), {
|
|
367
|
+
headers: { 'x-vercel-protection-bypass': bypassToken },
|
|
368
|
+
}).catch(() => null);
|
|
369
|
+
return response ? cookieHeaderFromSetCookie(response.headers) : null;
|
|
370
|
+
})();
|
|
371
|
+
vercelProtectionCookieCache.set(cacheKey, promise);
|
|
372
|
+
return promise;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
async function postAppRuntimeApi<TResponse>(
|
|
376
|
+
context: WorkerRuntimeApiContext,
|
|
377
|
+
body: RuntimeApiRequest,
|
|
378
|
+
): Promise<TResponse> {
|
|
379
|
+
const baseUrl = context.baseUrl.trim().replace(/\/$/, '');
|
|
380
|
+
const token = context.executorToken.trim();
|
|
381
|
+
if (!baseUrl) {
|
|
382
|
+
throw new Error('Worker runtime API requires baseUrl.');
|
|
383
|
+
}
|
|
384
|
+
if (!token) {
|
|
385
|
+
throw new Error('Worker runtime API requires executorToken.');
|
|
386
|
+
}
|
|
387
|
+
const vercelProtectionCookie = await resolveVercelProtectionCookie(context);
|
|
388
|
+
|
|
389
|
+
const maxAttempts = appRuntimeMaxAttempts(body.action);
|
|
390
|
+
|
|
391
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
392
|
+
let response: Response;
|
|
393
|
+
try {
|
|
394
|
+
const runtimeFetch = context.fetch ?? fetch;
|
|
395
|
+
response = await runtimeFetch(resolveAppRuntimeApiUrl(context), {
|
|
396
|
+
method: 'POST',
|
|
397
|
+
headers: {
|
|
398
|
+
'content-type': 'application/json',
|
|
399
|
+
authorization: `Bearer ${token}`,
|
|
400
|
+
...(context.vercelProtectionBypassToken?.trim()
|
|
401
|
+
? {
|
|
402
|
+
'x-vercel-protection-bypass':
|
|
403
|
+
context.vercelProtectionBypassToken.trim(),
|
|
404
|
+
}
|
|
405
|
+
: {}),
|
|
406
|
+
...(vercelProtectionCookie ? { cookie: vercelProtectionCookie } : {}),
|
|
407
|
+
},
|
|
408
|
+
body: JSON.stringify(body),
|
|
409
|
+
});
|
|
410
|
+
} catch (error) {
|
|
411
|
+
if (
|
|
412
|
+
attempt < maxAttempts &&
|
|
413
|
+
isRetryableAppRuntimeFetchError({ action: body.action, error })
|
|
414
|
+
) {
|
|
415
|
+
await sleep(appRuntimeRetryDelayMs(body.action, attempt));
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
throw error;
|
|
419
|
+
}
|
|
420
|
+
if (response.ok) {
|
|
421
|
+
return (await response.json()) as TResponse;
|
|
422
|
+
}
|
|
423
|
+
const responseText = await response.text();
|
|
424
|
+
if (
|
|
425
|
+
attempt < maxAttempts &&
|
|
426
|
+
isRetryableAppRuntimeResponse({
|
|
427
|
+
action: body.action,
|
|
428
|
+
status: response.status,
|
|
429
|
+
body: responseText,
|
|
430
|
+
})
|
|
431
|
+
) {
|
|
432
|
+
await sleep(appRuntimeRetryDelayMs(body.action, attempt));
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
throw new Error(
|
|
436
|
+
`App runtime API ${body.action} failed with status ${response.status}: ${responseText}`,
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
throw new Error(`App runtime API ${body.action} failed after retries.`);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
type SignedR2ReadUrlResponse = {
|
|
444
|
+
url: string;
|
|
445
|
+
storageKey: string;
|
|
446
|
+
expiresAt: string;
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
function logSignedR2FetchPerf(input: {
|
|
450
|
+
kind: 'artifact' | 'staged_file';
|
|
451
|
+
storageKey: string;
|
|
452
|
+
startedAt: number;
|
|
453
|
+
bytes: number;
|
|
454
|
+
}) {
|
|
455
|
+
console.info('[perf][worker.r2.signed_fetch]', {
|
|
456
|
+
kind: input.kind,
|
|
457
|
+
storageKey: input.storageKey,
|
|
458
|
+
bytes: input.bytes,
|
|
459
|
+
ms: Date.now() - input.startedAt,
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
async function fetchSignedR2Buffer(input: {
|
|
464
|
+
kind: 'artifact' | 'staged_file';
|
|
465
|
+
signed: SignedR2ReadUrlResponse;
|
|
466
|
+
}): Promise<Buffer> {
|
|
467
|
+
const startedAt = Date.now();
|
|
468
|
+
const response = await fetch(input.signed.url);
|
|
469
|
+
if (!response.ok) {
|
|
470
|
+
throw new Error(
|
|
471
|
+
`Signed R2 ${input.kind} fetch failed for ${input.signed.storageKey} with status ${response.status}: ${await response.text()}`,
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
475
|
+
logSignedR2FetchPerf({
|
|
476
|
+
kind: input.kind,
|
|
477
|
+
storageKey: input.signed.storageKey,
|
|
478
|
+
startedAt,
|
|
479
|
+
bytes: buffer.byteLength,
|
|
480
|
+
});
|
|
481
|
+
return buffer;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
async function fetchSignedR2ToFile(input: {
|
|
485
|
+
kind: 'staged_file';
|
|
486
|
+
signed: SignedR2ReadUrlResponse;
|
|
487
|
+
targetPath: string;
|
|
488
|
+
}): Promise<void> {
|
|
489
|
+
const startedAt = Date.now();
|
|
490
|
+
const response = await fetch(input.signed.url);
|
|
491
|
+
if (!response.ok) {
|
|
492
|
+
throw new Error(
|
|
493
|
+
`Signed R2 ${input.kind} fetch failed for ${input.signed.storageKey} with status ${response.status}: ${await response.text()}`,
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
if (!response.body) {
|
|
497
|
+
throw new Error(
|
|
498
|
+
`Signed R2 ${input.kind} fetch returned an empty response body for ${input.signed.storageKey}.`,
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
await pipeline(
|
|
502
|
+
Readable.fromWeb(response.body as Parameters<typeof Readable.fromWeb>[0]),
|
|
503
|
+
createWriteStream(input.targetPath),
|
|
504
|
+
);
|
|
505
|
+
const written = await stat(input.targetPath);
|
|
506
|
+
logSignedR2FetchPerf({
|
|
507
|
+
kind: input.kind,
|
|
508
|
+
storageKey: input.signed.storageKey,
|
|
509
|
+
startedAt,
|
|
510
|
+
bytes: written.size,
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
export async function loadArtifactFromAppRuntime(
|
|
515
|
+
context: WorkerRuntimeApiContext,
|
|
516
|
+
storageKey: string,
|
|
517
|
+
): Promise<StoredPlayArtifactPayload> {
|
|
518
|
+
const signed = await postAppRuntimeApi<SignedR2ReadUrlResponse>(context, {
|
|
519
|
+
action: 'create_signed_artifact_url',
|
|
520
|
+
storageKey,
|
|
521
|
+
});
|
|
522
|
+
const buffer = await fetchSignedR2Buffer({
|
|
523
|
+
kind: 'artifact',
|
|
524
|
+
signed,
|
|
525
|
+
});
|
|
526
|
+
return JSON.parse(buffer.toString('utf-8')) as StoredPlayArtifactPayload;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
export async function loadStagedFileFromAppRuntime(
|
|
530
|
+
context: WorkerRuntimeApiContext,
|
|
531
|
+
file: Pick<PlayStagedFileRef, 'storageKey'>,
|
|
532
|
+
): Promise<Buffer> {
|
|
533
|
+
const signed = await postAppRuntimeApi<SignedR2ReadUrlResponse>(context, {
|
|
534
|
+
action: 'create_signed_staged_file_url',
|
|
535
|
+
file,
|
|
536
|
+
});
|
|
537
|
+
return fetchSignedR2Buffer({
|
|
538
|
+
kind: 'staged_file',
|
|
539
|
+
signed,
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
export async function createSignedStagedFileReadUrl(
|
|
544
|
+
context: WorkerRuntimeApiContext,
|
|
545
|
+
file: Pick<PlayStagedFileRef, 'storageKey'>,
|
|
546
|
+
): Promise<SignedR2ReadUrlResponse> {
|
|
547
|
+
return await postAppRuntimeApi<SignedR2ReadUrlResponse>(context, {
|
|
548
|
+
action: 'create_signed_staged_file_url',
|
|
549
|
+
file,
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
export async function writeStagedFileFromAppRuntime(
|
|
554
|
+
context: WorkerRuntimeApiContext,
|
|
555
|
+
file: Pick<PlayStagedFileRef, 'storageKey'>,
|
|
556
|
+
targetPath: string,
|
|
557
|
+
): Promise<void> {
|
|
558
|
+
const signed = await postAppRuntimeApi<SignedR2ReadUrlResponse>(context, {
|
|
559
|
+
action: 'create_signed_staged_file_url',
|
|
560
|
+
file,
|
|
561
|
+
});
|
|
562
|
+
await fetchSignedR2ToFile({
|
|
563
|
+
kind: 'staged_file',
|
|
564
|
+
signed,
|
|
565
|
+
targetPath,
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
export async function updateRunStatusViaAppRuntime(
|
|
570
|
+
context: WorkerRuntimeApiContext,
|
|
571
|
+
update: RuntimeStatusUpdate,
|
|
572
|
+
): Promise<void> {
|
|
573
|
+
const previous =
|
|
574
|
+
runStatusUpdateChains.get(update.playId) ?? Promise.resolve();
|
|
575
|
+
const queued = previous
|
|
576
|
+
.catch(() => {})
|
|
577
|
+
.then(() => updateRunStatusViaAppRuntimeUnlocked(context, update));
|
|
578
|
+
const tracked = queued.finally(() => {
|
|
579
|
+
if (runStatusUpdateChains.get(update.playId) === tracked) {
|
|
580
|
+
runStatusUpdateChains.delete(update.playId);
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
runStatusUpdateChains.set(update.playId, tracked);
|
|
584
|
+
await tracked;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
async function updateRunStatusViaAppRuntimeUnlocked(
|
|
588
|
+
context: WorkerRuntimeApiContext,
|
|
589
|
+
update: RuntimeStatusUpdate,
|
|
590
|
+
): Promise<void> {
|
|
591
|
+
const previousSnapshot =
|
|
592
|
+
runStatusLedgerSnapshots.get(update.playId) ??
|
|
593
|
+
createEmptyPlayRunLedgerSnapshot({
|
|
594
|
+
runId: update.playId,
|
|
595
|
+
status: 'queued',
|
|
596
|
+
});
|
|
597
|
+
// Positional cursor over this producer's log buffer. Running updates forward
|
|
598
|
+
// only the unsent suffix; terminal updates resend the retained buffer so the
|
|
599
|
+
// durable stream can recover any progress flush that was lost in transit.
|
|
600
|
+
const sentCount = isTerminalRuntimeStatus(update.status)
|
|
601
|
+
? 0
|
|
602
|
+
: (runLogChannelSentCounts.get(update.playId) ?? 0);
|
|
603
|
+
const logSlice = Array.isArray(update.liveLogs)
|
|
604
|
+
? slicePositionalLogLines({
|
|
605
|
+
bufferLines: update.liveLogs,
|
|
606
|
+
bufferTotalCount: update.liveLogTotalCount ?? update.liveLogs.length,
|
|
607
|
+
sentCount,
|
|
608
|
+
})
|
|
609
|
+
: null;
|
|
610
|
+
const terminalLogReplay =
|
|
611
|
+
update.terminalLogReplay && update.terminalLogReplay.lines.length > 0
|
|
612
|
+
? update.terminalLogReplay
|
|
613
|
+
: isTerminalRuntimeStatus(update.status) && Array.isArray(update.liveLogs)
|
|
614
|
+
? {
|
|
615
|
+
lines: update.liveLogs,
|
|
616
|
+
totalCount: update.liveLogTotalCount,
|
|
617
|
+
}
|
|
618
|
+
: null;
|
|
619
|
+
const statusPatchLogSlice = terminalLogReplay ? null : logSlice;
|
|
620
|
+
const events = buildPlayRunLedgerEventsFromStatusPatch({
|
|
621
|
+
patch: {
|
|
622
|
+
runId: update.playId,
|
|
623
|
+
status: update.status,
|
|
624
|
+
error: update.error ?? null,
|
|
625
|
+
runtimeBackend: update.runtimeBackend ?? null,
|
|
626
|
+
lastCheckpointAt: update.lastCheckpointAt ?? null,
|
|
627
|
+
liveLogs: statusPatchLogSlice?.lines ?? null,
|
|
628
|
+
liveLogsChannelOffset: statusPatchLogSlice?.channelOffset ?? null,
|
|
629
|
+
liveNodeProgress: update.liveNodeProgress ?? null,
|
|
630
|
+
result: update.result,
|
|
631
|
+
},
|
|
632
|
+
previousSnapshot,
|
|
633
|
+
now: update.lastCheckpointAt ?? Date.now(),
|
|
634
|
+
source: 'temporal',
|
|
635
|
+
});
|
|
636
|
+
if (terminalLogReplay && terminalLogReplay.lines.length > 0) {
|
|
637
|
+
events.push(
|
|
638
|
+
...buildTerminalLogReplayEvents({
|
|
639
|
+
runId: update.playId,
|
|
640
|
+
source: 'temporal',
|
|
641
|
+
occurredAt: update.lastCheckpointAt ?? Date.now(),
|
|
642
|
+
lines: terminalLogReplay.lines,
|
|
643
|
+
liveLogTotalCount: terminalLogReplay.totalCount,
|
|
644
|
+
}),
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
if (events.length === 0) {
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
await appendRunEventsViaAppRuntime(context, {
|
|
651
|
+
playId: update.playId,
|
|
652
|
+
events,
|
|
653
|
+
});
|
|
654
|
+
if (statusPatchLogSlice) {
|
|
655
|
+
runLogChannelSentCounts.set(
|
|
656
|
+
update.playId,
|
|
657
|
+
statusPatchLogSlice.channelOffset + statusPatchLogSlice.lines.length,
|
|
658
|
+
);
|
|
659
|
+
}
|
|
660
|
+
rememberRunStatusLedgerSnapshot(
|
|
661
|
+
update.playId,
|
|
662
|
+
reducePlayRunLedgerEvents(previousSnapshot, events),
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
export async function appendRunEventsViaAppRuntime(
|
|
667
|
+
context: WorkerRuntimeApiContext,
|
|
668
|
+
input: { playId: string; events: PlayRunLedgerEvent[] },
|
|
669
|
+
): Promise<void> {
|
|
670
|
+
await postAppRuntimeApi<{ ok: true }>(context, {
|
|
671
|
+
action: 'append_run_events',
|
|
672
|
+
...input,
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
export async function startRunViaAppRuntime(
|
|
677
|
+
context: WorkerRuntimeApiContext,
|
|
678
|
+
input: {
|
|
679
|
+
playName: string;
|
|
680
|
+
runId: string;
|
|
681
|
+
workflowFamilyKey?: string | null;
|
|
682
|
+
artifactStorageKey?: string | null;
|
|
683
|
+
artifactHash?: string | null;
|
|
684
|
+
graphHash?: string | null;
|
|
685
|
+
runtimeBackend?: string | null;
|
|
686
|
+
schedulerBackend?: string | null;
|
|
687
|
+
schedulerSchema?: string | null;
|
|
688
|
+
executionProfile?: string | null;
|
|
689
|
+
maxCreditsPerRun?: number | null;
|
|
690
|
+
staticPipeline?: unknown;
|
|
691
|
+
source?: 'published' | 'ad_hoc' | 'draft';
|
|
692
|
+
activeRunLimit?: number | null;
|
|
693
|
+
},
|
|
694
|
+
): Promise<void> {
|
|
695
|
+
await postAppRuntimeApi<{ ok: true }>(context, {
|
|
696
|
+
action: 'start_inline_child_run',
|
|
697
|
+
...input,
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
export async function saveResultsViaAppRuntime(
|
|
702
|
+
context: WorkerRuntimeApiContext,
|
|
703
|
+
input: RuntimeSaveResults,
|
|
704
|
+
): Promise<void> {
|
|
705
|
+
await postAppRuntimeApi<{ ok: true }>(context, {
|
|
706
|
+
action: 'save_results',
|
|
707
|
+
...input,
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
export async function applyRowUpdatesViaAppRuntime(
|
|
712
|
+
context: WorkerRuntimeApiContext,
|
|
713
|
+
input: Extract<
|
|
714
|
+
RuntimeApiRequest,
|
|
715
|
+
{ action: 'apply_row_updates' }
|
|
716
|
+
> extends infer T
|
|
717
|
+
? Omit<T & { action: 'apply_row_updates' }, 'action'>
|
|
718
|
+
: never,
|
|
719
|
+
): Promise<void> {
|
|
720
|
+
await postAppRuntimeApi<{ ok: true }>(context, {
|
|
721
|
+
action: 'apply_row_updates',
|
|
722
|
+
...input,
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
export async function createDbSessionViaAppRuntime(
|
|
727
|
+
context: WorkerRuntimeApiContext,
|
|
728
|
+
input: CreateDbSessionRequest,
|
|
729
|
+
): Promise<CreateDbSessionResponse> {
|
|
730
|
+
return await postAppRuntimeApi<CreateDbSessionResponse>(context, {
|
|
731
|
+
action: 'create_db_session',
|
|
732
|
+
...input,
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
export async function upsertComputeBillingSessionViaAppRuntime(
|
|
737
|
+
context: WorkerRuntimeApiContext,
|
|
738
|
+
input: Omit<
|
|
739
|
+
Extract<RuntimeApiRequest, { action: 'compute_billing_upsert' }>,
|
|
740
|
+
'action'
|
|
741
|
+
>,
|
|
742
|
+
): Promise<void> {
|
|
743
|
+
await postAppRuntimeApi<{ ok: true }>(context, {
|
|
744
|
+
action: 'compute_billing_upsert',
|
|
745
|
+
...input,
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
export async function recordComputeBillingItemViaAppRuntime(
|
|
750
|
+
context: WorkerRuntimeApiContext,
|
|
751
|
+
input: Omit<
|
|
752
|
+
Extract<RuntimeApiRequest, { action: 'compute_billing_record_item' }>,
|
|
753
|
+
'action'
|
|
754
|
+
>,
|
|
755
|
+
): Promise<void> {
|
|
756
|
+
await postAppRuntimeApi<{ ok: true }>(context, {
|
|
757
|
+
action: 'compute_billing_record_item',
|
|
758
|
+
...input,
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
export async function finalizeComputeBillingSessionViaAppRuntime(
|
|
763
|
+
context: WorkerRuntimeApiContext,
|
|
764
|
+
input: Omit<
|
|
765
|
+
Extract<RuntimeApiRequest, { action: 'compute_billing_finalize' }>,
|
|
766
|
+
'action'
|
|
767
|
+
>,
|
|
768
|
+
): Promise<void> {
|
|
769
|
+
await postAppRuntimeApi<{ ok: true }>(context, {
|
|
770
|
+
action: 'compute_billing_finalize',
|
|
771
|
+
...input,
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
export async function getRuntimeStepReceiptViaAppRuntime(
|
|
776
|
+
context: WorkerRuntimeApiContext,
|
|
777
|
+
input: Omit<
|
|
778
|
+
Extract<RuntimeApiRequest, { action: 'get_runtime_step_receipt' }>,
|
|
779
|
+
'action'
|
|
780
|
+
>,
|
|
781
|
+
): Promise<RuntimeStepReceipt | null> {
|
|
782
|
+
return await postAppRuntimeApi<RuntimeStepReceipt | null>(context, {
|
|
783
|
+
action: 'get_runtime_step_receipt',
|
|
784
|
+
...input,
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
export async function claimRuntimeStepReceiptViaAppRuntime(
|
|
789
|
+
context: WorkerRuntimeApiContext,
|
|
790
|
+
input: Omit<
|
|
791
|
+
Extract<RuntimeApiRequest, { action: 'claim_runtime_step_receipt' }>,
|
|
792
|
+
'action'
|
|
793
|
+
>,
|
|
794
|
+
): Promise<RuntimeStepReceipt | null> {
|
|
795
|
+
return await postAppRuntimeApi<RuntimeStepReceipt | null>(context, {
|
|
796
|
+
action: 'claim_runtime_step_receipt',
|
|
797
|
+
...input,
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
export async function completeRuntimeStepReceiptViaAppRuntime(
|
|
802
|
+
context: WorkerRuntimeApiContext,
|
|
803
|
+
input: Omit<
|
|
804
|
+
Extract<RuntimeApiRequest, { action: 'complete_runtime_step_receipt' }>,
|
|
805
|
+
'action'
|
|
806
|
+
>,
|
|
807
|
+
): Promise<RuntimeStepReceipt | null> {
|
|
808
|
+
return await postAppRuntimeApi<RuntimeStepReceipt | null>(context, {
|
|
809
|
+
action: 'complete_runtime_step_receipt',
|
|
810
|
+
...input,
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
export async function failRuntimeStepReceiptViaAppRuntime(
|
|
815
|
+
context: WorkerRuntimeApiContext,
|
|
816
|
+
input: Omit<
|
|
817
|
+
Extract<RuntimeApiRequest, { action: 'fail_runtime_step_receipt' }>,
|
|
818
|
+
'action'
|
|
819
|
+
>,
|
|
820
|
+
): Promise<RuntimeStepReceipt | null> {
|
|
821
|
+
return await postAppRuntimeApi<RuntimeStepReceipt | null>(context, {
|
|
822
|
+
action: 'fail_runtime_step_receipt',
|
|
823
|
+
...input,
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
export async function skipRuntimeStepReceiptViaAppRuntime(
|
|
828
|
+
context: WorkerRuntimeApiContext,
|
|
829
|
+
input: Omit<
|
|
830
|
+
Extract<RuntimeApiRequest, { action: 'skip_runtime_step_receipt' }>,
|
|
831
|
+
'action'
|
|
832
|
+
>,
|
|
833
|
+
): Promise<RuntimeStepReceipt | null> {
|
|
834
|
+
return await postAppRuntimeApi<RuntimeStepReceipt | null>(context, {
|
|
835
|
+
action: 'skip_runtime_step_receipt',
|
|
836
|
+
...input,
|
|
837
|
+
});
|
|
838
|
+
}
|