deepline 0.3.128 → 0.3.130

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.
Files changed (130) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +34 -9
  2. package/dist/bundling-sources/sdk/src/http.ts +22 -0
  3. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  4. package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +22 -0
  5. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +265 -2
  6. package/dist/bundling-sources/shared_libs/play-runtime/bounded-batch-function.ts +682 -0
  7. package/dist/bundling-sources/shared_libs/play-runtime/child-execution-strategy.ts +21 -5
  8. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +5390 -1732
  9. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +107 -1
  10. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +4 -1
  11. package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-execution-relay.ts +7 -0
  12. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +229 -7
  13. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +25 -4
  14. package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-gateway-capacity.ts +71 -0
  15. package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-gateway-drain.ts +1 -1
  16. package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-topology.ts +4 -1
  17. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +694 -28
  18. package/dist/bundling-sources/shared_libs/play-runtime/egress-bandwidth-probe.ts +167 -0
  19. package/dist/bundling-sources/shared_libs/play-runtime/execute-server-timing.ts +103 -0
  20. package/dist/bundling-sources/shared_libs/play-runtime/execution-gateway-receipt-output-reference.ts +34 -0
  21. package/dist/bundling-sources/shared_libs/play-runtime/execution-gateway-response-size.ts +27 -0
  22. package/dist/bundling-sources/shared_libs/play-runtime/gateway-postgres-admission.ts +66 -1
  23. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +425 -71
  24. package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +210 -32
  25. package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +27 -13
  26. package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +19 -6
  27. package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +61 -2
  28. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/contracts.ts +33 -1
  29. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/job.ts +42 -1
  30. package/dist/bundling-sources/shared_libs/play-runtime/launch-source-policy.ts +11 -11
  31. package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +49 -16
  32. package/dist/bundling-sources/shared_libs/play-runtime/map-memory-limits.ts +1653 -98
  33. package/dist/bundling-sources/shared_libs/play-runtime/memory-ledger.ts +807 -0
  34. package/dist/bundling-sources/shared_libs/play-runtime/memory-pressure-signal.ts +138 -0
  35. package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +85 -3
  36. package/dist/bundling-sources/shared_libs/play-runtime/persistence-latch.ts +60 -2
  37. package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +46 -1
  38. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/contracts.ts +2 -0
  39. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/job.ts +1 -0
  40. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/ports.ts +1 -0
  41. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/postgres-adapter.ts +1 -0
  42. package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-semantics.ts +70 -27
  43. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +56 -0
  44. package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/adaptive-provider-capacity-controller.ts +192 -0
  45. package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/epoch-aimd-rate-controller.ts +194 -0
  46. package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/fixture-capacity-simulator.ts +220 -0
  47. package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/gradient2-concurrency-controller.ts +214 -0
  48. package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-capacity-policy.ts +43 -0
  49. package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-concurrency-policy.ts +30 -0
  50. package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-rate-policy.ts +95 -0
  51. package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-throttle-classifier.ts +40 -0
  52. package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +1535 -11
  53. package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +49 -2
  54. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +6 -1
  55. package/dist/bundling-sources/shared_libs/play-runtime/run-log-buffer.ts +55 -0
  56. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/egress-probe.ts +221 -0
  57. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +339 -29
  58. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-deadline.ts +28 -1
  59. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-progress-push.ts +192 -165
  60. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +6 -0
  61. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +90 -5
  62. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +281 -6
  63. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +27 -1
  64. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/local-process.ts +19 -0
  65. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/modal.ts +108 -0
  66. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +40 -0
  67. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +11 -5
  68. package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +30 -0
  69. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api-compression.ts +276 -0
  70. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +723 -115
  71. package/dist/bundling-sources/shared_libs/play-runtime/runtime-capacity-policy.ts +114 -4
  72. package/dist/bundling-sources/shared_libs/play-runtime/runtime-contract.ts +3 -2
  73. package/dist/bundling-sources/shared_libs/play-runtime/runtime-environment.ts +41 -4
  74. package/dist/bundling-sources/shared_libs/play-runtime/runtime-flow.ts +448 -0
  75. package/dist/bundling-sources/shared_libs/play-runtime/runtime-map-row-feed.ts +215 -0
  76. package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +11 -0
  77. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-store-adapter.ts +161 -14
  78. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-value.ts +184 -0
  79. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-writer.ts +607 -121
  80. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sandbox-placement-policy.ts +4 -0
  81. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-writer.ts +21 -0
  82. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +15 -2
  83. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +71 -14
  84. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-deploy-task.ts +2 -2
  85. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +288 -119
  86. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +8 -6
  87. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +28 -3
  88. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd.ts +28 -8
  89. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/canonical-integration-operation-store.ts +179 -0
  90. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-heavy-request-admission.ts +80 -2
  91. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-progress-registry.ts +31 -2
  92. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/integration-operation-store-contract.ts +104 -0
  93. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/integration-operation-value-reference.ts +47 -0
  94. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/integration-operation-value-retirement.ts +193 -0
  95. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/integration-operation-value-storage.ts +420 -0
  96. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +146 -15
  97. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +134 -3
  98. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +1657 -95
  99. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +904 -77
  100. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-completion-coalescer.ts +452 -0
  101. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +601 -42
  102. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-terminal-transition.ts +1 -0
  103. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-receipt-value-storage.ts +371 -0
  104. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/worker-resource-metrics.ts +86 -7
  105. package/dist/bundling-sources/shared_libs/play-runtime/secret-redaction.ts +153 -22
  106. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/index.ts +1 -0
  107. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/receipt-cohort.ts +188 -38
  108. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/runtime-step-receipts-adapter.ts +28 -13
  109. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +44 -1
  110. package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +56 -4
  111. package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +2 -0
  112. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +16 -10
  113. package/dist/bundling-sources/shared_libs/plays/dataset.ts +4 -1
  114. package/dist/cli/index.js +250 -38
  115. package/dist/cli/index.mjs +250 -38
  116. package/dist/{compiler-manifest-DfSnbCTW.d.mts → compiler-manifest-BIqRyj5m.d.mts} +1 -1
  117. package/dist/{compiler-manifest-DfSnbCTW.d.ts → compiler-manifest-BIqRyj5m.d.ts} +1 -1
  118. package/dist/index.d.mts +4 -2
  119. package/dist/index.d.ts +4 -2
  120. package/dist/index.js +231 -35
  121. package/dist/index.mjs +231 -35
  122. package/dist/install-integrity.json +31 -2
  123. package/dist/plays/bundle-play-file.d.mts +2 -2
  124. package/dist/plays/bundle-play-file.d.ts +2 -2
  125. package/dist/plays/bundle-play-file.mjs +65 -1
  126. package/dist/release.d.mts +1 -1
  127. package/dist/release.d.ts +1 -1
  128. package/dist/release.js +1 -1
  129. package/dist/release.mjs +1 -1
  130. package/package.json +1 -1
@@ -0,0 +1,448 @@
1
+ /**
2
+ * Private runtime admission composition.
3
+ *
4
+ * A flow is deliberately smaller than a queue: it owns no payloads, retries,
5
+ * workers, or durable state. It acquires the capacity already owned by its
6
+ * stages, and releases every acquired stage in reverse order. That gives a
7
+ * map row, provider dispatch, or result handoff one idiomatic permit without
8
+ * inventing a second runtime scheduler.
9
+ */
10
+
11
+ export type RuntimeFlowLease = {
12
+ release(): void;
13
+ };
14
+
15
+ export type RuntimeFlowStage<Input> = {
16
+ /** Stable diagnostic name. It never changes execution behavior. */
17
+ name: string;
18
+ acquire(input: Input): Promise<RuntimeFlowLease>;
19
+ };
20
+
21
+ export type RuntimeFlow<Input> = {
22
+ /**
23
+ * Admit and run one logical unit through every capacity boundary in order.
24
+ *
25
+ * A later boundary rejecting returns earlier permits immediately. The permits
26
+ * stay private to the callback and return in reverse order on every exit.
27
+ */
28
+ run<Output>(
29
+ input: Input,
30
+ work: () => Output | Promise<Output>,
31
+ ): Promise<Output>;
32
+ };
33
+
34
+ export function createRuntimeFlow<Input>(input: {
35
+ stages: readonly RuntimeFlowStage<Input>[];
36
+ }): RuntimeFlow<Input> {
37
+ const stages = [...input.stages];
38
+ if (stages.length === 0) {
39
+ throw new Error('Runtime flow requires at least one admission stage.');
40
+ }
41
+ const names = new Set<string>();
42
+ for (const stage of stages) {
43
+ const name = stage.name.trim();
44
+ if (!name) throw new Error('Runtime flow stages require a name.');
45
+ if (names.has(name)) {
46
+ throw new Error(`Runtime flow stage "${name}" was registered twice.`);
47
+ }
48
+ names.add(name);
49
+ }
50
+
51
+ const admit = async (value: Input): Promise<RuntimeFlowLease[]> => {
52
+ const leases: RuntimeFlowLease[] = [];
53
+ try {
54
+ for (const stage of stages) {
55
+ leases.push(await stage.acquire(value));
56
+ }
57
+ } catch (error) {
58
+ releaseRuntimeFlowLeases(leases);
59
+ throw error;
60
+ }
61
+
62
+ return leases;
63
+ };
64
+
65
+ return {
66
+ async run<Output>(
67
+ value: Input,
68
+ work: () => Output | Promise<Output>,
69
+ ): Promise<Output> {
70
+ const leases = await admit(value);
71
+ try {
72
+ return await work();
73
+ } finally {
74
+ releaseRuntimeFlowLeases(leases);
75
+ }
76
+ },
77
+ };
78
+ }
79
+
80
+ /**
81
+ * A provider permit has a distinct pre-dispatch cancellation path. `park`,
82
+ * when present, returns a due permit that lost the local execution-slot race
83
+ * to its source for immediate local re-draw instead of refunding it.
84
+ */
85
+ export type RuntimeDispatchProviderPermit = RuntimeFlowLease & {
86
+ cancel(): Promise<void>;
87
+ park?(): Promise<void>;
88
+ };
89
+
90
+ export type RuntimeDispatchFlowInput = {
91
+ providerResourceKey?: string | null;
92
+ signal?: AbortSignal;
93
+ /** Fixtures consume provider capacity but acquire app transport after delay. */
94
+ requiresTransportPermit: boolean;
95
+ /** Emits the request-side transport wait observed by the caller's metrics. */
96
+ onTransportAdmitted?: (waitMs: number) => void;
97
+ };
98
+
99
+ type RuntimeDispatchPermit<
100
+ ProviderPermit extends RuntimeDispatchProviderPermit,
101
+ > = {
102
+ providerPermit: ProviderPermit;
103
+ executionSlot: RuntimeFlowLease;
104
+ integrationRequestLease: RuntimeFlowLease | null;
105
+ };
106
+
107
+ /**
108
+ * The only capability exposed while a provider-dispatch flow is admitted.
109
+ *
110
+ * `request` brackets the physical HTTP exchange, including consuming its
111
+ * body. It never exposes the provider, execution, or transport leases, so a
112
+ * caller cannot accidentally retain capacity after that exchange or return a
113
+ * provider permit before it knows whether the request began.
114
+ */
115
+ export type RuntimeDispatchScope = {
116
+ /**
117
+ * Run the one physical request. `beforeRelease` executes after the response
118
+ * is known but while the provider lease is still valid, so a caller can
119
+ * durably record response-bound feedback that the lease authorizes.
120
+ */
121
+ request<Output>(
122
+ work: () => Output | Promise<Output>,
123
+ beforeRelease?: () => void | Promise<void>,
124
+ ): Promise<Output>;
125
+ };
126
+
127
+ export type RuntimeDispatchFlow<
128
+ ProviderPermit extends RuntimeDispatchProviderPermit,
129
+ > = {
130
+ /**
131
+ * Admit and run exactly one physical provider request.
132
+ *
133
+ * Work that exits before `request` returns the provider permit through its
134
+ * cancellation path. Once `request` starts, the permit is released after
135
+ * the request body is consumed, even if that body cannot be verified. This
136
+ * preserves the ambiguity boundary while making resource lifetime private.
137
+ */
138
+ run<Output>(
139
+ input: RuntimeDispatchFlowInput,
140
+ work: (scope: RuntimeDispatchScope) => Output | Promise<Output>,
141
+ ): Promise<Output>;
142
+ };
143
+
144
+ /**
145
+ * Compose provider, sandbox-execution, and app-transport capacity at the
146
+ * dispatch edge. A provider permit is only useful when the local execution
147
+ * slot (and, for a live call, app transport) is immediately available. If a
148
+ * later stage is full, this flow returns every acquired permit and observes
149
+ * that stage's next availability. An execution slot won that way is kept
150
+ * only if a provider permit is already due locally (`tryAcquireProviderPermit`);
151
+ * otherwise the flow releases it and admits from the provider boundary
152
+ * again. No execution slot is ever held across a blocking provider acquire.
153
+ *
154
+ * It is not a queue and retains no tool input or result. The caller receives
155
+ * only a scoped request callback; Flow releases or cancels every lease based
156
+ * on whether that callback actually began.
157
+ */
158
+ export function createRuntimeDispatchFlow<
159
+ ProviderPermit extends RuntimeDispatchProviderPermit,
160
+ >(input: {
161
+ acquireProviderPermit: (input: {
162
+ signal?: AbortSignal;
163
+ }) => Promise<ProviderPermit>;
164
+ /** Synchronous local-only admission; must never block or go remote. */
165
+ tryAcquireProviderPermit?: () => ProviderPermit | null;
166
+ tryAcquireExecutionSlot: (input: {
167
+ providerResourceKey?: string | null;
168
+ }) => RuntimeFlowLease | null;
169
+ waitForExecutionSlot: (input: {
170
+ providerResourceKey?: string | null;
171
+ signal?: AbortSignal;
172
+ }) => Promise<RuntimeFlowLease>;
173
+ tryAcquireTransportSlot: () => RuntimeFlowLease | null;
174
+ waitForTransportSlot: (input: {
175
+ signal?: AbortSignal;
176
+ }) => Promise<RuntimeFlowLease>;
177
+ }): RuntimeDispatchFlow<ProviderPermit> {
178
+ const admit = async (
179
+ admission: RuntimeDispatchFlowInput,
180
+ ): Promise<RuntimeDispatchPermit<ProviderPermit>> => {
181
+ while (true) {
182
+ let providerPermit: ProviderPermit | null = null;
183
+ let executionSlot: RuntimeFlowLease | null = null;
184
+ const releaseExecutionSlot = (): void => {
185
+ const slot = executionSlot;
186
+ executionSlot = null;
187
+ slot?.release();
188
+ };
189
+ const cancelProviderPermit = async (): Promise<void> => {
190
+ const permit = providerPermit;
191
+ providerPermit = null;
192
+ await permit?.cancel();
193
+ };
194
+ // The execution-slot wait is brief and the permit is already due, so
195
+ // keep it local for the retry instead of refunding it to the store.
196
+ const parkProviderPermit = async (): Promise<void> => {
197
+ const permit = providerPermit;
198
+ providerPermit = null;
199
+ if (!permit) return;
200
+ if (permit.park) await permit.park();
201
+ else await permit.cancel();
202
+ };
203
+ try {
204
+ providerPermit = await input.acquireProviderPermit({
205
+ signal: admission.signal,
206
+ });
207
+ executionSlot = input.tryAcquireExecutionSlot({
208
+ providerResourceKey: admission.providerResourceKey,
209
+ });
210
+ if (!executionSlot) {
211
+ await parkProviderPermit();
212
+ executionSlot = await input.waitForExecutionSlot({
213
+ providerResourceKey: admission.providerResourceKey,
214
+ signal: admission.signal,
215
+ });
216
+ // Releasing this slot would hand it to the next FIFO waiter, so
217
+ // keep it if the parked (or any due) permit can be re-drawn without
218
+ // blocking. Otherwise the blocking provider acquire must not run
219
+ // while a slot is held.
220
+ providerPermit = input.tryAcquireProviderPermit
221
+ ? input.tryAcquireProviderPermit()
222
+ : null;
223
+ if (!providerPermit) {
224
+ releaseExecutionSlot();
225
+ continue;
226
+ }
227
+ }
228
+
229
+ if (!admission.requiresTransportPermit) {
230
+ return {
231
+ providerPermit,
232
+ executionSlot,
233
+ integrationRequestLease: null,
234
+ };
235
+ }
236
+
237
+ const integrationRequestLease = input.tryAcquireTransportSlot();
238
+ if (integrationRequestLease) {
239
+ return {
240
+ providerPermit,
241
+ executionSlot,
242
+ integrationRequestLease,
243
+ };
244
+ }
245
+
246
+ releaseExecutionSlot();
247
+ await cancelProviderPermit();
248
+ const availability = await input.waitForTransportSlot({
249
+ signal: admission.signal,
250
+ });
251
+ availability.release();
252
+ } catch (error) {
253
+ await cleanupRuntimeDispatchAdmissionFailure({
254
+ cause: error,
255
+ executionSlot,
256
+ providerPermit,
257
+ });
258
+ }
259
+ }
260
+ };
261
+
262
+ return {
263
+ async run<Output>(
264
+ admission: RuntimeDispatchFlowInput,
265
+ work: (scope: RuntimeDispatchScope) => Output | Promise<Output>,
266
+ ): Promise<Output> {
267
+ const permit = await admit(admission);
268
+ let transportLease = permit.integrationRequestLease;
269
+ let requestStarted = false;
270
+ let requestUsed = false;
271
+ let scopeOpen = true;
272
+ let requestPromise: Promise<unknown> | null = null;
273
+ let permitReleased = false;
274
+ const releasePermit = async (): Promise<void> => {
275
+ if (permitReleased) return;
276
+ permitReleased = true;
277
+ await releaseRuntimeDispatchPermit({
278
+ transportLease,
279
+ executionSlot: permit.executionSlot,
280
+ providerPermit: permit.providerPermit,
281
+ requestStarted,
282
+ });
283
+ };
284
+ try {
285
+ const output = await work({
286
+ request: <RequestOutput>(
287
+ request: () => RequestOutput | Promise<RequestOutput>,
288
+ beforeRelease?: () => void | Promise<void>,
289
+ ): Promise<RequestOutput> => {
290
+ if (!scopeOpen) {
291
+ return Promise.reject(
292
+ new Error('Runtime dispatch flow scope has already closed.'),
293
+ );
294
+ }
295
+ if (requestUsed) {
296
+ return Promise.reject(
297
+ new Error(
298
+ 'Runtime dispatch flow permits exactly one physical request.',
299
+ ),
300
+ );
301
+ }
302
+ requestUsed = true;
303
+ requestPromise = (async () => {
304
+ try {
305
+ if (transportLease) {
306
+ admission.onTransportAdmitted?.(0);
307
+ } else {
308
+ const transportStartedAt = Date.now();
309
+ transportLease = await input.waitForTransportSlot({
310
+ signal: admission.signal,
311
+ });
312
+ admission.onTransportAdmitted?.(
313
+ Date.now() - transportStartedAt,
314
+ );
315
+ }
316
+ requestStarted = true;
317
+ return await request();
318
+ } finally {
319
+ // Feedback is response-bound, but it is not allowed to strand
320
+ // the capacity that made the response possible. Preserve the
321
+ // ordering (feedback while the provider lease is valid) and
322
+ // always release all leases even when feedback persistence
323
+ // fails.
324
+ try {
325
+ if (requestStarted) await beforeRelease?.();
326
+ } finally {
327
+ await releasePermit();
328
+ }
329
+ }
330
+ })();
331
+ return requestPromise as Promise<RequestOutput>;
332
+ },
333
+ });
334
+ // A caller normally returns `await request(...)`. Waiting here also
335
+ // makes an accidental fire-and-forget request drain before its scope
336
+ // can close and prevents an early release of its capacity.
337
+ await requestPromise;
338
+ return output;
339
+ } finally {
340
+ scopeOpen = false;
341
+ // `work` may throw after it deliberately started a fire-and-forget
342
+ // request. That request has already claimed this permit's ownership,
343
+ // even when it is still waiting to acquire transport. Drain it before
344
+ // the outer cleanup: releasing first would make the request's own
345
+ // finally a no-op and leak a transport lease it acquires afterwards.
346
+ // Its rejection cannot replace the original work failure, but its
347
+ // cleanup must finish before any permit is returned.
348
+ if (requestPromise) {
349
+ try {
350
+ await requestPromise;
351
+ } catch {
352
+ // The normal path above already surfaces request failures. This
353
+ // path only preserves an earlier failure from `work`.
354
+ }
355
+ }
356
+ await releasePermit();
357
+ }
358
+ },
359
+ };
360
+ }
361
+
362
+ async function cleanupRuntimeDispatchAdmissionFailure<
363
+ ProviderPermit extends RuntimeDispatchProviderPermit,
364
+ >(input: {
365
+ cause: unknown;
366
+ executionSlot: RuntimeFlowLease | null;
367
+ providerPermit: ProviderPermit | null;
368
+ }): Promise<never> {
369
+ const failures = [input.cause];
370
+ try {
371
+ input.executionSlot?.release();
372
+ } catch (error) {
373
+ failures.push(error);
374
+ }
375
+ try {
376
+ await input.providerPermit?.cancel();
377
+ } catch (error) {
378
+ failures.push(error);
379
+ }
380
+ if (failures.length === 1) {
381
+ throw input.cause;
382
+ }
383
+ throw new AggregateError(
384
+ failures,
385
+ 'Runtime dispatch admission and cleanup both failed.',
386
+ );
387
+ }
388
+
389
+ function releaseRuntimeFlowLeases(leases: readonly RuntimeFlowLease[]): void {
390
+ let failure: unknown = null;
391
+ let hasFailure = false;
392
+ for (let index = leases.length - 1; index >= 0; index -= 1) {
393
+ try {
394
+ leases[index]?.release();
395
+ } catch (error) {
396
+ if (!hasFailure) {
397
+ failure = error;
398
+ hasFailure = true;
399
+ }
400
+ }
401
+ }
402
+ if (hasFailure) {
403
+ throw failure;
404
+ }
405
+ }
406
+
407
+ async function releaseRuntimeDispatchPermit<
408
+ ProviderPermit extends RuntimeDispatchProviderPermit,
409
+ >(input: {
410
+ transportLease: RuntimeFlowLease | null;
411
+ executionSlot: RuntimeFlowLease;
412
+ providerPermit: ProviderPermit;
413
+ requestStarted: boolean;
414
+ }): Promise<void> {
415
+ let failure: unknown = null;
416
+ let hasFailure = false;
417
+ const release = (work: () => void): void => {
418
+ try {
419
+ work();
420
+ } catch (error) {
421
+ if (!hasFailure) {
422
+ failure = error;
423
+ hasFailure = true;
424
+ }
425
+ }
426
+ };
427
+ const releaseAsync = async (work: () => Promise<void>): Promise<void> => {
428
+ try {
429
+ await work();
430
+ } catch (error) {
431
+ if (!hasFailure) {
432
+ failure = error;
433
+ hasFailure = true;
434
+ }
435
+ }
436
+ };
437
+
438
+ release(() => input.transportLease?.release());
439
+ release(() => input.executionSlot.release());
440
+ if (input.requestStarted) {
441
+ release(() => input.providerPermit.release());
442
+ } else {
443
+ await releaseAsync(async () => await input.providerPermit.cancel());
444
+ }
445
+ if (hasFailure) {
446
+ throw failure;
447
+ }
448
+ }
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Hands source pages to one running map worker pool so the pool never drains
3
+ * between pages. Workers that outrun the appended rows wait here; the page
4
+ * pump appends the next page as soon as the previous one is fully dispatched,
5
+ * so at most one undispatched page and one prepared page are resident.
6
+ */
7
+ export type RuntimeMapRowFeedSnapshot = {
8
+ appendedRows: number;
9
+ dispatchedRows: number;
10
+ pagesAppended: number;
11
+ closed: boolean;
12
+ failed: boolean;
13
+ workersWaiting: number;
14
+ pumpWaitingForDrain: boolean;
15
+ };
16
+
17
+ export const RUNTIME_MAP_ROW_FEED_MAX_WAIT_MS = 30 * 60 * 1000;
18
+
19
+ export class RuntimeMapRowFeedStalledError extends Error {
20
+ readonly snapshot: RuntimeMapRowFeedSnapshot;
21
+
22
+ constructor(input: {
23
+ waiter: 'worker' | 'pump';
24
+ waitMs: number;
25
+ snapshot: RuntimeMapRowFeedSnapshot;
26
+ }) {
27
+ super(
28
+ `Runtime map row feed stalled: ${input.waiter} waited ${input.waitMs} ms ` +
29
+ `(${JSON.stringify(input.snapshot)}).`,
30
+ );
31
+ this.name = 'RuntimeMapRowFeedStalledError';
32
+ this.snapshot = input.snapshot;
33
+ }
34
+ }
35
+
36
+ type Waiter<T> = {
37
+ resolve: (value: T) => void;
38
+ reject: (error: unknown) => void;
39
+ timer: ReturnType<typeof setTimeout>;
40
+ };
41
+
42
+ export class RuntimeMapRowFeed {
43
+ #appended = 0;
44
+ #dispatched = 0;
45
+ #pages = 0;
46
+ #closed = false;
47
+ #failure: unknown = null;
48
+ #failed = false;
49
+ readonly #rowWaiters = new Map<Waiter<boolean>, number>();
50
+ #drainWaiter: Waiter<void> | null = null;
51
+ #onAppended: ((fromIndex: number, toIndex: number) => void) | null = null;
52
+ readonly #maxWaitMs: number;
53
+
54
+ constructor(input?: { maxWaitMs?: number }) {
55
+ this.#maxWaitMs =
56
+ input?.maxWaitMs !== undefined &&
57
+ Number.isFinite(input.maxWaitMs) &&
58
+ input.maxWaitMs > 0
59
+ ? input.maxWaitMs
60
+ : RUNTIME_MAP_ROW_FEED_MAX_WAIT_MS;
61
+ }
62
+
63
+ onAppended(listener: (fromIndex: number, toIndex: number) => void): void {
64
+ this.#onAppended = listener;
65
+ }
66
+
67
+ append(rowCount: number): void {
68
+ if (this.#failed) throw this.#failure;
69
+ if (this.#closed) {
70
+ throw new Error('Runtime map row feed is closed; cannot append rows.');
71
+ }
72
+ if (!Number.isInteger(rowCount) || rowCount < 0) {
73
+ throw new Error(`Runtime map row feed append count must be a non-negative integer, got ${String(rowCount)}.`);
74
+ }
75
+ const fromIndex = this.#appended;
76
+ this.#appended += rowCount;
77
+ this.#pages += 1;
78
+ this.#onAppended?.(fromIndex, this.#appended);
79
+ this.#wakeRowWaiters();
80
+ }
81
+
82
+ close(): void {
83
+ if (this.#closed || this.#failed) return;
84
+ this.#closed = true;
85
+ this.#wakeRowWaiters();
86
+ this.#settleDrainWaiter();
87
+ }
88
+
89
+ fail(error: unknown): void {
90
+ if (this.#failed) return;
91
+ this.#failed = true;
92
+ this.#failure = error;
93
+ for (const [waiter] of this.#rowWaiters) {
94
+ clearTimeout(waiter.timer);
95
+ waiter.reject(error);
96
+ }
97
+ this.#rowWaiters.clear();
98
+ if (this.#drainWaiter) {
99
+ clearTimeout(this.#drainWaiter.timer);
100
+ this.#drainWaiter.reject(error);
101
+ this.#drainWaiter = null;
102
+ }
103
+ }
104
+
105
+ get failed(): boolean {
106
+ return this.#failed;
107
+ }
108
+
109
+ get closed(): boolean {
110
+ return this.#closed;
111
+ }
112
+
113
+ markDispatched(count = 1): void {
114
+ this.#dispatched += count;
115
+ if (this.#dispatched > this.#appended) {
116
+ throw new Error(
117
+ `Runtime map row feed dispatched ${this.#dispatched} rows but only ${this.#appended} were appended.`,
118
+ );
119
+ }
120
+ this.#settleDrainWaiter();
121
+ }
122
+
123
+ /**
124
+ * Resolves true once row `index` has been appended, false once the feed is
125
+ * closed with no such row. Rejects with the feed's failure.
126
+ */
127
+ waitForRows(index: number): Promise<boolean> {
128
+ if (this.#failed) return Promise.reject(this.#failure);
129
+ if (index < this.#appended) return Promise.resolve(true);
130
+ if (this.#closed) return Promise.resolve(false);
131
+ return new Promise<boolean>((resolve, reject) => {
132
+ const startedAt = Date.now();
133
+ const waiter: Waiter<boolean> = {
134
+ resolve,
135
+ reject,
136
+ timer: setTimeout(() => {
137
+ this.#rowWaiters.delete(waiter);
138
+ reject(
139
+ new RuntimeMapRowFeedStalledError({
140
+ waiter: 'worker',
141
+ waitMs: Date.now() - startedAt,
142
+ snapshot: this.snapshot(),
143
+ }),
144
+ );
145
+ }, this.#maxWaitMs),
146
+ };
147
+ waiter.timer.unref?.();
148
+ this.#rowWaiters.set(waiter, index);
149
+ });
150
+ }
151
+
152
+ /** Resolves once every appended row has been dispatched to a worker. */
153
+ waitUntilDrained(): Promise<void> {
154
+ if (this.#failed) return Promise.reject(this.#failure);
155
+ if (this.#dispatched >= this.#appended) return Promise.resolve();
156
+ if (this.#drainWaiter) {
157
+ return Promise.reject(
158
+ new Error('Runtime map row feed already has a pump waiting to drain.'),
159
+ );
160
+ }
161
+ return new Promise<void>((resolve, reject) => {
162
+ const startedAt = Date.now();
163
+ this.#drainWaiter = {
164
+ resolve,
165
+ reject,
166
+ timer: setTimeout(() => {
167
+ this.#drainWaiter = null;
168
+ reject(
169
+ new RuntimeMapRowFeedStalledError({
170
+ waiter: 'pump',
171
+ waitMs: Date.now() - startedAt,
172
+ snapshot: this.snapshot(),
173
+ }),
174
+ );
175
+ }, this.#maxWaitMs),
176
+ };
177
+ this.#drainWaiter.timer.unref?.();
178
+ });
179
+ }
180
+
181
+ snapshot(): RuntimeMapRowFeedSnapshot {
182
+ return {
183
+ appendedRows: this.#appended,
184
+ dispatchedRows: this.#dispatched,
185
+ pagesAppended: this.#pages,
186
+ closed: this.#closed,
187
+ failed: this.#failed,
188
+ workersWaiting: this.#rowWaiters.size,
189
+ pumpWaitingForDrain: this.#drainWaiter !== null,
190
+ };
191
+ }
192
+
193
+ #wakeRowWaiters(): void {
194
+ for (const [waiter, index] of this.#rowWaiters) {
195
+ if (index < this.#appended) {
196
+ this.#rowWaiters.delete(waiter);
197
+ clearTimeout(waiter.timer);
198
+ waiter.resolve(true);
199
+ } else if (this.#closed) {
200
+ this.#rowWaiters.delete(waiter);
201
+ clearTimeout(waiter.timer);
202
+ waiter.resolve(false);
203
+ }
204
+ }
205
+ }
206
+
207
+ #settleDrainWaiter(): void {
208
+ if (!this.#drainWaiter) return;
209
+ if (this.#dispatched < this.#appended && !this.#closed) return;
210
+ const waiter = this.#drainWaiter;
211
+ this.#drainWaiter = null;
212
+ clearTimeout(waiter.timer);
213
+ waiter.resolve();
214
+ }
215
+ }
@@ -24,6 +24,7 @@ export const RUNTIME_OPERATION_CAPABILITIES = {
24
24
  mark_runtime_step_receipts_queued: 'receipt.write',
25
25
  complete_runtime_step_receipt: 'receipt.write',
26
26
  complete_runtime_step_receipts: 'receipt.write',
27
+ complete_runtime_step_receipts_by_reference: 'receipt.write',
27
28
  release_runtime_step_receipt: 'receipt.write',
28
29
  fail_runtime_step_receipt: 'receipt.write',
29
30
  fail_runtime_step_receipts: 'receipt.write',
@@ -54,6 +55,16 @@ export const RUNTIME_OPERATION_CONTRACT: DeployedOperationContract =
54
55
  deployed.operation({
55
56
  id: 'runtime-api-actions',
56
57
  actions: RUNTIME_OPERATION_CAPABILITIES,
58
+ olderReceiver: {
59
+ // The runner retains the complete result before attempting this
60
+ // compact completion. An older app receiver reports the action as
61
+ // unsupported, and the adapter retries the established full-payload
62
+ // completion without re-executing the provider call.
63
+ complete_runtime_step_receipts_by_reference: {
64
+ kind: 'equivalent-fallback',
65
+ action: 'complete_runtime_step_receipts',
66
+ },
67
+ },
57
68
  });
58
69
 
59
70
  export function runtimeOperationCapability(