deepline 0.1.21 → 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/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.21";
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
@@ -533,7 +533,7 @@ function isRecord(value) {
533
533
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
534
534
  }
535
535
  function normalizePlayStatus(raw) {
536
- const status = typeof raw.status === "string" ? raw.status : typeof raw.temporalStatus === "string" ? mapLegacyTemporalStatus(raw.temporalStatus) : "running";
536
+ const status = typeof raw.status === "string" ? raw.status : "running";
537
537
  const runId = typeof raw.runId === "string" ? raw.runId : typeof raw.workflowId === "string" ? raw.workflowId : "";
538
538
  return {
539
539
  ...raw,
@@ -541,23 +541,6 @@ function normalizePlayStatus(raw) {
541
541
  status
542
542
  };
543
543
  }
544
- function mapLegacyTemporalStatus(status) {
545
- switch (status.trim().toUpperCase()) {
546
- case "PENDING":
547
- return "queued";
548
- case "COMPLETED":
549
- return "completed";
550
- case "FAILED":
551
- return "failed";
552
- case "CANCELLED":
553
- case "TERMINATED":
554
- case "TIMED_OUT":
555
- return "cancelled";
556
- case "RUNNING":
557
- default:
558
- return "running";
559
- }
560
- }
561
544
  function decodeBase64Bytes(value) {
562
545
  const binary = atob(value);
563
546
  const bytes = new Uint8Array(binary.length);
@@ -566,6 +549,79 @@ function decodeBase64Bytes(value) {
566
549
  }
567
550
  return bytes;
568
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;
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
+ };
624
+ }
569
625
  var DeeplineClient = class {
570
626
  http;
571
627
  config;
@@ -675,7 +731,7 @@ var DeeplineClient = class {
675
731
  /**
676
732
  * Search available tools using Deepline's ranked backend search.
677
733
  *
678
- * This is the same discovery surface used by the legacy CLI: it ranks across
734
+ * This is the same discovery surface used by the CLI: it ranks across
679
735
  * tool metadata, categories, agent guidance, and input schema fields.
680
736
  */
681
737
  async searchTools(options = {}) {
@@ -768,7 +824,7 @@ var DeeplineClient = class {
768
824
  * `progress.logs`; they are not part of the user output object.
769
825
  *
770
826
  * @param request - Play run configuration (name, code, input, etc.)
771
- * @returns Workflow metadata including the `workflowId` for status polling
827
+ * @returns Run metadata including the public `workflowId`
772
828
  *
773
829
  * @example
774
830
  * ```typescript
@@ -1060,9 +1116,6 @@ var DeeplineClient = class {
1060
1116
  * Internal/advanced primitive. Public callers should usually prefer
1061
1117
  * {@link runPlay}, {@link PlayJob.get}, or `deepline play run --watch`.
1062
1118
  *
1063
- * Poll this method until `status` reaches a terminal state:
1064
- * `'completed'`, `'failed'`, or `'cancelled'`.
1065
- *
1066
1119
  * @param workflowId - Play-run id from {@link startPlayRun}
1067
1120
  * @returns Current status with progress logs and partial results
1068
1121
  *
@@ -1084,35 +1137,11 @@ var DeeplineClient = class {
1084
1137
  );
1085
1138
  return normalizePlayStatus(response);
1086
1139
  }
1087
- /**
1088
- * Get the lightweight tail-polling status for a play execution.
1089
- *
1090
- * This is intentionally smaller than {@link getPlayStatus}: it returns the
1091
- * fields needed for CLI log tailing while the run is in flight, without
1092
- * forcing the API to rebuild final result views on every poll. Call
1093
- * {@link getPlayStatus} once after a terminal state for the full result.
1094
- */
1095
- async getPlayTailStatus(workflowId, options) {
1096
- const params = new URLSearchParams({ mode: "tail" });
1097
- if (typeof options?.afterLogIndex === "number") {
1098
- params.set("afterLogIndex", String(options.afterLogIndex));
1099
- }
1100
- if (typeof options?.waitMs === "number") {
1101
- params.set("waitMs", String(options.waitMs));
1102
- }
1103
- if (options?.terminalOnly) {
1104
- params.set("terminalOnly", "true");
1105
- }
1106
- const response = await this.http.get(
1107
- `/api/v2/plays/run/${encodeURIComponent(workflowId)}?${params.toString()}`
1108
- );
1109
- return normalizePlayStatus(response);
1110
- }
1111
1140
  /**
1112
1141
  * Stream semantic play-run events using the same SSE feed as the dashboard.
1113
1142
  *
1114
- * Consumers should still keep a polling fallback: SSE is the fast live-update
1115
- * transport, while the status endpoints remain the authoritative recovery path.
1143
+ * The server emits a canonical `play.run.snapshot` event first for every
1144
+ * connection, then incremental live events until terminal state or reconnect.
1116
1145
  */
1117
1146
  async *streamPlayRunEvents(workflowId, options) {
1118
1147
  const headers = options?.lastEventId && options.lastEventId.trim() ? { "Last-Event-ID": options.lastEventId.trim() } : void 0;
@@ -1132,7 +1161,7 @@ var DeeplineClient = class {
1132
1161
  *
1133
1162
  * Sends a stop request for the run.
1134
1163
  *
1135
- * @param workflowId - Temporal workflow ID to cancel
1164
+ * @param workflowId - Public Deepline play-run id to cancel
1136
1165
  *
1137
1166
  * @example
1138
1167
  * ```typescript
@@ -1148,7 +1177,7 @@ var DeeplineClient = class {
1148
1177
  /**
1149
1178
  * Stop a running play execution, including open HITL waits.
1150
1179
  *
1151
- * @param workflowId - Temporal workflow ID to stop
1180
+ * @param workflowId - Public Deepline play-run id to stop
1152
1181
  * @param options.reason - Optional audit/debug reason
1153
1182
  */
1154
1183
  async stopPlay(workflowId, options) {
@@ -1220,32 +1249,42 @@ var DeeplineClient = class {
1220
1249
  );
1221
1250
  return response.runs ?? [];
1222
1251
  }
1223
- /**
1224
- * Fetch the lightweight tail status for a run using the public runs resource model.
1225
- *
1226
- * This is the SDK equivalent of:
1227
- *
1228
- * ```bash
1229
- * deepline runs tail <run-id> --json
1230
- * ```
1231
- */
1252
+ /** Read the canonical run stream and return the latest run snapshot. */
1232
1253
  async tailRun(runId, options) {
1233
- const afterLogIndex = typeof options?.afterLogIndex === "number" ? options.afterLogIndex : typeof options?.cursor === "number" ? options.cursor : typeof options?.cursor === "string" && options.cursor.trim() ? Number(options.cursor) : void 0;
1234
- const params = new URLSearchParams();
1235
- if (Number.isFinite(afterLogIndex)) {
1236
- params.set("afterLogIndex", String(Number(afterLogIndex)));
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
+ }
1237
1273
  }
1238
- if (typeof options?.waitMs === "number") {
1239
- params.set("waitMs", String(options.waitMs));
1274
+ if (terminal && state.latest) {
1275
+ return await this.getRunStatus(state.latest.runId || runId).catch(
1276
+ () => state.latest ?? playRunStatusFromState(state)
1277
+ );
1240
1278
  }
1241
- if (options?.terminalOnly) {
1242
- params.set("terminalOnly", "true");
1279
+ if (state.latest) {
1280
+ return state.latest;
1243
1281
  }
1244
- const suffix = params.toString() ? `?${params.toString()}` : "";
1245
- const response = await this.http.get(
1246
- `/api/v2/runs/${encodeURIComponent(runId)}/tail${suffix}`
1282
+ throw new DeeplineError(
1283
+ `Run stream for ${runId} ended before the initial snapshot.`,
1284
+ void 0,
1285
+ "PLAY_RUN_STREAM_EMPTY",
1286
+ { runId }
1247
1287
  );
1248
- return normalizePlayStatus(response);
1249
1288
  }
1250
1289
  /**
1251
1290
  * Fetch persisted logs for a run using the public runs resource model.
@@ -1402,11 +1441,11 @@ var DeeplineClient = class {
1402
1441
  // Plays — high-level orchestration
1403
1442
  // ——————————————————————————————————————————————————————————
1404
1443
  /**
1405
- * Run a play end-to-end: submit, poll until terminal, return result.
1444
+ * Run a play end-to-end: submit, stream until terminal, return result.
1406
1445
  *
1407
1446
  * This is the highest-level play execution method. It submits the play,
1408
- * polls for status updates, and returns a structured result with logs
1409
- * 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`.
1410
1449
  *
1411
1450
  * @param code - Source string fallback; pass the bundled artifact in `options.artifact`
1412
1451
  * @param csvPath - Input CSV path, or `null`
@@ -1422,7 +1461,6 @@ var DeeplineClient = class {
1422
1461
  * const logs = status.progress?.logs ?? [];
1423
1462
  * console.log(`[${status.status}] ${logs.length} log lines`);
1424
1463
  * },
1425
- * pollIntervalMs: 1000,
1426
1464
  * });
1427
1465
  *
1428
1466
  * if (result.success) {
@@ -1453,33 +1491,53 @@ var DeeplineClient = class {
1453
1491
  packagedFiles: options?.packagedFiles,
1454
1492
  force: options?.force
1455
1493
  });
1456
- const pollInterval = options?.pollIntervalMs ?? 500;
1457
1494
  const start = Date.now();
1458
- while (true) {
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
+ })) {
1459
1515
  if (options?.signal?.aborted) {
1460
1516
  await this.cancelPlay(workflowId);
1461
1517
  return {
1462
1518
  success: false,
1463
1519
  runId: workflowId,
1464
- logs: [],
1520
+ logs: state.logs,
1465
1521
  durationMs: Date.now() - start,
1466
1522
  error: "Cancelled by user"
1467
1523
  };
1468
1524
  }
1469
- const status = await this.getPlayStatus(workflowId);
1525
+ const status = updatePlayLiveStatusState(state, event);
1526
+ if (!status) {
1527
+ continue;
1528
+ }
1470
1529
  options?.onProgress?.(status);
1471
1530
  if (TERMINAL_PLAY_STATUSES.has(status.status)) {
1472
- return {
1473
- success: status.status === "completed",
1474
- runId: status.runId || workflowId,
1475
- result: status.result,
1476
- logs: status.progress?.logs ?? [],
1477
- durationMs: Date.now() - start,
1478
- error: status.progress?.error ?? (status.status !== "completed" ? status.status : void 0)
1479
- };
1531
+ const finalStatus = await this.getPlayStatus(status.runId || workflowId).catch(() => status);
1532
+ return playRunResultFromStatus(finalStatus, start, workflowId);
1480
1533
  }
1481
- await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
1482
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
+ );
1483
1541
  }
1484
1542
  // ——————————————————————————————————————————————————————————
1485
1543
  // Health