deepline 0.3.229 → 0.3.231

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.
Files changed (30) hide show
  1. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  2. package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +18 -0
  3. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +19 -0
  4. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +47 -32
  5. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +3 -0
  6. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +38 -2
  7. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/gateway-adapter.ts +8 -3
  8. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +9 -0
  9. package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +39 -0
  10. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +293 -4
  11. package/dist/bundling-sources/shared_libs/play-runtime/run-snapshot-stream.ts +29 -0
  12. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +50 -10
  13. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/progress-sidecar.ts +1 -0
  14. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/local-process.ts +4 -0
  15. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +4 -0
  16. package/dist/bundling-sources/shared_libs/play-runtime/runtime-capacity-policy.ts +187 -14
  17. package/dist/bundling-sources/shared_libs/play-runtime/runtime-work-counters.ts +52 -2
  18. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +5 -0
  19. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +30 -2
  20. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +118 -6
  21. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +135 -21
  22. package/dist/cli/index.js +109 -7
  23. package/dist/cli/index.mjs +109 -7
  24. package/dist/index.js +93 -2
  25. package/dist/index.mjs +93 -2
  26. package/dist/release.d.mts +1 -1
  27. package/dist/release.d.ts +1 -1
  28. package/dist/release.js +1 -1
  29. package/dist/release.mjs +1 -1
  30. package/package.json +1 -1
@@ -79,12 +79,17 @@ import {
79
79
  import type { PlayStaticPipeline } from '../../plays/static-pipeline';
80
80
  import {
81
81
  LOG_TAIL_LIMIT,
82
+ normalizePlayRunLedgerTerminalWorkCounterSegment,
82
83
  type AcceptedPlayRunLedgerEvent,
83
84
  type PlayRunLedgerEvent,
84
85
  type PlayRunLedgerIngressEvent,
86
+ type PlayRunLedgerTerminalWorkCounterSegment,
85
87
  } from '../run-ledger';
86
88
  import { stableStringify } from '../../plays/row-identity';
87
- import { runtimeWorkCountersFromResources } from '../runtime-work-counters';
89
+ import {
90
+ runtimeWorkCountersFromResources,
91
+ runtimeWorkCountersFromStats,
92
+ } from '../runtime-work-counters';
88
93
  import {
89
94
  isCtxFetchHttpFailureDiagnostic,
90
95
  parseCtxFetchHttpFailureDiagnostic,
@@ -9456,6 +9461,28 @@ export type PostgresSchedulerDirectRunnerTerminalOutcome =
9456
9461
  | 'wake_required'
9457
9462
  | 'not_found';
9458
9463
 
9464
+ function terminalWorkCounterSegmentFromRunnerResult(
9465
+ result: unknown,
9466
+ attempt: number,
9467
+ ): PlayRunLedgerTerminalWorkCounterSegment | undefined {
9468
+ if (!result || typeof result !== 'object' || Array.isArray(result)) {
9469
+ return undefined;
9470
+ }
9471
+ const stats = (result as { stats?: unknown }).stats;
9472
+ if (!stats || typeof stats !== 'object' || Array.isArray(stats)) {
9473
+ return undefined;
9474
+ }
9475
+ const segment = (stats as { runtimeWorkCounterSegment?: unknown })
9476
+ .runtimeWorkCounterSegment;
9477
+ if (!segment || typeof segment !== 'object' || Array.isArray(segment)) {
9478
+ return undefined;
9479
+ }
9480
+ return normalizePlayRunLedgerTerminalWorkCounterSegment({
9481
+ ...segment,
9482
+ attempt,
9483
+ });
9484
+ }
9485
+
9459
9486
  /**
9460
9487
  * Reduce an ordinary detached-runner completion at terminal ingress.
9461
9488
  *
@@ -9522,6 +9549,10 @@ export async function directCompletePostgresSchedulerRunnerTerminal(
9522
9549
  input.terminalLogOutbox,
9523
9550
  );
9524
9551
  const runtimeTiming = extractRunnerRuntimeTiming(input.result);
9552
+ const terminalWorkCounterSegment = terminalWorkCounterSegmentFromRunnerResult(
9553
+ input.result,
9554
+ input.attempt,
9555
+ );
9525
9556
  // `workCompletedAtMs` is useful lifecycle telemetry, but it comes from the
9526
9557
  // sandbox process where play code can alter Date.now. Billing must stop on
9527
9558
  // the first database receipt, whose clock and first-write semantics are
@@ -9767,7 +9798,8 @@ export async function directCompletePostgresSchedulerRunnerTerminal(
9767
9798
  'output', $6::jsonb,
9768
9799
  'terminalLogLines', $7::jsonb,
9769
9800
  'terminalProgressEvents', $8::jsonb,
9770
- 'resultSummary', $16::jsonb
9801
+ 'resultSummary', $16::jsonb,
9802
+ 'terminalWorkCounterSegment', $17::jsonb
9771
9803
  ),
9772
9804
  ${causalOutboxCreatedAt('run_terminal.run_id', options)}
9773
9805
  FROM run_terminal
@@ -9802,6 +9834,7 @@ export async function directCompletePostgresSchedulerRunnerTerminal(
9802
9834
  input.engineWake.wakeChannel,
9803
9835
  input.allowCappedCompletion === true,
9804
9836
  stringifyPostgresJson(resultSummary),
9837
+ stringifyPostgresJson(terminalWorkCounterSegment ?? null),
9805
9838
  ],
9806
9839
  );
9807
9840
  if (completed.rows.length > 0) return 'completed';
@@ -11815,6 +11848,7 @@ export async function completePostgresSchedulerAttempt(
11815
11848
  rowOutcomes?: unknown;
11816
11849
  runtimeTiming?: PlayRunnerRuntimeTiming | null;
11817
11850
  terminalLogLines?: readonly string[] | null;
11851
+ terminalWorkCounterSegment?: PlayRunLedgerTerminalWorkCounterSegment;
11818
11852
  },
11819
11853
  options?: Pick<PostgresSchedulerOptions, 'schema'>,
11820
11854
  ): Promise<boolean> {
@@ -12002,7 +12036,8 @@ export async function completePostgresSchedulerAttempt(
12002
12036
  jsonb_build_object(
12003
12037
  'output', $9::jsonb,
12004
12038
  'terminalLogLines', $8::jsonb,
12005
- 'resultSummary', $10::jsonb
12039
+ 'resultSummary', $10::jsonb,
12040
+ 'terminalWorkCounterSegment', $11::jsonb
12006
12041
  ),
12007
12042
  ${causalOutboxCreatedAt('run_terminal.run_id', options)}
12008
12043
  FROM run_terminal
@@ -12024,6 +12059,7 @@ export async function completePostgresSchedulerAttempt(
12024
12059
  JSON.stringify(terminalLogLines),
12025
12060
  stringifyPostgresJson(ledgerTerminalResult ?? null),
12026
12061
  stringifyPostgresJson(resultSummary),
12062
+ stringifyPostgresJson(input.terminalWorkCounterSegment ?? null),
12027
12063
  ],
12028
12064
  );
12029
12065
  if (completed.rows.length === 0) {
@@ -12070,6 +12106,10 @@ export async function failPostgresSchedulerAttempt(
12070
12106
  const resultSummary = terminalRowOutcomesSummary(
12071
12107
  (input.result as { rowOutcomes?: unknown } | null)?.rowOutcomes,
12072
12108
  );
12109
+ const terminalWorkCounterSegment = terminalWorkCounterSegmentFromRunnerResult(
12110
+ input.result,
12111
+ input.attempt,
12112
+ );
12073
12113
  // Keep the recovery tail separate from result: large failures are represented
12074
12114
  // by a result reference, but their customer guidance must still be logged.
12075
12115
  const terminalLogLines = (input.terminalLogLines ?? [])
@@ -12311,7 +12351,8 @@ export async function failPostgresSchedulerAttempt(
12311
12351
  'error', $4::jsonb ->> 'message',
12312
12352
  'result', $8::jsonb,
12313
12353
  'terminalLogLines', $12::jsonb,
12314
- 'resultSummary', $13::jsonb
12354
+ 'resultSummary', $13::jsonb,
12355
+ 'terminalWorkCounterSegment', $14::jsonb
12315
12356
  ),
12316
12357
  ${causalOutboxCreatedAt('run_terminal.run_id', options)}
12317
12358
  FROM run_terminal
@@ -12336,6 +12377,7 @@ export async function failPostgresSchedulerAttempt(
12336
12377
  input.preserveRunnerTerminal === true,
12337
12378
  JSON.stringify(terminalLogLines),
12338
12379
  stringifyPostgresJson(resultSummary),
12380
+ stringifyPostgresJson(terminalWorkCounterSegment ?? null),
12339
12381
  ],
12340
12382
  );
12341
12383
  return failed.rows.length > 0;
@@ -13111,10 +13153,11 @@ export function attachRunnerWorkProgressMetadata(
13111
13153
  // Keep the two scalar counts when the detailed runtimeResources record
13112
13154
  // exceeds its metadata budget. Compact status must not scan a call log to
13113
13155
  // reconstruct physical work.
13114
- const runtimeCounters = runtimeWorkCountersFromResources(
13115
- (runnerResult as { stats?: { runtimeResources?: unknown } }).stats
13116
- ?.runtimeResources,
13117
- );
13156
+ const stats = (runnerResult as { stats?: { runtimeResources?: unknown } })
13157
+ .stats;
13158
+ const runtimeCounters =
13159
+ runtimeWorkCountersFromStats(stats) ??
13160
+ runtimeWorkCountersFromResources(stats?.runtimeResources);
13118
13161
  const outputWarnings = Array.isArray(
13119
13162
  (runnerResult as { outputWarnings?: unknown }).outputWarnings,
13120
13163
  )
@@ -13294,6 +13337,10 @@ export async function executePostgresSchedulerClaim(
13294
13337
  output: terminalOutput,
13295
13338
  rowOutcomes: (output as { rowOutcomes?: unknown } | null)?.rowOutcomes,
13296
13339
  runtimeTiming: extractRunnerRuntimeTiming(output),
13340
+ terminalWorkCounterSegment: terminalWorkCounterSegmentFromRunnerResult(
13341
+ output,
13342
+ claim.attempt,
13343
+ ),
13297
13344
  terminalLogLines: terminalLogLinesForOutbox(
13298
13345
  output,
13299
13346
  options.terminalLogOutbox,
@@ -16928,6 +16975,10 @@ export function buildRunLedgerEventsFromPostgresSchedulerOutbox(
16928
16975
  ];
16929
16976
  }
16930
16977
  if (event.eventType === 'run.completed') {
16978
+ const terminalWorkCounterSegment =
16979
+ normalizePlayRunLedgerTerminalWorkCounterSegment(
16980
+ payloadField(event.payload, 'terminalWorkCounterSegment'),
16981
+ );
16931
16982
  const progressEvents = ledgerEventsPayloadField(
16932
16983
  event.payload,
16933
16984
  'terminalProgressEvents',
@@ -16953,6 +17004,7 @@ export function buildRunLedgerEventsFromPostgresSchedulerOutbox(
16953
17004
  runId: event.runId,
16954
17005
  occurredAt,
16955
17006
  source: 'system',
17007
+ ...(terminalWorkCounterSegment ? { terminalWorkCounterSegment } : {}),
16956
17008
  result: terminalRunResultForLedger(
16957
17009
  payloadField(event.payload, 'output'),
16958
17010
  ),
@@ -16963,6 +17015,10 @@ export function buildRunLedgerEventsFromPostgresSchedulerOutbox(
16963
17015
  ];
16964
17016
  }
16965
17017
  if (event.eventType === 'run.failed') {
17018
+ const terminalWorkCounterSegment =
17019
+ normalizePlayRunLedgerTerminalWorkCounterSegment(
17020
+ payloadField(event.payload, 'terminalWorkCounterSegment'),
17021
+ );
16966
17022
  const progressEvents = ledgerEventsPayloadField(
16967
17023
  event.payload,
16968
17024
  'terminalProgressEvents',
@@ -16991,6 +17047,7 @@ export function buildRunLedgerEventsFromPostgresSchedulerOutbox(
16991
17047
  runId: event.runId,
16992
17048
  occurredAt,
16993
17049
  source: 'system',
17050
+ ...(terminalWorkCounterSegment ? { terminalWorkCounterSegment } : {}),
16994
17051
  error: stringPayloadField(event.payload, 'error'),
16995
17052
  ...(result === null || result === undefined ? {} : { result }),
16996
17053
  ...(resultSummary === undefined || resultSummary === null
@@ -17210,17 +17267,18 @@ export async function listPostgresSchedulerOutboxMaterializationPlans(
17210
17267
  }
17211
17268
 
17212
17269
  /**
17213
- * Where the projector gets its runtime-API executor token when one is not
17214
- * supplied per-event via `runtimeApi`.
17270
+ * Where the projector gets its runtime-API executor token.
17215
17271
  *
17216
17272
  * - `local_mint`: sign the token in-process with `BETTER_AUTH_SECRET`. ONLY the
17217
17273
  * app (Vercel) legitimately holds the signing key, so this is app-side only
17218
17274
  * (read-model heal path). It is the AUTHORITATIVE projector.
17219
- * - `gateway`: prove the active outbox lease to the launch-pinned deployment and
17220
- * receive a short-lived executor JWT (`requestRunLedgerDispatchToken`). The
17221
- * Fly worker has no signing key and MUST
17222
- * use this. Delivery failures use the same structured retry-or-block policy
17223
- * as the app-side projector.
17275
+ * - `gateway`: always prove the active outbox lease to the launch-pinned
17276
+ * deployment and receive a short-lived executor JWT
17277
+ * (`requestRunLedgerDispatchToken`), even if the caller supplied a
17278
+ * `runtimeApi`. The Fly worker has no signing key and MUST use this. A
17279
+ * supplied context contributes transport options only; its executor token
17280
+ * cannot bypass the lease-scoped gateway hop. Delivery failures use the same
17281
+ * structured retry-or-block policy as the app-side projector.
17224
17282
  *
17225
17283
  * Explicit by design: the old code sniffed `process.env.BETTER_AUTH_SECRET` to
17226
17284
  * pick the branch, so the worker's projection silently depended on the secret
@@ -17262,15 +17320,20 @@ export function postgresSchedulerCancellationOutboxLease(runId: string): {
17262
17320
  }
17263
17321
 
17264
17322
  export type RunLedgerOutboxDispatchInput = {
17323
+ /**
17324
+ * Optional runtime context. `gateway` authority always replaces its
17325
+ * credentials with a fresh lease-scoped token and keeps only supported
17326
+ * transport options; `local_mint` and the default authority preserve the
17327
+ * explicit context as before.
17328
+ */
17265
17329
  runtimeApi?: WorkerRuntimeApiContext | null;
17266
17330
  limit?: number;
17267
17331
  runId?: string | null;
17268
17332
  leaseOwner?: string | null;
17269
17333
  leaseSeconds?: number;
17270
17334
  /**
17271
- * Token authority for events without a per-event `runtimeApi`. Defaults to
17272
- * `local_mint` for the app-side authoritative projector. The Fly worker MUST
17273
- * pass `gateway`.
17335
+ * Token authority for the outbox dispatch. Defaults to `local_mint` for the
17336
+ * app-side authoritative projector. The Fly worker MUST pass `gateway`.
17274
17337
  */
17275
17338
  tokenAuthority?: RunLedgerOutboxTokenAuthority;
17276
17339
  };
@@ -17568,7 +17631,24 @@ export async function dispatchRunLedgerOutboxToLedgerBatchOnceWithClientScope(
17568
17631
 
17569
17632
  try {
17570
17633
  const first = events[0]!;
17634
+ const tokenAuthority = input.tokenAuthority ?? 'local_mint';
17635
+ const gatewayRuntimeApi =
17636
+ tokenAuthority === 'gateway'
17637
+ ? await withClient((client) =>
17638
+ loadPostgresSchedulerRuntimeApiForRun(
17639
+ client,
17640
+ first.runId,
17641
+ first.leaseOwner
17642
+ ? { eventId: first.eventId, leaseOwner: first.leaseOwner }
17643
+ : null,
17644
+ tokenAuthority,
17645
+ options,
17646
+ input.runtimeApi?.signal,
17647
+ ),
17648
+ )
17649
+ : null;
17571
17650
  const resolvedRuntimeApi =
17651
+ gatewayRuntimeApi ??
17572
17652
  input.runtimeApi ??
17573
17653
  (await withClient((client) =>
17574
17654
  loadPostgresSchedulerRuntimeApiForRun(
@@ -17577,11 +17657,36 @@ export async function dispatchRunLedgerOutboxToLedgerBatchOnceWithClientScope(
17577
17657
  first.leaseOwner
17578
17658
  ? { eventId: first.eventId, leaseOwner: first.leaseOwner }
17579
17659
  : null,
17580
- input.tokenAuthority ?? 'local_mint',
17660
+ tokenAuthority,
17581
17661
  options,
17582
17662
  ),
17583
17663
  ));
17584
- const runtimeApi = { ...resolvedRuntimeApi, retryPolicy: 'none' as const };
17664
+ const runtimeApi = {
17665
+ ...resolvedRuntimeApi,
17666
+ ...(gatewayRuntimeApi && input.runtimeApi
17667
+ ? {
17668
+ ...(input.runtimeApi.fetch
17669
+ ? { fetch: input.runtimeApi.fetch }
17670
+ : {}),
17671
+ ...(input.runtimeApi.requestTimeoutMs !== undefined
17672
+ ? { requestTimeoutMs: input.runtimeApi.requestTimeoutMs }
17673
+ : {}),
17674
+ ...(input.runtimeApi.onResponseMeta
17675
+ ? { onResponseMeta: input.runtimeApi.onResponseMeta }
17676
+ : {}),
17677
+ ...(input.runtimeApi.runtimeTestFaultHeader !== undefined
17678
+ ? {
17679
+ runtimeTestFaultHeader:
17680
+ input.runtimeApi.runtimeTestFaultHeader,
17681
+ }
17682
+ : {}),
17683
+ ...(input.runtimeApi.signal
17684
+ ? { signal: input.runtimeApi.signal }
17685
+ : {}),
17686
+ }
17687
+ : {}),
17688
+ retryPolicy: 'none' as const,
17689
+ };
17585
17690
  const renewDelivery = () =>
17586
17691
  withClient((client) =>
17587
17692
  renewPostgresRunLedgerDelivery(
@@ -17839,6 +17944,7 @@ async function loadPostgresSchedulerRuntimeApiForRun(
17839
17944
  dispatchLease: { eventId: string; leaseOwner: string } | null,
17840
17945
  tokenAuthority: RunLedgerOutboxTokenAuthority,
17841
17946
  options?: Pick<PostgresSchedulerOptions, 'schema'>,
17947
+ signal?: AbortSignal,
17842
17948
  ): Promise<WorkerRuntimeApiContext> {
17843
17949
  const result = await client.query<{ launch_json: unknown }>(
17844
17950
  `
@@ -17879,6 +17985,7 @@ async function loadPostgresSchedulerRuntimeApiForRun(
17879
17985
  eventId: dispatchLease.eventId,
17880
17986
  leaseOwner: dispatchLease.leaseOwner,
17881
17987
  schedulerSchema: options?.schema ?? null,
17988
+ signal,
17882
17989
  });
17883
17990
  }
17884
17991
  return {
@@ -17893,6 +18000,7 @@ async function requestRunLedgerDispatchToken(input: {
17893
18000
  eventId: string;
17894
18001
  leaseOwner: string;
17895
18002
  schedulerSchema: string | null;
18003
+ signal?: AbortSignal;
17896
18004
  }): Promise<string> {
17897
18005
  const internalToken = process.env.DEEPLINE_INTERNAL_TOKEN?.trim();
17898
18006
  if (!internalToken || !input.eventId || !input.leaseOwner) {
@@ -17904,10 +18012,16 @@ async function requestRunLedgerDispatchToken(input: {
17904
18012
  const vercelProtectionHeaders = await vercelProtectionBypassHeaders({
17905
18013
  baseUrl: runtimeApiBaseUrlFromLaunch(input.launch),
17906
18014
  token: input.launch.vercelProtectionBypassToken,
18015
+ signal: input.signal,
17907
18016
  });
17908
18017
  const response = await fetch(url, {
17909
18018
  method: 'POST',
17910
- signal: AbortSignal.timeout(RUN_LEDGER_DISPATCH_TOKEN_TIMEOUT_MS),
18019
+ signal: input.signal
18020
+ ? AbortSignal.any([
18021
+ input.signal,
18022
+ AbortSignal.timeout(RUN_LEDGER_DISPATCH_TOKEN_TIMEOUT_MS),
18023
+ ])
18024
+ : AbortSignal.timeout(RUN_LEDGER_DISPATCH_TOKEN_TIMEOUT_MS),
17911
18025
  headers: {
17912
18026
  'content-type': 'application/json',
17913
18027
  'x-deepline-internal-token': internalToken,
package/dist/cli/index.js CHANGED
@@ -3051,7 +3051,7 @@ var SDK_RELEASE = {
3051
3051
  // getters keep their established compatibility behavior.
3052
3052
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3053
3053
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3054
- version: "0.3.229",
3054
+ version: "0.3.231",
3055
3055
  updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
3056
3056
  packageCapabilities: {
3057
3057
  updatePreferences: 1
@@ -5384,12 +5384,84 @@ function normalizeDatasetBornFrom(value) {
5384
5384
 
5385
5385
  // ../play-runtime/run-ledger.ts
5386
5386
  var LOG_TAIL_LIMIT = 100;
5387
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
5388
+ "completed",
5389
+ "failed",
5390
+ "cancelled",
5391
+ "terminated",
5392
+ "timed_out"
5393
+ ]);
5387
5394
  function isRecord5(value) {
5388
5395
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
5389
5396
  }
5390
5397
  function finiteNumber(value) {
5391
5398
  return typeof value === "number" && Number.isFinite(value) ? value : null;
5392
5399
  }
5400
+ function nonnegativeSafeInteger(value) {
5401
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
5402
+ }
5403
+ function isWorkCounterSegmentId(value) {
5404
+ return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(
5405
+ value
5406
+ );
5407
+ }
5408
+ function normalizePlayRunLedgerTerminalWorkCounterSegment(value) {
5409
+ if (!isRecord5(value)) return void 0;
5410
+ if (!nonnegativeSafeInteger(value.attempt) || !nonnegativeSafeInteger(value.invocationSeq) || value.invocationSeq === 0 || !isWorkCounterSegmentId(value.segmentId)) {
5411
+ return void 0;
5412
+ }
5413
+ return {
5414
+ attempt: value.attempt,
5415
+ invocationSeq: value.invocationSeq,
5416
+ segmentId: value.segmentId
5417
+ };
5418
+ }
5419
+ function hasConfirmedPlayRunLedgerWorkCounters(snapshot) {
5420
+ const counters = snapshot.workCounters;
5421
+ const terminal = snapshot.terminalWorkCounterSegment;
5422
+ return Boolean(
5423
+ isTerminalPlayRunLedgerStatus(snapshot.status) && (snapshot.terminalSource === "worker" || snapshot.terminalSource === "system") && counters?.final && counters.completeThroughAttempt && counters.consistent && terminal && counters.attempt === terminal.attempt && counters.invocationSeq === terminal.invocationSeq && counters.segmentId === terminal.segmentId && Number.isSafeInteger(
5424
+ counters.completedLogicalCalls + counters.logicalCalls
5425
+ ) && Number.isSafeInteger(
5426
+ counters.completedProviderRequests + counters.providerRequests
5427
+ ) && Number.isSafeInteger(
5428
+ counters.completedProvider429s + counters.provider429s
5429
+ )
5430
+ );
5431
+ }
5432
+ function normalizeWorkCounters(value) {
5433
+ if (!isRecord5(value)) return void 0;
5434
+ for (const field of [
5435
+ "attempt",
5436
+ "invocationSeq",
5437
+ "logicalCalls",
5438
+ "providerRequests",
5439
+ "provider429s",
5440
+ "completedLogicalCalls",
5441
+ "completedProviderRequests",
5442
+ "completedProvider429s"
5443
+ ]) {
5444
+ if (!nonnegativeSafeInteger(value[field])) return void 0;
5445
+ }
5446
+ if (value.invocationSeq === 0 || !isWorkCounterSegmentId(value.segmentId) || typeof value.final !== "boolean" || typeof value.completeThroughAttempt !== "boolean" || typeof value.consistent !== "boolean") {
5447
+ return void 0;
5448
+ }
5449
+ return {
5450
+ ...value,
5451
+ attempt: value.attempt,
5452
+ invocationSeq: value.invocationSeq,
5453
+ segmentId: value.segmentId,
5454
+ logicalCalls: value.logicalCalls,
5455
+ providerRequests: value.providerRequests,
5456
+ provider429s: value.provider429s,
5457
+ final: value.final,
5458
+ completedLogicalCalls: value.completedLogicalCalls,
5459
+ completedProviderRequests: value.completedProviderRequests,
5460
+ completedProvider429s: value.completedProvider429s,
5461
+ completeThroughAttempt: value.completeThroughAttempt,
5462
+ consistent: value.consistent
5463
+ };
5464
+ }
5393
5465
  function optionalFiniteNumber(value) {
5394
5466
  const normalized = finiteNumber(value);
5395
5467
  return normalized === null ? void 0 : normalized;
@@ -5431,6 +5503,9 @@ function normalizePlayRunLedgerStatus(value) {
5431
5503
  return "unknown";
5432
5504
  }
5433
5505
  }
5506
+ function isTerminalPlayRunLedgerStatus(status) {
5507
+ return TERMINAL_STATUSES.has(status);
5508
+ }
5434
5509
  function summarizeRunRowOutcomes(snapshot) {
5435
5510
  let completedRows = 0;
5436
5511
  let failedRows = 0;
@@ -5565,6 +5640,10 @@ function normalizePlayRunLedgerSnapshot(value, fallback) {
5565
5640
  const error = Object.prototype.hasOwnProperty.call(value, "error") ? optionalNullableString(value.error) ?? null : fallback.error ?? null;
5566
5641
  const rawTail = Array.isArray(value.logTail) ? value.logTail : value.logs;
5567
5642
  const logTail = Array.isArray(rawTail) ? rawTail.filter((line) => typeof line === "string") : [];
5643
+ const workCounters = normalizeWorkCounters(value.workCounters);
5644
+ const terminalWorkCounterSegment = normalizePlayRunLedgerTerminalWorkCounterSegment(
5645
+ value.terminalWorkCounterSegment
5646
+ );
5568
5647
  return {
5569
5648
  runId: optionalString(value.runId) ?? fallback.runId,
5570
5649
  playName: optionalNullableString(value.playName) ?? fallback.playName ?? null,
@@ -5587,6 +5666,8 @@ function normalizePlayRunLedgerSnapshot(value, fallback) {
5587
5666
  (activityId) => typeof activityId === "string" && Boolean(activitiesById[activityId])
5588
5667
  ),
5589
5668
  activitiesById,
5669
+ ...workCounters ? { workCounters } : {},
5670
+ ...terminalWorkCounterSegment ? { terminalWorkCounterSegment } : {},
5590
5671
  logTail: logTail.slice(-LOG_TAIL_LIMIT),
5591
5672
  // Snapshots persisted before totalLogCount existed only know the retained
5592
5673
  // tail, so the best lower bound for the cumulative count is the tail size.
@@ -5894,6 +5975,13 @@ function buildSnapshotFromLedger(snapshot) {
5894
5975
  const liveStatus = normalizePlayRunLiveStatus(snapshot.status);
5895
5976
  const terminalRowOutcomes = isTerminalPlayRunLiveStatus(liveStatus) ? summarizeRunRowOutcomes(snapshot) : null;
5896
5977
  const rowOutcomes = terminalRowOutcomes && (Object.keys(snapshot.stepsById).length > 0 || terminalRowOutcomes.totalRows > 0 || (terminalRowOutcomes.supersededRows ?? 0) > 0) ? terminalRowOutcomes : null;
5978
+ const workCounters = snapshot.workCounters;
5979
+ const calls = workCounters ? {
5980
+ logicalCalls: workCounters.completedLogicalCalls + workCounters.logicalCalls,
5981
+ providerRequests: workCounters.completedProviderRequests + workCounters.providerRequests,
5982
+ provider429s: workCounters.completedProvider429s + workCounters.provider429s,
5983
+ confirmed: isTerminalPlayRunLiveStatus(liveStatus) && hasConfirmedPlayRunLedgerWorkCounters(snapshot)
5984
+ } : null;
5897
5985
  return {
5898
5986
  runId: snapshot.runId,
5899
5987
  status: liveStatus,
@@ -5918,7 +6006,10 @@ function buildSnapshotFromLedger(snapshot) {
5918
6006
  activeActivity: snapshot.activeActivityId ? snapshot.activitiesById[snapshot.activeActivityId] ?? null : null,
5919
6007
  nodeStates,
5920
6008
  activeNodeId: snapshot.activeStepId ?? null,
5921
- ...rowOutcomes ? { rowOutcomes } : {}
6009
+ ...rowOutcomes ? { rowOutcomes } : {},
6010
+ ...calls && Object.values(calls).every(
6011
+ (value) => typeof value === "boolean" || Number.isSafeInteger(value)
6012
+ ) ? { calls } : {}
5922
6013
  };
5923
6014
  }
5924
6015
  function buildPlayRunStatusSnapshot(input2) {
@@ -25044,6 +25135,15 @@ function getProgressLinesFromLiveEvent(event) {
25044
25135
  `progress ${formatProgressLabel(record3.nodeId ?? progress.artifactTableNamespace)}: ${counts}${messageSuffix}`
25045
25136
  );
25046
25137
  }
25138
+ const calls = readRecord(payload.calls);
25139
+ const callCounts = calls ? [calls.logicalCalls, calls.providerRequests, calls.provider429s] : [];
25140
+ if (callCounts.length === 3 && callCounts.every(
25141
+ (count) => typeof count === "number" && Number.isSafeInteger(count) && count >= 0
25142
+ )) {
25143
+ lines.push(
25144
+ `progress calls: ${formatInteger(callCounts[0])} logical, ${formatInteger(callCounts[1])} provider requests, ${formatInteger(callCounts[2])} provider 429s${calls?.confirmed === true ? "" : " (observed)"}`
25145
+ );
25146
+ }
25047
25147
  const rowOutcomes = readRowOutcomeSummary({
25048
25148
  rowOutcomes: payload.rowOutcomes
25049
25149
  });
@@ -50084,7 +50184,7 @@ async function searchTools(queryInput, options = {}) {
50084
50184
  tools: result.tools.slice(0, 8).map(compactTool)
50085
50185
  } : result;
50086
50186
  printCommandEnvelope(payload, {
50087
- json: options.json || shouldEmitJson()
50187
+ json: options.json === true
50088
50188
  });
50089
50189
  return 0;
50090
50190
  }
@@ -50313,11 +50413,13 @@ Notes:
50313
50413
  Use a provider name in the query; --prefix is not a supported option.
50314
50414
  The grep alias is the same ranked retrieval surface with a more literal name
50315
50415
  for agents that are filtering a registry rather than choosing a workflow.
50416
+ Search prints a readable result list by default, piped or not, and that is
50417
+ the recommended form. Pass --json only when a program parses the result.
50316
50418
 
50317
50419
  Examples:
50318
- deepline tools search email --limit 10 --json
50319
- deepline tools search email --limit 10 --offset 10 --json
50320
- deepline tools search linkedin --task "I have 200 LinkedIn profile URLs and need each person's current title and company" --json
50420
+ deepline tools search email --limit 10
50421
+ deepline tools search email --limit 10 --offset 10
50422
+ deepline tools search linkedin --task "I have 200 LinkedIn profile URLs and need each person's current title and company"
50321
50423
  deepline tools search --categories company_search --search_terms "investors,funding"
50322
50424
  deepline tools grep "company enrichment" --categories enrichment --json
50323
50425
  deepline tools search verifier --search-mode v2 --json
@@ -50331,7 +50433,7 @@ Examples:
50331
50433
  ).option("--search-terms <terms>", "Alias for --search_terms").option(
50332
50434
  "--task <sentence>",
50333
50435
  "What you are trying to accomplish: input you have -> result you need"
50334
- ).option("--limit <count>", "Maximum ranked results to return (1-50)").option("--offset <count>", "Zero-based ranked result offset").option("--search-mode <mode>", "Ranked search mode: v1 or v2").option("--include-search-debug", "Include ranked search debug metadata").option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
50436
+ ).option("--limit <count>", "Maximum ranked results to return (1-50)").option("--offset <count>", "Zero-based ranked result offset").option("--search-mode <mode>", "Ranked search mode: v1 or v2").option("--include-search-debug", "Include ranked search debug metadata").option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output instead of the readable default").action(async (query, options) => {
50335
50437
  process.exitCode = await searchTools(query, {
50336
50438
  json: options.json,
50337
50439
  compact: options.compact,