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.
- package/dist/bundling-sources/sdk/src/play.ts +8 -1
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/types.ts +18 -4
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +10 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +20 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +11 -0
- package/dist/bundling-sources/shared_libs/plays/dataset.ts +134 -2
- package/dist/cli/index.js +77 -4
- package/dist/cli/index.mjs +77 -4
- package/dist/index.d.mts +23 -5
- package/dist/index.d.ts +23 -5
- package/dist/index.js +97 -3
- package/dist/index.mjs +97 -3
- package/dist/viewer/viewer.css +64 -61
- package/package.json +1 -1
|
@@ -1862,7 +1862,9 @@ function attachSdkQueryResultDatasetResult(
|
|
|
1862
1862
|
}
|
|
1863
1863
|
const datasetLimit =
|
|
1864
1864
|
finitePositiveInteger(dataset.returned_limit) ?? totalRows;
|
|
1865
|
-
const
|
|
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.
|
|
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
|
|
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?:
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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 ? [
|