deepline 0.1.186 → 0.1.188
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/entry.ts +53 -17
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/workflow-preview.ts +26 -0
- package/dist/bundling-sources/sdk/src/play.ts +24 -3
- package/dist/bundling-sources/sdk/src/release.ts +2 -2
- package/dist/bundling-sources/sdk/src/types.ts +88 -0
- package/dist/cli/index.js +1206 -216
- package/dist/cli/index.mjs +1152 -162
- package/dist/index.d.mts +113 -3
- package/dist/index.d.ts +113 -3
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
|
@@ -168,6 +168,10 @@ import {
|
|
|
168
168
|
WorkerRunWorkDispatcher,
|
|
169
169
|
type WorkerRunMapBatchesResult,
|
|
170
170
|
} from './runtime/run-work-dispatcher';
|
|
171
|
+
import {
|
|
172
|
+
boundedWorkflowPreviewRows,
|
|
173
|
+
WORKFLOW_MAP_CHUNK_PREVIEW_MAX_BYTES,
|
|
174
|
+
} from './runtime/workflow-preview';
|
|
171
175
|
import { WORKER_PLATFORM_SUBREQUESTS_PER_UNBATCHED_TOOL_CALL } from './runtime/worker-platform-budget';
|
|
172
176
|
import {
|
|
173
177
|
PLAY_RUNTIME_CONTRACT,
|
|
@@ -252,6 +256,7 @@ import { normalizePlayRunFailure } from '../../../shared_libs/play-runtime/run-f
|
|
|
252
256
|
import {
|
|
253
257
|
createRuntimePersistenceLatch,
|
|
254
258
|
isRuntimePersistenceCircuitOpenError,
|
|
259
|
+
RuntimePersistenceCircuitOpenError,
|
|
255
260
|
tripRuntimePersistenceLatch,
|
|
256
261
|
} from '../../../shared_libs/play-runtime/persistence-latch';
|
|
257
262
|
import {
|
|
@@ -2420,7 +2425,8 @@ type WorkerMapBlockedChunkSummary = {
|
|
|
2420
2425
|
};
|
|
2421
2426
|
|
|
2422
2427
|
type WorkerMapChunkSummary<T extends Record<string, unknown>> =
|
|
2423
|
-
WorkerMapCompletedChunkSummary<T>
|
|
2428
|
+
| WorkerMapCompletedChunkSummary<T>
|
|
2429
|
+
| WorkerMapBlockedChunkSummary;
|
|
2424
2430
|
|
|
2425
2431
|
function serializeDurableStepValue<T>(value: T, depth = 0): T {
|
|
2426
2432
|
if (depth > 20 || value == null) return value;
|
|
@@ -2479,7 +2485,9 @@ type WorkerConditionalStepResolver = {
|
|
|
2479
2485
|
type WorkerStepProgramStep = {
|
|
2480
2486
|
name: string;
|
|
2481
2487
|
resolver:
|
|
2482
|
-
|
|
2488
|
+
| WorkerStepResolver
|
|
2489
|
+
| WorkerConditionalStepResolver
|
|
2490
|
+
| WorkerStepProgram;
|
|
2483
2491
|
};
|
|
2484
2492
|
|
|
2485
2493
|
type WorkerStepProgram = {
|
|
@@ -3416,7 +3424,9 @@ function resolveSheetContractFromReq(
|
|
|
3416
3424
|
// `staticPipeline` field is what `resolveSheetContractForTableNamespace`
|
|
3417
3425
|
// expects. Reach in safely.
|
|
3418
3426
|
const snapshot = req.contractSnapshot as
|
|
3419
|
-
{ staticPipeline?: unknown }
|
|
3427
|
+
| { staticPipeline?: unknown }
|
|
3428
|
+
| undefined
|
|
3429
|
+
| null;
|
|
3420
3430
|
const pipeline = snapshot?.staticPipeline;
|
|
3421
3431
|
if (!pipeline || typeof pipeline !== 'object' || Array.isArray(pipeline)) {
|
|
3422
3432
|
return null;
|
|
@@ -3508,7 +3518,9 @@ async function releaseRuntimeLeasesOnTeardown(input: {
|
|
|
3508
3518
|
|
|
3509
3519
|
function staticPipelineFromReq(req: RunRequest): PlayStaticPipeline | null {
|
|
3510
3520
|
const snapshot = req.contractSnapshot as
|
|
3511
|
-
{ staticPipeline?: unknown }
|
|
3521
|
+
| { staticPipeline?: unknown }
|
|
3522
|
+
| undefined
|
|
3523
|
+
| null;
|
|
3512
3524
|
const pipeline = snapshot?.staticPipeline;
|
|
3513
3525
|
if (!pipeline || typeof pipeline !== 'object' || Array.isArray(pipeline)) {
|
|
3514
3526
|
return null;
|
|
@@ -5100,6 +5112,15 @@ function createMinimalWorkerCtx(
|
|
|
5100
5112
|
}
|
|
5101
5113
|
};
|
|
5102
5114
|
|
|
5115
|
+
const runtimePersistenceCircuitError = (): Error | null => {
|
|
5116
|
+
if (persistFailure) {
|
|
5117
|
+
tripRuntimePersistenceLatch(persistenceLatch, persistFailure);
|
|
5118
|
+
}
|
|
5119
|
+
return persistenceLatch.tripped
|
|
5120
|
+
? new RuntimePersistenceCircuitOpenError(persistenceLatch)
|
|
5121
|
+
: null;
|
|
5122
|
+
};
|
|
5123
|
+
|
|
5103
5124
|
const persistExecutedRows = async () => {
|
|
5104
5125
|
const rowsToPersist = executedRows
|
|
5105
5126
|
.map((row, executedIndex) =>
|
|
@@ -5207,11 +5228,13 @@ function createMinimalWorkerCtx(
|
|
|
5207
5228
|
pendingPersistRows = 0;
|
|
5208
5229
|
pendingPersistBytes = 0;
|
|
5209
5230
|
const task = persistFlushChain.then(async () => {
|
|
5210
|
-
|
|
5231
|
+
const circuitError = runtimePersistenceCircuitError();
|
|
5232
|
+
if (circuitError) throw circuitError;
|
|
5211
5233
|
await persistExecutedRows();
|
|
5212
5234
|
});
|
|
5213
5235
|
persistFlushChain = task.catch((error) => {
|
|
5214
5236
|
persistFailure ??= error;
|
|
5237
|
+
tripRuntimePersistenceLatch(persistenceLatch, error);
|
|
5215
5238
|
});
|
|
5216
5239
|
return task;
|
|
5217
5240
|
};
|
|
@@ -5296,26 +5319,31 @@ function createMinimalWorkerCtx(
|
|
|
5296
5319
|
return Promise.resolve();
|
|
5297
5320
|
};
|
|
5298
5321
|
|
|
5299
|
-
const schedulePersistExecutedRows = () => {
|
|
5300
|
-
|
|
5322
|
+
const schedulePersistExecutedRows = (): Promise<void> | null => {
|
|
5323
|
+
const circuitError = runtimePersistenceCircuitError();
|
|
5324
|
+
if (circuitError) return Promise.reject(circuitError);
|
|
5301
5325
|
if (
|
|
5302
5326
|
pendingPersistRows >= MAP_INCREMENTAL_PERSIST_CHUNK_ROWS ||
|
|
5303
5327
|
pendingPersistBytes >= MAP_INCREMENTAL_PERSIST_CHUNK_BYTES
|
|
5304
5328
|
) {
|
|
5305
|
-
|
|
5306
|
-
return;
|
|
5329
|
+
return enqueuePersistExecutedRows();
|
|
5307
5330
|
}
|
|
5308
|
-
if (scheduledPersistTimer) return;
|
|
5331
|
+
if (scheduledPersistTimer) return null;
|
|
5309
5332
|
scheduledPersistTimer = setTimeout(() => {
|
|
5310
5333
|
scheduledPersistTimer = null;
|
|
5311
5334
|
void enqueuePersistExecutedRows().catch(() => undefined);
|
|
5312
5335
|
}, MAP_INCREMENTAL_PERSIST_INTERVAL_MS);
|
|
5336
|
+
return null;
|
|
5313
5337
|
};
|
|
5314
5338
|
|
|
5315
|
-
const notePersistableRow = (
|
|
5339
|
+
const notePersistableRow = async (
|
|
5340
|
+
row: Record<string, unknown>,
|
|
5341
|
+
): Promise<void> => {
|
|
5316
5342
|
pendingPersistRows += 1;
|
|
5317
5343
|
pendingPersistBytes += JSON.stringify(row).length;
|
|
5318
|
-
schedulePersistExecutedRows();
|
|
5344
|
+
await (schedulePersistExecutedRows() ?? Promise.resolve());
|
|
5345
|
+
const circuitError = runtimePersistenceCircuitError();
|
|
5346
|
+
if (circuitError) throw circuitError;
|
|
5319
5347
|
};
|
|
5320
5348
|
|
|
5321
5349
|
let idx = 0;
|
|
@@ -5325,6 +5353,8 @@ function createMinimalWorkerCtx(
|
|
|
5325
5353
|
(async () => {
|
|
5326
5354
|
while (true) {
|
|
5327
5355
|
if (abortSignal?.aborted) return;
|
|
5356
|
+
const circuitError = runtimePersistenceCircuitError();
|
|
5357
|
+
if (circuitError) throw circuitError;
|
|
5328
5358
|
const myIndex = idx++;
|
|
5329
5359
|
if (myIndex >= rowsToExecute.length) return;
|
|
5330
5360
|
const rowSlot = await governor.acquireRowSlot({
|
|
@@ -5472,7 +5502,7 @@ function createMinimalWorkerCtx(
|
|
|
5472
5502
|
executedRows[myIndex] = enriched as T &
|
|
5473
5503
|
Record<string, unknown>;
|
|
5474
5504
|
completedExecutedRows += 1;
|
|
5475
|
-
notePersistableRow(enriched);
|
|
5505
|
+
await notePersistableRow(enriched);
|
|
5476
5506
|
reportChunkProgress(false);
|
|
5477
5507
|
} catch (rowError) {
|
|
5478
5508
|
// Receipt persistence errors stay run-fatal, but keep the
|
|
@@ -5522,7 +5552,7 @@ function createMinimalWorkerCtx(
|
|
|
5522
5552
|
};
|
|
5523
5553
|
failedExecutedRows += 1;
|
|
5524
5554
|
if (!failFastRowErrors) {
|
|
5525
|
-
notePersistableRow(enriched);
|
|
5555
|
+
await notePersistableRow(enriched);
|
|
5526
5556
|
}
|
|
5527
5557
|
// Bounded per-chunk samples: every failure is persisted on
|
|
5528
5558
|
// its row, but only the first few get a log line so a wide
|
|
@@ -5636,7 +5666,8 @@ function createMinimalWorkerCtx(
|
|
|
5636
5666
|
rangeStart: baseOffset + chunkStart,
|
|
5637
5667
|
rangeEnd: baseOffset + chunkStart,
|
|
5638
5668
|
rowsRead: chunkRows.length,
|
|
5639
|
-
rowsWritten:
|
|
5669
|
+
rowsWritten:
|
|
5670
|
+
persistedExecutedIndexes.size + persistedFailedIndexes.size,
|
|
5640
5671
|
rowsExecuted: rowsToExecute.length,
|
|
5641
5672
|
rowsCached: 0,
|
|
5642
5673
|
rowsDuplicateReused: duplicateInputReuseCount,
|
|
@@ -5867,7 +5898,11 @@ function createMinimalWorkerCtx(
|
|
|
5867
5898
|
// storage may keep only the bounded preview sample; same-run play code
|
|
5868
5899
|
// that needs more rows uses volatileWorkflowChunkRows, which is not
|
|
5869
5900
|
// part of the persisted step result.
|
|
5870
|
-
preview:
|
|
5901
|
+
preview: boundedWorkflowPreviewRows(publicOut, {
|
|
5902
|
+
maxRows: WORKER_DATASET_PREVIEW_ROWS,
|
|
5903
|
+
maxBytes: WORKFLOW_MAP_CHUNK_PREVIEW_MAX_BYTES,
|
|
5904
|
+
serialize: toWorkflowSerializableValue,
|
|
5905
|
+
}),
|
|
5871
5906
|
cachedRows:
|
|
5872
5907
|
includeCachedRowsInChunkResult &&
|
|
5873
5908
|
out.length <= WORKER_DATASET_IN_MEMORY_ROWS
|
|
@@ -6993,7 +7028,8 @@ function createMinimalWorkerCtx(
|
|
|
6993
7028
|
// the small structural shape ChildPlayAwait needs; bridge it the
|
|
6994
7029
|
// same way the inline implementation did.
|
|
6995
7030
|
workflowStep: workflowStep as unknown as
|
|
6996
|
-
|
|
7031
|
+
| WorkflowStepLike
|
|
7032
|
+
| undefined,
|
|
6997
7033
|
workflowId,
|
|
6998
7034
|
playName: resolvedName,
|
|
6999
7035
|
key: normalizedKey,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const WORKFLOW_MAP_CHUNK_PREVIEW_MAX_BYTES = 64 * 1024;
|
|
2
|
+
|
|
3
|
+
const jsonByteLength = (value: unknown): number =>
|
|
4
|
+
new TextEncoder().encode(JSON.stringify(value)).byteLength;
|
|
5
|
+
|
|
6
|
+
export function boundedWorkflowPreviewRows<T extends Record<string, unknown>>(
|
|
7
|
+
rows: readonly T[],
|
|
8
|
+
input: {
|
|
9
|
+
maxRows: number;
|
|
10
|
+
maxBytes: number;
|
|
11
|
+
serialize?: (row: T) => T;
|
|
12
|
+
},
|
|
13
|
+
): T[] {
|
|
14
|
+
const preview: T[] = [];
|
|
15
|
+
let bytes = 2; // Opening and closing array brackets.
|
|
16
|
+
for (const row of rows) {
|
|
17
|
+
if (preview.length >= input.maxRows) break;
|
|
18
|
+
const serialized = input.serialize ? input.serialize(row) : row;
|
|
19
|
+
const rowBytes = jsonByteLength(serialized) + (preview.length > 0 ? 1 : 0);
|
|
20
|
+
if (rowBytes > input.maxBytes) continue;
|
|
21
|
+
if (bytes + rowBytes > input.maxBytes) break;
|
|
22
|
+
preview.push(serialized);
|
|
23
|
+
bytes += rowBytes;
|
|
24
|
+
}
|
|
25
|
+
return preview;
|
|
26
|
+
}
|
|
@@ -117,9 +117,16 @@ import type { ToolExecution } from './client.js';
|
|
|
117
117
|
/**
|
|
118
118
|
* Optional trigger bindings for a play.
|
|
119
119
|
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
120
|
+
* A play can be triggered three ways, declared as the third argument to
|
|
121
|
+
* {@link definePlay}:
|
|
122
|
+
* - `webhook` — an inbound HTTP call (with optional HMAC signature verification);
|
|
123
|
+
* - `cron` — a schedule; or
|
|
124
|
+
* - `sqlListeners` — a **monitor**: the play runs whenever a monitor writes a new
|
|
125
|
+
* row to its output stream. This is how you build a play "on top of" a monitor
|
|
126
|
+
* (e.g. run enrichment every time a watched company posts a new job). Each
|
|
127
|
+
* listener binds to a monitor tool id + one of its output stream keys (see
|
|
128
|
+
* `deepline monitors available <id>` for a tool's streams and row columns).
|
|
129
|
+
* The changed row is delivered to the handler as the listener event's `after`.
|
|
123
130
|
*
|
|
124
131
|
* @example Webhook with HMAC verification
|
|
125
132
|
* ```typescript
|
|
@@ -141,6 +148,20 @@ import type { ToolExecution } from './client.js';
|
|
|
141
148
|
* });
|
|
142
149
|
* ```
|
|
143
150
|
*
|
|
151
|
+
* @example Monitor-triggered (run a play on a monitor's output)
|
|
152
|
+
* ```typescript
|
|
153
|
+
* definePlay('on-new-job-opening', handler, {
|
|
154
|
+
* sqlListeners: [
|
|
155
|
+
* {
|
|
156
|
+
* id: 'jobs',
|
|
157
|
+
* tool: 'tamradar.company_radar',
|
|
158
|
+
* stream: 'company_job_openings',
|
|
159
|
+
* operations: ['INSERT'],
|
|
160
|
+
* },
|
|
161
|
+
* ],
|
|
162
|
+
* });
|
|
163
|
+
* ```
|
|
164
|
+
*
|
|
144
165
|
* @sdkReference runtime 030
|
|
145
166
|
*/
|
|
146
167
|
export type PlayBindings = {
|
|
@@ -105,10 +105,10 @@ export const SDK_RELEASE = {
|
|
|
105
105
|
// 0.1.154 removes the short-lived generated enrich StepOptions recompute
|
|
106
106
|
// fields shipped in 0.1.153.
|
|
107
107
|
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
108
|
-
version: '0.1.
|
|
108
|
+
version: '0.1.188',
|
|
109
109
|
apiContract: '2026-06-dataset-handle-results-hard-cutover',
|
|
110
110
|
supportPolicy: {
|
|
111
|
-
latest: '0.1.
|
|
111
|
+
latest: '0.1.188',
|
|
112
112
|
minimumSupported: '0.1.53',
|
|
113
113
|
deprecatedBelow: '0.1.53',
|
|
114
114
|
commandMinimumSupported: [
|
|
@@ -922,10 +922,98 @@ export interface PlayCheckResult {
|
|
|
922
922
|
warnings?: string[];
|
|
923
923
|
staticPipeline?: Record<string, unknown> | null;
|
|
924
924
|
toolGetterHints?: PlayCheckToolGetterHint[];
|
|
925
|
+
/**
|
|
926
|
+
* Recognized trigger bindings parsed from the play source (`sqlListeners` /
|
|
927
|
+
* cron / webhook). Present only when the play declares at least one trigger,
|
|
928
|
+
* so an author can confirm the binding was recognized rather than silently
|
|
929
|
+
* dropped. Field names mirror the `definePlay` binding contract.
|
|
930
|
+
*/
|
|
931
|
+
triggers?: PlayCheckTriggersSummary | null;
|
|
932
|
+
/**
|
|
933
|
+
* Structured, machine-actionable issues surfaced by the check. An ADDITIVE
|
|
934
|
+
* channel alongside `errors[]`: every `error`-severity issue is also present
|
|
935
|
+
* in `errors[]` (so string-level tooling keeps working), while an agent can
|
|
936
|
+
* read `code` / `validOptions` / `docsHint` to self-correct. `warning`
|
|
937
|
+
* severity issues do NOT make the check invalid.
|
|
938
|
+
*/
|
|
939
|
+
issues?: PlayCheckIssue[];
|
|
940
|
+
/**
|
|
941
|
+
* Affirmative echo of what Deepline recognized — triggers, tools,
|
|
942
|
+
* datasets/columns, inputs, outputs — so a valid check reflects the parsed
|
|
943
|
+
* shape rather than a bare "ok".
|
|
944
|
+
*/
|
|
945
|
+
recognized?: PlayCheckRecognizedSummary;
|
|
946
|
+
/**
|
|
947
|
+
* Human one-liner over {@link PlayCheckResult.recognized}, e.g.
|
|
948
|
+
* `1 trigger · 2 tools · 1 dataset · 14 columns`.
|
|
949
|
+
*/
|
|
950
|
+
summary?: string;
|
|
925
951
|
artifactHash?: string | null;
|
|
926
952
|
graphHash?: string | null;
|
|
927
953
|
}
|
|
928
954
|
|
|
955
|
+
/** Severity of a {@link PlayCheckIssue}. `error` fails the check; `warning` does not. */
|
|
956
|
+
export type PlayCheckIssueSeverity = 'error' | 'warning';
|
|
957
|
+
|
|
958
|
+
/**
|
|
959
|
+
* One structured, machine-actionable issue surfaced by `deepline plays check`.
|
|
960
|
+
* Mirrors the server-side `PlayCheckIssue` contract. `code` is a stable machine
|
|
961
|
+
* code from a closed server-side set; `validOptions` enumerates the valid values
|
|
962
|
+
* (tool ids / stream keys / columns / operators) so an agent self-corrects by
|
|
963
|
+
* reading the structure instead of brute-forcing the compiler.
|
|
964
|
+
*/
|
|
965
|
+
export interface PlayCheckIssue {
|
|
966
|
+
code: string;
|
|
967
|
+
severity: PlayCheckIssueSeverity;
|
|
968
|
+
message: string;
|
|
969
|
+
path?: string;
|
|
970
|
+
hint?: string;
|
|
971
|
+
validOptions?: string[];
|
|
972
|
+
docsHint?: string;
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
/**
|
|
976
|
+
* Affirmative "here's what Deepline recognized" echo returned alongside a
|
|
977
|
+
* check's issues. Field names reuse the public play binding contract.
|
|
978
|
+
*/
|
|
979
|
+
export interface PlayCheckRecognizedSummary {
|
|
980
|
+
triggers?: PlayCheckTriggersSummary;
|
|
981
|
+
tools?: string[];
|
|
982
|
+
datasets?: { name: string; columns?: string[] }[];
|
|
983
|
+
inputs?: string[];
|
|
984
|
+
outputs?: string[];
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
/**
|
|
988
|
+
* One recognized SQL-listener trigger echoed back by {@link DeeplineClient.checkPlayArtifact}.
|
|
989
|
+
*/
|
|
990
|
+
export interface PlayCheckSqlListenerTrigger {
|
|
991
|
+
id: string;
|
|
992
|
+
tool?: string;
|
|
993
|
+
stream?: string;
|
|
994
|
+
operations: string[];
|
|
995
|
+
/**
|
|
996
|
+
* The recognized `sqlListeners.where` row filter, echoed back so an author can
|
|
997
|
+
* confirm Deepline bound it. Mirrors the server `StoredSqlListenerWhere` shape
|
|
998
|
+
* (`before` / `after` maps of column → operator filter). Absent when the
|
|
999
|
+
* listener declares no `where`.
|
|
1000
|
+
*/
|
|
1001
|
+
where?: {
|
|
1002
|
+
before?: Record<string, Record<string, unknown>>;
|
|
1003
|
+
after?: Record<string, Record<string, unknown>>;
|
|
1004
|
+
};
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
/**
|
|
1008
|
+
* Concise summary of the trigger bindings the server recognized for a play.
|
|
1009
|
+
* Only present triggers are populated.
|
|
1010
|
+
*/
|
|
1011
|
+
export interface PlayCheckTriggersSummary {
|
|
1012
|
+
sqlListeners?: PlayCheckSqlListenerTrigger[];
|
|
1013
|
+
cron?: { schedule: string; timezone?: string };
|
|
1014
|
+
webhook?: true;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
929
1017
|
export interface PlayCheckToolGetterHint {
|
|
930
1018
|
toolId: string;
|
|
931
1019
|
lists: Array<{
|