deepline 0.1.242 → 0.1.244
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 +1 -1
- package/dist/bundling-sources/sdk/src/plays/bundle-play-file.ts +5 -25
- package/dist/bundling-sources/sdk/src/release.ts +23 -21
- package/dist/bundling-sources/sdk/src/types.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/backend.ts +2 -21
- package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +5 -6
- package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +6 -13
- package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +9 -26
- package/dist/bundling-sources/shared_libs/play-runtime/internal-step-ids.ts +1 -2
- package/dist/bundling-sources/shared_libs/play-runtime/map-row-identity.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +191 -29
- package/dist/bundling-sources/shared_libs/play-runtime/play-latency-trace.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/providers.ts +1 -36
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +2 -3
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/index.ts +0 -7
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +1 -12
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-pg.ts +2 -3
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver.ts +5 -15
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +6 -21
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +3 -4
- package/dist/bundling-sources/shared_libs/plays/artifact-kind-guard.ts +16 -29
- package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +4 -8
- package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +21 -712
- package/dist/bundling-sources/shared_libs/plays/bundling/limits.ts +1 -18
- package/dist/cli/index.js +39 -74
- package/dist/cli/index.mjs +39 -74
- package/dist/{compiler-manifest-CYcwzSOJ.d.ts → compiler-manifest-DlE7dnRm.d.mts} +2 -8
- package/dist/{compiler-manifest-CYcwzSOJ.d.mts → compiler-manifest-DlE7dnRm.d.ts} +2 -8
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +24 -22
- package/dist/index.mjs +24 -22
- package/dist/plays/bundle-play-file.d.mts +7 -22
- package/dist/plays/bundle-play-file.d.ts +7 -22
- package/dist/plays/bundle-play-file.mjs +26 -614
- package/package.json +2 -2
- package/dist/bundling-sources/apps/play-runner-workers/src/coordinator-entry.ts +0 -4504
- package/dist/bundling-sources/apps/play-runner-workers/src/dedup-do.ts +0 -1386
- package/dist/bundling-sources/apps/play-runner-workers/src/durable-object-deploy-handoff.ts +0 -30
- package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +0 -8385
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/README.md +0 -21
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/batching.ts +0 -251
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/coordinator-progress.ts +0 -289
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/csv-rows.ts +0 -85
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/customer-console.ts +0 -23
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/dataset-handles.ts +0 -528
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/harness-receipt-store.ts +0 -229
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/ledger-event-batches.ts +0 -81
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/live-progress.ts +0 -22
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/map-chunk-plan.ts +0 -920
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/map-latency-profile.ts +0 -90
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/output-datasets.ts +0 -475
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/receipts.ts +0 -570
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/result-dataset-persistence.ts +0 -50
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/row-isolation.ts +0 -5
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/run-work-dispatcher.ts +0 -519
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-batch.ts +0 -107
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-dispatch.ts +0 -2541
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-http-errors.ts +0 -7
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-receipts.ts +0 -227
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/work-budget.ts +0 -130
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/worker-platform-budget.ts +0 -39
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/workflow-preview.ts +0 -26
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime-api-retry.ts +0 -23
- package/dist/bundling-sources/apps/play-runner-workers/src/workflow-instance-create.ts +0 -47
- package/dist/bundling-sources/apps/play-runner-workers/src/workflow-retry-state.ts +0 -167
- package/dist/bundling-sources/apps/play-runner-workers/src/workflow-retry.ts +0 -91
- package/dist/bundling-sources/sdk/src/plays/harness-stub.ts +0 -329
- package/dist/bundling-sources/sdk/src/worker-play-entry.ts +0 -240
- package/dist/bundling-sources/shared_libs/play-runtime/governor/coordinator-rate-state-backend.ts +0 -252
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-neon-serverless.ts +0 -217
package/README.md
CHANGED
|
@@ -326,7 +326,7 @@ V2 prebuilt play sources are authored directly in `src/lib/plays/v2/`. After
|
|
|
326
326
|
editing them, regenerate the committed Workers and share-page artifacts:
|
|
327
327
|
|
|
328
328
|
```bash
|
|
329
|
-
bun scripts/regen.ts
|
|
329
|
+
bun scripts/regen.ts prebuilt-share-pages
|
|
330
330
|
```
|
|
331
331
|
|
|
332
332
|
## File structure
|
|
@@ -44,7 +44,7 @@ const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
|
44
44
|
const SDK_PACKAGE_ROOT = resolve(MODULE_DIR, '..', '..');
|
|
45
45
|
const SOURCE_REPO_ROOT = resolve(SDK_PACKAGE_ROOT, '..');
|
|
46
46
|
const HAS_SOURCE_BUNDLING_SOURCES = existsSync(
|
|
47
|
-
resolve(SOURCE_REPO_ROOT, '
|
|
47
|
+
resolve(SOURCE_REPO_ROOT, 'shared_libs', 'plays', 'bundling', 'index.ts'),
|
|
48
48
|
);
|
|
49
49
|
const PACKAGED_BUNDLING_SOURCE_ROOT = resolve(
|
|
50
50
|
SDK_PACKAGE_ROOT,
|
|
@@ -54,10 +54,10 @@ const PACKAGED_BUNDLING_SOURCE_ROOT = resolve(
|
|
|
54
54
|
const HAS_PACKAGED_BUNDLING_SOURCES = existsSync(
|
|
55
55
|
resolve(
|
|
56
56
|
PACKAGED_BUNDLING_SOURCE_ROOT,
|
|
57
|
-
'
|
|
58
|
-
'
|
|
59
|
-
'
|
|
60
|
-
'
|
|
57
|
+
'shared_libs',
|
|
58
|
+
'plays',
|
|
59
|
+
'bundling',
|
|
60
|
+
'index.ts',
|
|
61
61
|
),
|
|
62
62
|
);
|
|
63
63
|
const PROJECT_ROOT = HAS_SOURCE_BUNDLING_SOURCES
|
|
@@ -75,20 +75,6 @@ const SDK_ENTRY_FILE = resolve(SDK_SOURCE_ROOT, 'index.ts');
|
|
|
75
75
|
const SDK_TYPES_ENTRY_FILE = HAS_SOURCE_BUNDLING_SOURCES
|
|
76
76
|
? SDK_ENTRY_FILE
|
|
77
77
|
: resolve(SDK_PACKAGE_ROOT, 'dist', 'index.d.ts');
|
|
78
|
-
const SDK_WORKERS_ENTRY_FILE = resolve(SDK_SOURCE_ROOT, 'worker-play-entry.ts');
|
|
79
|
-
const WORKERS_HARNESS_ENTRY_FILE = resolve(
|
|
80
|
-
PROJECT_ROOT,
|
|
81
|
-
'apps',
|
|
82
|
-
'play-runner-workers',
|
|
83
|
-
'src',
|
|
84
|
-
'entry.ts',
|
|
85
|
-
);
|
|
86
|
-
const WORKERS_HARNESS_FILES_DIR = resolve(
|
|
87
|
-
PROJECT_ROOT,
|
|
88
|
-
'apps',
|
|
89
|
-
'play-runner-workers',
|
|
90
|
-
'src',
|
|
91
|
-
);
|
|
92
78
|
let hasWarnedAboutNonDevelopmentBundling = false;
|
|
93
79
|
|
|
94
80
|
/**
|
|
@@ -150,12 +136,6 @@ export function createSdkPlayBundlingAdapter(): PlayBundlingAdapter {
|
|
|
150
136
|
HAS_SOURCE_BUNDLING_SOURCES || !existsSync(SDK_TYPES_ENTRY_FILE)
|
|
151
137
|
? SDK_ENTRY_FILE
|
|
152
138
|
: SDK_TYPES_ENTRY_FILE,
|
|
153
|
-
sdkWorkersEntryFile: SDK_WORKERS_ENTRY_FILE,
|
|
154
|
-
workersHarnessEntryFile: WORKERS_HARNESS_ENTRY_FILE,
|
|
155
|
-
workersHarnessFilesDir: WORKERS_HARNESS_FILES_DIR,
|
|
156
|
-
workersRuntimeFingerprintDirs: [
|
|
157
|
-
resolve(PROJECT_ROOT, 'shared_libs', 'play-runtime'),
|
|
158
|
-
],
|
|
159
139
|
discoverPackagedLocalFiles,
|
|
160
140
|
warnAboutNonDevelopmentBundling,
|
|
161
141
|
};
|
|
@@ -113,10 +113,12 @@ export const SDK_RELEASE = {
|
|
|
113
113
|
// 0.1.241 hard-cuts published and launched plays to immutable cjs_node20
|
|
114
114
|
// artifacts. Older clients can submit esm_workers artifacts that the Absurd
|
|
115
115
|
// runtime intentionally no longer compiles at publish or launch time.
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
// 0.1.242 removes the retired Workers/ESM compiler, generated bundles, and
|
|
117
|
+
// deploy-time artifact migration. Play authoring now has one CJS contract.
|
|
118
|
+
version: '0.1.244',
|
|
119
|
+
apiContract: '2026-07-cjs-absurd-only-play-runtime-hard-cutover',
|
|
118
120
|
supportPolicy: {
|
|
119
|
-
latest: '0.1.
|
|
121
|
+
latest: '0.1.244',
|
|
120
122
|
minimumSupported: '0.1.53',
|
|
121
123
|
deprecatedBelow: '0.1.219',
|
|
122
124
|
commandMinimumSupported: [
|
|
@@ -128,61 +130,61 @@ export const SDK_RELEASE = {
|
|
|
128
130
|
},
|
|
129
131
|
{
|
|
130
132
|
command: 'plays',
|
|
131
|
-
minimumSupported: '0.1.
|
|
133
|
+
minimumSupported: '0.1.241',
|
|
132
134
|
reason:
|
|
133
|
-
'
|
|
135
|
+
'Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract. Update before checking, publishing, or running plays.',
|
|
134
136
|
},
|
|
135
137
|
{
|
|
136
138
|
command: 'plays run',
|
|
137
|
-
minimumSupported: '0.1.
|
|
139
|
+
minimumSupported: '0.1.241',
|
|
138
140
|
reason:
|
|
139
|
-
'
|
|
141
|
+
'Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract.',
|
|
140
142
|
},
|
|
141
143
|
{
|
|
142
144
|
command: 'run',
|
|
143
145
|
displayCommand: 'plays run',
|
|
144
|
-
minimumSupported: '0.1.
|
|
146
|
+
minimumSupported: '0.1.241',
|
|
145
147
|
reason:
|
|
146
|
-
'
|
|
148
|
+
'Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract.',
|
|
147
149
|
},
|
|
148
150
|
{
|
|
149
151
|
command: 'plays check',
|
|
150
|
-
minimumSupported: '0.1.
|
|
152
|
+
minimumSupported: '0.1.241',
|
|
151
153
|
reason:
|
|
152
|
-
'
|
|
154
|
+
'Older SDK CLI versions predate dataset-native Play authoring and validate against the retired esm_workers artifact contract.',
|
|
153
155
|
},
|
|
154
156
|
{
|
|
155
157
|
command: 'check',
|
|
156
158
|
displayCommand: 'plays check',
|
|
157
|
-
minimumSupported: '0.1.
|
|
159
|
+
minimumSupported: '0.1.241',
|
|
158
160
|
reason:
|
|
159
|
-
'
|
|
161
|
+
'Older SDK CLI versions predate dataset-native Play authoring and validate against the retired esm_workers artifact contract.',
|
|
160
162
|
},
|
|
161
163
|
{
|
|
162
164
|
command: 'plays publish',
|
|
163
|
-
minimumSupported: '0.1.
|
|
165
|
+
minimumSupported: '0.1.241',
|
|
164
166
|
reason:
|
|
165
|
-
'
|
|
167
|
+
'Older SDK CLI versions predate dataset-native Play artifacts and can publish the retired esm_workers artifact contract.',
|
|
166
168
|
},
|
|
167
169
|
{
|
|
168
170
|
command: 'publish',
|
|
169
171
|
displayCommand: 'plays publish',
|
|
170
|
-
minimumSupported: '0.1.
|
|
172
|
+
minimumSupported: '0.1.241',
|
|
171
173
|
reason:
|
|
172
|
-
'
|
|
174
|
+
'Older SDK CLI versions predate dataset-native Play artifacts and can publish the retired esm_workers artifact contract.',
|
|
173
175
|
},
|
|
174
176
|
{
|
|
175
177
|
command: 'plays set-live',
|
|
176
|
-
minimumSupported: '0.1.
|
|
178
|
+
minimumSupported: '0.1.241',
|
|
177
179
|
reason:
|
|
178
|
-
'
|
|
180
|
+
'Older SDK CLI versions predate dataset-native Play artifacts and can publish the retired esm_workers artifact contract.',
|
|
179
181
|
},
|
|
180
182
|
{
|
|
181
183
|
command: 'set-live',
|
|
182
184
|
displayCommand: 'plays set-live',
|
|
183
|
-
minimumSupported: '0.1.
|
|
185
|
+
minimumSupported: '0.1.241',
|
|
184
186
|
reason:
|
|
185
|
-
'
|
|
187
|
+
'Older SDK CLI versions predate dataset-native Play artifacts and can publish the retired esm_workers artifact contract.',
|
|
186
188
|
},
|
|
187
189
|
{
|
|
188
190
|
command: 'runs',
|
|
@@ -1221,7 +1221,7 @@ export interface StartPlayRunRequest {
|
|
|
1221
1221
|
waitForCompletionMs?: number;
|
|
1222
1222
|
/**
|
|
1223
1223
|
* Per-run execution profile override. The server defaults to absurd. The
|
|
1224
|
-
*
|
|
1224
|
+
* Only `absurd` is accepted; most callers should leave this unset.
|
|
1225
1225
|
*/
|
|
1226
1226
|
profile?: string;
|
|
1227
1227
|
/** Optional per-run provider execution mode for eval/smoke runs. */
|
|
@@ -1,27 +1,17 @@
|
|
|
1
1
|
export const PLAY_RUNTIME_BACKENDS = {
|
|
2
2
|
localProcess: 'local_process',
|
|
3
3
|
daytona: 'daytona',
|
|
4
|
-
// Artifact/runtime contract for Cloudflare Dynamic Workers. This is no
|
|
5
|
-
// longer a standalone runner backend; use profile=workers_edge so the
|
|
6
|
-
// cf-workflows scheduler owns loading and execution.
|
|
7
|
-
cloudflareWorkers: 'cloudflare_workers',
|
|
8
4
|
} as const;
|
|
9
5
|
|
|
10
6
|
export type PlayRuntimeBackendId =
|
|
11
7
|
(typeof PLAY_RUNTIME_BACKENDS)[keyof typeof PLAY_RUNTIME_BACKENDS];
|
|
12
8
|
|
|
13
9
|
/**
|
|
14
|
-
* The
|
|
15
|
-
*
|
|
16
|
-
* - cjs_node20: Daytona + local-process (full Node.js sandbox).
|
|
17
|
-
* - esm_workers: Cloudflare Workers (V8 isolate, no `fs`/`child_process`).
|
|
18
|
-
*
|
|
19
|
-
* The CLI selects which kind to build based on the target backend; the worker
|
|
20
|
-
* validates the kind matches the backend it's about to dispatch to.
|
|
10
|
+
* The one executable Play artifact contract. Daytona and local-process both
|
|
11
|
+
* load CommonJS under Node 20.
|
|
21
12
|
*/
|
|
22
13
|
export const PLAY_ARTIFACT_KINDS = {
|
|
23
14
|
cjsNode20: 'cjs_node20',
|
|
24
|
-
esmWorkers: 'esm_workers',
|
|
25
15
|
} as const;
|
|
26
16
|
|
|
27
17
|
export type PlayArtifactKind =
|
|
@@ -49,11 +39,6 @@ export const PLAY_BACKEND_DESCRIPTORS: Record<
|
|
|
49
39
|
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
50
40
|
label: 'Daytona sandbox',
|
|
51
41
|
},
|
|
52
|
-
[PLAY_RUNTIME_BACKENDS.cloudflareWorkers]: {
|
|
53
|
-
id: PLAY_RUNTIME_BACKENDS.cloudflareWorkers,
|
|
54
|
-
artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
|
|
55
|
-
label: 'Cloudflare Dynamic Workers',
|
|
56
|
-
},
|
|
57
42
|
};
|
|
58
43
|
|
|
59
44
|
export function describePlayBackend(
|
|
@@ -84,10 +69,6 @@ export function normalizePlayRuntimeBackend(
|
|
|
84
69
|
return PLAY_RUNTIME_BACKENDS.localProcess;
|
|
85
70
|
}
|
|
86
71
|
|
|
87
|
-
if (normalized === PLAY_RUNTIME_BACKENDS.cloudflareWorkers) {
|
|
88
|
-
return PLAY_RUNTIME_BACKENDS.cloudflareWorkers;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
72
|
throw new Error(
|
|
92
73
|
`Unsupported play runtime backend "${normalized}". Expected one of: ${Object.values(
|
|
93
74
|
PLAY_RUNTIME_BACKENDS,
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Play Execution Governor — the deep module that owns execution policy.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* to resolve a row, batch a tool call, or submit a child); the Governor owns the
|
|
8
|
-
* "may I, and how many at once" policy. See ADR 0007 + CONTEXT.md.
|
|
4
|
+
* The CJS runner gates work through one Governor instance per run-attempt. The
|
|
5
|
+
* runner owns execution mechanics; the Governor owns the "may I, and how many
|
|
6
|
+
* at once" policy. See ADR 0007 + CONTEXT.md.
|
|
9
7
|
*
|
|
10
8
|
* Surface (small, by design):
|
|
11
9
|
* - acquireRowSlot / acquireToolSlot → blocking leases
|
|
@@ -283,7 +281,8 @@ export function createPlayExecutionGovernor(
|
|
|
283
281
|
}
|
|
284
282
|
|
|
285
283
|
const scopeFor = (toolId: string | undefined, provider: string) =>
|
|
286
|
-
scopeByTool.get(toolId ?? '') ??
|
|
284
|
+
scopeByTool.get(toolId ?? '') ??
|
|
285
|
+
([orgBucket(provider), ''] as [string, string]);
|
|
287
286
|
|
|
288
287
|
async function resolveAdaptivePacing(toolId: string): Promise<{
|
|
289
288
|
provider: string;
|
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
* Play Execution Governor — the single policy table.
|
|
3
3
|
*
|
|
4
4
|
* This is the ONE source of truth for every concurrency, budget, and pacing
|
|
5
|
-
* number in the play runtime.
|
|
6
|
-
*
|
|
7
|
-
* cannot drift. See ADR 0007 and the "Play Execution Governor" entry in
|
|
8
|
-
* CONTEXT.md.
|
|
5
|
+
* number in the CJS/Node play runtime. See ADR 0007 and the "Play Execution
|
|
6
|
+
* Governor" entry in CONTEXT.md.
|
|
9
7
|
*
|
|
10
8
|
* Tuning philosophy (product decision):
|
|
11
9
|
* - Caps are explicit resource admission boundaries. A run should queue behind
|
|
@@ -51,13 +49,9 @@ export interface ExecutionBudgetPolicy {
|
|
|
51
49
|
/**
|
|
52
50
|
* Per-provider rate pacing — the real outbound throughput governor.
|
|
53
51
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* `cjs_node20`; on `esm_workers` it is intentionally excluded from the pacing
|
|
58
|
-
* contract because a fanned-out run cannot guarantee the per-isolate release
|
|
59
|
-
* signal an in-flight count needs, so only the org-wide tool-concurrency
|
|
60
|
-
* backstop applies there. See PacingRule.maxConcurrency in rate-state-backend.ts.
|
|
52
|
+
* Per-provider request rate and optional in-flight concurrency are enforced by
|
|
53
|
+
* the same CJS/Node substrate. See PacingRule.maxConcurrency in
|
|
54
|
+
* rate-state-backend.ts.
|
|
61
55
|
*/
|
|
62
56
|
export interface ExecutionPacingPolicy {
|
|
63
57
|
/** RPS applied to a provider that declares no explicit rate limit. */
|
|
@@ -120,7 +114,7 @@ export const SHARED_EXECUTION_POLICY: ResolvedExecutionPolicy = {
|
|
|
120
114
|
},
|
|
121
115
|
};
|
|
122
116
|
|
|
123
|
-
export type AdapterId = 'cjs_node20'
|
|
117
|
+
export type AdapterId = 'cjs_node20';
|
|
124
118
|
|
|
125
119
|
/**
|
|
126
120
|
* One level deep on purpose: each policy section is a flat record of numbers, so
|
|
@@ -141,7 +135,6 @@ type PolicyOverride = {
|
|
|
141
135
|
*/
|
|
142
136
|
export const ADAPTER_POLICY_OVERRIDES: Record<AdapterId, PolicyOverride> = {
|
|
143
137
|
cjs_node20: {},
|
|
144
|
-
esm_workers: {},
|
|
145
138
|
};
|
|
146
139
|
|
|
147
140
|
/** Merge the shared policy with any documented Adapter override. */
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Rate State Backend — the one swappable seam of the Play Execution Governor.
|
|
3
3
|
*
|
|
4
|
-
* Per-`(org, provider)` rate windows are
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* slots) stays Governor-local and threads down the lineage via the snapshot.
|
|
8
|
-
*
|
|
9
|
-
* Adapters: an in-memory backend for the single-process `cjs_node20` runner, and
|
|
10
|
-
* a shared backend (Run Coordination Cache Durable Object, or server-side Redis)
|
|
11
|
-
* for `esm_workers`. See ADR 0007 and CONTEXT.md (Rate State Backend).
|
|
4
|
+
* Per-`(org, provider)` rate windows are shared across CJS runner processes.
|
|
5
|
+
* Everything else the Governor owns stays local to one run attempt and threads
|
|
6
|
+
* down the lineage via the snapshot. See ADR 0007 and CONTEXT.md.
|
|
12
7
|
*/
|
|
13
8
|
|
|
14
9
|
/** A single resolved rate rule for a bucket (from rate-limit-definitions). */
|
|
@@ -19,16 +14,8 @@ export interface PacingRule {
|
|
|
19
14
|
/**
|
|
20
15
|
* Optional simultaneous-in-flight cap for this rule.
|
|
21
16
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* and release it on permit.release). On `esm_workers` it is intentionally NOT
|
|
25
|
-
* enforced: a run fans across V8 isolates and a dying isolate cannot guarantee
|
|
26
|
-
* the release signal a leased in-flight count would require, so the
|
|
27
|
-
* coordinator DO debits `requestsPerWindow` only. The Governor's global
|
|
28
|
-
* tool-concurrency semaphore is the cross-isolate in-flight backstop there.
|
|
29
|
-
* `requestsPerWindow`/`windowMs` (the request-RATE governor) ARE enforced on
|
|
30
|
-
* both substrates. See coordinator-rate-state-backend.ts and dedup-do.ts
|
|
31
|
-
* (computeRateAcquire) for the workers side.
|
|
17
|
+
* The CJS runtime holds a reliable in-flight count and releases it on
|
|
18
|
+
* permit.release. `requestsPerWindow`/`windowMs` enforce request rate.
|
|
32
19
|
*/
|
|
33
20
|
readonly maxConcurrency: number | null;
|
|
34
21
|
}
|
|
@@ -60,25 +47,21 @@ export interface PacingPermit {
|
|
|
60
47
|
* Discriminates the backend so the Governor can adapt its policy to it. Only
|
|
61
48
|
* `app_runtime_postgres` (the Absurd/Node substrate's DB-backed pacer) is
|
|
62
49
|
* db-authoritative: it runs the whole token-bucket + AIMD in Postgres, so the
|
|
63
|
-
* Governor's in-memory adaptive admission
|
|
64
|
-
* pacing to the row. The in-memory
|
|
65
|
-
* undefined and keep the Governor's in-memory adaptive admission (byte-identical
|
|
66
|
-
* to today).
|
|
50
|
+
* Governor's in-memory adaptive admission becomes a passthrough and defers
|
|
51
|
+
* pacing to the row. The in-memory backend leaves `kind` undefined.
|
|
67
52
|
*/
|
|
68
53
|
export type RateStateBackendKind = 'app_runtime_postgres';
|
|
69
54
|
|
|
70
55
|
export interface RateStateBackend {
|
|
71
56
|
/**
|
|
72
57
|
* When present, tells the Governor this backend owns pacing authoritatively.
|
|
73
|
-
* Absent on the in-memory
|
|
74
|
-
* in-memory adaptive admission.
|
|
58
|
+
* Absent on the in-memory backend.
|
|
75
59
|
*/
|
|
76
60
|
readonly kind?: RateStateBackendKind;
|
|
77
61
|
|
|
78
62
|
/**
|
|
79
63
|
* Block until one outbound call is permitted for `bucketId` under all `rules`
|
|
80
|
-
* (request windows
|
|
81
|
-
* `cjs_node20` backend — see {@link PacingRule.maxConcurrency}), then debit and
|
|
64
|
+
* (request windows and per-rule `maxConcurrency`), then debit and
|
|
82
65
|
* return a permit. `bucketId` is `${orgId}:${provider}` so the window is global
|
|
83
66
|
* per (org, provider). Resolves immediately when `rules` is empty (provider has
|
|
84
67
|
* no configured limit — pacing is a no-op, the global tool-concurrency backstop
|
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
* machine-generated source line range (`lines_<startLine>_<endLine>`, built in
|
|
7
7
|
* `src/lib/plays/static-analysis.ts` → `createCodeStageForStatements`). The
|
|
8
8
|
* execution plan / runtime node ids namespace every substep by its type
|
|
9
|
-
* (`getStaticSubstepNodeId` in `src/lib/plays/step-progress.ts`
|
|
10
|
-
* `apps/play-runner-workers/src/entry.ts`), so glue nodes are ALWAYS
|
|
9
|
+
* (`getStaticSubstepNodeId` in `src/lib/plays/step-progress.ts`), so glue nodes are ALWAYS
|
|
11
10
|
* `run_javascript:<alias>` on the wire (ledger stepsById, snapshot
|
|
12
11
|
* nodeStates, `play.step.*` stream events).
|
|
13
12
|
*
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
derivePlayRowIdentityFromKey,
|
|
4
4
|
// Relative (not '@shared_libs/...') because this file ships inside the
|
|
5
5
|
// packed SDK's dist/bundling-sources graph (reachable from the
|
|
6
|
-
//
|
|
6
|
+
// packaged runner entry), where only relative imports resolve.
|
|
7
7
|
} from '../plays/row-identity';
|
|
8
8
|
import type { MapExecutionScope } from './ctx-types';
|
|
9
9
|
|
|
@@ -13,7 +13,16 @@ export const TERMINAL_RUN_RESULT_MAX_BYTES = 2_500_000;
|
|
|
13
13
|
* of provider payload — which is durable in scheduler Postgres and never read
|
|
14
14
|
* back from Convex, yet deterministically wedged the append.
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
// The terminal projection is persisted twice on `playRuns` (top-level result
|
|
17
|
+
// and runSnapshot.result), in addition to the event document. Keep one copy at
|
|
18
|
+
// 256 KiB so ordinary snapshots retain headroom under Convex's 1 MiB document
|
|
19
|
+
// ceiling. The runtime route has a reference-only fallback for an unusually
|
|
20
|
+
// large pre-existing snapshot that still exceeds the aggregate document cap.
|
|
21
|
+
export const LEDGER_TERMINAL_RESULT_MAX_BYTES = 256 * 1024;
|
|
22
|
+
export const LEDGER_TERMINAL_RESULT_MAX_DEPTH = 10;
|
|
23
|
+
export const CONVEX_LEDGER_ARRAY_MAX_ITEMS = 8_192;
|
|
24
|
+
export const CONVEX_LEDGER_OBJECT_MAX_FIELDS = 1_024;
|
|
25
|
+
export const CONVEX_LEDGER_FIELD_NAME_MAX_LENGTH = 1_024;
|
|
17
26
|
export const CUSTOMER_OUTPUT_VALUE_MAX_BYTES = 1 * 1024 * 1024;
|
|
18
27
|
export const CUSTOMER_OUTPUT_TOTAL_MAX_BYTES = 2 * 1024 * 1024;
|
|
19
28
|
/** Inline Postgres receipt contract: one serialized output is at most 10 MiB. */
|
|
@@ -121,13 +130,183 @@ export type LedgerTerminalResultRef = {
|
|
|
121
130
|
key: 'terminal_result_json';
|
|
122
131
|
/** Serialized byte size of the result that was elided from the ledger. */
|
|
123
132
|
bytes: number;
|
|
124
|
-
reason:
|
|
133
|
+
reason: LedgerTerminalResultRefReason;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export type LedgerTerminalResultRefReason =
|
|
137
|
+
| 'terminal_result_exceeds_ledger_limit'
|
|
138
|
+
| 'terminal_result_exceeds_ledger_depth'
|
|
139
|
+
| 'terminal_result_has_invalid_field_name'
|
|
140
|
+
| 'terminal_result_array_too_long'
|
|
141
|
+
| 'terminal_result_object_too_wide'
|
|
142
|
+
| 'terminal_result_not_json_serializable'
|
|
143
|
+
| 'terminal_result_rejected_by_convex';
|
|
144
|
+
|
|
145
|
+
export type ConvexLedgerPayloadIssue = {
|
|
146
|
+
reason:
|
|
147
|
+
| 'size_limit'
|
|
148
|
+
| 'depth_limit'
|
|
149
|
+
| 'invalid_field_name'
|
|
150
|
+
| 'array_too_long'
|
|
151
|
+
| 'object_too_wide'
|
|
152
|
+
| 'not_json_serializable';
|
|
153
|
+
bytes?: number;
|
|
125
154
|
};
|
|
126
155
|
|
|
127
156
|
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
128
157
|
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
129
158
|
}
|
|
130
159
|
|
|
160
|
+
function isConvexFieldName(value: string): boolean {
|
|
161
|
+
if (
|
|
162
|
+
value.length > CONVEX_LEDGER_FIELD_NAME_MAX_LENGTH ||
|
|
163
|
+
value.startsWith('$')
|
|
164
|
+
) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
168
|
+
const code = value.charCodeAt(index);
|
|
169
|
+
if (code < 32 || code >= 127) return false;
|
|
170
|
+
}
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Validate the part of Convex's value contract that can permanently poison a
|
|
176
|
+
* durable run-ledger append. The walk is iterative and stops at the depth
|
|
177
|
+
* boundary, so adversarial nesting cannot overflow the JS stack while being
|
|
178
|
+
* classified. It intentionally returns no path or customer field name.
|
|
179
|
+
*/
|
|
180
|
+
export function inspectConvexLedgerPayload(
|
|
181
|
+
value: unknown,
|
|
182
|
+
): ConvexLedgerPayloadIssue | null {
|
|
183
|
+
const stack: Array<{ value: unknown; depth: number }> = [
|
|
184
|
+
{
|
|
185
|
+
value,
|
|
186
|
+
depth: value !== null && typeof value === 'object' ? 1 : 0,
|
|
187
|
+
},
|
|
188
|
+
];
|
|
189
|
+
|
|
190
|
+
while (stack.length > 0) {
|
|
191
|
+
const current = stack.pop()!;
|
|
192
|
+
if (current.depth > LEDGER_TERMINAL_RESULT_MAX_DEPTH) {
|
|
193
|
+
return { reason: 'depth_limit' };
|
|
194
|
+
}
|
|
195
|
+
if (Array.isArray(current.value)) {
|
|
196
|
+
if (current.value.length > CONVEX_LEDGER_ARRAY_MAX_ITEMS) {
|
|
197
|
+
return { reason: 'array_too_long' };
|
|
198
|
+
}
|
|
199
|
+
for (const item of current.value) {
|
|
200
|
+
stack.push({
|
|
201
|
+
value: item,
|
|
202
|
+
depth:
|
|
203
|
+
item !== null && typeof item === 'object'
|
|
204
|
+
? current.depth + 1
|
|
205
|
+
: current.depth,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (!current.value || typeof current.value !== 'object') continue;
|
|
211
|
+
|
|
212
|
+
const entries = Object.entries(current.value as Record<string, unknown>);
|
|
213
|
+
if (entries.length > CONVEX_LEDGER_OBJECT_MAX_FIELDS) {
|
|
214
|
+
return { reason: 'object_too_wide' };
|
|
215
|
+
}
|
|
216
|
+
for (const [key, entry] of entries) {
|
|
217
|
+
if (!isConvexFieldName(key)) {
|
|
218
|
+
return { reason: 'invalid_field_name' };
|
|
219
|
+
}
|
|
220
|
+
stack.push({
|
|
221
|
+
value: entry,
|
|
222
|
+
depth:
|
|
223
|
+
entry !== null && typeof entry === 'object'
|
|
224
|
+
? current.depth + 1
|
|
225
|
+
: current.depth,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
try {
|
|
231
|
+
const bytes = jsonByteLength(value);
|
|
232
|
+
return bytes > LEDGER_TERMINAL_RESULT_MAX_BYTES
|
|
233
|
+
? { reason: 'size_limit', bytes }
|
|
234
|
+
: null;
|
|
235
|
+
} catch {
|
|
236
|
+
return { reason: 'not_json_serializable' };
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export function isLedgerTerminalResultRef(
|
|
241
|
+
value: unknown,
|
|
242
|
+
): value is LedgerTerminalResultRef {
|
|
243
|
+
return (
|
|
244
|
+
isPlainObject(value) &&
|
|
245
|
+
value.__kind === 'deepline.ledger_terminal_result_ref.v1' &&
|
|
246
|
+
value.store === 'scheduler_postgres' &&
|
|
247
|
+
value.key === 'terminal_result_json'
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export function stripReplayOnlyTerminalResult(value: unknown): unknown {
|
|
252
|
+
if (!isPlainObject(value) || isLedgerTerminalResultRef(value)) return value;
|
|
253
|
+
const stripped: Record<string, unknown> = {};
|
|
254
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
255
|
+
if (
|
|
256
|
+
(LEDGER_STRIPPED_TERMINAL_RESULT_KEYS as readonly string[]).includes(key)
|
|
257
|
+
) {
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
stripped[key] = entry;
|
|
261
|
+
}
|
|
262
|
+
return stripped;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function refReasonForIssue(
|
|
266
|
+
issue: ConvexLedgerPayloadIssue['reason'],
|
|
267
|
+
): LedgerTerminalResultRefReason {
|
|
268
|
+
switch (issue) {
|
|
269
|
+
case 'size_limit':
|
|
270
|
+
return 'terminal_result_exceeds_ledger_limit';
|
|
271
|
+
case 'depth_limit':
|
|
272
|
+
return 'terminal_result_exceeds_ledger_depth';
|
|
273
|
+
case 'invalid_field_name':
|
|
274
|
+
return 'terminal_result_has_invalid_field_name';
|
|
275
|
+
case 'array_too_long':
|
|
276
|
+
return 'terminal_result_array_too_long';
|
|
277
|
+
case 'object_too_wide':
|
|
278
|
+
return 'terminal_result_object_too_wide';
|
|
279
|
+
case 'not_json_serializable':
|
|
280
|
+
return 'terminal_result_not_json_serializable';
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export function ledgerTerminalResultRefForValue(
|
|
285
|
+
value: unknown,
|
|
286
|
+
reason: LedgerTerminalResultRefReason,
|
|
287
|
+
): LedgerTerminalResultRef {
|
|
288
|
+
let bytes = 0;
|
|
289
|
+
try {
|
|
290
|
+
bytes = jsonByteLength(value);
|
|
291
|
+
} catch {
|
|
292
|
+
// The bounded reason is the useful diagnostic. Never serialize the
|
|
293
|
+
// customer payload again merely to populate reference metadata.
|
|
294
|
+
}
|
|
295
|
+
return {
|
|
296
|
+
__kind: 'deepline.ledger_terminal_result_ref.v1',
|
|
297
|
+
store: 'scheduler_postgres',
|
|
298
|
+
key: 'terminal_result_json',
|
|
299
|
+
bytes,
|
|
300
|
+
reason,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** Optional derived summaries must never block the terminal lifecycle event. */
|
|
305
|
+
export function ledgerSummaryForLedger(value: unknown): unknown {
|
|
306
|
+
if (value === undefined || value === null) return value;
|
|
307
|
+
return inspectConvexLedgerPayload(value) ? undefined : value;
|
|
308
|
+
}
|
|
309
|
+
|
|
131
310
|
/**
|
|
132
311
|
* Shape a terminal run result for the Convex run ledger. Control-plane only:
|
|
133
312
|
*
|
|
@@ -138,40 +317,23 @@ function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
|
138
317
|
* the durable scheduler copy, so the ledger event stays small and the
|
|
139
318
|
* Convex append cannot wedge on an oversized/over-nested document.
|
|
140
319
|
*
|
|
141
|
-
*
|
|
142
|
-
* Postgres
|
|
320
|
+
* Any result accepted by the existing terminal persistence contract remains
|
|
321
|
+
* durable in scheduler Postgres; this only governs what the ledger embeds.
|
|
143
322
|
*/
|
|
144
323
|
export function terminalRunResultForLedger(value: unknown): unknown {
|
|
145
324
|
if (value === undefined || value === null) {
|
|
146
325
|
return value;
|
|
147
326
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (
|
|
153
|
-
(LEDGER_STRIPPED_TERMINAL_RESULT_KEYS as readonly string[]).includes(
|
|
154
|
-
key,
|
|
155
|
-
)
|
|
156
|
-
) {
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
stripped[key] = entry;
|
|
160
|
-
}
|
|
161
|
-
candidate = stripped;
|
|
162
|
-
}
|
|
163
|
-
const bytes = jsonByteLength(candidate);
|
|
164
|
-
if (bytes <= LEDGER_TERMINAL_RESULT_MAX_BYTES) {
|
|
327
|
+
if (isLedgerTerminalResultRef(value)) return value;
|
|
328
|
+
const candidate = stripReplayOnlyTerminalResult(value);
|
|
329
|
+
const issue = inspectConvexLedgerPayload(candidate);
|
|
330
|
+
if (!issue) {
|
|
165
331
|
return candidate;
|
|
166
332
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
bytes,
|
|
172
|
-
reason: 'terminal_result_exceeds_ledger_limit',
|
|
173
|
-
};
|
|
174
|
-
return ref;
|
|
333
|
+
return ledgerTerminalResultRefForValue(
|
|
334
|
+
candidate,
|
|
335
|
+
refReasonForIssue(issue.reason),
|
|
336
|
+
);
|
|
175
337
|
}
|
|
176
338
|
|
|
177
339
|
export function assertCustomerOutputValueWithinLimit(input: {
|
|
@@ -107,7 +107,7 @@ export const PLAY_LATENCY_SUMMARY_COLUMNS: PlayLatencyPhaseDefinition[] = [
|
|
|
107
107
|
header: 'route_child',
|
|
108
108
|
phase: 'server.start_route_resolve_child_manifests',
|
|
109
109
|
source: 'server',
|
|
110
|
-
description: 'Start route child play manifest resolution
|
|
110
|
+
description: 'Start route child play manifest resolution.',
|
|
111
111
|
},
|
|
112
112
|
{
|
|
113
113
|
header: 'route_active',
|