deepline 0.1.20 → 0.1.22
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/cli/index.js +845 -337
- package/dist/cli/index.mjs +902 -389
- package/dist/index.d.mts +23 -58
- package/dist/index.d.ts +23 -58
- package/dist/index.js +195 -92
- package/dist/index.mjs +195 -92
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +888 -227
- package/dist/repo/apps/play-runner-workers/src/dedup-do.ts +540 -36
- package/dist/repo/apps/play-runner-workers/src/entry.ts +477 -374
- package/dist/repo/sdk/src/client.ts +245 -118
- package/dist/repo/sdk/src/http.ts +19 -1
- package/dist/repo/sdk/src/plays/harness-stub.ts +12 -0
- package/dist/repo/sdk/src/types.ts +8 -14
- package/dist/repo/sdk/src/version.ts +1 -1
- package/dist/repo/shared_libs/play-runtime/profiles.ts +4 -14
- package/dist/repo/shared_libs/play-runtime/runtime-actions.ts +1 -1
- package/dist/repo/shared_libs/play-runtime/scheduler-backend.ts +3 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -241,7 +241,7 @@ function resolveConfig(options) {
|
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
// src/version.ts
|
|
244
|
-
var SDK_VERSION = "0.1.
|
|
244
|
+
var SDK_VERSION = "0.1.22";
|
|
245
245
|
var SDK_API_CONTRACT = "2026-05-runs-v2";
|
|
246
246
|
|
|
247
247
|
// ../shared_libs/play-runtime/coordinator-headers.ts
|
|
@@ -324,7 +324,7 @@ var HttpClient = class {
|
|
|
324
324
|
const response = await fetch(candidateUrl, {
|
|
325
325
|
method,
|
|
326
326
|
headers,
|
|
327
|
-
body: options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
|
|
327
|
+
body: options?.formData !== void 0 ? options.formData : options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
|
|
328
328
|
signal: controller.signal
|
|
329
329
|
});
|
|
330
330
|
clearTimeout(timeoutId);
|
|
@@ -443,6 +443,13 @@ var HttpClient = class {
|
|
|
443
443
|
headers
|
|
444
444
|
});
|
|
445
445
|
}
|
|
446
|
+
async postFormData(path, formData, headers) {
|
|
447
|
+
return this.request(path, {
|
|
448
|
+
method: "POST",
|
|
449
|
+
formData,
|
|
450
|
+
headers
|
|
451
|
+
});
|
|
452
|
+
}
|
|
446
453
|
/**
|
|
447
454
|
* Send a DELETE request.
|
|
448
455
|
*
|
|
@@ -526,7 +533,7 @@ function isRecord(value) {
|
|
|
526
533
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
527
534
|
}
|
|
528
535
|
function normalizePlayStatus(raw) {
|
|
529
|
-
const status = typeof raw.status === "string" ? raw.status :
|
|
536
|
+
const status = typeof raw.status === "string" ? raw.status : "running";
|
|
530
537
|
const runId = typeof raw.runId === "string" ? raw.runId : typeof raw.workflowId === "string" ? raw.workflowId : "";
|
|
531
538
|
return {
|
|
532
539
|
...raw,
|
|
@@ -534,22 +541,86 @@ function normalizePlayStatus(raw) {
|
|
|
534
541
|
status
|
|
535
542
|
};
|
|
536
543
|
}
|
|
537
|
-
function
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
544
|
+
function decodeBase64Bytes(value) {
|
|
545
|
+
const binary = atob(value);
|
|
546
|
+
const bytes = new Uint8Array(binary.length);
|
|
547
|
+
for (let index = 0; index < binary.length; index += 1) {
|
|
548
|
+
bytes[index] = binary.charCodeAt(index);
|
|
549
|
+
}
|
|
550
|
+
return bytes;
|
|
551
|
+
}
|
|
552
|
+
function readStringArray(value) {
|
|
553
|
+
return Array.isArray(value) ? value.filter((line) => typeof line === "string") : [];
|
|
554
|
+
}
|
|
555
|
+
function getPlayLiveEventPayload(event) {
|
|
556
|
+
return event.payload && typeof event.payload === "object" ? event.payload : {};
|
|
557
|
+
}
|
|
558
|
+
function normalizeLiveStatus(value) {
|
|
559
|
+
if (value === "queued" || value === "running" || value === "waiting" || value === "completed" || value === "failed" || value === "cancelled") {
|
|
560
|
+
return value;
|
|
561
|
+
}
|
|
562
|
+
return null;
|
|
563
|
+
}
|
|
564
|
+
function updatePlayLiveStatusState(state, event) {
|
|
565
|
+
const payload = getPlayLiveEventPayload(event);
|
|
566
|
+
if (event.type === "play.run.log") {
|
|
567
|
+
state.logs.push(...readStringArray(payload.lines));
|
|
568
|
+
return null;
|
|
569
|
+
}
|
|
570
|
+
if (event.type !== "play.run.snapshot" && event.type !== "play.run.status" && event.type !== "play.run.final_status") {
|
|
571
|
+
return null;
|
|
572
|
+
}
|
|
573
|
+
const runId = typeof payload.runId === "string" && payload.runId ? payload.runId : state.runId;
|
|
574
|
+
const status = normalizeLiveStatus(payload.status) ?? state.status;
|
|
575
|
+
const logs = readStringArray(payload.logs);
|
|
576
|
+
if (logs.length > 0 || event.type === "play.run.snapshot") {
|
|
577
|
+
state.logs = logs;
|
|
578
|
+
}
|
|
579
|
+
if ("result" in payload) {
|
|
580
|
+
state.result = payload.result;
|
|
552
581
|
}
|
|
582
|
+
if (typeof payload.error === "string" && payload.error.trim()) {
|
|
583
|
+
state.error = payload.error;
|
|
584
|
+
}
|
|
585
|
+
state.runId = runId;
|
|
586
|
+
state.status = status;
|
|
587
|
+
const progressRecord = payload.progress && typeof payload.progress === "object" && !Array.isArray(payload.progress) ? payload.progress : {};
|
|
588
|
+
const next = {
|
|
589
|
+
...payload,
|
|
590
|
+
runId,
|
|
591
|
+
status,
|
|
592
|
+
progress: {
|
|
593
|
+
...progressRecord,
|
|
594
|
+
status: typeof progressRecord.status === "string" ? progressRecord.status : status,
|
|
595
|
+
logs: state.logs,
|
|
596
|
+
...state.error ? { error: state.error } : {}
|
|
597
|
+
},
|
|
598
|
+
..."result" in state ? { result: state.result } : {}
|
|
599
|
+
};
|
|
600
|
+
state.latest = next;
|
|
601
|
+
return next;
|
|
602
|
+
}
|
|
603
|
+
function playRunResultFromStatus(status, startedAt, fallbackRunId) {
|
|
604
|
+
return {
|
|
605
|
+
success: status.status === "completed",
|
|
606
|
+
runId: status.runId || fallbackRunId,
|
|
607
|
+
result: status.result,
|
|
608
|
+
logs: status.progress?.logs ?? [],
|
|
609
|
+
durationMs: Date.now() - startedAt,
|
|
610
|
+
error: status.progress?.error ?? (status.status !== "completed" ? status.status : void 0)
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
function playRunStatusFromState(state) {
|
|
614
|
+
return {
|
|
615
|
+
runId: state.runId,
|
|
616
|
+
status: state.status,
|
|
617
|
+
progress: {
|
|
618
|
+
status: state.status,
|
|
619
|
+
logs: state.logs,
|
|
620
|
+
...state.error ? { error: state.error } : {}
|
|
621
|
+
},
|
|
622
|
+
..."result" in state ? { result: state.result } : {}
|
|
623
|
+
};
|
|
553
624
|
}
|
|
554
625
|
var DeeplineClient = class {
|
|
555
626
|
http;
|
|
@@ -660,7 +731,7 @@ var DeeplineClient = class {
|
|
|
660
731
|
/**
|
|
661
732
|
* Search available tools using Deepline's ranked backend search.
|
|
662
733
|
*
|
|
663
|
-
* This is the same discovery surface used by the
|
|
734
|
+
* This is the same discovery surface used by the CLI: it ranks across
|
|
664
735
|
* tool metadata, categories, agent guidance, and input schema fields.
|
|
665
736
|
*/
|
|
666
737
|
async searchTools(options = {}) {
|
|
@@ -753,7 +824,7 @@ var DeeplineClient = class {
|
|
|
753
824
|
* `progress.logs`; they are not part of the user output object.
|
|
754
825
|
*
|
|
755
826
|
* @param request - Play run configuration (name, code, input, etc.)
|
|
756
|
-
* @returns
|
|
827
|
+
* @returns Run metadata including the public `workflowId`
|
|
757
828
|
*
|
|
758
829
|
* @example
|
|
759
830
|
* ```typescript
|
|
@@ -1002,9 +1073,34 @@ var DeeplineClient = class {
|
|
|
1002
1073
|
* ```
|
|
1003
1074
|
*/
|
|
1004
1075
|
async stagePlayFiles(files) {
|
|
1005
|
-
const
|
|
1076
|
+
const formData = new FormData();
|
|
1077
|
+
formData.set(
|
|
1078
|
+
"metadata",
|
|
1079
|
+
JSON.stringify({
|
|
1080
|
+
files: files.map((file, index) => ({
|
|
1081
|
+
index,
|
|
1082
|
+
logicalPath: file.logicalPath,
|
|
1083
|
+
contentHash: file.contentHash,
|
|
1084
|
+
contentType: file.contentType,
|
|
1085
|
+
bytes: file.bytes
|
|
1086
|
+
}))
|
|
1087
|
+
})
|
|
1088
|
+
);
|
|
1089
|
+
for (const [index, file] of files.entries()) {
|
|
1090
|
+
const bytes = decodeBase64Bytes(file.contentBase64);
|
|
1091
|
+
const body = bytes.buffer.slice(
|
|
1092
|
+
bytes.byteOffset,
|
|
1093
|
+
bytes.byteOffset + bytes.byteLength
|
|
1094
|
+
);
|
|
1095
|
+
formData.set(
|
|
1096
|
+
`file:${index}`,
|
|
1097
|
+
new Blob([body], { type: file.contentType }),
|
|
1098
|
+
file.logicalPath
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
1101
|
+
const response = await this.http.postFormData(
|
|
1006
1102
|
"/api/v2/plays/files/stage",
|
|
1007
|
-
|
|
1103
|
+
formData
|
|
1008
1104
|
);
|
|
1009
1105
|
return response.files;
|
|
1010
1106
|
}
|
|
@@ -1020,9 +1116,6 @@ var DeeplineClient = class {
|
|
|
1020
1116
|
* Internal/advanced primitive. Public callers should usually prefer
|
|
1021
1117
|
* {@link runPlay}, {@link PlayJob.get}, or `deepline play run --watch`.
|
|
1022
1118
|
*
|
|
1023
|
-
* Poll this method until `status` reaches a terminal state:
|
|
1024
|
-
* `'completed'`, `'failed'`, or `'cancelled'`.
|
|
1025
|
-
*
|
|
1026
1119
|
* @param workflowId - Play-run id from {@link startPlayRun}
|
|
1027
1120
|
* @returns Current status with progress logs and partial results
|
|
1028
1121
|
*
|
|
@@ -1033,41 +1126,22 @@ var DeeplineClient = class {
|
|
|
1033
1126
|
* console.log(`Logs: ${status.progress?.logs.length ?? 0} lines`);
|
|
1034
1127
|
* ```
|
|
1035
1128
|
*/
|
|
1036
|
-
async getPlayStatus(workflowId) {
|
|
1037
|
-
const
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
return normalizePlayStatus(response);
|
|
1041
|
-
}
|
|
1042
|
-
/**
|
|
1043
|
-
* Get the lightweight tail-polling status for a play execution.
|
|
1044
|
-
*
|
|
1045
|
-
* This is intentionally smaller than {@link getPlayStatus}: it returns the
|
|
1046
|
-
* fields needed for CLI log tailing while the run is in flight, without
|
|
1047
|
-
* forcing the API to rebuild final result views on every poll. Call
|
|
1048
|
-
* {@link getPlayStatus} once after a terminal state for the full result.
|
|
1049
|
-
*/
|
|
1050
|
-
async getPlayTailStatus(workflowId, options) {
|
|
1051
|
-
const params = new URLSearchParams({ mode: "tail" });
|
|
1052
|
-
if (typeof options?.afterLogIndex === "number") {
|
|
1053
|
-
params.set("afterLogIndex", String(options.afterLogIndex));
|
|
1054
|
-
}
|
|
1055
|
-
if (typeof options?.waitMs === "number") {
|
|
1056
|
-
params.set("waitMs", String(options.waitMs));
|
|
1057
|
-
}
|
|
1058
|
-
if (options?.terminalOnly) {
|
|
1059
|
-
params.set("terminalOnly", "true");
|
|
1129
|
+
async getPlayStatus(workflowId, options) {
|
|
1130
|
+
const params = new URLSearchParams();
|
|
1131
|
+
if (options?.billing === false) {
|
|
1132
|
+
params.set("billing", "false");
|
|
1060
1133
|
}
|
|
1134
|
+
const query = params.size > 0 ? `?${params.toString()}` : "";
|
|
1061
1135
|
const response = await this.http.get(
|
|
1062
|
-
`/api/v2/plays/run/${encodeURIComponent(workflowId)}
|
|
1136
|
+
`/api/v2/plays/run/${encodeURIComponent(workflowId)}${query}`
|
|
1063
1137
|
);
|
|
1064
1138
|
return normalizePlayStatus(response);
|
|
1065
1139
|
}
|
|
1066
1140
|
/**
|
|
1067
1141
|
* Stream semantic play-run events using the same SSE feed as the dashboard.
|
|
1068
1142
|
*
|
|
1069
|
-
*
|
|
1070
|
-
*
|
|
1143
|
+
* The server emits a canonical `play.run.snapshot` event first for every
|
|
1144
|
+
* connection, then incremental live events until terminal state or reconnect.
|
|
1071
1145
|
*/
|
|
1072
1146
|
async *streamPlayRunEvents(workflowId, options) {
|
|
1073
1147
|
const headers = options?.lastEventId && options.lastEventId.trim() ? { "Last-Event-ID": options.lastEventId.trim() } : void 0;
|
|
@@ -1087,7 +1161,7 @@ var DeeplineClient = class {
|
|
|
1087
1161
|
*
|
|
1088
1162
|
* Sends a stop request for the run.
|
|
1089
1163
|
*
|
|
1090
|
-
* @param workflowId -
|
|
1164
|
+
* @param workflowId - Public Deepline play-run id to cancel
|
|
1091
1165
|
*
|
|
1092
1166
|
* @example
|
|
1093
1167
|
* ```typescript
|
|
@@ -1103,7 +1177,7 @@ var DeeplineClient = class {
|
|
|
1103
1177
|
/**
|
|
1104
1178
|
* Stop a running play execution, including open HITL waits.
|
|
1105
1179
|
*
|
|
1106
|
-
* @param workflowId -
|
|
1180
|
+
* @param workflowId - Public Deepline play-run id to stop
|
|
1107
1181
|
* @param options.reason - Optional audit/debug reason
|
|
1108
1182
|
*/
|
|
1109
1183
|
async stopPlay(workflowId, options) {
|
|
@@ -1175,32 +1249,42 @@ var DeeplineClient = class {
|
|
|
1175
1249
|
);
|
|
1176
1250
|
return response.runs ?? [];
|
|
1177
1251
|
}
|
|
1178
|
-
/**
|
|
1179
|
-
* Fetch the lightweight tail status for a run using the public runs resource model.
|
|
1180
|
-
*
|
|
1181
|
-
* This is the SDK equivalent of:
|
|
1182
|
-
*
|
|
1183
|
-
* ```bash
|
|
1184
|
-
* deepline runs tail <run-id> --json
|
|
1185
|
-
* ```
|
|
1186
|
-
*/
|
|
1252
|
+
/** Read the canonical run stream and return the latest run snapshot. */
|
|
1187
1253
|
async tailRun(runId, options) {
|
|
1188
|
-
const
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1254
|
+
const state = {
|
|
1255
|
+
runId,
|
|
1256
|
+
status: "running",
|
|
1257
|
+
logs: [],
|
|
1258
|
+
latest: null
|
|
1259
|
+
};
|
|
1260
|
+
let terminal = false;
|
|
1261
|
+
for await (const event of this.streamPlayRunEvents(runId, {
|
|
1262
|
+
mode: "cli",
|
|
1263
|
+
signal: options?.signal
|
|
1264
|
+
})) {
|
|
1265
|
+
const status = updatePlayLiveStatusState(state, event);
|
|
1266
|
+
if (!status) {
|
|
1267
|
+
continue;
|
|
1268
|
+
}
|
|
1269
|
+
terminal = TERMINAL_PLAY_STATUSES.has(status.status);
|
|
1270
|
+
if (terminal) {
|
|
1271
|
+
break;
|
|
1272
|
+
}
|
|
1192
1273
|
}
|
|
1193
|
-
if (
|
|
1194
|
-
|
|
1274
|
+
if (terminal && state.latest) {
|
|
1275
|
+
return await this.getRunStatus(state.latest.runId || runId).catch(
|
|
1276
|
+
() => state.latest ?? playRunStatusFromState(state)
|
|
1277
|
+
);
|
|
1195
1278
|
}
|
|
1196
|
-
if (
|
|
1197
|
-
|
|
1279
|
+
if (state.latest) {
|
|
1280
|
+
return state.latest;
|
|
1198
1281
|
}
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1282
|
+
throw new DeeplineError(
|
|
1283
|
+
`Run stream for ${runId} ended before the initial snapshot.`,
|
|
1284
|
+
void 0,
|
|
1285
|
+
"PLAY_RUN_STREAM_EMPTY",
|
|
1286
|
+
{ runId }
|
|
1202
1287
|
);
|
|
1203
|
-
return normalizePlayStatus(response);
|
|
1204
1288
|
}
|
|
1205
1289
|
/**
|
|
1206
1290
|
* Fetch persisted logs for a run using the public runs resource model.
|
|
@@ -1357,11 +1441,11 @@ var DeeplineClient = class {
|
|
|
1357
1441
|
// Plays — high-level orchestration
|
|
1358
1442
|
// ——————————————————————————————————————————————————————————
|
|
1359
1443
|
/**
|
|
1360
|
-
* Run a play end-to-end: submit,
|
|
1444
|
+
* Run a play end-to-end: submit, stream until terminal, return result.
|
|
1361
1445
|
*
|
|
1362
1446
|
* This is the highest-level play execution method. It submits the play,
|
|
1363
|
-
*
|
|
1364
|
-
* and timing. Supports cancellation via `AbortSignal`.
|
|
1447
|
+
* reads the canonical run stream for status updates, and returns a structured
|
|
1448
|
+
* result with logs and timing. Supports cancellation via `AbortSignal`.
|
|
1365
1449
|
*
|
|
1366
1450
|
* @param code - Source string fallback; pass the bundled artifact in `options.artifact`
|
|
1367
1451
|
* @param csvPath - Input CSV path, or `null`
|
|
@@ -1377,7 +1461,6 @@ var DeeplineClient = class {
|
|
|
1377
1461
|
* const logs = status.progress?.logs ?? [];
|
|
1378
1462
|
* console.log(`[${status.status}] ${logs.length} log lines`);
|
|
1379
1463
|
* },
|
|
1380
|
-
* pollIntervalMs: 1000,
|
|
1381
1464
|
* });
|
|
1382
1465
|
*
|
|
1383
1466
|
* if (result.success) {
|
|
@@ -1408,33 +1491,53 @@ var DeeplineClient = class {
|
|
|
1408
1491
|
packagedFiles: options?.packagedFiles,
|
|
1409
1492
|
force: options?.force
|
|
1410
1493
|
});
|
|
1411
|
-
const pollInterval = options?.pollIntervalMs ?? 500;
|
|
1412
1494
|
const start = Date.now();
|
|
1413
|
-
|
|
1495
|
+
const state = {
|
|
1496
|
+
runId: workflowId,
|
|
1497
|
+
status: "running",
|
|
1498
|
+
logs: [],
|
|
1499
|
+
latest: null
|
|
1500
|
+
};
|
|
1501
|
+
if (options?.signal?.aborted) {
|
|
1502
|
+
await this.cancelPlay(workflowId);
|
|
1503
|
+
return {
|
|
1504
|
+
success: false,
|
|
1505
|
+
runId: workflowId,
|
|
1506
|
+
logs: [],
|
|
1507
|
+
durationMs: Date.now() - start,
|
|
1508
|
+
error: "Cancelled by user"
|
|
1509
|
+
};
|
|
1510
|
+
}
|
|
1511
|
+
for await (const event of this.streamPlayRunEvents(workflowId, {
|
|
1512
|
+
mode: "cli",
|
|
1513
|
+
signal: options?.signal
|
|
1514
|
+
})) {
|
|
1414
1515
|
if (options?.signal?.aborted) {
|
|
1415
1516
|
await this.cancelPlay(workflowId);
|
|
1416
1517
|
return {
|
|
1417
1518
|
success: false,
|
|
1418
1519
|
runId: workflowId,
|
|
1419
|
-
logs:
|
|
1520
|
+
logs: state.logs,
|
|
1420
1521
|
durationMs: Date.now() - start,
|
|
1421
1522
|
error: "Cancelled by user"
|
|
1422
1523
|
};
|
|
1423
1524
|
}
|
|
1424
|
-
const status =
|
|
1525
|
+
const status = updatePlayLiveStatusState(state, event);
|
|
1526
|
+
if (!status) {
|
|
1527
|
+
continue;
|
|
1528
|
+
}
|
|
1425
1529
|
options?.onProgress?.(status);
|
|
1426
1530
|
if (TERMINAL_PLAY_STATUSES.has(status.status)) {
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
runId: status.runId || workflowId,
|
|
1430
|
-
result: status.result,
|
|
1431
|
-
logs: status.progress?.logs ?? [],
|
|
1432
|
-
durationMs: Date.now() - start,
|
|
1433
|
-
error: status.progress?.error ?? (status.status !== "completed" ? status.status : void 0)
|
|
1434
|
-
};
|
|
1531
|
+
const finalStatus = await this.getPlayStatus(status.runId || workflowId).catch(() => status);
|
|
1532
|
+
return playRunResultFromStatus(finalStatus, start, workflowId);
|
|
1435
1533
|
}
|
|
1436
|
-
await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
|
|
1437
1534
|
}
|
|
1535
|
+
throw new DeeplineError(
|
|
1536
|
+
`Run stream for ${workflowId} ended before the run reached a terminal state.`,
|
|
1537
|
+
void 0,
|
|
1538
|
+
"PLAY_RUN_STREAM_ENDED",
|
|
1539
|
+
{ runId: workflowId, workflowId }
|
|
1540
|
+
);
|
|
1438
1541
|
}
|
|
1439
1542
|
// ——————————————————————————————————————————————————————————
|
|
1440
1543
|
// Health
|