deepline 0.1.318 → 0.1.320

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.
@@ -1862,7 +1862,9 @@ function attachSdkQueryResultDatasetResult(
1862
1862
  }
1863
1863
  const datasetLimit =
1864
1864
  finitePositiveInteger(dataset.returned_limit) ?? totalRows;
1865
- const previewRows = rowsFromUnknown(raw?.rows).slice(0, 25);
1865
+ const effectiveCount = Math.min(totalRows, datasetLimit);
1866
+ const rawRows = rowsFromUnknown(raw?.rows);
1867
+ const previewRows = rawRows.slice(0, 25);
1866
1868
  const fetchPage = async (
1867
1869
  offset: number,
1868
1870
  limit: number,
@@ -1927,10 +1929,15 @@ function attachSdkQueryResultDatasetResult(
1927
1929
  datasetId: `sdk-tool-list:${toolId}:${stableHash(datasetScope)}:${datasetLimit}:${safeNonce}`,
1928
1930
  count: Math.min(totalRows, datasetLimit),
1929
1931
  previewRows,
1932
+ residentRows:
1933
+ rawRows.length >= effectiveCount
1934
+ ? rawRows.slice(0, effectiveCount)
1935
+ : null,
1930
1936
  sourceLabel: 'query result rows',
1931
1937
  tableNamespace: null,
1932
1938
  resolvers: {
1933
1939
  count: async () => Math.min(totalRows, datasetLimit),
1940
+ at: async (index) => (await fetchPage(index, 1))[0],
1934
1941
  peek: async (limit) => collectRows(limit),
1935
1942
  materialize: async (limit) => collectRows(limit),
1936
1943
  iterate: () =>
@@ -157,7 +157,7 @@ export const SDK_RELEASE = {
157
157
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
158
158
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
159
159
  // Operators use the checkout-local deepline-admin binary instead.
160
- version: '0.1.318',
160
+ version: '0.1.320',
161
161
  contracts: {
162
162
  api: {
163
163
  name: 'sdk-http-api',
@@ -276,16 +276,30 @@ export interface ToolDefinition {
276
276
  }>;
277
277
  /**
278
278
  * Whether this tool is callable in the current workspace. `false` for a
279
- * bring-your-own-credential provider (e.g. Apollo) that has not been
280
- * connected — the agent should offer to connect it rather than call it.
279
+ * bring-your-own-credential provider that has not been connected.
281
280
  */
282
281
  connected?: boolean;
282
+ /** Whether the tool can be executed. Exact lookup may return non-callable deprecated aliases. */
283
+ callable?: boolean;
284
+ /** True when callers should migrate this exact tool id to its replacement. */
285
+ deprecated?: boolean;
286
+ /** Deprecation reason, replacement, and compatibility execution behavior. */
287
+ deprecation?: {
288
+ replacementToolId: string;
289
+ message: string;
290
+ execution?: 'terminal' | 'forward';
291
+ };
283
292
  /**
284
293
  * Connection status for discovery: `managed` (Deepline-run credentials),
285
294
  * `connected` (your own credential is connected), or `requires_connection`
286
- * (BYO provider not yet connected in this workspace).
295
+ * (BYO provider not yet connected in this workspace). `deprecated` means
296
+ * connecting credentials will not make the tool callable.
287
297
  */
288
- credentialStatus?: 'managed' | 'connected' | 'requires_connection';
298
+ credentialStatus?:
299
+ | 'managed'
300
+ | 'connected'
301
+ | 'requires_connection'
302
+ | 'deprecated';
289
303
  /** True when the tool requires a customer-provided credential to run. */
290
304
  requiresOwnCredential?: boolean;
291
305
  /** Actionable message shown when a connection is required. */
@@ -3658,6 +3658,7 @@ export class PlayContextImpl {
3658
3658
  const originalRequestInput = requestInput as Record<string, unknown>;
3659
3659
  const datasetLimit =
3660
3660
  finitePositiveInteger(dataset.returned_limit) ?? totalRows;
3661
+ const effectiveCount = Math.min(totalRows, datasetLimit);
3661
3662
  const previewRows = rows.slice(0, Math.min(rows.length, 25));
3662
3663
  const executionNonce =
3663
3664
  typeof wrapped.job_id === 'string' && wrapped.job_id.trim()
@@ -3718,12 +3719,15 @@ export class PlayContextImpl {
3718
3719
  const playDataset = createDeferredPlayDataset({
3719
3720
  datasetKind: 'csv',
3720
3721
  datasetId,
3721
- count: Math.min(totalRows, datasetLimit),
3722
+ count: effectiveCount,
3722
3723
  previewRows,
3724
+ residentRows:
3725
+ rows.length >= effectiveCount ? rows.slice(0, effectiveCount) : null,
3723
3726
  sourceLabel: 'query result rows',
3724
3727
  tableNamespace: null,
3725
3728
  resolvers: {
3726
3729
  count: async () => Math.min(totalRows, datasetLimit),
3730
+ at: async (index) => (await fetchPage(index, 1))[0],
3727
3731
  peek: async (limit) => collectRows(limit),
3728
3732
  materialize: async (limit) => collectRows(limit),
3729
3733
  iterate: () =>
@@ -4803,6 +4807,10 @@ export class PlayContextImpl {
4803
4807
  },
4804
4808
  },
4805
4809
  previewRows,
4810
+ residentRows:
4811
+ immediateMaterializedRows.length === successfulCount
4812
+ ? immediateMaterializedRows
4813
+ : null,
4806
4814
  tableNamespace: resolvedTableNamespace,
4807
4815
  workProgress: {
4808
4816
  total: totalInputCount,
@@ -5417,6 +5425,7 @@ export class PlayContextImpl {
5417
5425
  previewRows: results
5418
5426
  .slice(0, 5)
5419
5427
  .map((row) => this.toMaterializedOutputRow(row)),
5428
+ residentRows: terminalRows,
5420
5429
  tableNamespace: resolvedTableNamespace,
5421
5430
  workProgress: {
5422
5431
  total: totalInputCount,
@@ -8139,7 +8139,8 @@ export function createRuntimeBackedPlayDataset(input: {
8139
8139
  }): PlayDataset<Record<string, unknown>> {
8140
8140
  const csvRows =
8141
8141
  input.datasetKind === 'csv' &&
8142
- (input.initialPreviewRows?.length ?? 0) >= (input.initialCount ?? 0)
8142
+ typeof input.initialCount === 'number' &&
8143
+ (input.initialPreviewRows?.length ?? 0) >= input.initialCount
8143
8144
  ? [...(input.initialPreviewRows ?? [])]
8144
8145
  : null;
8145
8146
  if (csvRows) {
@@ -8151,6 +8152,7 @@ export function createRuntimeBackedPlayDataset(input: {
8151
8152
  ),
8152
8153
  count: input.initialCount ?? csvRows.length,
8153
8154
  previewRows: csvRows.slice(0, 10),
8155
+ residentRows: csvRows,
8154
8156
  sourceLabel: input.sourceLabel ?? null,
8155
8157
  resolvers: {
8156
8158
  count: async () => csvRows.length,
@@ -8181,6 +8183,7 @@ export function createRuntimeBackedPlayDataset(input: {
8181
8183
  input.tableNamespace,
8182
8184
  ),
8183
8185
  count: input.initialCount ?? 0,
8186
+ knownCount: input.initialCount ?? null,
8184
8187
  backing: {
8185
8188
  storage: 'neon_sheet',
8186
8189
  sheet: {
@@ -8222,6 +8225,22 @@ export function createRuntimeBackedPlayDataset(input: {
8222
8225
  );
8223
8226
  return rows.map((row) => row.data);
8224
8227
  },
8228
+ at: async (index) => {
8229
+ const session = await getRuntimeDbSession(runtimeContext, {
8230
+ tableNamespace: input.tableNamespace,
8231
+ logicalTable: 'sheet_rows',
8232
+ operations: ['rows.read'],
8233
+ });
8234
+ const rows = await readRuntimeRows(
8235
+ requireRuntimePostgresSession(session),
8236
+ {
8237
+ limit: 1,
8238
+ offset: index,
8239
+ runId: input.runId ?? null,
8240
+ },
8241
+ );
8242
+ return rows[0]?.data;
8243
+ },
8225
8244
  materialize: async (limit) => {
8226
8245
  const pageSize = 1000;
8227
8246
  const materialized: Record<string, unknown>[] = [];
@@ -42,6 +42,7 @@ import {
42
42
  createDeferredPlayDataset,
43
43
  createPlayDataset,
44
44
  isSerializedPlayDataset,
45
+ residentPlayDatasetRows,
45
46
  trimSerializedPlayDatasetPreview,
46
47
  type PlayDataset,
47
48
  type SerializedPlayDataset,
@@ -1395,6 +1396,15 @@ function serializedListRowsFromResult(input: {
1395
1396
  ]);
1396
1397
  const entries = [...names].flatMap((name) => {
1397
1398
  const dataset = input.listDatasets?.[name];
1399
+ const liveDataset = input.value.extractedLists[name]?.get();
1400
+ const residentRows = liveDataset
1401
+ ? residentPlayDatasetRows(liveDataset)
1402
+ : null;
1403
+ if (residentRows && (!dataset || residentRows.length >= dataset.count)) {
1404
+ return [
1405
+ [name, [...residentRows] as Array<Record<string, unknown>>] as const,
1406
+ ];
1407
+ }
1398
1408
  const preservedRows = preserved?.[name];
1399
1409
  if (preservedRows && (!dataset || preservedRows.length >= dataset.count)) {
1400
1410
  return [[name, preservedRows]] as const;
@@ -1509,6 +1519,7 @@ function createDatasetFromSerializedToolList(
1509
1519
  count: serialized.count,
1510
1520
  backing: serialized.backing,
1511
1521
  previewRows: preview,
1522
+ residentRows: isPartialPreview ? null : sourceRows,
1512
1523
  sourceLabel: serialized.sourceLabel ?? null,
1513
1524
  tableNamespace: serialized.tableNamespace ?? null,
1514
1525
  workProgress: serialized._metadata?.workProgress,
@@ -2,6 +2,7 @@ import type { PlayExecutionFileRef } from './file-refs';
2
2
 
3
3
  const PLAY_DATASET_BRAND = Symbol.for('deepline.play.dataset');
4
4
  const NODE_INSPECT_CUSTOM = Symbol.for('nodejs.util.inspect.custom');
5
+ const residentRowsByDataset = new WeakMap<object, readonly unknown[]>();
5
6
  const DEFAULT_MATERIALIZE_LIMIT = 10_000;
6
7
  export const PLAY_DATASET_EXECUTION_PAGE_ROWS = 1_000;
7
8
  export const PLAY_DATASET_EXECUTION_PAGE_BYTES = 64 * 1024 * 1024;
@@ -109,8 +110,12 @@ export type PlayDatasetTransformOptions = {
109
110
  *
110
111
  * @sdkReference runtime 190
111
112
  */
112
- export interface PlayDataset<T> extends AsyncIterable<T> {
113
+ export interface PlayDataset<T> extends AsyncIterable<T>, Iterable<T> {
113
114
  readonly [PLAY_DATASET_BRAND]: true;
115
+ /** Authoritative row count when known without I/O. */
116
+ readonly length: number;
117
+ /** Resident row access. Throws when the requested row requires I/O. */
118
+ readonly [index: number]: T;
114
119
  /** Dataset kind. */
115
120
  readonly datasetKind: PlayDatasetKind;
116
121
  /** Dataset id. */
@@ -125,6 +130,10 @@ export interface PlayDataset<T> extends AsyncIterable<T> {
125
130
  count(): Promise<number>;
126
131
  /** Preview rows. */
127
132
  peek(limit?: number): Promise<T[]>;
133
+ /** First row, loading it asynchronously when necessary. */
134
+ first(): Promise<T | undefined>;
135
+ /** Row at an array-style index, loading it asynchronously when necessary. */
136
+ at(index: number): Promise<T | undefined>;
128
137
  map<U>(
129
138
  mapper: (row: T, index: number) => U | Promise<U>,
130
139
  options?: PlayDatasetTransformOptions,
@@ -164,6 +173,7 @@ export interface PlayDataset<T> extends AsyncIterable<T> {
164
173
  type PlayDatasetResolvers<T> = {
165
174
  count: () => Promise<number>;
166
175
  peek: (limit: number) => Promise<T[]>;
176
+ at?: (index: number) => Promise<T | undefined>;
167
177
  materialize: (limit?: number) => Promise<T[]>;
168
178
  materializeFullPersistedDataset?: (limit?: number) => Promise<T[]>;
169
179
  iterate: () => AsyncIterable<T>;
@@ -223,6 +233,13 @@ export function isPlayDataset<T>(value: unknown): value is PlayDataset<T> {
223
233
  );
224
234
  }
225
235
 
236
+ /** Internal compatibility view for preserving proven-complete rows on replay. */
237
+ export function residentPlayDatasetRows<T>(
238
+ dataset: PlayDataset<T>,
239
+ ): readonly T[] | null {
240
+ return (residentRowsByDataset.get(dataset as object) as readonly T[]) ?? null;
241
+ }
242
+
226
243
  export function isSerializedPlayDataset<T>(
227
244
  value: unknown,
228
245
  ): value is SerializedPlayDataset<T> {
@@ -317,6 +334,7 @@ export function deserializePlayDatasetCell<T>(
317
334
  count: rows.length,
318
335
  backing: dataset.backing,
319
336
  previewRows: rows.slice(0, 10),
337
+ residentRows: rows,
320
338
  sourceLabel: dataset.sourceLabel ?? null,
321
339
  tableNamespace: dataset.tableNamespace ?? null,
322
340
  workProgress: dataset._metadata?.workProgress,
@@ -355,6 +373,7 @@ export function deserializeLegacyPlayDataset<T>(
355
373
  count: dataset.count,
356
374
  backing: dataset.backing,
357
375
  previewRows: rows,
376
+ residentRows: complete ? rows : null,
358
377
  sourceLabel: dataset.sourceLabel ?? null,
359
378
  tableNamespace: dataset.tableNamespace ?? null,
360
379
  workProgress: dataset._metadata?.workProgress,
@@ -394,6 +413,7 @@ export function trimSerializedPlayDatasetPreview<T>(
394
413
  }
395
414
 
396
415
  class DeferredPlayDataset<T> implements PlayDataset<T> {
416
+ readonly [index: number]: T;
397
417
  readonly [PLAY_DATASET_BRAND] = true as const;
398
418
  readonly datasetKind: PlayDatasetKind;
399
419
  readonly datasetId: string;
@@ -404,14 +424,18 @@ class DeferredPlayDataset<T> implements PlayDataset<T> {
404
424
  private readonly previewColumns?: string[];
405
425
  private readonly workProgress?: PlayDatasetWorkProgressSummary;
406
426
  private cachedCount: number;
427
+ private knownCount: number | null;
428
+ private readonly residentRows: readonly T[] | null;
407
429
  private readonly resolvers: PlayDatasetResolvers<T>;
408
430
 
409
431
  constructor(input: {
410
432
  datasetKind: PlayDatasetKind;
411
433
  datasetId: string;
412
434
  count: number;
435
+ knownCount?: number | null;
413
436
  backing?: PlayDatasetBacking;
414
437
  previewRows: readonly T[];
438
+ residentRows?: readonly T[] | null;
415
439
  sourceLabel?: string | null;
416
440
  tableNamespace?: string | null;
417
441
  workProgress?: PlayDatasetWorkProgressSummary;
@@ -420,8 +444,11 @@ class DeferredPlayDataset<T> implements PlayDataset<T> {
420
444
  this.datasetKind = input.datasetKind;
421
445
  this.datasetId = input.datasetId;
422
446
  this.cachedCount = input.count;
447
+ this.knownCount =
448
+ input.knownCount === undefined ? input.count : input.knownCount;
423
449
  this.backing = input.backing;
424
450
  this.previewRows = input.previewRows;
451
+ this.residentRows = input.residentRows ?? null;
425
452
  this.previewColumns = inferPreviewColumns(this.previewRows);
426
453
  this.sourceLabel = input.sourceLabel ?? null;
427
454
  this.tableNamespace = input.tableNamespace ?? null;
@@ -429,8 +456,18 @@ class DeferredPlayDataset<T> implements PlayDataset<T> {
429
456
  this.resolvers = input.resolvers;
430
457
  }
431
458
 
459
+ get length(): number {
460
+ if (this.knownCount === null) {
461
+ throw this.requiresAsyncAccess(
462
+ 'The row count is not known until this lazy transform executes.',
463
+ );
464
+ }
465
+ return this.knownCount;
466
+ }
467
+
432
468
  async count(): Promise<number> {
433
469
  this.cachedCount = await this.resolvers.count();
470
+ this.knownCount = this.cachedCount;
434
471
  return this.cachedCount;
435
472
  }
436
473
 
@@ -441,6 +478,29 @@ class DeferredPlayDataset<T> implements PlayDataset<T> {
441
478
  return await this.resolvers.peek(limit);
442
479
  }
443
480
 
481
+ async first(): Promise<T | undefined> {
482
+ return await this.at(0);
483
+ }
484
+
485
+ async at(index: number): Promise<T | undefined> {
486
+ if (!Number.isFinite(index)) return undefined;
487
+ const integer = Math.trunc(index);
488
+ const count = integer < 0 ? await this.count() : this.knownCount;
489
+ const normalized =
490
+ integer < 0 && count !== null ? count + integer : integer;
491
+ if (normalized < 0 || (count !== null && normalized >= count)) {
492
+ return undefined;
493
+ }
494
+ if (this.residentRows) return this.residentRows[normalized];
495
+ if (this.resolvers.at) return await this.resolvers.at(normalized);
496
+ let current = 0;
497
+ for await (const row of this.resolvers.iterate()) {
498
+ if (current === normalized) return row;
499
+ current += 1;
500
+ }
501
+ return undefined;
502
+ }
503
+
444
504
  map<U>(
445
505
  mapper: (row: T, index: number) => U | Promise<U>,
446
506
  options?: PlayDatasetTransformOptions,
@@ -531,6 +591,33 @@ class DeferredPlayDataset<T> implements PlayDataset<T> {
531
591
  }
532
592
  }
533
593
 
594
+ [Symbol.iterator](): Iterator<T> {
595
+ if (!this.residentRows) {
596
+ throw this.requiresAsyncAccess(
597
+ 'Synchronous iteration is available only when every row is resident.',
598
+ );
599
+ }
600
+ return this.residentRows[Symbol.iterator]();
601
+ }
602
+
603
+ residentAt(index: number): T | undefined {
604
+ if (this.knownCount !== null && index >= this.knownCount) return undefined;
605
+ if (!this.residentRows) {
606
+ throw this.requiresAsyncAccess(
607
+ `Row ${index} is not resident and may require dataset paging.`,
608
+ );
609
+ }
610
+ return this.residentRows[index];
611
+ }
612
+
613
+ private requiresAsyncAccess(detail: string): Error {
614
+ return new Error(
615
+ `PLAY_DATASET_REQUIRES_ASYNC_ACCESS: ${detail} ` +
616
+ `Dataset Handle ${this.sourceLabel ?? this.datasetId}. ` +
617
+ 'Use await dataset.first(), await dataset.at(index), await dataset.materialize(limit), or for await...of.',
618
+ );
619
+ }
620
+
534
621
  toJSON() {
535
622
  return {
536
623
  kind: 'dataset' as const,
@@ -666,6 +753,7 @@ function createTransformedPlayDataset<T, U>(
666
753
  key: options?.key,
667
754
  }),
668
755
  count: 0,
756
+ knownCount: null,
669
757
  backing: source.backing,
670
758
  sourceLabel,
671
759
  tableNamespace: options?.key ?? null,
@@ -687,17 +775,60 @@ export function createDeferredPlayDataset<T>(input: {
687
775
  datasetKind: PlayDatasetKind;
688
776
  datasetId: string;
689
777
  count: number;
778
+ /** Authoritative synchronous count, or null when execution must determine it. */
779
+ knownCount?: number | null;
690
780
  backing?: PlayDatasetBacking;
691
781
  previewRows?: readonly T[];
782
+ /** Complete in-memory row set. Never pass a bounded preview here. */
783
+ residentRows?: readonly T[] | null;
692
784
  sourceLabel?: string | null;
693
785
  tableNamespace?: string | null;
694
786
  workProgress?: PlayDatasetWorkProgressSummary;
695
787
  resolvers: PlayDatasetResolvers<T>;
696
788
  }): PlayDataset<T> {
697
- return new DeferredPlayDataset({
789
+ if (
790
+ input.residentRows &&
791
+ input.knownCount !== null &&
792
+ input.residentRows.length !== (input.knownCount ?? input.count)
793
+ ) {
794
+ throw new Error(
795
+ `Resident Dataset Handle ${input.datasetId} has ${input.residentRows.length} rows but declares ${input.knownCount ?? input.count}.`,
796
+ );
797
+ }
798
+ const target = new DeferredPlayDataset({
698
799
  ...input,
699
800
  previewRows: input.previewRows ?? [],
700
801
  });
802
+ const boundMethods = new Map<PropertyKey, unknown>();
803
+ const dataset = new Proxy(target, {
804
+ get(dataset, property) {
805
+ if (typeof property === 'string' && /^(0|[1-9]\d*)$/.test(property)) {
806
+ return dataset.residentAt(Number(property));
807
+ }
808
+ const value = Reflect.get(dataset, property, dataset);
809
+ if (typeof value !== 'function') return value;
810
+ if (!boundMethods.has(property)) {
811
+ boundMethods.set(property, value.bind(dataset));
812
+ }
813
+ return boundMethods.get(property);
814
+ },
815
+ set(_dataset, property) {
816
+ if (
817
+ property === 'length' ||
818
+ (typeof property === 'string' && /^(0|[1-9]\d*)$/.test(property))
819
+ ) {
820
+ throw new Error(
821
+ 'PLAY_DATASET_READ_ONLY: Dataset Handle rows cannot be assigned directly.',
822
+ );
823
+ }
824
+ return false;
825
+ },
826
+ });
827
+ if (input.residentRows) {
828
+ residentRowsByDataset.set(target, input.residentRows);
829
+ residentRowsByDataset.set(dataset, input.residentRows);
830
+ }
831
+ return dataset;
701
832
  }
702
833
 
703
834
  export function createPlayDataset<T>(
@@ -719,6 +850,7 @@ export function createPlayDataset<T>(
719
850
  `${metadata?.kind ?? 'map'}:${metadata?.tableNamespace ?? metadata?.sourceLabel ?? 'inline'}`,
720
851
  count: materializedRows.length,
721
852
  previewRows: materializedRows.slice(0, 5),
853
+ residentRows: materializedRows,
722
854
  sourceLabel: metadata?.sourceLabel ?? null,
723
855
  tableNamespace: metadata?.tableNamespace ?? null,
724
856
  resolvers: {
package/dist/cli/index.js CHANGED
@@ -1037,7 +1037,7 @@ var SDK_RELEASE = {
1037
1037
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
1038
1038
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
1039
1039
  // Operators use the checkout-local deepline-admin binary instead.
1040
- version: "0.1.318",
1040
+ version: "0.1.320",
1041
1041
  contracts: {
1042
1042
  api: {
1043
1043
  name: "sdk-http-api",
@@ -11991,7 +11991,7 @@ async function traceCliSpan(phase, fields, run) {
11991
11991
 
11992
11992
  // src/cli/play-check-hints.ts
11993
11993
  var EXTRACTED_GETTER_ERROR_HINT = "Deepline hint: extractedValues/extractedLists .get() only works for declared Deepline getters listed by `deepline tools describe <tool> --json`. Use `toolExecutionResult.toolResponse.raw` for provider/tool-specific scalar fields, and `toolExecutionResult.extractedLists.<name>.get()` for declared row/list outputs.";
11994
- var DATASET_API_HINT = "Deepline hint: PlayDataset is lazy and durable. Use `.peek(n)` for a small preview or `.materialize()` when you intentionally need rows in memory; do not use `.rows`, `.toArray()`, or array methods directly on the dataset handle.";
11994
+ var DATASET_API_HINT = "Deepline hint: PlayDataset is lazy and durable. Complete resident handles support read-only length/index/iteration. For paged rows use `.first()`, `.at(index)`, `.peek(n)`, `.materialize(limit)`, or async iteration; do not use `.rows` or `.toArray()`.";
11995
11995
  var ROW_PROPERTY_HINT = "Deepline hint: this row type only contains fields produced by the CSV/schema and previous map steps. Check source column casing and the exact output field names from earlier steps before scaling.";
11996
11996
  var TOOLS_EXECUTE_SIGNATURE_HINT = "Deepline hint: ctx.tools.execute requires a request object: `ctx.tools.execute({ id, tool, input, description })`. The stable `id` is required for logs, metadata, and receipt attachment; provider-call reuse is based on play, tool, semantic input, auth scope, provider action version, and cache policy.";
11997
11997
  var RUN_PLAY_SIGNATURE_HINT = "Deepline hint: ctx.runPlay uses a stable key plus a composable child play reference. Direct-run-only or dataset-backed batch plays must be run directly, exported, then consumed by a separate play.";
@@ -28589,14 +28589,23 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
28589
28589
  "deeplineUsdPerPricingUnit",
28590
28590
  "deepline_usd_per_pricing_unit"
28591
28591
  );
28592
- const starterScript = !isPlayLikeTool(tool) && extractedLists.length > 0 ? starterScriptJson(
28592
+ const deprecation = recordField2(tool, "deprecation");
28593
+ const replacementToolId = stringField2(
28594
+ deprecation,
28595
+ "replacementToolId",
28596
+ "replacement_tool_id"
28597
+ );
28598
+ const deprecationMessage = stringField2(deprecation, "message");
28599
+ const deprecationExecution = stringField2(deprecation, "execution");
28600
+ const deprecated = tool.deprecated === true || stringField2(tool, "credentialStatus", "credential_status") === "deprecated";
28601
+ const starterScript = !deprecated && !isPlayLikeTool(tool) && extractedLists.length > 0 ? starterScriptJson(
28593
28602
  seedToolListScript({
28594
28603
  toolId,
28595
28604
  payload: samplePayloadForInputFields(inputFields),
28596
28605
  rows: []
28597
28606
  })
28598
28607
  ) : null;
28599
- const executeCommand = isPlayLikeTool(tool) ? playRunCommandForTool(tool, toolId) : `deepline tools execute ${toolId} --input '{...}' --json`;
28608
+ const executeCommand = deprecated && replacementToolId ? `deepline tools execute ${replacementToolId} --input '{...}' --json` : isPlayLikeTool(tool) ? playRunCommandForTool(tool, toolId) : `deepline tools execute ${toolId} --input '{...}' --json`;
28600
28609
  return {
28601
28610
  schemaVersion: 1,
28602
28611
  toolId,
@@ -28604,6 +28613,15 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
28604
28613
  displayName: tool.displayName,
28605
28614
  description: tool.description,
28606
28615
  categories: tool.categories,
28616
+ ...deprecated ? {
28617
+ deprecated: true,
28618
+ callable: tool.callable !== false,
28619
+ deprecation: {
28620
+ replacementToolId,
28621
+ message: deprecationMessage,
28622
+ ...deprecationExecution ? { execution: deprecationExecution } : {}
28623
+ }
28624
+ } : {},
28607
28625
  inputFields: inputFields.map((field) => ({
28608
28626
  name: field.name,
28609
28627
  type: field.type ?? "unknown",
@@ -28746,6 +28764,29 @@ function printCompactToolContract(tool, requestedToolId) {
28746
28764
  if (Array.isArray(contract.categories) && contract.categories.length) {
28747
28765
  console.log(`Tags: ${contract.categories.join(", ")}`);
28748
28766
  }
28767
+ if (contract.deprecated === true) {
28768
+ const deprecation = isRecord11(contract.deprecation) ? contract.deprecation : {};
28769
+ const message = stringField2(deprecation, "message");
28770
+ const replacementToolId = stringField2(
28771
+ deprecation,
28772
+ "replacementToolId",
28773
+ "replacement_tool_id"
28774
+ );
28775
+ console.log(
28776
+ contract.callable === false ? "Status: deprecated \u2014 this tool cannot be executed" : "Status: deprecated \u2014 legacy executions forward for compatibility"
28777
+ );
28778
+ if (message) console.log(`Migration: ${message}`);
28779
+ if (replacementToolId) {
28780
+ console.log(
28781
+ `Use: deepline tools execute ${replacementToolId} --input '{...}'`
28782
+ );
28783
+ }
28784
+ console.log("");
28785
+ console.log(
28786
+ `More: deepline tools describe ${replacementToolId || contract.toolId} --json`
28787
+ );
28788
+ return;
28789
+ }
28749
28790
  printToolPricingOnly(tool, requestedToolId, { heading: "Cost" });
28750
28791
  if (inputFields.length) {
28751
28792
  console.log("");
@@ -29245,6 +29286,32 @@ function samplePayload(samples, key) {
29245
29286
  function commandEnvelopeFromRawResponse(rawResponse) {
29246
29287
  return isRecord11(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
29247
29288
  }
29289
+ function extractToolExecutionWarningMessages(rawResponse) {
29290
+ if (!isRecord11(rawResponse)) return [];
29291
+ const candidates = [
29292
+ recordField2(recordField2(rawResponse, "toolResponse"), "meta"),
29293
+ recordField2(
29294
+ recordField2(recordField2(rawResponse, "toolResponse"), "raw"),
29295
+ "meta"
29296
+ ),
29297
+ recordField2(rawResponse, "meta"),
29298
+ recordField2(recordField2(rawResponse, "result"), "meta")
29299
+ ];
29300
+ const messages = [];
29301
+ for (const candidate of candidates) {
29302
+ const warnings = candidate?.warnings;
29303
+ if (!Array.isArray(warnings)) continue;
29304
+ for (const warning of warnings) {
29305
+ if (typeof warning === "string" && warning.trim()) {
29306
+ messages.push(warning.trim());
29307
+ } else if (isRecord11(warning)) {
29308
+ const message = stringField2(warning, "message");
29309
+ if (message) messages.push(message);
29310
+ }
29311
+ }
29312
+ }
29313
+ return [...new Set(messages)];
29314
+ }
29248
29315
  function apifySyncRecoveryNext(rawResponse) {
29249
29316
  if (!isRecord11(rawResponse) || rawResponse.status !== "running") return null;
29250
29317
  const toolResponse = recordField2(rawResponse, "toolResponse");
@@ -29512,6 +29579,9 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
29512
29579
  }
29513
29580
  function buildToolExecuteBaseEnvelope(input2) {
29514
29581
  const envelope = commandEnvelopeFromRawResponse(input2.rawResponse);
29582
+ const warningMessages = extractToolExecutionWarningMessages(
29583
+ input2.rawResponse
29584
+ );
29515
29585
  const apifyRecovery = apifySyncRecoveryNext(input2.rawResponse);
29516
29586
  const summaryEntries = Object.entries(input2.summary);
29517
29587
  const outputPreview = input2.listConversion ? {
@@ -29549,6 +29619,7 @@ function buildToolExecuteBaseEnvelope(input2) {
29549
29619
  ...envelope,
29550
29620
  ...envelopeHasCanonicalOutput || envelopeHasDeclaredOutput ? { output_preview: outputPreview } : { output: outputPreview },
29551
29621
  ...summaryEntries.length > 0 ? { summary: input2.summary } : {},
29622
+ ...warningMessages.length > 0 ? { warnings: warningMessages } : {},
29552
29623
  next: {
29553
29624
  inspect: inspectCommand,
29554
29625
  ...apifyRecovery ?? {},
@@ -29560,6 +29631,7 @@ function buildToolExecuteBaseEnvelope(input2) {
29560
29631
  },
29561
29632
  render: {
29562
29633
  sections: input2.listConversion ? [
29634
+ ...warningMessages.length > 0 ? [{ title: "warnings", lines: warningMessages }] : [],
29563
29635
  {
29564
29636
  title: "output",
29565
29637
  lines: [
@@ -29570,6 +29642,7 @@ function buildToolExecuteBaseEnvelope(input2) {
29570
29642
  ]
29571
29643
  }
29572
29644
  ] : [
29645
+ ...warningMessages.length > 0 ? [{ title: "warnings", lines: warningMessages }] : [],
29573
29646
  {
29574
29647
  title: "result",
29575
29648
  lines: apifyRecovery ? [