deepline 0.1.153 → 0.1.154
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundling-sources/apps/play-runner-workers/src/coordinator-entry.ts +15 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +1180 -825
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/batching.ts +34 -18
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/harness-receipt-store.ts +41 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/receipts.ts +143 -8
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-receipts.ts +104 -0
- package/dist/bundling-sources/sdk/src/index.ts +0 -1
- package/dist/bundling-sources/sdk/src/play.ts +3 -48
- package/dist/bundling-sources/sdk/src/plays/harness-stub.ts +27 -2
- package/dist/bundling-sources/sdk/src/release.ts +2 -2
- package/dist/bundling-sources/sdk/src/worker-play-entry.ts +0 -10
- package/dist/bundling-sources/shared_libs/play-data-plane/index.ts +0 -1
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +87 -0
- package/dist/bundling-sources/shared_libs/play-runtime/batch-runtime.ts +0 -59
- package/dist/bundling-sources/shared_libs/play-runtime/cell-staleness.ts +0 -253
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +805 -1570
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +47 -74
- package/dist/bundling-sources/shared_libs/play-runtime/default-batch-strategies.ts +36 -14
- package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +145 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +284 -0
- package/dist/bundling-sources/shared_libs/play-runtime/postgres-json.ts +12 -5
- package/dist/bundling-sources/shared_libs/play-runtime/run-lifecycle-policy.ts +78 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-snapshot-stream.ts +10 -45
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +923 -535
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-neon-serverless.ts +45 -76
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver.ts +12 -1
- package/dist/bundling-sources/shared_libs/play-runtime/step-program-dataset-builder.ts +1 -14
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execution-outcome.ts +159 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result-types.ts +4 -1
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +32 -0
- package/dist/bundling-sources/shared_libs/plays/definition.ts +4 -2
- package/dist/bundling-sources/shared_libs/plays/runtime-validation.ts +3 -14
- package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +1 -43
- package/dist/cli/index.js +1301 -399
- package/dist/cli/index.mjs +1269 -361
- package/dist/{compiler-manifest-BjoRENv9.d.ts → compiler-manifest-DW1flrHk.d.mts} +0 -9
- package/dist/{compiler-manifest-BjoRENv9.d.mts → compiler-manifest-DW1flrHk.d.ts} +0 -9
- package/dist/index.d.mts +9 -38
- package/dist/index.d.ts +9 -38
- package/dist/index.js +22 -11
- package/dist/index.mjs +22 -11
- package/dist/plays/bundle-play-file.d.mts +2 -2
- package/dist/plays/bundle-play-file.d.ts +2 -2
- package/package.json +1 -1
- package/dist/bundling-sources/shared_libs/play-data-plane/cell-policy.ts +0 -76
- package/dist/bundling-sources/shared_libs/play-runtime/progress-emitter.ts +0 -197
- package/dist/bundling-sources/shared_libs/play-runtime/waterfall-replay.ts +0 -79
|
@@ -46,7 +46,6 @@
|
|
|
46
46
|
|
|
47
47
|
import {
|
|
48
48
|
registerRuntimePoolFactory,
|
|
49
|
-
registerRuntimeOneShotQueryFactory,
|
|
50
49
|
type RuntimePool,
|
|
51
50
|
type RuntimePoolClient,
|
|
52
51
|
} from './runtime-pg-driver';
|
|
@@ -91,15 +90,6 @@ interface NeonPoolConfig {
|
|
|
91
90
|
|
|
92
91
|
interface NeonModule {
|
|
93
92
|
Pool: new (config: NeonPoolConfig) => NeonPoolInstance;
|
|
94
|
-
neon: (
|
|
95
|
-
connectionString: string,
|
|
96
|
-
options?: { fullResults?: boolean },
|
|
97
|
-
) => {
|
|
98
|
-
query<R = Record<string, unknown>>(
|
|
99
|
-
text: string,
|
|
100
|
-
params?: unknown[],
|
|
101
|
-
): Promise<{ rows: R[] }>;
|
|
102
|
-
};
|
|
103
93
|
}
|
|
104
94
|
|
|
105
95
|
function assertBindParams(params: unknown[] | undefined): void {
|
|
@@ -177,72 +167,51 @@ function wrapNeonPool(pool: NeonPoolInstance): RuntimePool {
|
|
|
177
167
|
* until the import() resolves.
|
|
178
168
|
*/
|
|
179
169
|
export function installNeonServerlessRuntimePoolDriver(): void {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
return sqlPromise;
|
|
189
|
-
}
|
|
190
|
-
return {
|
|
191
|
-
query: async <
|
|
192
|
-
R extends Record<string, unknown> = Record<string, unknown>,
|
|
193
|
-
>(
|
|
194
|
-
text: string,
|
|
195
|
-
params?: unknown[],
|
|
196
|
-
) => {
|
|
197
|
-
assertBindParams(params);
|
|
198
|
-
const sql = await getSql();
|
|
199
|
-
return await sql.query<R>(text, params);
|
|
200
|
-
},
|
|
201
|
-
};
|
|
202
|
-
});
|
|
170
|
+
registerRuntimePoolFactory(
|
|
171
|
+
(input) => {
|
|
172
|
+
// Captured lazily so a Pool is only constructed if the play actually
|
|
173
|
+
// connects. Most plays that don't touch Postgres directly never even
|
|
174
|
+
// reach this branch — the factory is registered but never invoked.
|
|
175
|
+
let lazyPool: NeonPoolInstance | null = null;
|
|
203
176
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
idleTimeoutMillis: input.idleTimeoutMs ?? 15_000,
|
|
229
|
-
connectionTimeoutMillis: input.connectTimeoutMs ?? 10_000,
|
|
230
|
-
});
|
|
231
|
-
lazyPool = pool;
|
|
232
|
-
return pool;
|
|
233
|
-
}
|
|
177
|
+
/**
|
|
178
|
+
* Resolve the lazy Pool, creating it on first call.
|
|
179
|
+
*
|
|
180
|
+
* Race safety: workerd executes within a single JS event loop, so
|
|
181
|
+
* two concurrent `connect()` calls on the SAME wrapper run their
|
|
182
|
+
* "lazyPool == null" checks in turn — the first creates the Pool,
|
|
183
|
+
* the second sees it. No locking needed.
|
|
184
|
+
*
|
|
185
|
+
* If pool creation fails (e.g. DNS, bad connection string), the
|
|
186
|
+
* error propagates out of connect() to the caller. We don't cache
|
|
187
|
+
* a failed pool so retries can succeed on transient failures.
|
|
188
|
+
*/
|
|
189
|
+
async function ensurePool(): Promise<NeonPoolInstance> {
|
|
190
|
+
if (lazyPool) return lazyPool;
|
|
191
|
+
const neon = await loadNeonModule();
|
|
192
|
+
const pool = new neon.Pool({
|
|
193
|
+
connectionString: input.connectionString,
|
|
194
|
+
max: input.maxConnections ?? 4,
|
|
195
|
+
idleTimeoutMillis: input.idleTimeoutMs ?? 15_000,
|
|
196
|
+
connectionTimeoutMillis: input.connectTimeoutMs ?? 10_000,
|
|
197
|
+
});
|
|
198
|
+
lazyPool = pool;
|
|
199
|
+
return pool;
|
|
200
|
+
}
|
|
234
201
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
202
|
+
return {
|
|
203
|
+
connect: async () => {
|
|
204
|
+
const pool = await ensurePool();
|
|
205
|
+
return wrapNeonClient(await pool.connect());
|
|
206
|
+
},
|
|
207
|
+
end: async () => {
|
|
208
|
+
if (lazyPool) {
|
|
209
|
+
await lazyPool.end();
|
|
210
|
+
lazyPool = null;
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
},
|
|
215
|
+
{ canReuseAcrossRequests: false },
|
|
216
|
+
);
|
|
248
217
|
}
|
|
@@ -58,6 +58,7 @@ const runtimePgDriverRegistryKey = Symbol.for(
|
|
|
58
58
|
type RuntimePgDriverRegistry = {
|
|
59
59
|
poolFactory: RuntimePoolFactory | null;
|
|
60
60
|
oneShotQueryFactory: RuntimeOneShotQueryFactory | null;
|
|
61
|
+
canReusePoolsAcrossRequests: boolean;
|
|
61
62
|
};
|
|
62
63
|
|
|
63
64
|
function getRuntimePgDriverRegistry(): RuntimePgDriverRegistry {
|
|
@@ -67,6 +68,7 @@ function getRuntimePgDriverRegistry(): RuntimePgDriverRegistry {
|
|
|
67
68
|
globalWithRegistry[runtimePgDriverRegistryKey] ??= {
|
|
68
69
|
poolFactory: null,
|
|
69
70
|
oneShotQueryFactory: null,
|
|
71
|
+
canReusePoolsAcrossRequests: true,
|
|
70
72
|
};
|
|
71
73
|
return globalWithRegistry[runtimePgDriverRegistryKey];
|
|
72
74
|
}
|
|
@@ -76,7 +78,10 @@ function getRuntimePgDriverRegistry(): RuntimePgDriverRegistry {
|
|
|
76
78
|
* with different factories will throw to prevent silent driver swaps that
|
|
77
79
|
* would otherwise drop in-flight pooled connections.
|
|
78
80
|
*/
|
|
79
|
-
export function registerRuntimePoolFactory(
|
|
81
|
+
export function registerRuntimePoolFactory(
|
|
82
|
+
factory: RuntimePoolFactory,
|
|
83
|
+
options: { canReuseAcrossRequests?: boolean } = {},
|
|
84
|
+
): void {
|
|
80
85
|
const registry = getRuntimePgDriverRegistry();
|
|
81
86
|
if (registry.poolFactory && registry.poolFactory !== factory) {
|
|
82
87
|
throw new Error(
|
|
@@ -85,12 +90,17 @@ export function registerRuntimePoolFactory(factory: RuntimePoolFactory): void {
|
|
|
85
90
|
);
|
|
86
91
|
}
|
|
87
92
|
registry.poolFactory = factory;
|
|
93
|
+
registry.canReusePoolsAcrossRequests = options.canReuseAcrossRequests ?? true;
|
|
88
94
|
}
|
|
89
95
|
|
|
90
96
|
export function isRuntimePoolFactoryRegistered(): boolean {
|
|
91
97
|
return getRuntimePgDriverRegistry().poolFactory !== null;
|
|
92
98
|
}
|
|
93
99
|
|
|
100
|
+
export function canReuseRuntimePostgresPoolsAcrossRequests(): boolean {
|
|
101
|
+
return getRuntimePgDriverRegistry().canReusePoolsAcrossRequests;
|
|
102
|
+
}
|
|
103
|
+
|
|
94
104
|
export function registerRuntimeOneShotQueryFactory(
|
|
95
105
|
factory: RuntimeOneShotQueryFactory,
|
|
96
106
|
): void {
|
|
@@ -146,4 +156,5 @@ export function __resetRuntimePoolFactoryForTests(): void {
|
|
|
146
156
|
const registry = getRuntimePgDriverRegistry();
|
|
147
157
|
registry.poolFactory = null;
|
|
148
158
|
registry.oneShotQueryFactory = null;
|
|
159
|
+
registry.canReusePoolsAcrossRequests = true;
|
|
149
160
|
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PreviousCell } from './cell-staleness';
|
|
2
2
|
|
|
3
3
|
export type StepProgramDatasetOptions = {
|
|
4
4
|
runIf?: (
|
|
5
5
|
row: Record<string, unknown>,
|
|
6
6
|
index: number,
|
|
7
7
|
) => boolean | Promise<boolean>;
|
|
8
|
-
recompute?: boolean;
|
|
9
|
-
recomputeOnError?: boolean;
|
|
10
|
-
staleAfterSeconds?: AuthoredStaleAfterSeconds;
|
|
11
8
|
};
|
|
12
9
|
|
|
13
10
|
export type StepProgramDatasetColumnRunInput<Value = unknown> = {
|
|
@@ -50,10 +47,7 @@ function isPreviousCell(value: unknown): value is PreviousCell {
|
|
|
50
47
|
|
|
51
48
|
export type StepProgramDatasetStep<TResolver> = {
|
|
52
49
|
name: string;
|
|
53
|
-
recompute?: boolean;
|
|
54
|
-
recomputeOnError?: boolean;
|
|
55
50
|
resolver: TResolver;
|
|
56
|
-
staleAfterSeconds?: AuthoredStaleAfterSeconds;
|
|
57
51
|
};
|
|
58
52
|
|
|
59
53
|
export type StepProgramDatasetProgram<TStep> = {
|
|
@@ -134,13 +128,6 @@ export class StepProgramDatasetBuilder<
|
|
|
134
128
|
normalized.resolver,
|
|
135
129
|
normalized.options,
|
|
136
130
|
),
|
|
137
|
-
...(normalized.options?.staleAfterSeconds !== undefined
|
|
138
|
-
? { staleAfterSeconds: normalized.options.staleAfterSeconds }
|
|
139
|
-
: {}),
|
|
140
|
-
...(normalized.options?.recompute === true ? { recompute: true } : {}),
|
|
141
|
-
...(normalized.options?.recomputeOnError === true
|
|
142
|
-
? { recomputeOnError: true }
|
|
143
|
-
: {}),
|
|
144
131
|
} as TStep,
|
|
145
132
|
];
|
|
146
133
|
return this;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cloneToolExecuteResultWithExecution,
|
|
3
|
+
isToolExecuteResult,
|
|
4
|
+
type ToolExecuteResult,
|
|
5
|
+
type ToolResultExecutionMetadata,
|
|
6
|
+
} from './tool-result';
|
|
7
|
+
|
|
8
|
+
type OptionalKey = string | null | undefined;
|
|
9
|
+
|
|
10
|
+
type BaseToolExecutionOutcome = {
|
|
11
|
+
cacheKey?: OptionalKey;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type ToolExecutionOutcome =
|
|
15
|
+
| (BaseToolExecutionOutcome & {
|
|
16
|
+
kind: 'live';
|
|
17
|
+
receiptKey?: OptionalKey;
|
|
18
|
+
})
|
|
19
|
+
| (BaseToolExecutionOutcome & {
|
|
20
|
+
kind: 'checkpoint';
|
|
21
|
+
})
|
|
22
|
+
| (BaseToolExecutionOutcome & {
|
|
23
|
+
kind: 'cache';
|
|
24
|
+
receiptKey: string;
|
|
25
|
+
attachedToReceiptKey?: OptionalKey;
|
|
26
|
+
})
|
|
27
|
+
| (BaseToolExecutionOutcome & {
|
|
28
|
+
kind: 'in_flight';
|
|
29
|
+
receiptKey: string;
|
|
30
|
+
attachedToReceiptKey?: OptionalKey;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export type DurableReceiptRecoverySource = 'cache' | 'in_flight' | 'owner';
|
|
34
|
+
|
|
35
|
+
function trimmed(value: OptionalKey): string | null {
|
|
36
|
+
const normalized = value?.trim();
|
|
37
|
+
return normalized ? normalized : null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function optionalCacheKey(value: OptionalKey): Pick<
|
|
41
|
+
ToolResultExecutionMetadata,
|
|
42
|
+
'cacheKey'
|
|
43
|
+
> {
|
|
44
|
+
const cacheKey = trimmed(value);
|
|
45
|
+
return cacheKey ? { cacheKey } : {};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function followerAttachment(input: {
|
|
49
|
+
receiptKey: string;
|
|
50
|
+
attachedToReceiptKey?: OptionalKey;
|
|
51
|
+
}): Pick<ToolResultExecutionMetadata, 'attachedToReceiptKey'> {
|
|
52
|
+
return {
|
|
53
|
+
attachedToReceiptKey:
|
|
54
|
+
trimmed(input.attachedToReceiptKey) ?? input.receiptKey,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function toolExecutionMetadataForOutcome(
|
|
59
|
+
outcome: ToolExecutionOutcome,
|
|
60
|
+
): ToolResultExecutionMetadata {
|
|
61
|
+
switch (outcome.kind) {
|
|
62
|
+
case 'live': {
|
|
63
|
+
const receiptKey = trimmed(outcome.receiptKey);
|
|
64
|
+
return {
|
|
65
|
+
idempotent: true,
|
|
66
|
+
cached: false,
|
|
67
|
+
source: 'live',
|
|
68
|
+
...optionalCacheKey(outcome.cacheKey),
|
|
69
|
+
...(receiptKey ? { receiptRole: 'owner' as const, receiptKey } : {}),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
case 'checkpoint':
|
|
73
|
+
return {
|
|
74
|
+
idempotent: true,
|
|
75
|
+
cached: true,
|
|
76
|
+
source: 'checkpoint',
|
|
77
|
+
...optionalCacheKey(outcome.cacheKey),
|
|
78
|
+
};
|
|
79
|
+
case 'cache': {
|
|
80
|
+
const receiptKey = trimmed(outcome.receiptKey);
|
|
81
|
+
if (!receiptKey) {
|
|
82
|
+
throw new Error('Cached durable tool results require a receipt key.');
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
idempotent: true,
|
|
86
|
+
cached: true,
|
|
87
|
+
source: 'cache',
|
|
88
|
+
...optionalCacheKey(outcome.cacheKey),
|
|
89
|
+
receiptRole: 'follower',
|
|
90
|
+
receiptKey,
|
|
91
|
+
...followerAttachment({
|
|
92
|
+
receiptKey,
|
|
93
|
+
attachedToReceiptKey: outcome.attachedToReceiptKey,
|
|
94
|
+
}),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
case 'in_flight': {
|
|
98
|
+
const receiptKey = trimmed(outcome.receiptKey);
|
|
99
|
+
if (!receiptKey) {
|
|
100
|
+
throw new Error('In-flight durable tool results require a receipt key.');
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
idempotent: true,
|
|
104
|
+
cached: false,
|
|
105
|
+
source: 'in_flight',
|
|
106
|
+
...optionalCacheKey(outcome.cacheKey),
|
|
107
|
+
receiptRole: 'follower',
|
|
108
|
+
receiptKey,
|
|
109
|
+
...followerAttachment({
|
|
110
|
+
receiptKey,
|
|
111
|
+
attachedToReceiptKey: outcome.attachedToReceiptKey,
|
|
112
|
+
}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
default: {
|
|
116
|
+
const exhaustive: never = outcome;
|
|
117
|
+
return exhaustive;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function toolExecutionOutcomeForDurableReceipt(input: {
|
|
123
|
+
source: DurableReceiptRecoverySource;
|
|
124
|
+
receiptKey: string;
|
|
125
|
+
cacheKey?: OptionalKey;
|
|
126
|
+
}): ToolExecutionOutcome {
|
|
127
|
+
return input.source === 'owner'
|
|
128
|
+
? {
|
|
129
|
+
kind: 'live',
|
|
130
|
+
receiptKey: input.receiptKey,
|
|
131
|
+
cacheKey: input.cacheKey,
|
|
132
|
+
}
|
|
133
|
+
: {
|
|
134
|
+
kind: input.source,
|
|
135
|
+
receiptKey: input.receiptKey,
|
|
136
|
+
attachedToReceiptKey: input.receiptKey,
|
|
137
|
+
cacheKey: input.cacheKey,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function cloneToolExecuteResultWithOutcome<TResult>(
|
|
142
|
+
value: ToolExecuteResult<TResult>,
|
|
143
|
+
outcome: ToolExecutionOutcome,
|
|
144
|
+
): ToolExecuteResult<TResult> {
|
|
145
|
+
return cloneToolExecuteResultWithExecution(
|
|
146
|
+
value,
|
|
147
|
+
toolExecutionMetadataForOutcome(outcome),
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function markToolExecuteResultExecutionOutcome(
|
|
152
|
+
value: unknown,
|
|
153
|
+
outcome: ToolExecutionOutcome,
|
|
154
|
+
): unknown {
|
|
155
|
+
if (!isToolExecuteResult(value)) {
|
|
156
|
+
return value;
|
|
157
|
+
}
|
|
158
|
+
return cloneToolExecuteResultWithOutcome(value, outcome);
|
|
159
|
+
}
|
|
@@ -5,8 +5,11 @@ import type { PlayDataset, SerializedPlayDataset } from '../plays/dataset';
|
|
|
5
5
|
export type ToolResultExecutionMetadata = {
|
|
6
6
|
idempotent: true;
|
|
7
7
|
cached: boolean;
|
|
8
|
-
source: 'live' | 'checkpoint' | 'cache';
|
|
8
|
+
source: 'live' | 'checkpoint' | 'cache' | 'in_flight';
|
|
9
9
|
cacheKey?: string;
|
|
10
|
+
receiptRole?: 'owner' | 'follower';
|
|
11
|
+
receiptKey?: string;
|
|
12
|
+
attachedToReceiptKey?: string;
|
|
10
13
|
};
|
|
11
14
|
|
|
12
15
|
export type ToolResultTargetMetadata = {
|
|
@@ -18,6 +18,30 @@ export type WorkReceiptCommand = {
|
|
|
18
18
|
runId: string;
|
|
19
19
|
key: string;
|
|
20
20
|
reclaimRunning?: boolean;
|
|
21
|
+
forceRefresh?: boolean;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type WorkReceiptBatchClaimCommand = {
|
|
25
|
+
playName: string;
|
|
26
|
+
runId: string;
|
|
27
|
+
keys: string[];
|
|
28
|
+
reclaimRunning?: boolean;
|
|
29
|
+
forceRefresh?: boolean;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type WorkReceiptBatchCompleteCommand = {
|
|
33
|
+
playName: string;
|
|
34
|
+
receipts: Array<{ runId: string; key: string; output: unknown }>;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type WorkReceiptBatchFailCommand = {
|
|
38
|
+
playName: string;
|
|
39
|
+
receipts: Array<{ runId: string; key: string; error: string }>;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type WorkReceiptGetCommand = {
|
|
43
|
+
playName: string;
|
|
44
|
+
key: string;
|
|
21
45
|
};
|
|
22
46
|
|
|
23
47
|
export type WorkReceiptClaim =
|
|
@@ -39,13 +63,21 @@ export type WorkReceiptClaim =
|
|
|
39
63
|
};
|
|
40
64
|
|
|
41
65
|
export type WorkReceiptStore = {
|
|
66
|
+
getReceipt?(input: WorkReceiptGetCommand): Promise<WorkReceipt | null>;
|
|
42
67
|
claimReceipt(input: WorkReceiptCommand): Promise<WorkReceiptClaim>;
|
|
68
|
+
claimReceipts?(
|
|
69
|
+
input: WorkReceiptBatchClaimCommand,
|
|
70
|
+
): Promise<WorkReceiptClaim[]>;
|
|
43
71
|
completeReceipt(
|
|
44
72
|
input: WorkReceiptCommand & { output: unknown },
|
|
45
73
|
): Promise<WorkReceipt | null>;
|
|
74
|
+
completeReceipts?(
|
|
75
|
+
input: WorkReceiptBatchCompleteCommand,
|
|
76
|
+
): Promise<WorkReceipt[]>;
|
|
46
77
|
failReceipt(
|
|
47
78
|
input: WorkReceiptCommand & { error: string },
|
|
48
79
|
): Promise<WorkReceipt | null>;
|
|
80
|
+
failReceipts?(input: WorkReceiptBatchFailCommand): Promise<WorkReceipt[]>;
|
|
49
81
|
};
|
|
50
82
|
|
|
51
83
|
const SCOPED_WORK_RECEIPT_KEY_VERSION = 'ctxv2';
|
|
@@ -198,8 +198,10 @@ export function validatePlayStructuredDefinition(definition: unknown): {
|
|
|
198
198
|
if (typedStep.type === 'tool' && !typedStep.toolId?.trim()) {
|
|
199
199
|
errors.push(`Tool step ${typedStep.alias || index} requires toolId.`);
|
|
200
200
|
}
|
|
201
|
-
if (typedStep.type === 'waterfall'
|
|
202
|
-
errors.push(
|
|
201
|
+
if (typedStep.type === 'waterfall') {
|
|
202
|
+
errors.push(
|
|
203
|
+
`Waterfall step ${typedStep.alias || index} is no longer supported. Use explicit tool steps or a steps(...) program.`,
|
|
204
|
+
);
|
|
203
205
|
}
|
|
204
206
|
if (typedStep.type === 'run_javascript') {
|
|
205
207
|
if (!typedStep.execute?.source?.trim()) {
|
|
@@ -111,20 +111,9 @@ function validatePlayMapStructure(code: string): string[] {
|
|
|
111
111
|
callExpression.callee.property.type === 'Identifier' &&
|
|
112
112
|
callExpression.callee.property.name === 'waterfall'
|
|
113
113
|
) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
(prop) =>
|
|
118
|
-
prop.type === 'Property' &&
|
|
119
|
-
prop.key.type === 'Identifier' &&
|
|
120
|
-
prop.key.name === 'minResults',
|
|
121
|
-
);
|
|
122
|
-
if (!minResultsProperty) {
|
|
123
|
-
errors.push(
|
|
124
|
-
'Inline ctx.waterfall({...}) calls must declare minResults.',
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
114
|
+
errors.push(
|
|
115
|
+
'ctx.waterfall(...) has been removed. Use explicit ctx.tools.execute(...) calls with steps(...) or ordinary TypeScript fallback logic.',
|
|
116
|
+
);
|
|
128
117
|
}
|
|
129
118
|
return;
|
|
130
119
|
}
|
|
@@ -131,9 +131,6 @@ export interface PlayStaticColumnProducer {
|
|
|
131
131
|
toolId?: string;
|
|
132
132
|
playId?: string;
|
|
133
133
|
dependsOnFields?: string[];
|
|
134
|
-
recompute?: boolean;
|
|
135
|
-
recomputeOnError?: boolean;
|
|
136
|
-
staleAfterSeconds?: number;
|
|
137
134
|
conditional?: boolean;
|
|
138
135
|
sourceRange?: PlayStaticSourceRange;
|
|
139
136
|
steps?: PlayStaticColumnProducer[];
|
|
@@ -144,9 +141,6 @@ export interface PlayStaticDatasetColumn {
|
|
|
144
141
|
id: string;
|
|
145
142
|
source: PlaySheetColumnSource;
|
|
146
143
|
sqlName?: string;
|
|
147
|
-
recompute?: boolean;
|
|
148
|
-
recomputeOnError?: boolean;
|
|
149
|
-
staleAfterSeconds?: number;
|
|
150
144
|
producers: PlayStaticColumnProducer[];
|
|
151
145
|
}
|
|
152
146
|
|
|
@@ -337,9 +331,6 @@ export interface PlayStaticSourceRange {
|
|
|
337
331
|
type PlayStaticSubstepMetadata = {
|
|
338
332
|
conditional?: boolean;
|
|
339
333
|
dependsOnFields?: string[];
|
|
340
|
-
recompute?: boolean;
|
|
341
|
-
recomputeOnError?: boolean;
|
|
342
|
-
staleAfterSeconds?: number;
|
|
343
334
|
};
|
|
344
335
|
|
|
345
336
|
export type PlayStaticSubstep = PlayStaticSubstepMetadata &
|
|
@@ -663,39 +654,11 @@ function compileDatasetColumns(
|
|
|
663
654
|
sqlSafePlayColumnName(field),
|
|
664
655
|
);
|
|
665
656
|
if (!column) continue;
|
|
666
|
-
const pipelineSubstep =
|
|
667
|
-
substep.staleAfterSeconds === undefined &&
|
|
668
|
-
substep.recompute !== true &&
|
|
669
|
-
substep.recomputeOnError !== true
|
|
670
|
-
? pipelineSubsteps.find(
|
|
671
|
-
(candidate) => fieldForColumnProducer(candidate) === field,
|
|
672
|
-
)
|
|
673
|
-
: undefined;
|
|
674
657
|
const producer = columnProducerFromSubstep(
|
|
675
|
-
|
|
676
|
-
(pipelineSubstep.staleAfterSeconds !== undefined ||
|
|
677
|
-
pipelineSubstep.recompute === true ||
|
|
678
|
-
pipelineSubstep.recomputeOnError === true)
|
|
679
|
-
? pipelineSubstep
|
|
680
|
-
: substep,
|
|
658
|
+
substep,
|
|
681
659
|
field,
|
|
682
660
|
);
|
|
683
661
|
column.producers.push(producer);
|
|
684
|
-
if (
|
|
685
|
-
column.staleAfterSeconds === undefined &&
|
|
686
|
-
producer.staleAfterSeconds !== undefined
|
|
687
|
-
) {
|
|
688
|
-
column.staleAfterSeconds = producer.staleAfterSeconds;
|
|
689
|
-
}
|
|
690
|
-
if (column.recompute !== true && producer.recompute === true) {
|
|
691
|
-
column.recompute = true;
|
|
692
|
-
}
|
|
693
|
-
if (
|
|
694
|
-
column.recomputeOnError !== true &&
|
|
695
|
-
producer.recomputeOnError === true
|
|
696
|
-
) {
|
|
697
|
-
column.recomputeOnError = true;
|
|
698
|
-
}
|
|
699
662
|
}
|
|
700
663
|
|
|
701
664
|
return [...columnsById.values()];
|
|
@@ -745,11 +708,6 @@ function columnProducerFromSubstep(
|
|
|
745
708
|
...(substep.dependsOnFields?.length
|
|
746
709
|
? { dependsOnFields: [...substep.dependsOnFields] }
|
|
747
710
|
: {}),
|
|
748
|
-
...(substep.recompute === true ? { recompute: true } : {}),
|
|
749
|
-
...(substep.recomputeOnError === true ? { recomputeOnError: true } : {}),
|
|
750
|
-
...(substep.staleAfterSeconds !== undefined
|
|
751
|
-
? { staleAfterSeconds: substep.staleAfterSeconds }
|
|
752
|
-
: {}),
|
|
753
711
|
...(substep.conditional ? { conditional: true } : {}),
|
|
754
712
|
...(substep.sourceRange ? { sourceRange: substep.sourceRange } : {}),
|
|
755
713
|
...(steps && steps.length > 0 ? { steps } : {}),
|