deepline 0.1.146 → 0.1.148
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/apps/play-runner-workers/src/entry.ts +205 -75
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/dataset-handles.ts +8 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/output-datasets.ts +363 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/result-dataset-persistence.ts +50 -0
- package/dist/bundling-sources/sdk/src/release.ts +54 -21
- package/dist/bundling-sources/sdk/src/tool-output.ts +18 -7
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result-types.ts +2 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +81 -5
- package/dist/cli/index.js +198 -41
- package/dist/cli/index.mjs +210 -53
- package/dist/index.d.mts +91 -89
- package/dist/index.d.ts +91 -89
- package/dist/index.js +545 -31
- package/dist/index.mjs +546 -32
- package/package.json +2 -2
|
@@ -38,6 +38,8 @@ import type {
|
|
|
38
38
|
ToolResultTargetAccessor,
|
|
39
39
|
ToolResultTargetMetadata,
|
|
40
40
|
} from './tool-result-types';
|
|
41
|
+
import { createPlayDataset, type PlayDataset } from '../plays/dataset';
|
|
42
|
+
import { normalizeTableNamespace, sha256Hex } from '../plays/row-identity';
|
|
41
43
|
|
|
42
44
|
type PathSegment = string | number | '*';
|
|
43
45
|
|
|
@@ -737,12 +739,22 @@ function resolveListRows(
|
|
|
737
739
|
);
|
|
738
740
|
let resolvedPath: string | null = null;
|
|
739
741
|
let rows: Record<string, unknown>[] | null = null;
|
|
742
|
+
let emptyMatch: { path: string; rows: Record<string, unknown>[] } | null =
|
|
743
|
+
null;
|
|
740
744
|
for (const candidate of candidates) {
|
|
741
745
|
rows = normalizeRows(getAtPath(result, candidate));
|
|
742
|
-
if (rows) {
|
|
746
|
+
if (!rows) {
|
|
747
|
+
continue;
|
|
748
|
+
}
|
|
749
|
+
if (rows.length > 0) {
|
|
743
750
|
resolvedPath = candidate;
|
|
744
751
|
break;
|
|
745
752
|
}
|
|
753
|
+
emptyMatch ??= { path: candidate, rows };
|
|
754
|
+
}
|
|
755
|
+
if (!rows && emptyMatch) {
|
|
756
|
+
resolvedPath = emptyMatch.path;
|
|
757
|
+
rows = emptyMatch.rows;
|
|
746
758
|
}
|
|
747
759
|
if (!rows) continue;
|
|
748
760
|
const storedPath = resolvedPath ?? path;
|
|
@@ -751,7 +763,12 @@ function resolveListRows(
|
|
|
751
763
|
.filter(Boolean)
|
|
752
764
|
.at(-1)
|
|
753
765
|
?.replace(/\[\d+\]$/, '');
|
|
754
|
-
|
|
766
|
+
const listName = name || storedPath;
|
|
767
|
+
const existing = lists[listName];
|
|
768
|
+
if (existing?.rows.length && rows.length === 0) {
|
|
769
|
+
continue;
|
|
770
|
+
}
|
|
771
|
+
lists[listName] = { path: storedPath, rows };
|
|
755
772
|
}
|
|
756
773
|
return lists;
|
|
757
774
|
}
|
|
@@ -935,10 +952,26 @@ function buildExtractedAccessors(
|
|
|
935
952
|
function buildListAccessors(
|
|
936
953
|
resolved: Record<string, { path: string; rows: Record<string, unknown>[] }>,
|
|
937
954
|
lists: Record<string, ToolResultListMetadata>,
|
|
955
|
+
toolId: string,
|
|
956
|
+
executionDiscriminator: string,
|
|
938
957
|
): Record<string, ToolResultListAccessor> {
|
|
939
958
|
return Object.fromEntries(
|
|
940
959
|
Object.entries(lists).map(([name, metadata]) => {
|
|
941
960
|
const rows = resolved[name]?.rows ?? [];
|
|
961
|
+
const datasetDiscriminator = `${executionDiscriminator}:${listRowsFingerprint(rows)}`;
|
|
962
|
+
const dataset = createPlayDataset(rows, {
|
|
963
|
+
kind: 'csv',
|
|
964
|
+
sourceLabel: metadata.path,
|
|
965
|
+
tableNamespace: listTableNamespace(
|
|
966
|
+
toolId,
|
|
967
|
+
name,
|
|
968
|
+
metadata.path,
|
|
969
|
+
datasetDiscriminator,
|
|
970
|
+
),
|
|
971
|
+
datasetId: `tool-list:${sha256Hex(
|
|
972
|
+
`${toolId}:${metadata.path}:${datasetDiscriminator}`,
|
|
973
|
+
)}`,
|
|
974
|
+
});
|
|
942
975
|
const accessor = {
|
|
943
976
|
path: metadata.path,
|
|
944
977
|
count: metadata.count,
|
|
@@ -946,7 +979,7 @@ function buildListAccessors(
|
|
|
946
979
|
} as ToolResultListAccessor;
|
|
947
980
|
Object.defineProperty(accessor, 'get', {
|
|
948
981
|
value() {
|
|
949
|
-
return
|
|
982
|
+
return dataset;
|
|
950
983
|
},
|
|
951
984
|
enumerable: false,
|
|
952
985
|
});
|
|
@@ -955,6 +988,44 @@ function buildListAccessors(
|
|
|
955
988
|
);
|
|
956
989
|
}
|
|
957
990
|
|
|
991
|
+
function listRowsFingerprint(rows: readonly Record<string, unknown>[]): string {
|
|
992
|
+
try {
|
|
993
|
+
return sha256Hex(
|
|
994
|
+
JSON.stringify(
|
|
995
|
+
{
|
|
996
|
+
count: rows.length,
|
|
997
|
+
rows,
|
|
998
|
+
},
|
|
999
|
+
(_key, value) => (typeof value === 'bigint' ? value.toString() : value),
|
|
1000
|
+
),
|
|
1001
|
+
).slice(0, 12);
|
|
1002
|
+
} catch {
|
|
1003
|
+
return sha256Hex(String(rows.length)).slice(0, 12);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
function listTableNamespace(
|
|
1008
|
+
toolId: string,
|
|
1009
|
+
name: string,
|
|
1010
|
+
path: string,
|
|
1011
|
+
discriminator: string,
|
|
1012
|
+
): string {
|
|
1013
|
+
const raw = `${toolId}_${name || path || 'rows'}_${sha256Hex(discriminator).slice(0, 10)}`;
|
|
1014
|
+
try {
|
|
1015
|
+
return normalizeTableNamespace(raw);
|
|
1016
|
+
} catch {
|
|
1017
|
+
const hash = sha256Hex(raw).slice(0, 10);
|
|
1018
|
+
const leaf = name || path.split('.').filter(Boolean).at(-1) || 'rows';
|
|
1019
|
+
let prefix = 'rows';
|
|
1020
|
+
try {
|
|
1021
|
+
prefix = normalizeTableNamespace(leaf).slice(0, 52) || 'rows';
|
|
1022
|
+
} catch {
|
|
1023
|
+
prefix = 'rows';
|
|
1024
|
+
}
|
|
1025
|
+
return normalizeTableNamespace(`${prefix}_${hash}`);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
|
|
958
1029
|
export function createToolExecuteResult<TResult = unknown>(input: {
|
|
959
1030
|
status: string;
|
|
960
1031
|
jobId?: string;
|
|
@@ -994,7 +1065,12 @@ export function createToolExecuteResult<TResult = unknown>(input: {
|
|
|
994
1065
|
...(result.meta ? { meta: result.meta } : {}),
|
|
995
1066
|
};
|
|
996
1067
|
const extractedValues = buildExtractedAccessors(targets);
|
|
997
|
-
const extractedLists = buildListAccessors(
|
|
1068
|
+
const extractedLists = buildListAccessors(
|
|
1069
|
+
resolvedLists,
|
|
1070
|
+
lists,
|
|
1071
|
+
input.metadata.toolId,
|
|
1072
|
+
input.jobId ?? input.execution.cacheKey ?? 'inline',
|
|
1073
|
+
);
|
|
998
1074
|
const wrapper = {
|
|
999
1075
|
status: input.status,
|
|
1000
1076
|
...(input.jobId ? { job_id: input.jobId } : {}),
|
|
@@ -1063,7 +1139,7 @@ export function readValue(
|
|
|
1063
1139
|
export function readList(
|
|
1064
1140
|
result: ToolExecuteResult,
|
|
1065
1141
|
selector?: readonly string[] | string,
|
|
1066
|
-
): Record<string, unknown>[] {
|
|
1142
|
+
): PlayDataset<Record<string, unknown>> | Record<string, unknown>[] {
|
|
1067
1143
|
if (selector) {
|
|
1068
1144
|
const paths = Array.isArray(selector) ? selector : [selector];
|
|
1069
1145
|
const found = findFirstTargetByPath(resultRootOf(result), paths)?.value;
|
package/dist/cli/index.js
CHANGED
|
@@ -619,10 +619,11 @@ var SDK_RELEASE = {
|
|
|
619
619
|
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
620
620
|
// the SDK enrich generator's one-second stale policy.
|
|
621
621
|
// 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
|
|
622
|
-
|
|
623
|
-
|
|
622
|
+
// 0.1.111 ships dataset-native tool list getters and result row datasets.
|
|
623
|
+
version: "0.1.148",
|
|
624
|
+
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
624
625
|
supportPolicy: {
|
|
625
|
-
latest: "0.1.
|
|
626
|
+
latest: "0.1.148",
|
|
626
627
|
minimumSupported: "0.1.53",
|
|
627
628
|
deprecatedBelow: "0.1.53",
|
|
628
629
|
commandMinimumSupported: [
|
|
@@ -633,52 +634,79 @@ var SDK_RELEASE = {
|
|
|
633
634
|
},
|
|
634
635
|
{
|
|
635
636
|
command: "plays",
|
|
636
|
-
minimumSupported: "0.1.
|
|
637
|
-
reason: "Play file commands now
|
|
637
|
+
minimumSupported: "0.1.111",
|
|
638
|
+
reason: "Play file commands now use dataset-native list getters and result row datasets."
|
|
638
639
|
},
|
|
639
640
|
{
|
|
640
641
|
command: "plays run",
|
|
641
|
-
minimumSupported: "0.1.
|
|
642
|
-
reason: "Play
|
|
642
|
+
minimumSupported: "0.1.111",
|
|
643
|
+
reason: "Play run results now promote row-shaped outputs into dataset handles for safe export."
|
|
643
644
|
},
|
|
644
645
|
{
|
|
645
646
|
command: "run",
|
|
646
647
|
displayCommand: "plays run",
|
|
647
|
-
minimumSupported: "0.1.
|
|
648
|
-
reason: "Play
|
|
648
|
+
minimumSupported: "0.1.111",
|
|
649
|
+
reason: "Play run results now promote row-shaped outputs into dataset handles for safe export."
|
|
649
650
|
},
|
|
650
651
|
{
|
|
651
652
|
command: "plays check",
|
|
652
|
-
minimumSupported: "0.1.
|
|
653
|
-
reason: "Play file
|
|
653
|
+
minimumSupported: "0.1.111",
|
|
654
|
+
reason: "Play file checks now validate dataset-native list getter authoring."
|
|
654
655
|
},
|
|
655
656
|
{
|
|
656
657
|
command: "check",
|
|
657
658
|
displayCommand: "plays check",
|
|
658
|
-
minimumSupported: "0.1.
|
|
659
|
-
reason: "Play file
|
|
659
|
+
minimumSupported: "0.1.111",
|
|
660
|
+
reason: "Play file checks now validate dataset-native list getter authoring."
|
|
660
661
|
},
|
|
661
662
|
{
|
|
662
663
|
command: "plays publish",
|
|
663
|
-
minimumSupported: "0.1.
|
|
664
|
-
reason: "
|
|
664
|
+
minimumSupported: "0.1.111",
|
|
665
|
+
reason: "Published play artifacts now target dataset-native list getters and result row datasets."
|
|
665
666
|
},
|
|
666
667
|
{
|
|
667
668
|
command: "publish",
|
|
668
669
|
displayCommand: "plays publish",
|
|
669
|
-
minimumSupported: "0.1.
|
|
670
|
-
reason: "
|
|
670
|
+
minimumSupported: "0.1.111",
|
|
671
|
+
reason: "Published play artifacts now target dataset-native list getters and result row datasets."
|
|
671
672
|
},
|
|
672
673
|
{
|
|
673
674
|
command: "plays set-live",
|
|
674
|
-
minimumSupported: "0.1.
|
|
675
|
-
reason: "
|
|
675
|
+
minimumSupported: "0.1.111",
|
|
676
|
+
reason: "Published play artifacts now target dataset-native list getters and result row datasets."
|
|
676
677
|
},
|
|
677
678
|
{
|
|
678
679
|
command: "set-live",
|
|
679
680
|
displayCommand: "plays set-live",
|
|
680
|
-
minimumSupported: "0.1.
|
|
681
|
-
reason: "
|
|
681
|
+
minimumSupported: "0.1.111",
|
|
682
|
+
reason: "Published play artifacts now target dataset-native list getters and result row datasets."
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
command: "runs",
|
|
686
|
+
minimumSupported: "0.1.111",
|
|
687
|
+
reason: "Run result rows now render as dataset handles with explicit export commands."
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
command: "runs get",
|
|
691
|
+
minimumSupported: "0.1.111",
|
|
692
|
+
reason: "Run result rows now render as dataset handles with explicit export commands."
|
|
693
|
+
},
|
|
694
|
+
{
|
|
695
|
+
command: "get",
|
|
696
|
+
displayCommand: "runs get",
|
|
697
|
+
minimumSupported: "0.1.111",
|
|
698
|
+
reason: "Run result rows now render as dataset handles with explicit export commands."
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
command: "runs export",
|
|
702
|
+
minimumSupported: "0.1.111",
|
|
703
|
+
reason: "Run result row datasets now use the dataset-handle export contract."
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
command: "export",
|
|
707
|
+
displayCommand: "runs export",
|
|
708
|
+
minimumSupported: "0.1.111",
|
|
709
|
+
reason: "Run result row datasets now use the dataset-handle export contract."
|
|
682
710
|
}
|
|
683
711
|
],
|
|
684
712
|
autoUpdatePatchLag: 2
|
|
@@ -8302,9 +8330,10 @@ function generateProviderSourceBlock(input2) {
|
|
|
8302
8330
|
input: ${inputName},
|
|
8303
8331
|
description: ${jsString(`Seed ${input2.entity} rows from ${input2.provider}.`)},
|
|
8304
8332
|
});
|
|
8305
|
-
// extractedLists.${getter}.get() returns provider-shaped rows. Do not assume canonical fields;
|
|
8333
|
+
// extractedLists.${getter}.get() returns a dataset handle of provider-shaped rows. Do not assume canonical fields;
|
|
8306
8334
|
// inspect source_${input2.index}.extractedLists.${getter}.keys or the provider output schema, then map explicitly below.
|
|
8307
|
-
const
|
|
8335
|
+
const sourceRowsDataset_${input2.index} = ${accessorExpression(`source_${input2.index}.extractedLists`, getter)}.get();
|
|
8336
|
+
const sourceRows_${input2.index} = (await sourceRowsDataset_${input2.index}.peek(limit)) as ${input2.collectionType}[];`;
|
|
8308
8337
|
}
|
|
8309
8338
|
function generateProviderSourceRowsBlock(input2) {
|
|
8310
8339
|
const blocks = input2.source.values.map(
|
|
@@ -10990,6 +11019,9 @@ function formatPlayLogLine(line, status, state) {
|
|
|
10990
11019
|
}
|
|
10991
11020
|
return `${prefix}${message}`;
|
|
10992
11021
|
}
|
|
11022
|
+
function isDatasetResultEnvelope(value) {
|
|
11023
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) && value.kind === "dataset";
|
|
11024
|
+
}
|
|
10993
11025
|
function compactReturnValue(value, depth = 0) {
|
|
10994
11026
|
if (depth >= 4) {
|
|
10995
11027
|
return value && typeof value === "object" ? "[Object]" : value;
|
|
@@ -11001,6 +11033,7 @@ function compactReturnValue(value, depth = 0) {
|
|
|
11001
11033
|
if (!value || typeof value !== "object") {
|
|
11002
11034
|
return value;
|
|
11003
11035
|
}
|
|
11036
|
+
const isDatasetEnvelope = isDatasetResultEnvelope(value);
|
|
11004
11037
|
const output2 = {};
|
|
11005
11038
|
for (const [key, entry] of Object.entries(value)) {
|
|
11006
11039
|
if (depth === 0 && key === "_metadata") {
|
|
@@ -11009,13 +11042,41 @@ function compactReturnValue(value, depth = 0) {
|
|
|
11009
11042
|
if (BULKY_RETURN_KEYS.has(key)) {
|
|
11010
11043
|
continue;
|
|
11011
11044
|
}
|
|
11012
|
-
if (key === "access") {
|
|
11045
|
+
if (isDatasetEnvelope && key === "access") {
|
|
11046
|
+
continue;
|
|
11047
|
+
}
|
|
11048
|
+
if (isDatasetEnvelope && (key === "queryDatasetCommand" || key === "cliCommand")) {
|
|
11049
|
+
continue;
|
|
11050
|
+
}
|
|
11051
|
+
if (isDatasetEnvelope && key === "slowExportAsCsvCommand") {
|
|
11052
|
+
output2.fullExportCommand = entry;
|
|
11013
11053
|
continue;
|
|
11014
11054
|
}
|
|
11015
11055
|
output2[key] = compactReturnValue(entry, depth + 1);
|
|
11016
11056
|
}
|
|
11017
11057
|
return output2;
|
|
11018
11058
|
}
|
|
11059
|
+
function defaultResultForEnvelope(value, depth = 0) {
|
|
11060
|
+
if (depth > 20 || value == null || typeof value !== "object") {
|
|
11061
|
+
return value;
|
|
11062
|
+
}
|
|
11063
|
+
if (Array.isArray(value)) {
|
|
11064
|
+
return value.map((entry) => defaultResultForEnvelope(entry, depth + 1));
|
|
11065
|
+
}
|
|
11066
|
+
const isDatasetEnvelope = isDatasetResultEnvelope(value);
|
|
11067
|
+
const output2 = {};
|
|
11068
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
11069
|
+
if (isDatasetEnvelope && (key === "queryDatasetCommand" || key === "cliCommand")) {
|
|
11070
|
+
continue;
|
|
11071
|
+
}
|
|
11072
|
+
if (isDatasetEnvelope && key === "slowExportAsCsvCommand") {
|
|
11073
|
+
output2.fullExportCommand = entry;
|
|
11074
|
+
continue;
|
|
11075
|
+
}
|
|
11076
|
+
output2[key] = defaultResultForEnvelope(entry, depth + 1);
|
|
11077
|
+
}
|
|
11078
|
+
return output2;
|
|
11079
|
+
}
|
|
11019
11080
|
function formatJsonPreview(value) {
|
|
11020
11081
|
const json = JSON.stringify(value, null, 2);
|
|
11021
11082
|
if (!json || json === "{}") {
|
|
@@ -11059,9 +11120,6 @@ function collectDatasetHandleLines(value, path = "result", datasetStats) {
|
|
|
11059
11120
|
if (datasetStats && (datasetStats.source === path || datasetStats.source === record.path)) {
|
|
11060
11121
|
lines2.push(...formatDatasetStatsLines(datasetStats.stats, " "));
|
|
11061
11122
|
}
|
|
11062
|
-
if (typeof record.queryDatasetCommand === "string") {
|
|
11063
|
-
lines2.push(` query dataset: ${record.queryDatasetCommand}`);
|
|
11064
|
-
}
|
|
11065
11123
|
if (typeof record.slowExportAsCsvCommand === "string") {
|
|
11066
11124
|
lines2.push(` export CSV: ${record.slowExportAsCsvCommand}`);
|
|
11067
11125
|
}
|
|
@@ -11472,7 +11530,7 @@ function compactPlayStatus(status) {
|
|
|
11472
11530
|
logs: normalizeLogsForEnvelope(status),
|
|
11473
11531
|
...displayError ? { error: displayError } : {},
|
|
11474
11532
|
...warnings.length > 0 ? { warnings } : {},
|
|
11475
|
-
...result !== void 0 ? { result } : {},
|
|
11533
|
+
...result !== void 0 ? { result: defaultResultForEnvelope(result) } : {},
|
|
11476
11534
|
...billing ? { billing } : {},
|
|
11477
11535
|
next: buildRunNextCommands(status)
|
|
11478
11536
|
};
|
|
@@ -20415,16 +20473,24 @@ function tryConvertToList(payload, options) {
|
|
|
20415
20473
|
(entry) => typeof entry === "string" && entry.trim().length > 0
|
|
20416
20474
|
) : [];
|
|
20417
20475
|
if (listExtractorPaths.length > 0) {
|
|
20476
|
+
let emptyMatch = null;
|
|
20418
20477
|
for (const root of candidateRoots(payload)) {
|
|
20419
20478
|
for (const extractorPath of listExtractorPaths) {
|
|
20420
20479
|
const resolved = getByDottedPath(root.value, extractorPath);
|
|
20421
20480
|
const rows = normalizeRows(resolved);
|
|
20422
|
-
if (rows
|
|
20423
|
-
|
|
20481
|
+
if (!rows) {
|
|
20482
|
+
continue;
|
|
20483
|
+
}
|
|
20484
|
+
const sourcePath = root.path ? `${root.path}.${extractorPath}` : extractorPath;
|
|
20485
|
+
if (rows.length > 0) {
|
|
20424
20486
|
return { rows, strategy: "configured_paths", sourcePath };
|
|
20425
20487
|
}
|
|
20488
|
+
emptyMatch ??= { rows, strategy: "configured_paths", sourcePath };
|
|
20426
20489
|
}
|
|
20427
20490
|
}
|
|
20491
|
+
if (emptyMatch) {
|
|
20492
|
+
return emptyMatch;
|
|
20493
|
+
}
|
|
20428
20494
|
}
|
|
20429
20495
|
for (const root of candidateRoots(payload)) {
|
|
20430
20496
|
const candidate = findBestArrayCandidate(root.value, root.path ?? "");
|
|
@@ -20448,9 +20514,9 @@ function writeJsonOutputFile(payload, stem) {
|
|
|
20448
20514
|
(0, import_node_fs12.writeFileSync)(outputPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
20449
20515
|
return outputPath;
|
|
20450
20516
|
}
|
|
20451
|
-
function writeCsvOutputFile(rows, stem) {
|
|
20452
|
-
const
|
|
20453
|
-
|
|
20517
|
+
function writeCsvOutputFile(rows, stem, options) {
|
|
20518
|
+
const outputPath = options?.outPath ? options.outPath : (0, import_node_path14.join)(ensureOutputDir(), `${stem}_${Date.now()}.csv`);
|
|
20519
|
+
(0, import_node_fs12.mkdirSync)((0, import_node_path14.dirname)(outputPath), { recursive: true });
|
|
20454
20520
|
const seen = /* @__PURE__ */ new Set();
|
|
20455
20521
|
const columns = [];
|
|
20456
20522
|
for (const row of rows) {
|
|
@@ -20979,6 +21045,7 @@ Examples:
|
|
|
20979
21045
|
deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
|
|
20980
21046
|
deepline tools execute hunter_email_verifier -p email=a@b.com
|
|
20981
21047
|
deepline tools execute test_rate_limit --input '{"key":"smoke"}' --json | jq '.status'
|
|
21048
|
+
deepline tools execute free_simple_company_search --input '{"sql":"SELECT company_name FROM companies LIMIT 10"}' --out companies.csv
|
|
20982
21049
|
`
|
|
20983
21050
|
).option(
|
|
20984
21051
|
"-p, --param <key=value>",
|
|
@@ -21000,6 +21067,9 @@ Examples:
|
|
|
21000
21067
|
).option(
|
|
21001
21068
|
"--output-format <format>",
|
|
21002
21069
|
"Output format: auto, csv, csv_file, json, or json_file"
|
|
21070
|
+
).option(
|
|
21071
|
+
"-o, --out <path>",
|
|
21072
|
+
"Write row-shaped tool output to this CSV path"
|
|
21003
21073
|
).option(
|
|
21004
21074
|
"--no-preview",
|
|
21005
21075
|
"Only print the extracted output path when applicable"
|
|
@@ -21012,6 +21082,7 @@ Examples:
|
|
|
21012
21082
|
...options.input ? ["--input", options.input] : [],
|
|
21013
21083
|
...options.payload ? ["--payload", options.payload] : [],
|
|
21014
21084
|
...options.outputFormat ? ["--output-format", options.outputFormat] : [],
|
|
21085
|
+
...options.out ? ["--out", options.out] : [],
|
|
21015
21086
|
...options.preview === false ? ["--no-preview"] : []
|
|
21016
21087
|
];
|
|
21017
21088
|
process.exitCode = await executeTool(args);
|
|
@@ -21462,7 +21533,7 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
|
|
|
21462
21533
|
invalidGetterHint: "If TypeScript says an extractedValues/extractedLists property does not exist, that field is not a declared Deepline getter.",
|
|
21463
21534
|
observeActualShape: observedOutputCommand,
|
|
21464
21535
|
observedOutput: observedOutputCommand,
|
|
21465
|
-
forPlayGetterBugs: "Run a tiny play, inspect `deepline runs get <run-id> --full --json`,
|
|
21536
|
+
forPlayGetterBugs: "Run a tiny play, inspect returned handles with `deepline runs get <run-id> --full --json`, then export row datasets with `deepline runs export`.",
|
|
21466
21537
|
executeOutputFields: "tools execute JSON may include output_preview for this direct probe only; play debugging uses run output and returned dataset handles."
|
|
21467
21538
|
},
|
|
21468
21539
|
...starterScript ? { starterScript } : {}
|
|
@@ -21669,12 +21740,13 @@ function parseExecuteOptions(args) {
|
|
|
21669
21740
|
const toolId = args[0];
|
|
21670
21741
|
if (!toolId) {
|
|
21671
21742
|
throw new Error(
|
|
21672
|
-
`Usage: deepline tools execute <toolId> [--param key=value ...] [--input '{"k":"v"}'] [--output-format auto|csv|csv_file|json|json_file] [--no-preview]`
|
|
21743
|
+
`Usage: deepline tools execute <toolId> [--param key=value ...] [--input '{"k":"v"}'] [--out rows.csv] [--output-format auto|csv|csv_file|json|json_file] [--no-preview]`
|
|
21673
21744
|
);
|
|
21674
21745
|
}
|
|
21675
21746
|
const params = {};
|
|
21676
21747
|
let outputFormat = "auto";
|
|
21677
21748
|
let noPreview = false;
|
|
21749
|
+
let outPath = null;
|
|
21678
21750
|
for (let index = 1; index < args.length; index += 1) {
|
|
21679
21751
|
const arg = args[index];
|
|
21680
21752
|
if ((arg === "--param" || arg === "-p") && args[index + 1]) {
|
|
@@ -21706,9 +21778,13 @@ function parseExecuteOptions(args) {
|
|
|
21706
21778
|
noPreview = true;
|
|
21707
21779
|
continue;
|
|
21708
21780
|
}
|
|
21781
|
+
if ((arg === "--out" || arg === "-o") && args[index + 1]) {
|
|
21782
|
+
outPath = (0, import_node_path15.resolve)(args[++index]);
|
|
21783
|
+
continue;
|
|
21784
|
+
}
|
|
21709
21785
|
throw new Error(`Unknown option: ${arg}`);
|
|
21710
21786
|
}
|
|
21711
|
-
return { toolId, params, outputFormat, noPreview };
|
|
21787
|
+
return { toolId, params, outputFormat, noPreview, outPath };
|
|
21712
21788
|
}
|
|
21713
21789
|
function safeFileStem(value) {
|
|
21714
21790
|
return value.trim().replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "tool";
|
|
@@ -21752,9 +21828,14 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
|
|
|
21752
21828
|
});
|
|
21753
21829
|
|
|
21754
21830
|
const list = Object.values(result.extractedLists)[0];
|
|
21755
|
-
|
|
21831
|
+
if (!list) {
|
|
21832
|
+
throw new Error('Expected ${input2.toolId} to expose an extracted list getter.');
|
|
21833
|
+
}
|
|
21834
|
+
const rows = list.get();
|
|
21756
21835
|
// ${sampleRows}
|
|
21757
21836
|
// columns: ${columns}
|
|
21837
|
+
// extractedLists.<name>.get() returns a dataset handle for row-shaped list outputs.
|
|
21838
|
+
// Pass it to ctx.dataset; use rows.peek/count/materialize only for deliberate bounded inspection.
|
|
21758
21839
|
// .withColumn('email_waterfall', (row, rowCtx) => rowCtx.runPlay('name_domain_email', 'name-and-domain-to-email', { first_name: String(row.first_name ?? ''), last_name: String(row.last_name ?? ''), domain: String(row.domain ?? '') }, { description: 'Resolve email.' }))
|
|
21759
21840
|
// .withColumn('phone_waterfall', (row, rowCtx) => rowCtx.runPlay('contact_phone', 'contact-to-phone', { first_name: String(row.first_name ?? ''), last_name: String(row.last_name ?? ''), email: String(row.email ?? '') }, { description: 'Resolve phone.' }))
|
|
21760
21841
|
// ctx.dataset is idempotent by dataset key + row key; reruns reuse completed rows.
|
|
@@ -21814,7 +21895,7 @@ function buildToolExecuteBaseEnvelope(input2) {
|
|
|
21814
21895
|
...summaryEntries.length > 0 ? { summary: input2.summary } : {},
|
|
21815
21896
|
next: {
|
|
21816
21897
|
inspect: inspectCommand,
|
|
21817
|
-
playDebugging: "When fixing a play getter, inspect
|
|
21898
|
+
playDebugging: "When fixing a play getter, inspect returned dataset handles with runs get and export rows with runs export; do not copy CLI preview paths blindly.",
|
|
21818
21899
|
...input2.listConversion ? {
|
|
21819
21900
|
expandToPlay: "Use stable map and step keys so reruns are idempotent: completed rows are reused, and only missing or stale work runs again.",
|
|
21820
21901
|
listSourcePath: input2.listConversion.sourcePath ?? "auto-detected list in the CLI response preview"
|
|
@@ -21826,7 +21907,7 @@ function buildToolExecuteBaseEnvelope(input2) {
|
|
|
21826
21907
|
title: "output",
|
|
21827
21908
|
lines: [
|
|
21828
21909
|
`${input2.listConversion.rows.length} row(s) extracted from ${input2.listConversion.sourcePath ?? "auto-detected list"}`,
|
|
21829
|
-
"paths above are observed from this execute response; use
|
|
21910
|
+
"paths above are observed from this execute response; use runs get and runs export to validate play output",
|
|
21830
21911
|
`columns: ${JSON.stringify(Object.keys(input2.listConversion.rows[0] ?? {}))}`,
|
|
21831
21912
|
`preview: ${JSON.stringify(input2.listConversion.rows.slice(0, 5))}`
|
|
21832
21913
|
]
|
|
@@ -21906,7 +21987,7 @@ async function executeTool(args) {
|
|
|
21906
21987
|
listConversion,
|
|
21907
21988
|
summary
|
|
21908
21989
|
});
|
|
21909
|
-
if (parsed.outputFormat === "json" || parsed.outputFormat === "auto" && shouldEmitJson()) {
|
|
21990
|
+
if (!parsed.outPath && (parsed.outputFormat === "json" || parsed.outputFormat === "auto" && shouldEmitJson())) {
|
|
21910
21991
|
printCommandEnvelope(baseEnvelope, { json: true });
|
|
21911
21992
|
return 0;
|
|
21912
21993
|
}
|
|
@@ -21928,6 +22009,17 @@ async function executeTool(args) {
|
|
|
21928
22009
|
return 0;
|
|
21929
22010
|
}
|
|
21930
22011
|
if (!listConversion) {
|
|
22012
|
+
if (parsed.outPath) {
|
|
22013
|
+
const error = new Error(
|
|
22014
|
+
`${parsed.toolId} did not expose row-shaped output to write as CSV. Re-run with --json to inspect the raw tool response.`
|
|
22015
|
+
);
|
|
22016
|
+
if (argsWantJson(args)) {
|
|
22017
|
+
printJsonError(error);
|
|
22018
|
+
} else {
|
|
22019
|
+
console.error(error.message);
|
|
22020
|
+
}
|
|
22021
|
+
return 1;
|
|
22022
|
+
}
|
|
21931
22023
|
if (parsed.outputFormat === "csv" || parsed.outputFormat === "csv_file") {
|
|
21932
22024
|
const jsonPath = writeJsonOutputFile(
|
|
21933
22025
|
rawResponse,
|
|
@@ -21949,7 +22041,8 @@ async function executeTool(args) {
|
|
|
21949
22041
|
}
|
|
21950
22042
|
const csv = writeCsvOutputFile(
|
|
21951
22043
|
listConversion.rows,
|
|
21952
|
-
`${parsed.toolId}_output
|
|
22044
|
+
`${parsed.toolId}_output`,
|
|
22045
|
+
parsed.outPath ? { outPath: parsed.outPath } : void 0
|
|
21953
22046
|
);
|
|
21954
22047
|
const seededScript = seedToolListScript({
|
|
21955
22048
|
toolId: parsed.toolId,
|
|
@@ -22022,6 +22115,27 @@ async function executeTool(args) {
|
|
|
22022
22115
|
);
|
|
22023
22116
|
return 0;
|
|
22024
22117
|
}
|
|
22118
|
+
if (parsed.outPath) {
|
|
22119
|
+
printCommandEnvelope(
|
|
22120
|
+
{
|
|
22121
|
+
...materializedEnvelope,
|
|
22122
|
+
csv_path: csv.path,
|
|
22123
|
+
row_count: csv.rowCount,
|
|
22124
|
+
row_count_returned: csv.rowCount,
|
|
22125
|
+
columns: csv.columns,
|
|
22126
|
+
preview: csv.preview,
|
|
22127
|
+
list_strategy: listConversion.strategy,
|
|
22128
|
+
list_source_path: listConversion.sourcePath,
|
|
22129
|
+
summary
|
|
22130
|
+
},
|
|
22131
|
+
{
|
|
22132
|
+
json: argsWantJson(args) || shouldEmitJson(),
|
|
22133
|
+
text: `Wrote ${csv.rowCount} row(s) to ${csv.path}
|
|
22134
|
+
`
|
|
22135
|
+
}
|
|
22136
|
+
);
|
|
22137
|
+
return 0;
|
|
22138
|
+
}
|
|
22025
22139
|
if (parsed.noPreview) {
|
|
22026
22140
|
printCommandEnvelope(
|
|
22027
22141
|
{
|
|
@@ -23563,6 +23677,40 @@ function isCi() {
|
|
|
23563
23677
|
function shouldSkipSelfUpdate() {
|
|
23564
23678
|
return envTruthy("DEEPLINE_SKIP_SELF_UPDATE") || envTruthy("DEEPLINE_NO_AUTO_UPDATE") || envTruthy("DEEPLINE_SKIP_SDK_AUTO_UPDATE") || envTruthy("DEEPLINE_DISABLE_AUTO_UPDATE") || isCi();
|
|
23565
23679
|
}
|
|
23680
|
+
function parseSemver(version) {
|
|
23681
|
+
const trimmed = version?.trim();
|
|
23682
|
+
if (!trimmed) return null;
|
|
23683
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec(
|
|
23684
|
+
trimmed
|
|
23685
|
+
);
|
|
23686
|
+
if (!match) return null;
|
|
23687
|
+
return {
|
|
23688
|
+
major: Number(match[1]),
|
|
23689
|
+
minor: Number(match[2]),
|
|
23690
|
+
patch: Number(match[3]),
|
|
23691
|
+
prerelease: match[4] ?? ""
|
|
23692
|
+
};
|
|
23693
|
+
}
|
|
23694
|
+
function compareSemver(left, right) {
|
|
23695
|
+
const a = parseSemver(left);
|
|
23696
|
+
const b = parseSemver(right);
|
|
23697
|
+
if (!a || !b) {
|
|
23698
|
+
return left.localeCompare(right);
|
|
23699
|
+
}
|
|
23700
|
+
for (const key of ["major", "minor", "patch"]) {
|
|
23701
|
+
if (a[key] !== b[key]) return a[key] > b[key] ? 1 : -1;
|
|
23702
|
+
}
|
|
23703
|
+
if (a.prerelease === b.prerelease) return 0;
|
|
23704
|
+
if (!a.prerelease) return 1;
|
|
23705
|
+
if (!b.prerelease) return -1;
|
|
23706
|
+
return a.prerelease.localeCompare(b.prerelease);
|
|
23707
|
+
}
|
|
23708
|
+
function isDowngradeAutoUpdateResponse(response) {
|
|
23709
|
+
const target = response?.latest?.trim();
|
|
23710
|
+
const current = response?.current?.trim() || SDK_VERSION;
|
|
23711
|
+
if (!target) return false;
|
|
23712
|
+
return compareSemver(target, current) < 0;
|
|
23713
|
+
}
|
|
23566
23714
|
function relaunchCurrentCommand(plan) {
|
|
23567
23715
|
return new Promise((resolve13) => {
|
|
23568
23716
|
const command = plan.kind === "python-sidecar" ? plan.sidecarPath : process.execPath;
|
|
@@ -23590,6 +23738,15 @@ async function maybeAutoUpdateAndRelaunch(response) {
|
|
|
23590
23738
|
if (!response || !autoUpdate?.should_auto_update || shouldSkipSelfUpdate()) {
|
|
23591
23739
|
return false;
|
|
23592
23740
|
}
|
|
23741
|
+
if (isDowngradeAutoUpdateResponse(response)) {
|
|
23742
|
+
const target = response.latest;
|
|
23743
|
+
const current = response.current?.trim() || SDK_VERSION;
|
|
23744
|
+
process.stderr.write(
|
|
23745
|
+
`Deepline SDK/CLI auto-update refused: server advertised older ${target} than current ${current}. Continuing without mutating the CLI.
|
|
23746
|
+
`
|
|
23747
|
+
);
|
|
23748
|
+
return false;
|
|
23749
|
+
}
|
|
23593
23750
|
const packageSpec = response.latest ? `deepline@${response.latest}` : void 0;
|
|
23594
23751
|
const plan = resolveUpdatePlan({ packageSpec });
|
|
23595
23752
|
if (plan.kind === "source") {
|