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.mjs CHANGED
@@ -367,7 +367,7 @@ var SDK_RELEASE = {
367
367
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
368
368
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
369
369
  // Operators use the checkout-local deepline-admin binary instead.
370
- version: "0.1.274",
370
+ version: "0.1.276",
371
371
  contracts: {
372
372
  api: {
373
373
  name: "sdk-http-api",
@@ -581,19 +581,19 @@ function isAbortLikeError(error) {
581
581
  const message = error.message.toLowerCase();
582
582
  return name === "aborterror" || message.includes("operation was aborted") || message === "aborted";
583
583
  }
584
- function mapNetworkError(baseUrl, error, targetLabel) {
584
+ function mapNetworkError(baseUrl, error, targetLabel2) {
585
585
  const tagged = error;
586
586
  const timeoutMs = tagged?.[REQUEST_TIMEOUT_MARKER];
587
587
  if (typeof timeoutMs === "number") {
588
588
  return {
589
- message: `Request to ${targetLabel} timed out after ${timeoutMs}ms while waiting for a response.`,
589
+ message: `Request to ${targetLabel2} timed out after ${timeoutMs}ms while waiting for a response.`,
590
590
  code: "NETWORK_TIMEOUT",
591
- details: { timeoutMs, target: targetLabel }
591
+ details: { timeoutMs, target: targetLabel2 }
592
592
  };
593
593
  }
594
594
  if (tagged?.[REQUEST_ABORT_MARKER]) {
595
595
  return {
596
- message: `Request to ${targetLabel} was aborted before it completed.`,
596
+ message: `Request to ${targetLabel2} was aborted before it completed.`,
597
597
  code: "NETWORK_ABORTED"
598
598
  };
599
599
  }
@@ -1254,9 +1254,277 @@ var RUNNER_POST_TERMINAL_DIAGNOSTIC_MAX_BYTES = 64 * 1024;
1254
1254
  // ../shared_libs/play-runtime/ledger-safe-payload.ts
1255
1255
  var ledgerIngressRedactor = createSecretRedactionContext();
1256
1256
 
1257
+ // ../shared_libs/play-runtime/activity-observation.ts
1258
+ function isRecord(value) {
1259
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
1260
+ }
1261
+ function isPlayActivityObservation(value) {
1262
+ 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)) {
1263
+ return false;
1264
+ }
1265
+ const targetKinds = /* @__PURE__ */ new Set([
1266
+ "provider",
1267
+ "dataset",
1268
+ "lease",
1269
+ "runner",
1270
+ "step",
1271
+ "capacity"
1272
+ ]);
1273
+ const stateKinds = /* @__PURE__ */ new Set([
1274
+ "active",
1275
+ "queued",
1276
+ "waiting",
1277
+ "retrying",
1278
+ "scheduled",
1279
+ "completed",
1280
+ "failed"
1281
+ ]);
1282
+ return typeof value.target.kind === "string" && targetKinds.has(value.target.kind) && typeof value.state.kind === "string" && stateKinds.has(value.state.kind);
1283
+ }
1284
+ function derivePlayActivityVisibility(input) {
1285
+ const { state } = input.observation;
1286
+ if (state.kind === "failed") return "action";
1287
+ if (state.kind === "waiting") {
1288
+ return state.reason.kind === "external_event" ? "action" : "headline";
1289
+ }
1290
+ if (state.kind === "queued" || state.kind === "scheduled") return "headline";
1291
+ if (state.kind === "retrying") {
1292
+ return state.retryAt - input.now <= 3e4 ? "hidden" : "timeline";
1293
+ }
1294
+ if (state.kind === "active") return "headline";
1295
+ return "timeline";
1296
+ }
1297
+ function targetLabel(target) {
1298
+ switch (target.kind) {
1299
+ case "provider":
1300
+ return target.label ?? `${target.provider} ${target.operation}`;
1301
+ case "dataset":
1302
+ return target.label ?? `dataset ${target.tableNamespace}`;
1303
+ case "lease":
1304
+ return `${target.resourceKind} ${target.resourceLabel}`;
1305
+ case "runner":
1306
+ return target.label ?? `${target.backend} runner`;
1307
+ case "step":
1308
+ return target.label ?? target.stepId;
1309
+ case "capacity":
1310
+ return target.label ?? `${target.pool} capacity`;
1311
+ }
1312
+ }
1313
+ function summarizePlayActivity(observation) {
1314
+ const label = targetLabel(observation.target);
1315
+ const { state } = observation;
1316
+ switch (state.kind) {
1317
+ case "active": {
1318
+ const progress = state.progress;
1319
+ const counts = typeof progress?.completed === "number" && typeof progress.total === "number" ? ` (${progress.completed}/${progress.total})` : "";
1320
+ return `Active: ${label}${counts}.`;
1321
+ }
1322
+ case "queued":
1323
+ return `Queued: waiting for ${label}.`;
1324
+ case "waiting":
1325
+ if (state.reason.kind === "external_event") {
1326
+ const provider = state.reason.provider ? ` from ${state.reason.provider}` : "";
1327
+ return `Blocked: waiting for an external event${provider}.`;
1328
+ }
1329
+ if (state.reason.kind === "dataset") {
1330
+ return `Blocked: waiting for dataset ${state.reason.tableNamespace} to become ${state.reason.requiredPhase}.`;
1331
+ }
1332
+ if (state.reason.kind === "lease") {
1333
+ return `Contended: waiting for ${state.reason.resourceKind} lease ${state.reason.resourceLabel}.`;
1334
+ }
1335
+ return `Paused: ${label}; the legacy producer did not report a typed reason.`;
1336
+ case "retrying":
1337
+ return `Delayed: ${label} will retry automatically.`;
1338
+ case "scheduled":
1339
+ return `Scheduled: ${label} will resume automatically.`;
1340
+ case "completed":
1341
+ return `Completed: ${label}.`;
1342
+ case "failed":
1343
+ return `Failed: ${label}.`;
1344
+ }
1345
+ }
1346
+ function isTerminalActivityState(state) {
1347
+ return state.kind === "completed" || state.kind === "failed";
1348
+ }
1349
+ function projection(observation, now, classified = true) {
1350
+ return {
1351
+ observation,
1352
+ summary: summarizePlayActivity(observation),
1353
+ visibility: derivePlayActivityVisibility({ observation, now }),
1354
+ classified
1355
+ };
1356
+ }
1357
+ function projectPlayRunActivity(input) {
1358
+ const now = input.now ?? Date.now();
1359
+ const observedAt = input.updatedAt ?? now;
1360
+ const normalizedStatus = input.status.trim().toLowerCase();
1361
+ if (normalizedStatus === "completed" || normalizedStatus === "failed" || normalizedStatus === "cancelled" || normalizedStatus === "terminated" || normalizedStatus === "timed_out") {
1362
+ return null;
1363
+ }
1364
+ const explicit = [...input.explicit ?? []].filter((candidate) => !isTerminalActivityState(candidate.state)).sort((left, right) => right.observedAt - left.observedAt)[0];
1365
+ if (explicit) return projection(explicit, now);
1366
+ if (input.waitKind === "detached_runner") {
1367
+ return projection(
1368
+ {
1369
+ schemaVersion: 1,
1370
+ activityId: "runner:managed",
1371
+ target: {
1372
+ kind: "runner",
1373
+ backend: input.runtimeBackend ?? "managed",
1374
+ label: "managed play runner"
1375
+ },
1376
+ state: { kind: "active" },
1377
+ observedAt
1378
+ },
1379
+ now
1380
+ );
1381
+ }
1382
+ if (input.waitKind === "sleep") {
1383
+ return projection(
1384
+ {
1385
+ schemaVersion: 1,
1386
+ activityId: "run:sleep",
1387
+ target: {
1388
+ kind: "step",
1389
+ stepId: input.activeNodeId ?? "run",
1390
+ label: input.playName ?? "play"
1391
+ },
1392
+ state: {
1393
+ kind: "scheduled",
1394
+ reason: "sleep",
1395
+ resumeAt: input.waitUntil ?? observedAt
1396
+ },
1397
+ observedAt
1398
+ },
1399
+ now
1400
+ );
1401
+ }
1402
+ if (input.waitKind === "integration_event" || input.waitKind === "integration_event_batch") {
1403
+ return projection(
1404
+ {
1405
+ schemaVersion: 1,
1406
+ activityId: `event:${input.activeNodeId ?? "run"}`,
1407
+ stepId: input.activeNodeId ?? void 0,
1408
+ target: {
1409
+ kind: "step",
1410
+ stepId: input.activeNodeId ?? "run",
1411
+ label: input.playName ?? "play"
1412
+ },
1413
+ state: {
1414
+ kind: "waiting",
1415
+ reason: {
1416
+ kind: "external_event",
1417
+ eventKey: input.eventKey ?? void 0,
1418
+ deadlineAt: input.waitUntil ?? void 0
1419
+ }
1420
+ },
1421
+ observedAt
1422
+ },
1423
+ now
1424
+ );
1425
+ }
1426
+ if (normalizedStatus === "waiting") {
1427
+ return projection(
1428
+ {
1429
+ schemaVersion: 1,
1430
+ activityId: "run:legacy-wait",
1431
+ target: {
1432
+ kind: "step",
1433
+ stepId: input.activeNodeId ?? "run",
1434
+ label: input.playName ?? "play"
1435
+ },
1436
+ state: { kind: "waiting", reason: { kind: "unknown" } },
1437
+ observedAt
1438
+ },
1439
+ now,
1440
+ false
1441
+ );
1442
+ }
1443
+ const pendingDataset = [...input.datasets ?? []].filter(
1444
+ (dataset) => dataset.phase === "registered" || dataset.complete !== true && dataset.phase !== "failed"
1445
+ ).sort((left, right) => (right.updatedAt ?? 0) - (left.updatedAt ?? 0))[0];
1446
+ if (pendingDataset) {
1447
+ return projection(
1448
+ {
1449
+ schemaVersion: 1,
1450
+ activityId: `dataset:${pendingDataset.datasetId ?? pendingDataset.tableNamespace}`,
1451
+ target: {
1452
+ kind: "dataset",
1453
+ tableNamespace: pendingDataset.tableNamespace,
1454
+ operation: "materializing"
1455
+ },
1456
+ state: {
1457
+ kind: "active",
1458
+ progress: {
1459
+ completed: pendingDataset.persistedRows,
1460
+ total: typeof pendingDataset.succeededRows === "number" || typeof pendingDataset.failedRows === "number" ? (pendingDataset.succeededRows ?? 0) + (pendingDataset.failedRows ?? 0) : void 0,
1461
+ failed: pendingDataset.failedRows
1462
+ }
1463
+ },
1464
+ observedAt: pendingDataset.updatedAt ?? observedAt
1465
+ },
1466
+ now
1467
+ );
1468
+ }
1469
+ const activeStep = input.nodeStates?.find(
1470
+ (candidate) => candidate.nodeId === input.activeNodeId
1471
+ ) ?? input.nodeStates?.find((candidate) => candidate.status === "running") ?? null;
1472
+ if (activeStep) {
1473
+ const toolId = activeStep.nodeId.startsWith("tool:") ? activeStep.nodeId.split(":").at(-1)?.trim() || null : null;
1474
+ const provider = toolId?.split(/[._]/)[0]?.trim() || null;
1475
+ return projection(
1476
+ {
1477
+ schemaVersion: 1,
1478
+ activityId: `step:${activeStep.nodeId}`,
1479
+ stepId: activeStep.nodeId,
1480
+ target: toolId && provider ? {
1481
+ kind: "provider",
1482
+ provider,
1483
+ operation: toolId,
1484
+ label: activeStep.label ?? toolId
1485
+ } : {
1486
+ kind: "step",
1487
+ stepId: activeStep.nodeId,
1488
+ label: activeStep.label
1489
+ },
1490
+ state: {
1491
+ kind: "active",
1492
+ progress: activeStep.progress ?? void 0
1493
+ },
1494
+ observedAt: activeStep.updatedAt ?? observedAt
1495
+ },
1496
+ now
1497
+ );
1498
+ }
1499
+ if (normalizedStatus === "queued") {
1500
+ return projection(
1501
+ {
1502
+ schemaVersion: 1,
1503
+ activityId: "capacity:worker",
1504
+ target: { kind: "capacity", pool: "worker" },
1505
+ state: { kind: "queued", reason: "capacity" },
1506
+ observedAt
1507
+ },
1508
+ now
1509
+ );
1510
+ }
1511
+ const fallback = {
1512
+ schemaVersion: 1,
1513
+ activityId: "run:legacy",
1514
+ target: {
1515
+ kind: "step",
1516
+ stepId: input.activeNodeId ?? "run",
1517
+ label: input.playName ?? "play"
1518
+ },
1519
+ state: normalizedStatus === "waiting" ? { kind: "waiting", reason: { kind: "unknown" } } : { kind: "active" },
1520
+ observedAt
1521
+ };
1522
+ return projection(fallback, now, normalizedStatus !== "waiting");
1523
+ }
1524
+
1257
1525
  // ../shared_libs/play-runtime/run-ledger.ts
1258
1526
  var LOG_TAIL_LIMIT = 100;
1259
- function isRecord(value) {
1527
+ function isRecord2(value) {
1260
1528
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
1261
1529
  }
1262
1530
  function finiteNumber(value) {
@@ -1340,30 +1608,33 @@ function createEmptyPlayRunLedgerSnapshot(input) {
1340
1608
  stepsById: {},
1341
1609
  orderedDatasetIds: [],
1342
1610
  datasetsById: {},
1611
+ orderedActivityIds: [],
1612
+ activitiesById: {},
1343
1613
  logTail: [],
1344
1614
  totalLogCount: 0,
1345
1615
  logsTruncated: false,
1346
1616
  activeStepId: null,
1617
+ activeActivityId: null,
1347
1618
  activeArtifactTableNamespace: null,
1348
1619
  resultTableNamespace: null
1349
1620
  };
1350
1621
  }
1351
1622
  function normalizePlayRunLedgerSnapshot(value, fallback) {
1352
- if (!isRecord(value)) {
1623
+ if (!isRecord2(value)) {
1353
1624
  return createEmptyPlayRunLedgerSnapshot(fallback);
1354
1625
  }
1355
1626
  const orderedStepIds = Array.isArray(value.orderedStepIds) ? value.orderedStepIds.filter(
1356
1627
  (entry) => typeof entry === "string" && Boolean(entry.trim())
1357
1628
  ) : [];
1358
- const rawSteps = isRecord(value.stepsById) ? value.stepsById : {};
1629
+ const rawSteps = isRecord2(value.stepsById) ? value.stepsById : {};
1359
1630
  const stepsById = {};
1360
1631
  for (const [stepId, rawStep] of Object.entries(rawSteps)) {
1361
- if (!stepId.trim() || !isRecord(rawStep)) continue;
1632
+ if (!stepId.trim() || !isRecord2(rawStep)) continue;
1362
1633
  const rawStatus = normalizeStepStatus(rawStep.status);
1363
1634
  if (!rawStatus) continue;
1364
1635
  const completedAt = finiteNumber(rawStep.completedAt);
1365
1636
  const status = rawStatus === "running" && completedAt !== null ? "completed" : rawStatus;
1366
- const rawProgress = isRecord(rawStep.progress) ? rawStep.progress : null;
1637
+ const rawProgress = isRecord2(rawStep.progress) ? rawStep.progress : null;
1367
1638
  stepsById[stepId] = {
1368
1639
  stepId,
1369
1640
  label: optionalString(rawStep.label),
@@ -1379,10 +1650,10 @@ function normalizePlayRunLedgerSnapshot(value, fallback) {
1379
1650
  progress: rawProgress ? normalizeStepProgress(rawProgress) : null
1380
1651
  };
1381
1652
  }
1382
- const rawDatasets = isRecord(value.datasetsById) ? value.datasetsById : {};
1653
+ const rawDatasets = isRecord2(value.datasetsById) ? value.datasetsById : {};
1383
1654
  const datasetsById = {};
1384
1655
  for (const [datasetId, rawDataset] of Object.entries(rawDatasets)) {
1385
- if (!datasetId.trim() || !isRecord(rawDataset)) continue;
1656
+ if (!datasetId.trim() || !isRecord2(rawDataset)) continue;
1386
1657
  const phase = rawDataset.phase === "available" || rawDataset.phase === "failed" ? rawDataset.phase : "registered";
1387
1658
  datasetsById[datasetId] = {
1388
1659
  datasetId,
@@ -1396,6 +1667,13 @@ function normalizePlayRunLedgerSnapshot(value, fallback) {
1396
1667
  updatedAt: finiteNumber(rawDataset.updatedAt) ?? 0
1397
1668
  };
1398
1669
  }
1670
+ const rawActivities = isRecord2(value.activitiesById) ? value.activitiesById : {};
1671
+ const activitiesById = {};
1672
+ for (const [activityId, rawActivity] of Object.entries(rawActivities)) {
1673
+ if (activityId.trim() && isPlayActivityObservation(rawActivity) && rawActivity.activityId === activityId) {
1674
+ activitiesById[activityId] = rawActivity;
1675
+ }
1676
+ }
1399
1677
  const createdAt = finiteNumber(value.createdAt) ?? fallback.createdAt ?? null;
1400
1678
  const startedAt = finiteNumber(value.startedAt) ?? fallback.startedAt ?? null;
1401
1679
  const finishedAt = finiteNumber(value.finishedAt) ?? fallback.finishedAt ?? null;
@@ -1419,6 +1697,10 @@ function normalizePlayRunLedgerSnapshot(value, fallback) {
1419
1697
  (datasetId) => typeof datasetId === "string" && Boolean(datasetsById[datasetId])
1420
1698
  ),
1421
1699
  datasetsById,
1700
+ orderedActivityIds: (Array.isArray(value.orderedActivityIds) ? value.orderedActivityIds : Object.keys(activitiesById)).filter(
1701
+ (activityId) => typeof activityId === "string" && Boolean(activitiesById[activityId])
1702
+ ),
1703
+ activitiesById,
1422
1704
  logTail: logTail.slice(-LOG_TAIL_LIMIT),
1423
1705
  // Snapshots persisted before totalLogCount existed only know the retained
1424
1706
  // tail, so the best lower bound for the cumulative count is the tail size.
@@ -1428,6 +1710,7 @@ function normalizePlayRunLedgerSnapshot(value, fallback) {
1428
1710
  ),
1429
1711
  logsTruncated: value.logsTruncated === true,
1430
1712
  activeStepId: optionalNullableString(value.activeStepId),
1713
+ activeActivityId: optionalNullableString(value.activeActivityId),
1431
1714
  activeArtifactTableNamespace: optionalNullableString(
1432
1715
  value.activeArtifactTableNamespace
1433
1716
  ),
@@ -1514,18 +1797,18 @@ function normalizePlayRunLiveStatus(value) {
1514
1797
  function isTerminalPlayRunLiveStatus(status) {
1515
1798
  return isTerminalPlayRunLifecycleStatus(status);
1516
1799
  }
1517
- function isRecord2(value) {
1800
+ function isRecord3(value) {
1518
1801
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
1519
1802
  }
1520
1803
  function finiteNumber2(value) {
1521
1804
  return typeof value === "number" && Number.isFinite(value) ? value : null;
1522
1805
  }
1523
1806
  function extractTerminalRunLogTail(result) {
1524
- if (!isRecord2(result) || !isRecord2(result._metadata)) {
1807
+ if (!isRecord3(result) || !isRecord3(result._metadata)) {
1525
1808
  return null;
1526
1809
  }
1527
1810
  const runLogTail = result._metadata.runLogTail;
1528
- if (!isRecord2(runLogTail) || !Array.isArray(runLogTail.tail)) {
1811
+ if (!isRecord3(runLogTail) || !Array.isArray(runLogTail.tail)) {
1529
1812
  return null;
1530
1813
  }
1531
1814
  const logTail = runLogTail.tail.filter(
@@ -1585,6 +1868,10 @@ function buildSnapshotFromLedger(snapshot) {
1585
1868
  datasets: snapshot.orderedDatasetIds.map((datasetId) => snapshot.datasetsById[datasetId]).filter(
1586
1869
  (dataset) => Boolean(dataset)
1587
1870
  ),
1871
+ activities: snapshot.orderedActivityIds.map((activityId) => snapshot.activitiesById[activityId]).filter(
1872
+ (activity) => Boolean(activity)
1873
+ ),
1874
+ activeActivity: snapshot.activeActivityId ? snapshot.activitiesById[snapshot.activeActivityId] ?? null : null,
1588
1875
  nodeStates,
1589
1876
  activeNodeId: snapshot.activeStepId ?? null,
1590
1877
  ...rowOutcomes ? { rowOutcomes } : {}
@@ -1601,14 +1888,29 @@ function buildPlayRunStatusSnapshot(input) {
1601
1888
  finishedAt: input.run.finishedAt ?? null
1602
1889
  });
1603
1890
  const terminalRunLogTail = extractTerminalRunLogTail(input.run.result);
1604
- if (terminalRunLogTail && terminalRunLogTail.totalLogCount > ledgerSnapshot.totalLogCount) {
1605
- return buildSnapshotFromLedger({
1606
- ...ledgerSnapshot,
1607
- logTail: terminalRunLogTail.logTail,
1608
- totalLogCount: terminalRunLogTail.totalLogCount
1609
- });
1610
- }
1611
- return buildSnapshotFromLedger(ledgerSnapshot);
1891
+ const projectedSnapshot = terminalRunLogTail && terminalRunLogTail.totalLogCount > ledgerSnapshot.totalLogCount ? buildSnapshotFromLedger({
1892
+ ...ledgerSnapshot,
1893
+ logTail: terminalRunLogTail.logTail,
1894
+ totalLogCount: terminalRunLogTail.totalLogCount
1895
+ }) : buildSnapshotFromLedger(ledgerSnapshot);
1896
+ const activity = projectPlayRunActivity({
1897
+ runId: input.run.workflowId,
1898
+ playName: input.run.name,
1899
+ status: projectedSnapshot.status,
1900
+ updatedAt: projectedSnapshot.updatedAt,
1901
+ waitKind: input.run.waitKind ?? input.run.wait?.kind ?? null,
1902
+ waitUntil: input.run.waitUntil,
1903
+ eventKey: input.run.wait?.eventKey ?? null,
1904
+ runtimeBackend: input.run.runtimeBackend,
1905
+ activeNodeId: input.run.activeBoundaryId ?? projectedSnapshot.activeNodeId,
1906
+ nodeStates: projectedSnapshot.nodeStates,
1907
+ datasets: projectedSnapshot.datasets,
1908
+ explicit: projectedSnapshot.activities
1909
+ });
1910
+ return {
1911
+ ...projectedSnapshot,
1912
+ activity
1913
+ };
1612
1914
  }
1613
1915
  function makeRunStreamEvent(input) {
1614
1916
  return {
@@ -1829,7 +2131,8 @@ function diffPlayRunStreamEvents(input) {
1829
2131
  payload: {
1830
2132
  runId: snapshot.runId,
1831
2133
  status: snapshot.status,
1832
- updatedAt: snapshot.updatedAt
2134
+ updatedAt: snapshot.updatedAt,
2135
+ ...snapshot.activity ? { activity: snapshot.activity } : {}
1833
2136
  }
1834
2137
  })
1835
2138
  );
@@ -2349,7 +2652,7 @@ function resolveToolExecuteTimeoutMs(toolId, input) {
2349
2652
  }
2350
2653
  var RUNS_FAILED_LOG_LIMIT = 20;
2351
2654
  var RUN_LOGS_PAGE_LIMIT = 1e3;
2352
- function isRecord3(value) {
2655
+ function isRecord4(value) {
2353
2656
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
2354
2657
  }
2355
2658
  function isPrebuiltPlayDescription(play) {
@@ -2506,7 +2809,7 @@ function updatePlayLiveStatusState(state, event) {
2506
2809
  }
2507
2810
  const runId = typeof payload.runId === "string" && payload.runId ? payload.runId : isPlayRunPackage(payload) ? payload.run.id : state.runId;
2508
2811
  const status = normalizeLiveStatus(payload.status) ?? (isPlayRunPackage(payload) ? normalizeLiveStatus(payload.run.status) : null) ?? state.status;
2509
- const progressPayload = isRecord3(payload.progress) ? payload.progress : {};
2812
+ const progressPayload = isRecord4(payload.progress) ? payload.progress : {};
2510
2813
  if (event.type === "play.run.final_status" && state.logs.length === 0 && state.lastLogSeq === 0) {
2511
2814
  const payloadLogs = readStringArray(payload.logs);
2512
2815
  const progressLogs = readStringArray(progressPayload.logs);
@@ -2640,9 +2943,9 @@ var DeeplineClient = class {
2640
2943
  return fields.length > 0 ? { fields } : schema;
2641
2944
  }
2642
2945
  schemaMetadata(schema, key) {
2643
- if (!isRecord3(schema)) return null;
2946
+ if (!isRecord4(schema)) return null;
2644
2947
  const value = schema[key];
2645
- return isRecord3(value) ? value : null;
2948
+ return isRecord4(value) ? value : null;
2646
2949
  }
2647
2950
  playRunCommand(play, options) {
2648
2951
  const target = play.reference || play.name;
@@ -2691,7 +2994,7 @@ var DeeplineClient = class {
2691
2994
  aliases,
2692
2995
  inputSchema: options?.compact ? this.compactSchema(play.inputSchema) : play.inputSchema ?? null,
2693
2996
  outputSchema: options?.compact ? this.compactSchema(play.outputSchema) : play.outputSchema ?? null,
2694
- staticPipeline: isRecord3(play.staticPipeline) ? play.staticPipeline : isRecord3(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord3(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
2997
+ staticPipeline: isRecord4(play.staticPipeline) ? play.staticPipeline : isRecord4(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord4(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
2695
2998
  ...csvInput ? { csvInput } : {},
2696
2999
  ...rowOutputSchema ? { rowOutputSchema } : {},
2697
3000
  runCommand,
@@ -2769,6 +3072,14 @@ var DeeplineClient = class {
2769
3072
  );
2770
3073
  return res.tools;
2771
3074
  }
3075
+ /** List discoverable providers without requiring a local plugin catalog. */
3076
+ async listProviders(options) {
3077
+ const suffix = options?.changed ? "?changed=true" : "";
3078
+ const res = await this.http.get(
3079
+ `/api/v2/tools/providers${suffix}`
3080
+ );
3081
+ return res.providers;
3082
+ }
2772
3083
  /**
2773
3084
  * Search available tools using Deepline's ranked backend search.
2774
3085
  *
@@ -5363,7 +5674,7 @@ var TARGET_FALLBACK_KEYS = {
5363
5674
  status: [/^email_status$/i, /^status$/i],
5364
5675
  email_status: [/^email_status$/i, /^status$/i]
5365
5676
  };
5366
- function isRecord4(value) {
5677
+ function isRecord5(value) {
5367
5678
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
5368
5679
  }
5369
5680
  function toV2RawToolOutputPath(path) {
@@ -5423,7 +5734,7 @@ function valuesAtSegments(current, segments, path = []) {
5423
5734
  if (!Array.isArray(current)) return [];
5424
5735
  return valuesAtSegments(current[segment], rest, [...path, segment]);
5425
5736
  }
5426
- if (!isRecord4(current)) return [];
5737
+ if (!isRecord5(current)) return [];
5427
5738
  const directMatches = valuesAtSegments(current[segment], rest, [
5428
5739
  ...path,
5429
5740
  segment
@@ -5453,7 +5764,7 @@ function getValuesAtPath(root, path) {
5453
5764
  return valuesAtSegments(root, parsePath(path)).map((entry) => entry.value);
5454
5765
  }
5455
5766
  function toResultEnvelope(value) {
5456
- if (isRecord4(value) && "data" in value) {
5767
+ if (isRecord5(value) && "data" in value) {
5457
5768
  const envelope = { data: value.data };
5458
5769
  if ("meta" in value) envelope.meta = value.meta;
5459
5770
  return envelope;
@@ -5506,7 +5817,7 @@ function getAtPath(root, path) {
5506
5817
  current = current[segment];
5507
5818
  continue;
5508
5819
  }
5509
- if (!isRecord4(current)) return void 0;
5820
+ if (!isRecord5(current)) return void 0;
5510
5821
  current = current[segment];
5511
5822
  }
5512
5823
  return current;
@@ -5523,7 +5834,7 @@ function normalizeString(value) {
5523
5834
  }
5524
5835
  function normalizeRows(value) {
5525
5836
  if (!Array.isArray(value)) return null;
5526
- return value.map((entry) => isRecord4(entry) ? entry : { value: entry });
5837
+ return value.map((entry) => isRecord5(entry) ? entry : { value: entry });
5527
5838
  }
5528
5839
  function findFirstTargetByPath(result, paths) {
5529
5840
  for (const path of paths ?? []) {
@@ -5582,7 +5893,7 @@ function findFirstTargetByKey(result, target, depth = 0, path = []) {
5582
5893
  }
5583
5894
  return null;
5584
5895
  }
5585
- if (!isRecord4(result)) return null;
5896
+ if (!isRecord5(result)) return null;
5586
5897
  const patterns = TARGET_FALLBACK_KEYS[target] ?? [
5587
5898
  new RegExp(`^${target}$`, "i")
5588
5899
  ];
@@ -5642,7 +5953,7 @@ function normalizeJobChangeStatus(value) {
5642
5953
  function firstExperienceDate(value) {
5643
5954
  if (!Array.isArray(value)) return null;
5644
5955
  for (const entry of value) {
5645
- if (!isRecord4(entry)) continue;
5956
+ if (!isRecord5(entry)) continue;
5646
5957
  const date = normalizeString(
5647
5958
  entry.start_date ?? entry.started_at ?? entry.startDate
5648
5959
  );
@@ -5651,10 +5962,10 @@ function firstExperienceDate(value) {
5651
5962
  return null;
5652
5963
  }
5653
5964
  function normalizeJobChange(value) {
5654
- const record = isRecord4(value) ? value : {};
5655
- const nested = isRecord4(record.job_change) ? record.job_change : record;
5656
- const output = isRecord4(nested.output) ? nested.output : nested;
5657
- const person = isRecord4(output.person) ? output.person : {};
5965
+ const record = isRecord5(value) ? value : {};
5966
+ const nested = isRecord5(record.job_change) ? record.job_change : record;
5967
+ const output = isRecord5(nested.output) ? nested.output : nested;
5968
+ const person = isRecord5(output.person) ? output.person : {};
5658
5969
  const status = normalizeJobChangeStatus(
5659
5970
  output.status ?? output.job_change_status ?? output.job_changed ?? output.changed
5660
5971
  );
@@ -6019,7 +6330,7 @@ function attachToolResultListDataset(result, input) {
6019
6330
  root = replaceAtPath(root, candidate, serialized.preview);
6020
6331
  break;
6021
6332
  }
6022
- if (isRecord4(root) && isRecord4(root.toolResponse) && Object.prototype.hasOwnProperty.call(root.toolResponse, "raw")) {
6333
+ if (isRecord5(root) && isRecord5(root.toolResponse) && Object.prototype.hasOwnProperty.call(root.toolResponse, "raw")) {
6023
6334
  result.toolResponse.raw = root.toolResponse.raw;
6024
6335
  result.toolOutput.raw = root.toolResponse.raw;
6025
6336
  }
@@ -6037,7 +6348,7 @@ function replaceAtPath(root, path, replacement) {
6037
6348
  copy[segment] = replace(copy[segment], index + 1);
6038
6349
  return copy;
6039
6350
  }
6040
- if (!isRecord4(current)) return current;
6351
+ if (!isRecord5(current)) return current;
6041
6352
  return {
6042
6353
  ...current,
6043
6354
  [segment]: replace(current[segment], index + 1)
@@ -6358,11 +6669,11 @@ var Deepline = class {
6358
6669
  return new DeeplineContext(options);
6359
6670
  }
6360
6671
  };
6361
- function isRecord5(value) {
6672
+ function isRecord6(value) {
6362
6673
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6363
6674
  }
6364
6675
  function stringArrayRecord(value) {
6365
- if (!isRecord5(value)) return {};
6676
+ if (!isRecord6(value)) return {};
6366
6677
  return Object.fromEntries(
6367
6678
  Object.entries(value).map(([key, paths]) => [
6368
6679
  key,
@@ -6374,7 +6685,7 @@ function stringArray(value) {
6374
6685
  return Array.isArray(value) ? value.map(String) : [];
6375
6686
  }
6376
6687
  function emailStatusExtractorConfig(value) {
6377
- if (!isRecord5(value)) return void 0;
6688
+ if (!isRecord6(value)) return void 0;
6378
6689
  const readPaths = (key) => {
6379
6690
  const paths = stringArray(value[key]).map((path) => path.trim()).filter(Boolean);
6380
6691
  return paths.length > 0 ? paths : void 0;
@@ -6401,7 +6712,7 @@ function emailStatusExtractorConfig(value) {
6401
6712
  const paths = readPaths(key);
6402
6713
  if (paths) config[key] = paths;
6403
6714
  }
6404
- if (isRecord5(value.statusMap)) {
6715
+ if (isRecord6(value.statusMap)) {
6405
6716
  config.statusMap = value.statusMap;
6406
6717
  }
6407
6718
  if (Array.isArray(value.rules)) {
@@ -6410,10 +6721,10 @@ function emailStatusExtractorConfig(value) {
6410
6721
  return config;
6411
6722
  }
6412
6723
  function extractorDescriptorRecord(value) {
6413
- if (!isRecord5(value)) return {};
6724
+ if (!isRecord6(value)) return {};
6414
6725
  return Object.fromEntries(
6415
6726
  Object.entries(value).flatMap(([key, descriptor]) => {
6416
- if (!isRecord5(descriptor)) return [];
6727
+ if (!isRecord6(descriptor)) return [];
6417
6728
  const paths = stringArray(descriptor.paths).map((path) => path.trim()).filter(Boolean);
6418
6729
  if (paths.length === 0) return [];
6419
6730
  const transforms = stringArray(descriptor.transforms).map((transform) => transform.trim()).filter(Boolean);
@@ -6435,7 +6746,7 @@ function extractorDescriptorRecord(value) {
6435
6746
  }
6436
6747
  function rowsFromUnknown(value) {
6437
6748
  if (!Array.isArray(value)) return [];
6438
- return value.map((row) => isRecord5(row) ? row : { value: row });
6749
+ return value.map((row) => isRecord6(row) ? row : { value: row });
6439
6750
  }
6440
6751
  function finiteNonNegativeInteger(value) {
6441
6752
  if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
@@ -6457,8 +6768,8 @@ function stableHash(value) {
6457
6768
  }
6458
6769
  function attachSdkQueryResultDatasetResult(toolId, result, options) {
6459
6770
  if (!options || !isQueryResultDatasetTool(toolId)) return result;
6460
- const raw = isRecord5(result.toolResponse.raw) ? result.toolResponse.raw : null;
6461
- const dataset = isRecord5(raw?.dataset) ? raw.dataset : null;
6771
+ const raw = isRecord6(result.toolResponse.raw) ? result.toolResponse.raw : null;
6772
+ const dataset = isRecord6(raw?.dataset) ? raw.dataset : null;
6462
6773
  const totalRows = finiteNonNegativeInteger(dataset?.total_rows);
6463
6774
  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;
6464
6775
  if (!dataset || totalRows === null || !sql) {
@@ -6488,7 +6799,7 @@ function attachSdkQueryResultDatasetResult(toolId, result, options) {
6488
6799
  } : {}
6489
6800
  }
6490
6801
  });
6491
- const pageRaw = isRecord5(response.toolResponse?.raw) ? response.toolResponse.raw : null;
6802
+ const pageRaw = isRecord6(response.toolResponse?.raw) ? response.toolResponse.raw : null;
6492
6803
  return rowsFromUnknown(pageRaw?.rows);
6493
6804
  };
6494
6805
  const collectRows = async (limit) => {
@@ -6541,8 +6852,8 @@ function attachSdkQueryResultDatasetResult(toolId, result, options) {
6541
6852
  function toolExecutionEnvelopeToResult(fallbackToolId, response, options) {
6542
6853
  const raw = response.toolResponse?.raw ?? null;
6543
6854
  const meta = response.toolResponse?.meta;
6544
- const metadata = isRecord5(response._metadata) ? response._metadata.tool : null;
6545
- const toolMetadata = isRecord5(metadata) ? metadata : {};
6855
+ const metadata = isRecord6(response._metadata) ? response._metadata.tool : null;
6856
+ const toolMetadata = isRecord6(metadata) ? metadata : {};
6546
6857
  return attachSdkQueryResultDatasetResult(
6547
6858
  fallbackToolId,
6548
6859
  createToolExecuteResult({
@@ -6550,7 +6861,7 @@ function toolExecutionEnvelopeToResult(fallbackToolId, response, options) {
6550
6861
  jobId: typeof response.job_id === "string" ? response.job_id : void 0,
6551
6862
  result: {
6552
6863
  data: raw,
6553
- ...isRecord5(meta) ? { meta } : {}
6864
+ ...isRecord6(meta) ? { meta } : {}
6554
6865
  },
6555
6866
  metadata: {
6556
6867
  toolId: typeof toolMetadata.toolId === "string" ? toolMetadata.toolId : fallbackToolId,
@@ -6566,7 +6877,7 @@ function toolExecutionEnvelopeToResult(fallbackToolId, response, options) {
6566
6877
  cached: false,
6567
6878
  source: "live"
6568
6879
  },
6569
- meta: isRecord5(response.meta) ? response.meta : void 0
6880
+ meta: isRecord6(response.meta) ? response.meta : void 0
6570
6881
  }),
6571
6882
  options
6572
6883
  );