deepline 0.1.274 → 0.1.276

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
@@ -438,7 +438,7 @@ var SDK_RELEASE = {
438
438
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
439
439
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
440
440
  // Operators use the checkout-local deepline-admin binary instead.
441
- version: "0.1.274",
441
+ version: "0.1.276",
442
442
  contracts: {
443
443
  api: {
444
444
  name: "sdk-http-api",
@@ -652,19 +652,19 @@ function isAbortLikeError(error) {
652
652
  const message = error.message.toLowerCase();
653
653
  return name === "aborterror" || message.includes("operation was aborted") || message === "aborted";
654
654
  }
655
- function mapNetworkError(baseUrl, error, targetLabel) {
655
+ function mapNetworkError(baseUrl, error, targetLabel2) {
656
656
  const tagged = error;
657
657
  const timeoutMs = tagged?.[REQUEST_TIMEOUT_MARKER];
658
658
  if (typeof timeoutMs === "number") {
659
659
  return {
660
- message: `Request to ${targetLabel} timed out after ${timeoutMs}ms while waiting for a response.`,
660
+ message: `Request to ${targetLabel2} timed out after ${timeoutMs}ms while waiting for a response.`,
661
661
  code: "NETWORK_TIMEOUT",
662
- details: { timeoutMs, target: targetLabel }
662
+ details: { timeoutMs, target: targetLabel2 }
663
663
  };
664
664
  }
665
665
  if (tagged?.[REQUEST_ABORT_MARKER]) {
666
666
  return {
667
- message: `Request to ${targetLabel} was aborted before it completed.`,
667
+ message: `Request to ${targetLabel2} was aborted before it completed.`,
668
668
  code: "NETWORK_ABORTED"
669
669
  };
670
670
  }
@@ -1325,9 +1325,277 @@ var RUNNER_POST_TERMINAL_DIAGNOSTIC_MAX_BYTES = 64 * 1024;
1325
1325
  // ../shared_libs/play-runtime/ledger-safe-payload.ts
1326
1326
  var ledgerIngressRedactor = createSecretRedactionContext();
1327
1327
 
1328
+ // ../shared_libs/play-runtime/activity-observation.ts
1329
+ function isRecord(value) {
1330
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
1331
+ }
1332
+ function isPlayActivityObservation(value) {
1333
+ if (!isRecord(value) || value.schemaVersion !== 1 || typeof value.activityId !== "string" || !value.activityId.trim() || typeof value.observedAt !== "number" || !Number.isFinite(value.observedAt) || !isRecord(value.target) || !isRecord(value.state)) {
1334
+ return false;
1335
+ }
1336
+ const targetKinds = /* @__PURE__ */ new Set([
1337
+ "provider",
1338
+ "dataset",
1339
+ "lease",
1340
+ "runner",
1341
+ "step",
1342
+ "capacity"
1343
+ ]);
1344
+ const stateKinds = /* @__PURE__ */ new Set([
1345
+ "active",
1346
+ "queued",
1347
+ "waiting",
1348
+ "retrying",
1349
+ "scheduled",
1350
+ "completed",
1351
+ "failed"
1352
+ ]);
1353
+ return typeof value.target.kind === "string" && targetKinds.has(value.target.kind) && typeof value.state.kind === "string" && stateKinds.has(value.state.kind);
1354
+ }
1355
+ function derivePlayActivityVisibility(input) {
1356
+ const { state } = input.observation;
1357
+ if (state.kind === "failed") return "action";
1358
+ if (state.kind === "waiting") {
1359
+ return state.reason.kind === "external_event" ? "action" : "headline";
1360
+ }
1361
+ if (state.kind === "queued" || state.kind === "scheduled") return "headline";
1362
+ if (state.kind === "retrying") {
1363
+ return state.retryAt - input.now <= 3e4 ? "hidden" : "timeline";
1364
+ }
1365
+ if (state.kind === "active") return "headline";
1366
+ return "timeline";
1367
+ }
1368
+ function targetLabel(target) {
1369
+ switch (target.kind) {
1370
+ case "provider":
1371
+ return target.label ?? `${target.provider} ${target.operation}`;
1372
+ case "dataset":
1373
+ return target.label ?? `dataset ${target.tableNamespace}`;
1374
+ case "lease":
1375
+ return `${target.resourceKind} ${target.resourceLabel}`;
1376
+ case "runner":
1377
+ return target.label ?? `${target.backend} runner`;
1378
+ case "step":
1379
+ return target.label ?? target.stepId;
1380
+ case "capacity":
1381
+ return target.label ?? `${target.pool} capacity`;
1382
+ }
1383
+ }
1384
+ function summarizePlayActivity(observation) {
1385
+ const label = targetLabel(observation.target);
1386
+ const { state } = observation;
1387
+ switch (state.kind) {
1388
+ case "active": {
1389
+ const progress = state.progress;
1390
+ const counts = typeof progress?.completed === "number" && typeof progress.total === "number" ? ` (${progress.completed}/${progress.total})` : "";
1391
+ return `Active: ${label}${counts}.`;
1392
+ }
1393
+ case "queued":
1394
+ return `Queued: waiting for ${label}.`;
1395
+ case "waiting":
1396
+ if (state.reason.kind === "external_event") {
1397
+ const provider = state.reason.provider ? ` from ${state.reason.provider}` : "";
1398
+ return `Blocked: waiting for an external event${provider}.`;
1399
+ }
1400
+ if (state.reason.kind === "dataset") {
1401
+ return `Blocked: waiting for dataset ${state.reason.tableNamespace} to become ${state.reason.requiredPhase}.`;
1402
+ }
1403
+ if (state.reason.kind === "lease") {
1404
+ return `Contended: waiting for ${state.reason.resourceKind} lease ${state.reason.resourceLabel}.`;
1405
+ }
1406
+ return `Paused: ${label}; the legacy producer did not report a typed reason.`;
1407
+ case "retrying":
1408
+ return `Delayed: ${label} will retry automatically.`;
1409
+ case "scheduled":
1410
+ return `Scheduled: ${label} will resume automatically.`;
1411
+ case "completed":
1412
+ return `Completed: ${label}.`;
1413
+ case "failed":
1414
+ return `Failed: ${label}.`;
1415
+ }
1416
+ }
1417
+ function isTerminalActivityState(state) {
1418
+ return state.kind === "completed" || state.kind === "failed";
1419
+ }
1420
+ function projection(observation, now, classified = true) {
1421
+ return {
1422
+ observation,
1423
+ summary: summarizePlayActivity(observation),
1424
+ visibility: derivePlayActivityVisibility({ observation, now }),
1425
+ classified
1426
+ };
1427
+ }
1428
+ function projectPlayRunActivity(input) {
1429
+ const now = input.now ?? Date.now();
1430
+ const observedAt = input.updatedAt ?? now;
1431
+ const normalizedStatus = input.status.trim().toLowerCase();
1432
+ if (normalizedStatus === "completed" || normalizedStatus === "failed" || normalizedStatus === "cancelled" || normalizedStatus === "terminated" || normalizedStatus === "timed_out") {
1433
+ return null;
1434
+ }
1435
+ const explicit = [...input.explicit ?? []].filter((candidate) => !isTerminalActivityState(candidate.state)).sort((left, right) => right.observedAt - left.observedAt)[0];
1436
+ if (explicit) return projection(explicit, now);
1437
+ if (input.waitKind === "detached_runner") {
1438
+ return projection(
1439
+ {
1440
+ schemaVersion: 1,
1441
+ activityId: "runner:managed",
1442
+ target: {
1443
+ kind: "runner",
1444
+ backend: input.runtimeBackend ?? "managed",
1445
+ label: "managed play runner"
1446
+ },
1447
+ state: { kind: "active" },
1448
+ observedAt
1449
+ },
1450
+ now
1451
+ );
1452
+ }
1453
+ if (input.waitKind === "sleep") {
1454
+ return projection(
1455
+ {
1456
+ schemaVersion: 1,
1457
+ activityId: "run:sleep",
1458
+ target: {
1459
+ kind: "step",
1460
+ stepId: input.activeNodeId ?? "run",
1461
+ label: input.playName ?? "play"
1462
+ },
1463
+ state: {
1464
+ kind: "scheduled",
1465
+ reason: "sleep",
1466
+ resumeAt: input.waitUntil ?? observedAt
1467
+ },
1468
+ observedAt
1469
+ },
1470
+ now
1471
+ );
1472
+ }
1473
+ if (input.waitKind === "integration_event" || input.waitKind === "integration_event_batch") {
1474
+ return projection(
1475
+ {
1476
+ schemaVersion: 1,
1477
+ activityId: `event:${input.activeNodeId ?? "run"}`,
1478
+ stepId: input.activeNodeId ?? void 0,
1479
+ target: {
1480
+ kind: "step",
1481
+ stepId: input.activeNodeId ?? "run",
1482
+ label: input.playName ?? "play"
1483
+ },
1484
+ state: {
1485
+ kind: "waiting",
1486
+ reason: {
1487
+ kind: "external_event",
1488
+ eventKey: input.eventKey ?? void 0,
1489
+ deadlineAt: input.waitUntil ?? void 0
1490
+ }
1491
+ },
1492
+ observedAt
1493
+ },
1494
+ now
1495
+ );
1496
+ }
1497
+ if (normalizedStatus === "waiting") {
1498
+ return projection(
1499
+ {
1500
+ schemaVersion: 1,
1501
+ activityId: "run:legacy-wait",
1502
+ target: {
1503
+ kind: "step",
1504
+ stepId: input.activeNodeId ?? "run",
1505
+ label: input.playName ?? "play"
1506
+ },
1507
+ state: { kind: "waiting", reason: { kind: "unknown" } },
1508
+ observedAt
1509
+ },
1510
+ now,
1511
+ false
1512
+ );
1513
+ }
1514
+ const pendingDataset = [...input.datasets ?? []].filter(
1515
+ (dataset) => dataset.phase === "registered" || dataset.complete !== true && dataset.phase !== "failed"
1516
+ ).sort((left, right) => (right.updatedAt ?? 0) - (left.updatedAt ?? 0))[0];
1517
+ if (pendingDataset) {
1518
+ return projection(
1519
+ {
1520
+ schemaVersion: 1,
1521
+ activityId: `dataset:${pendingDataset.datasetId ?? pendingDataset.tableNamespace}`,
1522
+ target: {
1523
+ kind: "dataset",
1524
+ tableNamespace: pendingDataset.tableNamespace,
1525
+ operation: "materializing"
1526
+ },
1527
+ state: {
1528
+ kind: "active",
1529
+ progress: {
1530
+ completed: pendingDataset.persistedRows,
1531
+ total: typeof pendingDataset.succeededRows === "number" || typeof pendingDataset.failedRows === "number" ? (pendingDataset.succeededRows ?? 0) + (pendingDataset.failedRows ?? 0) : void 0,
1532
+ failed: pendingDataset.failedRows
1533
+ }
1534
+ },
1535
+ observedAt: pendingDataset.updatedAt ?? observedAt
1536
+ },
1537
+ now
1538
+ );
1539
+ }
1540
+ const activeStep = input.nodeStates?.find(
1541
+ (candidate) => candidate.nodeId === input.activeNodeId
1542
+ ) ?? input.nodeStates?.find((candidate) => candidate.status === "running") ?? null;
1543
+ if (activeStep) {
1544
+ const toolId = activeStep.nodeId.startsWith("tool:") ? activeStep.nodeId.split(":").at(-1)?.trim() || null : null;
1545
+ const provider = toolId?.split(/[._]/)[0]?.trim() || null;
1546
+ return projection(
1547
+ {
1548
+ schemaVersion: 1,
1549
+ activityId: `step:${activeStep.nodeId}`,
1550
+ stepId: activeStep.nodeId,
1551
+ target: toolId && provider ? {
1552
+ kind: "provider",
1553
+ provider,
1554
+ operation: toolId,
1555
+ label: activeStep.label ?? toolId
1556
+ } : {
1557
+ kind: "step",
1558
+ stepId: activeStep.nodeId,
1559
+ label: activeStep.label
1560
+ },
1561
+ state: {
1562
+ kind: "active",
1563
+ progress: activeStep.progress ?? void 0
1564
+ },
1565
+ observedAt: activeStep.updatedAt ?? observedAt
1566
+ },
1567
+ now
1568
+ );
1569
+ }
1570
+ if (normalizedStatus === "queued") {
1571
+ return projection(
1572
+ {
1573
+ schemaVersion: 1,
1574
+ activityId: "capacity:worker",
1575
+ target: { kind: "capacity", pool: "worker" },
1576
+ state: { kind: "queued", reason: "capacity" },
1577
+ observedAt
1578
+ },
1579
+ now
1580
+ );
1581
+ }
1582
+ const fallback = {
1583
+ schemaVersion: 1,
1584
+ activityId: "run:legacy",
1585
+ target: {
1586
+ kind: "step",
1587
+ stepId: input.activeNodeId ?? "run",
1588
+ label: input.playName ?? "play"
1589
+ },
1590
+ state: normalizedStatus === "waiting" ? { kind: "waiting", reason: { kind: "unknown" } } : { kind: "active" },
1591
+ observedAt
1592
+ };
1593
+ return projection(fallback, now, normalizedStatus !== "waiting");
1594
+ }
1595
+
1328
1596
  // ../shared_libs/play-runtime/run-ledger.ts
1329
1597
  var LOG_TAIL_LIMIT = 100;
1330
- function isRecord(value) {
1598
+ function isRecord2(value) {
1331
1599
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
1332
1600
  }
1333
1601
  function finiteNumber(value) {
@@ -1411,30 +1679,33 @@ function createEmptyPlayRunLedgerSnapshot(input) {
1411
1679
  stepsById: {},
1412
1680
  orderedDatasetIds: [],
1413
1681
  datasetsById: {},
1682
+ orderedActivityIds: [],
1683
+ activitiesById: {},
1414
1684
  logTail: [],
1415
1685
  totalLogCount: 0,
1416
1686
  logsTruncated: false,
1417
1687
  activeStepId: null,
1688
+ activeActivityId: null,
1418
1689
  activeArtifactTableNamespace: null,
1419
1690
  resultTableNamespace: null
1420
1691
  };
1421
1692
  }
1422
1693
  function normalizePlayRunLedgerSnapshot(value, fallback) {
1423
- if (!isRecord(value)) {
1694
+ if (!isRecord2(value)) {
1424
1695
  return createEmptyPlayRunLedgerSnapshot(fallback);
1425
1696
  }
1426
1697
  const orderedStepIds = Array.isArray(value.orderedStepIds) ? value.orderedStepIds.filter(
1427
1698
  (entry) => typeof entry === "string" && Boolean(entry.trim())
1428
1699
  ) : [];
1429
- const rawSteps = isRecord(value.stepsById) ? value.stepsById : {};
1700
+ const rawSteps = isRecord2(value.stepsById) ? value.stepsById : {};
1430
1701
  const stepsById = {};
1431
1702
  for (const [stepId, rawStep] of Object.entries(rawSteps)) {
1432
- if (!stepId.trim() || !isRecord(rawStep)) continue;
1703
+ if (!stepId.trim() || !isRecord2(rawStep)) continue;
1433
1704
  const rawStatus = normalizeStepStatus(rawStep.status);
1434
1705
  if (!rawStatus) continue;
1435
1706
  const completedAt = finiteNumber(rawStep.completedAt);
1436
1707
  const status = rawStatus === "running" && completedAt !== null ? "completed" : rawStatus;
1437
- const rawProgress = isRecord(rawStep.progress) ? rawStep.progress : null;
1708
+ const rawProgress = isRecord2(rawStep.progress) ? rawStep.progress : null;
1438
1709
  stepsById[stepId] = {
1439
1710
  stepId,
1440
1711
  label: optionalString(rawStep.label),
@@ -1450,10 +1721,10 @@ function normalizePlayRunLedgerSnapshot(value, fallback) {
1450
1721
  progress: rawProgress ? normalizeStepProgress(rawProgress) : null
1451
1722
  };
1452
1723
  }
1453
- const rawDatasets = isRecord(value.datasetsById) ? value.datasetsById : {};
1724
+ const rawDatasets = isRecord2(value.datasetsById) ? value.datasetsById : {};
1454
1725
  const datasetsById = {};
1455
1726
  for (const [datasetId, rawDataset] of Object.entries(rawDatasets)) {
1456
- if (!datasetId.trim() || !isRecord(rawDataset)) continue;
1727
+ if (!datasetId.trim() || !isRecord2(rawDataset)) continue;
1457
1728
  const phase = rawDataset.phase === "available" || rawDataset.phase === "failed" ? rawDataset.phase : "registered";
1458
1729
  datasetsById[datasetId] = {
1459
1730
  datasetId,
@@ -1467,6 +1738,13 @@ function normalizePlayRunLedgerSnapshot(value, fallback) {
1467
1738
  updatedAt: finiteNumber(rawDataset.updatedAt) ?? 0
1468
1739
  };
1469
1740
  }
1741
+ const rawActivities = isRecord2(value.activitiesById) ? value.activitiesById : {};
1742
+ const activitiesById = {};
1743
+ for (const [activityId, rawActivity] of Object.entries(rawActivities)) {
1744
+ if (activityId.trim() && isPlayActivityObservation(rawActivity) && rawActivity.activityId === activityId) {
1745
+ activitiesById[activityId] = rawActivity;
1746
+ }
1747
+ }
1470
1748
  const createdAt = finiteNumber(value.createdAt) ?? fallback.createdAt ?? null;
1471
1749
  const startedAt = finiteNumber(value.startedAt) ?? fallback.startedAt ?? null;
1472
1750
  const finishedAt = finiteNumber(value.finishedAt) ?? fallback.finishedAt ?? null;
@@ -1490,6 +1768,10 @@ function normalizePlayRunLedgerSnapshot(value, fallback) {
1490
1768
  (datasetId) => typeof datasetId === "string" && Boolean(datasetsById[datasetId])
1491
1769
  ),
1492
1770
  datasetsById,
1771
+ orderedActivityIds: (Array.isArray(value.orderedActivityIds) ? value.orderedActivityIds : Object.keys(activitiesById)).filter(
1772
+ (activityId) => typeof activityId === "string" && Boolean(activitiesById[activityId])
1773
+ ),
1774
+ activitiesById,
1493
1775
  logTail: logTail.slice(-LOG_TAIL_LIMIT),
1494
1776
  // Snapshots persisted before totalLogCount existed only know the retained
1495
1777
  // tail, so the best lower bound for the cumulative count is the tail size.
@@ -1499,6 +1781,7 @@ function normalizePlayRunLedgerSnapshot(value, fallback) {
1499
1781
  ),
1500
1782
  logsTruncated: value.logsTruncated === true,
1501
1783
  activeStepId: optionalNullableString(value.activeStepId),
1784
+ activeActivityId: optionalNullableString(value.activeActivityId),
1502
1785
  activeArtifactTableNamespace: optionalNullableString(
1503
1786
  value.activeArtifactTableNamespace
1504
1787
  ),
@@ -1585,18 +1868,18 @@ function normalizePlayRunLiveStatus(value) {
1585
1868
  function isTerminalPlayRunLiveStatus(status) {
1586
1869
  return isTerminalPlayRunLifecycleStatus(status);
1587
1870
  }
1588
- function isRecord2(value) {
1871
+ function isRecord3(value) {
1589
1872
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
1590
1873
  }
1591
1874
  function finiteNumber2(value) {
1592
1875
  return typeof value === "number" && Number.isFinite(value) ? value : null;
1593
1876
  }
1594
1877
  function extractTerminalRunLogTail(result) {
1595
- if (!isRecord2(result) || !isRecord2(result._metadata)) {
1878
+ if (!isRecord3(result) || !isRecord3(result._metadata)) {
1596
1879
  return null;
1597
1880
  }
1598
1881
  const runLogTail = result._metadata.runLogTail;
1599
- if (!isRecord2(runLogTail) || !Array.isArray(runLogTail.tail)) {
1882
+ if (!isRecord3(runLogTail) || !Array.isArray(runLogTail.tail)) {
1600
1883
  return null;
1601
1884
  }
1602
1885
  const logTail = runLogTail.tail.filter(
@@ -1656,6 +1939,10 @@ function buildSnapshotFromLedger(snapshot) {
1656
1939
  datasets: snapshot.orderedDatasetIds.map((datasetId) => snapshot.datasetsById[datasetId]).filter(
1657
1940
  (dataset) => Boolean(dataset)
1658
1941
  ),
1942
+ activities: snapshot.orderedActivityIds.map((activityId) => snapshot.activitiesById[activityId]).filter(
1943
+ (activity) => Boolean(activity)
1944
+ ),
1945
+ activeActivity: snapshot.activeActivityId ? snapshot.activitiesById[snapshot.activeActivityId] ?? null : null,
1659
1946
  nodeStates,
1660
1947
  activeNodeId: snapshot.activeStepId ?? null,
1661
1948
  ...rowOutcomes ? { rowOutcomes } : {}
@@ -1672,14 +1959,29 @@ function buildPlayRunStatusSnapshot(input) {
1672
1959
  finishedAt: input.run.finishedAt ?? null
1673
1960
  });
1674
1961
  const terminalRunLogTail = extractTerminalRunLogTail(input.run.result);
1675
- if (terminalRunLogTail && terminalRunLogTail.totalLogCount > ledgerSnapshot.totalLogCount) {
1676
- return buildSnapshotFromLedger({
1677
- ...ledgerSnapshot,
1678
- logTail: terminalRunLogTail.logTail,
1679
- totalLogCount: terminalRunLogTail.totalLogCount
1680
- });
1681
- }
1682
- return buildSnapshotFromLedger(ledgerSnapshot);
1962
+ const projectedSnapshot = terminalRunLogTail && terminalRunLogTail.totalLogCount > ledgerSnapshot.totalLogCount ? buildSnapshotFromLedger({
1963
+ ...ledgerSnapshot,
1964
+ logTail: terminalRunLogTail.logTail,
1965
+ totalLogCount: terminalRunLogTail.totalLogCount
1966
+ }) : buildSnapshotFromLedger(ledgerSnapshot);
1967
+ const activity = projectPlayRunActivity({
1968
+ runId: input.run.workflowId,
1969
+ playName: input.run.name,
1970
+ status: projectedSnapshot.status,
1971
+ updatedAt: projectedSnapshot.updatedAt,
1972
+ waitKind: input.run.waitKind ?? input.run.wait?.kind ?? null,
1973
+ waitUntil: input.run.waitUntil,
1974
+ eventKey: input.run.wait?.eventKey ?? null,
1975
+ runtimeBackend: input.run.runtimeBackend,
1976
+ activeNodeId: input.run.activeBoundaryId ?? projectedSnapshot.activeNodeId,
1977
+ nodeStates: projectedSnapshot.nodeStates,
1978
+ datasets: projectedSnapshot.datasets,
1979
+ explicit: projectedSnapshot.activities
1980
+ });
1981
+ return {
1982
+ ...projectedSnapshot,
1983
+ activity
1984
+ };
1683
1985
  }
1684
1986
  function makeRunStreamEvent(input) {
1685
1987
  return {
@@ -1900,7 +2202,8 @@ function diffPlayRunStreamEvents(input) {
1900
2202
  payload: {
1901
2203
  runId: snapshot.runId,
1902
2204
  status: snapshot.status,
1903
- updatedAt: snapshot.updatedAt
2205
+ updatedAt: snapshot.updatedAt,
2206
+ ...snapshot.activity ? { activity: snapshot.activity } : {}
1904
2207
  }
1905
2208
  })
1906
2209
  );
@@ -2420,7 +2723,7 @@ function resolveToolExecuteTimeoutMs(toolId, input) {
2420
2723
  }
2421
2724
  var RUNS_FAILED_LOG_LIMIT = 20;
2422
2725
  var RUN_LOGS_PAGE_LIMIT = 1e3;
2423
- function isRecord3(value) {
2726
+ function isRecord4(value) {
2424
2727
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
2425
2728
  }
2426
2729
  function isPrebuiltPlayDescription(play) {
@@ -2577,7 +2880,7 @@ function updatePlayLiveStatusState(state, event) {
2577
2880
  }
2578
2881
  const runId = typeof payload.runId === "string" && payload.runId ? payload.runId : isPlayRunPackage(payload) ? payload.run.id : state.runId;
2579
2882
  const status = normalizeLiveStatus(payload.status) ?? (isPlayRunPackage(payload) ? normalizeLiveStatus(payload.run.status) : null) ?? state.status;
2580
- const progressPayload = isRecord3(payload.progress) ? payload.progress : {};
2883
+ const progressPayload = isRecord4(payload.progress) ? payload.progress : {};
2581
2884
  if (event.type === "play.run.final_status" && state.logs.length === 0 && state.lastLogSeq === 0) {
2582
2885
  const payloadLogs = readStringArray(payload.logs);
2583
2886
  const progressLogs = readStringArray(progressPayload.logs);
@@ -2711,9 +3014,9 @@ var DeeplineClient = class {
2711
3014
  return fields.length > 0 ? { fields } : schema;
2712
3015
  }
2713
3016
  schemaMetadata(schema, key) {
2714
- if (!isRecord3(schema)) return null;
3017
+ if (!isRecord4(schema)) return null;
2715
3018
  const value = schema[key];
2716
- return isRecord3(value) ? value : null;
3019
+ return isRecord4(value) ? value : null;
2717
3020
  }
2718
3021
  playRunCommand(play, options) {
2719
3022
  const target = play.reference || play.name;
@@ -2762,7 +3065,7 @@ var DeeplineClient = class {
2762
3065
  aliases,
2763
3066
  inputSchema: options?.compact ? this.compactSchema(play.inputSchema) : play.inputSchema ?? null,
2764
3067
  outputSchema: options?.compact ? this.compactSchema(play.outputSchema) : play.outputSchema ?? null,
2765
- staticPipeline: isRecord3(play.staticPipeline) ? play.staticPipeline : isRecord3(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord3(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
3068
+ staticPipeline: isRecord4(play.staticPipeline) ? play.staticPipeline : isRecord4(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord4(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
2766
3069
  ...csvInput ? { csvInput } : {},
2767
3070
  ...rowOutputSchema ? { rowOutputSchema } : {},
2768
3071
  runCommand,
@@ -2840,6 +3143,14 @@ var DeeplineClient = class {
2840
3143
  );
2841
3144
  return res.tools;
2842
3145
  }
3146
+ /** List discoverable providers without requiring a local plugin catalog. */
3147
+ async listProviders(options) {
3148
+ const suffix = options?.changed ? "?changed=true" : "";
3149
+ const res = await this.http.get(
3150
+ `/api/v2/tools/providers${suffix}`
3151
+ );
3152
+ return res.providers;
3153
+ }
2843
3154
  /**
2844
3155
  * Search available tools using Deepline's ranked backend search.
2845
3156
  *
@@ -5434,7 +5745,7 @@ var TARGET_FALLBACK_KEYS = {
5434
5745
  status: [/^email_status$/i, /^status$/i],
5435
5746
  email_status: [/^email_status$/i, /^status$/i]
5436
5747
  };
5437
- function isRecord4(value) {
5748
+ function isRecord5(value) {
5438
5749
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
5439
5750
  }
5440
5751
  function toV2RawToolOutputPath(path) {
@@ -5494,7 +5805,7 @@ function valuesAtSegments(current, segments, path = []) {
5494
5805
  if (!Array.isArray(current)) return [];
5495
5806
  return valuesAtSegments(current[segment], rest, [...path, segment]);
5496
5807
  }
5497
- if (!isRecord4(current)) return [];
5808
+ if (!isRecord5(current)) return [];
5498
5809
  const directMatches = valuesAtSegments(current[segment], rest, [
5499
5810
  ...path,
5500
5811
  segment
@@ -5524,7 +5835,7 @@ function getValuesAtPath(root, path) {
5524
5835
  return valuesAtSegments(root, parsePath(path)).map((entry) => entry.value);
5525
5836
  }
5526
5837
  function toResultEnvelope(value) {
5527
- if (isRecord4(value) && "data" in value) {
5838
+ if (isRecord5(value) && "data" in value) {
5528
5839
  const envelope = { data: value.data };
5529
5840
  if ("meta" in value) envelope.meta = value.meta;
5530
5841
  return envelope;
@@ -5577,7 +5888,7 @@ function getAtPath(root, path) {
5577
5888
  current = current[segment];
5578
5889
  continue;
5579
5890
  }
5580
- if (!isRecord4(current)) return void 0;
5891
+ if (!isRecord5(current)) return void 0;
5581
5892
  current = current[segment];
5582
5893
  }
5583
5894
  return current;
@@ -5594,7 +5905,7 @@ function normalizeString(value) {
5594
5905
  }
5595
5906
  function normalizeRows(value) {
5596
5907
  if (!Array.isArray(value)) return null;
5597
- return value.map((entry) => isRecord4(entry) ? entry : { value: entry });
5908
+ return value.map((entry) => isRecord5(entry) ? entry : { value: entry });
5598
5909
  }
5599
5910
  function findFirstTargetByPath(result, paths) {
5600
5911
  for (const path of paths ?? []) {
@@ -5653,7 +5964,7 @@ function findFirstTargetByKey(result, target, depth = 0, path = []) {
5653
5964
  }
5654
5965
  return null;
5655
5966
  }
5656
- if (!isRecord4(result)) return null;
5967
+ if (!isRecord5(result)) return null;
5657
5968
  const patterns = TARGET_FALLBACK_KEYS[target] ?? [
5658
5969
  new RegExp(`^${target}$`, "i")
5659
5970
  ];
@@ -5713,7 +6024,7 @@ function normalizeJobChangeStatus(value) {
5713
6024
  function firstExperienceDate(value) {
5714
6025
  if (!Array.isArray(value)) return null;
5715
6026
  for (const entry of value) {
5716
- if (!isRecord4(entry)) continue;
6027
+ if (!isRecord5(entry)) continue;
5717
6028
  const date = normalizeString(
5718
6029
  entry.start_date ?? entry.started_at ?? entry.startDate
5719
6030
  );
@@ -5722,10 +6033,10 @@ function firstExperienceDate(value) {
5722
6033
  return null;
5723
6034
  }
5724
6035
  function normalizeJobChange(value) {
5725
- const record = isRecord4(value) ? value : {};
5726
- const nested = isRecord4(record.job_change) ? record.job_change : record;
5727
- const output = isRecord4(nested.output) ? nested.output : nested;
5728
- const person = isRecord4(output.person) ? output.person : {};
6036
+ const record = isRecord5(value) ? value : {};
6037
+ const nested = isRecord5(record.job_change) ? record.job_change : record;
6038
+ const output = isRecord5(nested.output) ? nested.output : nested;
6039
+ const person = isRecord5(output.person) ? output.person : {};
5729
6040
  const status = normalizeJobChangeStatus(
5730
6041
  output.status ?? output.job_change_status ?? output.job_changed ?? output.changed
5731
6042
  );
@@ -6090,7 +6401,7 @@ function attachToolResultListDataset(result, input) {
6090
6401
  root = replaceAtPath(root, candidate, serialized.preview);
6091
6402
  break;
6092
6403
  }
6093
- if (isRecord4(root) && isRecord4(root.toolResponse) && Object.prototype.hasOwnProperty.call(root.toolResponse, "raw")) {
6404
+ if (isRecord5(root) && isRecord5(root.toolResponse) && Object.prototype.hasOwnProperty.call(root.toolResponse, "raw")) {
6094
6405
  result.toolResponse.raw = root.toolResponse.raw;
6095
6406
  result.toolOutput.raw = root.toolResponse.raw;
6096
6407
  }
@@ -6108,7 +6419,7 @@ function replaceAtPath(root, path, replacement) {
6108
6419
  copy[segment] = replace(copy[segment], index + 1);
6109
6420
  return copy;
6110
6421
  }
6111
- if (!isRecord4(current)) return current;
6422
+ if (!isRecord5(current)) return current;
6112
6423
  return {
6113
6424
  ...current,
6114
6425
  [segment]: replace(current[segment], index + 1)
@@ -6429,11 +6740,11 @@ var Deepline = class {
6429
6740
  return new DeeplineContext(options);
6430
6741
  }
6431
6742
  };
6432
- function isRecord5(value) {
6743
+ function isRecord6(value) {
6433
6744
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6434
6745
  }
6435
6746
  function stringArrayRecord(value) {
6436
- if (!isRecord5(value)) return {};
6747
+ if (!isRecord6(value)) return {};
6437
6748
  return Object.fromEntries(
6438
6749
  Object.entries(value).map(([key, paths]) => [
6439
6750
  key,
@@ -6445,7 +6756,7 @@ function stringArray(value) {
6445
6756
  return Array.isArray(value) ? value.map(String) : [];
6446
6757
  }
6447
6758
  function emailStatusExtractorConfig(value) {
6448
- if (!isRecord5(value)) return void 0;
6759
+ if (!isRecord6(value)) return void 0;
6449
6760
  const readPaths = (key) => {
6450
6761
  const paths = stringArray(value[key]).map((path) => path.trim()).filter(Boolean);
6451
6762
  return paths.length > 0 ? paths : void 0;
@@ -6472,7 +6783,7 @@ function emailStatusExtractorConfig(value) {
6472
6783
  const paths = readPaths(key);
6473
6784
  if (paths) config[key] = paths;
6474
6785
  }
6475
- if (isRecord5(value.statusMap)) {
6786
+ if (isRecord6(value.statusMap)) {
6476
6787
  config.statusMap = value.statusMap;
6477
6788
  }
6478
6789
  if (Array.isArray(value.rules)) {
@@ -6481,10 +6792,10 @@ function emailStatusExtractorConfig(value) {
6481
6792
  return config;
6482
6793
  }
6483
6794
  function extractorDescriptorRecord(value) {
6484
- if (!isRecord5(value)) return {};
6795
+ if (!isRecord6(value)) return {};
6485
6796
  return Object.fromEntries(
6486
6797
  Object.entries(value).flatMap(([key, descriptor]) => {
6487
- if (!isRecord5(descriptor)) return [];
6798
+ if (!isRecord6(descriptor)) return [];
6488
6799
  const paths = stringArray(descriptor.paths).map((path) => path.trim()).filter(Boolean);
6489
6800
  if (paths.length === 0) return [];
6490
6801
  const transforms = stringArray(descriptor.transforms).map((transform) => transform.trim()).filter(Boolean);
@@ -6506,7 +6817,7 @@ function extractorDescriptorRecord(value) {
6506
6817
  }
6507
6818
  function rowsFromUnknown(value) {
6508
6819
  if (!Array.isArray(value)) return [];
6509
- return value.map((row) => isRecord5(row) ? row : { value: row });
6820
+ return value.map((row) => isRecord6(row) ? row : { value: row });
6510
6821
  }
6511
6822
  function finiteNonNegativeInteger(value) {
6512
6823
  if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
@@ -6528,8 +6839,8 @@ function stableHash(value) {
6528
6839
  }
6529
6840
  function attachSdkQueryResultDatasetResult(toolId, result, options) {
6530
6841
  if (!options || !isQueryResultDatasetTool(toolId)) return result;
6531
- const raw = isRecord5(result.toolResponse.raw) ? result.toolResponse.raw : null;
6532
- const dataset = isRecord5(raw?.dataset) ? raw.dataset : null;
6842
+ const raw = isRecord6(result.toolResponse.raw) ? result.toolResponse.raw : null;
6843
+ const dataset = isRecord6(raw?.dataset) ? raw.dataset : null;
6533
6844
  const totalRows = finiteNonNegativeInteger(dataset?.total_rows);
6534
6845
  const sql = typeof options.input.sql === "string" ? options.input.sql : typeof options.input.query === "string" ? options.input.query : typeof raw?.sql === "string" ? raw.sql : null;
6535
6846
  if (!dataset || totalRows === null || !sql) {
@@ -6559,7 +6870,7 @@ function attachSdkQueryResultDatasetResult(toolId, result, options) {
6559
6870
  } : {}
6560
6871
  }
6561
6872
  });
6562
- const pageRaw = isRecord5(response.toolResponse?.raw) ? response.toolResponse.raw : null;
6873
+ const pageRaw = isRecord6(response.toolResponse?.raw) ? response.toolResponse.raw : null;
6563
6874
  return rowsFromUnknown(pageRaw?.rows);
6564
6875
  };
6565
6876
  const collectRows = async (limit) => {
@@ -6612,8 +6923,8 @@ function attachSdkQueryResultDatasetResult(toolId, result, options) {
6612
6923
  function toolExecutionEnvelopeToResult(fallbackToolId, response, options) {
6613
6924
  const raw = response.toolResponse?.raw ?? null;
6614
6925
  const meta = response.toolResponse?.meta;
6615
- const metadata = isRecord5(response._metadata) ? response._metadata.tool : null;
6616
- const toolMetadata = isRecord5(metadata) ? metadata : {};
6926
+ const metadata = isRecord6(response._metadata) ? response._metadata.tool : null;
6927
+ const toolMetadata = isRecord6(metadata) ? metadata : {};
6617
6928
  return attachSdkQueryResultDatasetResult(
6618
6929
  fallbackToolId,
6619
6930
  createToolExecuteResult({
@@ -6621,7 +6932,7 @@ function toolExecutionEnvelopeToResult(fallbackToolId, response, options) {
6621
6932
  jobId: typeof response.job_id === "string" ? response.job_id : void 0,
6622
6933
  result: {
6623
6934
  data: raw,
6624
- ...isRecord5(meta) ? { meta } : {}
6935
+ ...isRecord6(meta) ? { meta } : {}
6625
6936
  },
6626
6937
  metadata: {
6627
6938
  toolId: typeof toolMetadata.toolId === "string" ? toolMetadata.toolId : fallbackToolId,
@@ -6637,7 +6948,7 @@ function toolExecutionEnvelopeToResult(fallbackToolId, response, options) {
6637
6948
  cached: false,
6638
6949
  source: "live"
6639
6950
  },
6640
- meta: isRecord5(response.meta) ? response.meta : void 0
6951
+ meta: isRecord6(response.meta) ? response.meta : void 0
6641
6952
  }),
6642
6953
  options
6643
6954
  );