deepline 0.1.85 → 0.1.89
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/cli/index.js +419 -70
- package/dist/cli/index.mjs +438 -83
- package/dist/index.d.mts +442 -60
- package/dist/index.d.ts +442 -60
- package/dist/index.js +161 -4
- package/dist/index.mjs +161 -4
- package/dist/repo/apps/play-runner-workers/src/dedup-do.ts +1 -0
- package/dist/repo/apps/play-runner-workers/src/entry.ts +276 -192
- package/dist/repo/sdk/src/client.ts +155 -1
- package/dist/repo/sdk/src/http.ts +11 -0
- package/dist/repo/sdk/src/index.ts +24 -1
- package/dist/repo/sdk/src/play.ts +198 -15
- package/dist/repo/sdk/src/release.ts +2 -2
- package/dist/repo/sdk/src/types.ts +61 -0
- package/dist/repo/sdk/src/worker-play-entry.ts +6 -3
- package/dist/repo/shared_libs/play-runtime/cell-staleness.ts +23 -0
- package/dist/repo/shared_libs/play-runtime/coordinator-headers.ts +10 -0
- package/dist/repo/shared_libs/play-runtime/scheduler-backend.ts +10 -1
- package/dist/repo/shared_libs/play-runtime/tool-result.ts +202 -12
- package/dist/repo/shared_libs/plays/bundling/index.ts +23 -16
- package/dist/repo/shared_libs/plays/dataset.ts +2 -0
- package/dist/repo/shared_libs/plays/row-identity.ts +14 -8
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -206,10 +206,10 @@ import { join as join2 } from "path";
|
|
|
206
206
|
|
|
207
207
|
// src/release.ts
|
|
208
208
|
var SDK_RELEASE = {
|
|
209
|
-
version: "0.1.
|
|
209
|
+
version: "0.1.89",
|
|
210
210
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
211
211
|
supportPolicy: {
|
|
212
|
-
latest: "0.1.
|
|
212
|
+
latest: "0.1.89",
|
|
213
213
|
minimumSupported: "0.1.53",
|
|
214
214
|
deprecatedBelow: "0.1.53"
|
|
215
215
|
}
|
|
@@ -223,6 +223,7 @@ var SDK_API_CONTRACT = SDK_RELEASE.apiContract;
|
|
|
223
223
|
var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
|
|
224
224
|
var COORDINATOR_URL_OVERRIDE_HEADER = "x-deepline-coordinator-url";
|
|
225
225
|
var WORKER_CALLBACK_URL_OVERRIDE_HEADER = "x-deepline-worker-callback-url";
|
|
226
|
+
var SYNTHETIC_RUN_HEADER = "x-deepline-synthetic-run";
|
|
226
227
|
|
|
227
228
|
// src/http.ts
|
|
228
229
|
var MAX_DIAGNOSTIC_HEADER_LENGTH = 120;
|
|
@@ -290,6 +291,10 @@ var HttpClient = class {
|
|
|
290
291
|
if (workerCallbackUrl?.trim()) {
|
|
291
292
|
headers[WORKER_CALLBACK_URL_OVERRIDE_HEADER] = workerCallbackUrl.trim();
|
|
292
293
|
}
|
|
294
|
+
const syntheticRun = typeof process !== "undefined" ? process.env?.DEEPLINE_SYNTHETIC_RUN : void 0;
|
|
295
|
+
if (syntheticRun && syntheticRun.trim() && syntheticRun.trim() !== "0") {
|
|
296
|
+
headers[SYNTHETIC_RUN_HEADER] = "1";
|
|
297
|
+
}
|
|
293
298
|
return headers;
|
|
294
299
|
}
|
|
295
300
|
/**
|
|
@@ -556,7 +561,7 @@ function decodeSseFrame(frame) {
|
|
|
556
561
|
return parsed;
|
|
557
562
|
}
|
|
558
563
|
function sleep(ms) {
|
|
559
|
-
return new Promise((
|
|
564
|
+
return new Promise((resolve14) => setTimeout(resolve14, ms));
|
|
560
565
|
}
|
|
561
566
|
|
|
562
567
|
// src/client.ts
|
|
@@ -566,7 +571,7 @@ var EXECUTE_RESPONSE_CONTRACT_HEADER = "x-deepline-execute-response-contract";
|
|
|
566
571
|
var V2_EXECUTE_RESPONSE_CONTRACT = "v2-tool-response";
|
|
567
572
|
var COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1e3];
|
|
568
573
|
function sleep2(ms) {
|
|
569
|
-
return new Promise((
|
|
574
|
+
return new Promise((resolve14) => setTimeout(resolve14, ms));
|
|
570
575
|
}
|
|
571
576
|
function isTransientCompileManifestError(error) {
|
|
572
577
|
if (error instanceof DeeplineError && typeof error.statusCode === "number") {
|
|
@@ -580,6 +585,21 @@ function isTransientCompileManifestError(error) {
|
|
|
580
585
|
function isRecord(value) {
|
|
581
586
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
582
587
|
}
|
|
588
|
+
function isPrebuiltPlayDescription(play) {
|
|
589
|
+
return play.origin === "prebuilt" || play.ownerType === "deepline";
|
|
590
|
+
}
|
|
591
|
+
function preferPrebuiltPlayDescriptions(plays) {
|
|
592
|
+
const prebuilt = [];
|
|
593
|
+
const owned = [];
|
|
594
|
+
for (const play of plays) {
|
|
595
|
+
if (isPrebuiltPlayDescription(play)) {
|
|
596
|
+
prebuilt.push(play);
|
|
597
|
+
} else {
|
|
598
|
+
owned.push(play);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return [...prebuilt, ...owned];
|
|
602
|
+
}
|
|
583
603
|
function isPlayRunPackage(value) {
|
|
584
604
|
return Boolean(
|
|
585
605
|
value && typeof value === "object" && !Array.isArray(value) && value.kind === "play_run" && value.run && typeof value.run?.id === "string"
|
|
@@ -703,8 +723,14 @@ function playRunStatusFromState(state) {
|
|
|
703
723
|
var DeeplineClient = class {
|
|
704
724
|
http;
|
|
705
725
|
config;
|
|
726
|
+
/** Canonical run lifecycle namespace backed by `/api/v2/runs`. */
|
|
706
727
|
runs;
|
|
707
728
|
/**
|
|
729
|
+
* Create a low-level SDK client.
|
|
730
|
+
*
|
|
731
|
+
* Most callers can omit options and let the SDK resolve auth/config from
|
|
732
|
+
* environment variables and CLI-managed credentials.
|
|
733
|
+
*
|
|
708
734
|
* @param options - Optional overrides for API key, base URL, timeout, and retries.
|
|
709
735
|
* @throws {@link ConfigError} if no API key can be resolved from any source.
|
|
710
736
|
*/
|
|
@@ -806,12 +832,19 @@ var DeeplineClient = class {
|
|
|
806
832
|
// ——————————————————————————————————————————————————————————
|
|
807
833
|
// Secrets
|
|
808
834
|
// ——————————————————————————————————————————————————————————
|
|
835
|
+
/** List secret metadata visible to the current workspace. */
|
|
809
836
|
async listSecrets() {
|
|
810
837
|
const response = await this.http.get(
|
|
811
838
|
"/api/v2/secrets"
|
|
812
839
|
);
|
|
813
840
|
return Array.isArray(response.secrets) ? response.secrets : [];
|
|
814
841
|
}
|
|
842
|
+
/**
|
|
843
|
+
* Check whether a named secret exists, is active, and has a stored value.
|
|
844
|
+
*
|
|
845
|
+
* @param name - Secret name. It is normalized to uppercase before lookup.
|
|
846
|
+
* @returns Matching active secret metadata, or `null`.
|
|
847
|
+
*/
|
|
815
848
|
async checkSecret(name) {
|
|
816
849
|
const normalized = name.trim().toUpperCase();
|
|
817
850
|
const secrets = await this.listSecrets();
|
|
@@ -924,9 +957,21 @@ var DeeplineClient = class {
|
|
|
924
957
|
headers
|
|
925
958
|
);
|
|
926
959
|
}
|
|
960
|
+
/**
|
|
961
|
+
* Back-compatible alias for {@link executeTool}.
|
|
962
|
+
*
|
|
963
|
+
* Retained for callers that still use the older raw naming while the response
|
|
964
|
+
* envelope remains the same.
|
|
965
|
+
*/
|
|
927
966
|
async executeToolRaw(toolId, input2, options) {
|
|
928
967
|
return this.executeTool(toolId, input2, options);
|
|
929
968
|
}
|
|
969
|
+
/**
|
|
970
|
+
* Run a bounded SQL query against the customer data plane.
|
|
971
|
+
*
|
|
972
|
+
* Use this from trusted backend or agent contexts only. The API enforces
|
|
973
|
+
* workspace scoping and row limits.
|
|
974
|
+
*/
|
|
930
975
|
async queryCustomerDb(input2) {
|
|
931
976
|
return this.http.post("/api/v2/db/query", {
|
|
932
977
|
sql: input2.sql,
|
|
@@ -998,6 +1043,17 @@ var DeeplineClient = class {
|
|
|
998
1043
|
);
|
|
999
1044
|
return normalizePlayRunStart(response);
|
|
1000
1045
|
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Start a play run and stream live runtime events from the same request.
|
|
1048
|
+
*
|
|
1049
|
+
* Use this when a caller wants low-level event handling instead of submitting
|
|
1050
|
+
* first and then connecting to `streamPlayRunEvents(runId)`.
|
|
1051
|
+
*
|
|
1052
|
+
* @param request - Play run configuration.
|
|
1053
|
+
* @param options - Optional streaming options.
|
|
1054
|
+
* @param options.signal - Optional abort signal for the streaming request.
|
|
1055
|
+
* @returns Async stream of play-scoped live events.
|
|
1056
|
+
*/
|
|
1001
1057
|
async *startPlayRunStream(request, options) {
|
|
1002
1058
|
const body = {
|
|
1003
1059
|
...request.name ? { name: request.name } : {},
|
|
@@ -1050,6 +1106,12 @@ var DeeplineClient = class {
|
|
|
1050
1106
|
compilerManifest
|
|
1051
1107
|
});
|
|
1052
1108
|
}
|
|
1109
|
+
/**
|
|
1110
|
+
* Register multiple bundled play artifacts in one request.
|
|
1111
|
+
*
|
|
1112
|
+
* Used by packaging and prebuilt publication flows. Each artifact is compiled
|
|
1113
|
+
* first when a compiler manifest is not already supplied.
|
|
1114
|
+
*/
|
|
1053
1115
|
async registerPlayArtifacts(artifacts) {
|
|
1054
1116
|
const compiledArtifacts = await Promise.all(
|
|
1055
1117
|
artifacts.map(async (artifact) => ({
|
|
@@ -1066,6 +1128,13 @@ var DeeplineClient = class {
|
|
|
1066
1128
|
artifacts: compiledArtifacts
|
|
1067
1129
|
});
|
|
1068
1130
|
}
|
|
1131
|
+
/**
|
|
1132
|
+
* Compile a bundled play artifact into the server-side compiler manifest.
|
|
1133
|
+
*
|
|
1134
|
+
* The manifest records imports, trigger bindings, static pipeline shape, and
|
|
1135
|
+
* runtime metadata needed before a play artifact can be checked, registered,
|
|
1136
|
+
* or run.
|
|
1137
|
+
*/
|
|
1069
1138
|
async compilePlayManifest(input2) {
|
|
1070
1139
|
const retryDelays = COMPILE_MANIFEST_RETRY_DELAYS_MS.slice(
|
|
1071
1140
|
0,
|
|
@@ -1094,9 +1163,21 @@ var DeeplineClient = class {
|
|
|
1094
1163
|
async checkPlayArtifact(input2) {
|
|
1095
1164
|
return this.http.post("/api/v2/plays/check", input2);
|
|
1096
1165
|
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Compile legacy enrich command arguments into a runtime plan.
|
|
1168
|
+
*
|
|
1169
|
+
* This is primarily used by CLI compatibility paths that translate older
|
|
1170
|
+
* enrichment commands onto the play runtime.
|
|
1171
|
+
*/
|
|
1097
1172
|
async compileEnrichPlan(input2) {
|
|
1098
1173
|
return this.http.post("/api/v2/enrich/compile", input2);
|
|
1099
1174
|
}
|
|
1175
|
+
/**
|
|
1176
|
+
* Register an already-bundled play artifact and start a run from it.
|
|
1177
|
+
*
|
|
1178
|
+
* This is the low-level file-backed run path used by SDK/CLI packaging
|
|
1179
|
+
* wrappers after local bundling has produced the runtime artifact.
|
|
1180
|
+
*/
|
|
1100
1181
|
async startPlayRunFromBundle(input2) {
|
|
1101
1182
|
const compilerManifest = input2.compilerManifest ?? await this.compilePlayManifest({
|
|
1102
1183
|
name: input2.name,
|
|
@@ -1254,6 +1335,12 @@ var DeeplineClient = class {
|
|
|
1254
1335
|
const response = await this.http.postFormData("/api/v2/plays/files/stage", buildFormData);
|
|
1255
1336
|
return response.files;
|
|
1256
1337
|
}
|
|
1338
|
+
/**
|
|
1339
|
+
* Resolve staged play files by content hash without uploading bytes.
|
|
1340
|
+
*
|
|
1341
|
+
* Missing files are returned so callers can upload only the files the server
|
|
1342
|
+
* does not already have.
|
|
1343
|
+
*/
|
|
1257
1344
|
async resolveStagedPlayFiles(files) {
|
|
1258
1345
|
return this.http.post("/api/v2/plays/files/stage", { files });
|
|
1259
1346
|
}
|
|
@@ -1470,6 +1557,12 @@ var DeeplineClient = class {
|
|
|
1470
1557
|
entries
|
|
1471
1558
|
};
|
|
1472
1559
|
}
|
|
1560
|
+
/**
|
|
1561
|
+
* Export persisted runtime-sheet rows for a play dataset/table namespace.
|
|
1562
|
+
*
|
|
1563
|
+
* This is the SDK form of exporting `ctx.dataset(...).run()` output for a
|
|
1564
|
+
* specific play and optional run id.
|
|
1565
|
+
*/
|
|
1473
1566
|
async getPlaySheetRows(input2) {
|
|
1474
1567
|
const params = new URLSearchParams({
|
|
1475
1568
|
tableNamespace: input2.tableNamespace,
|
|
@@ -1498,6 +1591,12 @@ var DeeplineClient = class {
|
|
|
1498
1591
|
options?.reason ? { reason: options.reason } : {}
|
|
1499
1592
|
);
|
|
1500
1593
|
}
|
|
1594
|
+
/**
|
|
1595
|
+
* List callable plays visible to the workspace.
|
|
1596
|
+
*
|
|
1597
|
+
* Pass `origin: "prebuilt"` for Deepline-managed prebuilts or
|
|
1598
|
+
* `origin: "owned"` for org-owned plays.
|
|
1599
|
+
*/
|
|
1501
1600
|
async listPlays(options) {
|
|
1502
1601
|
const params = new URLSearchParams();
|
|
1503
1602
|
if (options?.origin) params.set("origin", options.origin);
|
|
@@ -1512,15 +1611,32 @@ var DeeplineClient = class {
|
|
|
1512
1611
|
);
|
|
1513
1612
|
return response.plays ?? [];
|
|
1514
1613
|
}
|
|
1614
|
+
/**
|
|
1615
|
+
* Search callable plays and return compact play descriptions.
|
|
1616
|
+
*
|
|
1617
|
+
* Prebuilt plays are preferred by default because they have maintained
|
|
1618
|
+
* contracts and stable run behavior.
|
|
1619
|
+
*/
|
|
1515
1620
|
async searchPlays(options) {
|
|
1516
1621
|
const params = new URLSearchParams();
|
|
1517
1622
|
params.set("search", options.query.trim());
|
|
1623
|
+
const scope = options.scope ?? "prebuilt";
|
|
1624
|
+
if (scope !== "all") {
|
|
1625
|
+
params.set("origin", scope);
|
|
1626
|
+
}
|
|
1518
1627
|
const response = await this.http.get(
|
|
1519
1628
|
`/api/v2/plays?${params.toString()}`
|
|
1520
1629
|
);
|
|
1521
|
-
|
|
1630
|
+
const plays = (response.plays ?? []).map(
|
|
1522
1631
|
(play) => this.summarizePlayListItem(play, options)
|
|
1523
1632
|
);
|
|
1633
|
+
if (scope === "prebuilt") {
|
|
1634
|
+
return plays.filter(isPrebuiltPlayDescription);
|
|
1635
|
+
}
|
|
1636
|
+
if (scope === "owned") {
|
|
1637
|
+
return plays.filter((play) => !isPrebuiltPlayDescription(play));
|
|
1638
|
+
}
|
|
1639
|
+
return preferPrebuiltPlayDescriptions(plays);
|
|
1524
1640
|
}
|
|
1525
1641
|
/**
|
|
1526
1642
|
* Get the full definition and state of a named play.
|
|
@@ -1543,6 +1659,12 @@ var DeeplineClient = class {
|
|
|
1543
1659
|
const encodedName = encodeURIComponent(name);
|
|
1544
1660
|
return this.http.get(`/api/v2/plays/${encodedName}`);
|
|
1545
1661
|
}
|
|
1662
|
+
/**
|
|
1663
|
+
* Get a normalized play description suitable for agents and CLIs.
|
|
1664
|
+
*
|
|
1665
|
+
* The description includes runnable examples, input/output summaries, clone
|
|
1666
|
+
* guidance, revision state, and latest run metadata when available.
|
|
1667
|
+
*/
|
|
1546
1668
|
async describePlay(name, options) {
|
|
1547
1669
|
const detail = await this.getPlay(name);
|
|
1548
1670
|
return this.summarizePlayDetail(detail, options);
|
|
@@ -2409,7 +2531,7 @@ function buildCandidateUrls2(url) {
|
|
|
2409
2531
|
}
|
|
2410
2532
|
}
|
|
2411
2533
|
function sleep3(ms) {
|
|
2412
|
-
return new Promise((
|
|
2534
|
+
return new Promise((resolve14) => setTimeout(resolve14, ms));
|
|
2413
2535
|
}
|
|
2414
2536
|
function printDeeplineLogo() {
|
|
2415
2537
|
if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
|
|
@@ -4677,7 +4799,12 @@ function readPackageVersionFromPackageJson(packageJsonPath, packageName) {
|
|
|
4677
4799
|
return null;
|
|
4678
4800
|
}
|
|
4679
4801
|
function findPackageJsonPathFrom(startDir, packageName) {
|
|
4680
|
-
|
|
4802
|
+
if (!isAbsolute(startDir)) {
|
|
4803
|
+
throw new Error(
|
|
4804
|
+
`Package resolution requires an absolute start directory, got ${startDir}`
|
|
4805
|
+
);
|
|
4806
|
+
}
|
|
4807
|
+
let current = startDir;
|
|
4681
4808
|
while (true) {
|
|
4682
4809
|
const packageJsonPath = join4(
|
|
4683
4810
|
current,
|
|
@@ -4697,17 +4824,15 @@ function findPackageJsonPathFrom(startDir, packageName) {
|
|
|
4697
4824
|
}
|
|
4698
4825
|
function findPackageJsonPath(packageName, fromFile, adapter) {
|
|
4699
4826
|
const startDirs = [
|
|
4700
|
-
dirname5(fromFile),
|
|
4701
|
-
adapter.projectRoot,
|
|
4702
|
-
dirname5(adapter.sdkPackageJson)
|
|
4703
|
-
process.cwd()
|
|
4827
|
+
resolve6(dirname5(fromFile)),
|
|
4828
|
+
resolve6(adapter.projectRoot),
|
|
4829
|
+
resolve6(dirname5(adapter.sdkPackageJson))
|
|
4704
4830
|
];
|
|
4705
4831
|
const seen = /* @__PURE__ */ new Set();
|
|
4706
4832
|
for (const startDir of startDirs) {
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
const packageJsonPath = findPackageJsonPathFrom(normalized, packageName);
|
|
4833
|
+
if (seen.has(startDir)) continue;
|
|
4834
|
+
seen.add(startDir);
|
|
4835
|
+
const packageJsonPath = findPackageJsonPathFrom(startDir, packageName);
|
|
4711
4836
|
if (packageJsonPath) return packageJsonPath;
|
|
4712
4837
|
}
|
|
4713
4838
|
const adapterNodeModulesPackageJson = join4(
|
|
@@ -5165,13 +5290,13 @@ async function writeArtifactCache(artifact, adapter) {
|
|
|
5165
5290
|
"utf-8"
|
|
5166
5291
|
);
|
|
5167
5292
|
}
|
|
5168
|
-
function normalizeSourceMapForRuntime(sourceMapText) {
|
|
5293
|
+
function normalizeSourceMapForRuntime(sourceMapText, projectRoot) {
|
|
5169
5294
|
const parsed = JSON.parse(sourceMapText);
|
|
5170
5295
|
parsed.sources = (parsed.sources ?? []).map((sourcePath) => {
|
|
5171
5296
|
if (sourcePath.startsWith("data:") || sourcePath.startsWith("node:") || sourcePath.startsWith("/") || /^[a-zA-Z]+:\/\//.test(sourcePath)) {
|
|
5172
5297
|
return sourcePath;
|
|
5173
5298
|
}
|
|
5174
|
-
return
|
|
5299
|
+
return join4(projectRoot, sourcePath);
|
|
5175
5300
|
});
|
|
5176
5301
|
parsed.sourceRoot = void 0;
|
|
5177
5302
|
return JSON.stringify(parsed);
|
|
@@ -5437,7 +5562,10 @@ workers-harness:${harnessFingerprint}`
|
|
|
5437
5562
|
};
|
|
5438
5563
|
}
|
|
5439
5564
|
const { bundledCode, sourceMapText, outputExtension } = buildOutcome;
|
|
5440
|
-
const normalizedSourceMap = normalizeSourceMapForRuntime(
|
|
5565
|
+
const normalizedSourceMap = normalizeSourceMapForRuntime(
|
|
5566
|
+
sourceMapText,
|
|
5567
|
+
resolve6(adapter.projectRoot)
|
|
5568
|
+
);
|
|
5441
5569
|
const virtualBaseName = exportName === "default" ? basename(absolutePath).replace(/\.[^.]+$/, "") : `${basename(absolutePath).replace(/\.[^.]+$/, "")}.${exportName}`;
|
|
5442
5570
|
const virtualFilename = `/virtual/deepline-plays/${analysis.graphHash}/${virtualBaseName}.${outputExtension}`;
|
|
5443
5571
|
const executableCode = `${bundledCode}
|
|
@@ -7845,7 +7973,7 @@ function traceCliSync(phase, fields, run) {
|
|
|
7845
7973
|
}
|
|
7846
7974
|
}
|
|
7847
7975
|
function sleep4(ms) {
|
|
7848
|
-
return new Promise((
|
|
7976
|
+
return new Promise((resolve14) => setTimeout(resolve14, ms));
|
|
7849
7977
|
}
|
|
7850
7978
|
function parseReferencedPlayTarget2(target) {
|
|
7851
7979
|
const trimmed = target.trim();
|
|
@@ -8364,6 +8492,8 @@ var TERMINAL_PLAY_STATUSES2 = /* @__PURE__ */ new Set([
|
|
|
8364
8492
|
"cancelled"
|
|
8365
8493
|
]);
|
|
8366
8494
|
var PLAY_START_TRANSIENT_RETRY_DELAYS_MS = [500, 1500];
|
|
8495
|
+
var PLAY_PROGRESS_HEARTBEAT_INTERVAL_MS = 15e3;
|
|
8496
|
+
var PLAY_STATUS_HEARTBEAT_INTERVAL_MS = 15e3;
|
|
8367
8497
|
function getEventPayload(event) {
|
|
8368
8498
|
return event.payload && typeof event.payload === "object" ? event.payload : {};
|
|
8369
8499
|
}
|
|
@@ -8424,6 +8554,7 @@ function extractTableNamespaceFromLiveEvent(event) {
|
|
|
8424
8554
|
const payload = getEventPayload(event);
|
|
8425
8555
|
const candidates = [
|
|
8426
8556
|
payload.artifactTableNamespace,
|
|
8557
|
+
payload.activeArtifactTableNamespace,
|
|
8427
8558
|
payload.tableNamespace,
|
|
8428
8559
|
payload.mapNodeId
|
|
8429
8560
|
];
|
|
@@ -8502,6 +8633,20 @@ function formatProgressCounts(input2) {
|
|
|
8502
8633
|
const failed = typeof input2.failed === "number" && Number.isFinite(input2.failed) && input2.failed > 0 ? `, failed ${formatInteger(input2.failed)}` : "";
|
|
8503
8634
|
return `${formatInteger(completed)}/${formatInteger(total)} (${percent}%)${failed}`;
|
|
8504
8635
|
}
|
|
8636
|
+
function formatProgressMessageSuffix(input2) {
|
|
8637
|
+
const message = typeof input2.message === "string" ? input2.message.trim() : "";
|
|
8638
|
+
if (!message) {
|
|
8639
|
+
return "";
|
|
8640
|
+
}
|
|
8641
|
+
const completed = typeof input2.completed === "number" && Number.isFinite(input2.completed) ? input2.completed : null;
|
|
8642
|
+
if (/^[\d,]+\s*\/\s*[\d,]+\s+rows processed$/i.test(message)) {
|
|
8643
|
+
return "";
|
|
8644
|
+
}
|
|
8645
|
+
if (completed !== null && completed > 0 && /rows?\s+queued\b/i.test(message)) {
|
|
8646
|
+
return "";
|
|
8647
|
+
}
|
|
8648
|
+
return ` - ${message}`;
|
|
8649
|
+
}
|
|
8505
8650
|
function getProgressLinesFromLiveEvent(event) {
|
|
8506
8651
|
const payload = getEventPayload(event);
|
|
8507
8652
|
if (event.type === "play.step.progress") {
|
|
@@ -8511,7 +8656,13 @@ function getProgressLinesFromLiveEvent(event) {
|
|
|
8511
8656
|
failed: payload.failed
|
|
8512
8657
|
});
|
|
8513
8658
|
if (!counts) return [];
|
|
8514
|
-
|
|
8659
|
+
const messageSuffix = formatProgressMessageSuffix({
|
|
8660
|
+
message: payload.message,
|
|
8661
|
+
completed: payload.completed
|
|
8662
|
+
});
|
|
8663
|
+
return [
|
|
8664
|
+
`progress ${formatProgressLabel(payload.stepId)}: ${counts}${messageSuffix}`
|
|
8665
|
+
];
|
|
8515
8666
|
}
|
|
8516
8667
|
if (event.type !== "play.run.snapshot" && event.type !== "play.run.final_status") {
|
|
8517
8668
|
return [];
|
|
@@ -8535,22 +8686,69 @@ function getProgressLinesFromLiveEvent(event) {
|
|
|
8535
8686
|
if (!counts) {
|
|
8536
8687
|
continue;
|
|
8537
8688
|
}
|
|
8689
|
+
const messageSuffix = formatProgressMessageSuffix({
|
|
8690
|
+
message: progress.message,
|
|
8691
|
+
completed: progress.completed
|
|
8692
|
+
});
|
|
8538
8693
|
lines.push(
|
|
8539
|
-
`progress ${formatProgressLabel(record.nodeId ?? progress.artifactTableNamespace)}: ${counts}`
|
|
8694
|
+
`progress ${formatProgressLabel(record.nodeId ?? progress.artifactTableNamespace)}: ${counts}${messageSuffix}`
|
|
8540
8695
|
);
|
|
8541
8696
|
}
|
|
8542
8697
|
return lines;
|
|
8543
8698
|
}
|
|
8699
|
+
function shouldPrintPlayProgressLine(input2) {
|
|
8700
|
+
if (!input2.signature) {
|
|
8701
|
+
return false;
|
|
8702
|
+
}
|
|
8703
|
+
return input2.lastProgressSignature !== input2.signature || input2.nowMs - input2.lastProgressHeartbeatAt >= PLAY_PROGRESS_HEARTBEAT_INTERVAL_MS;
|
|
8704
|
+
}
|
|
8544
8705
|
function printPlayProgressLines(input2) {
|
|
8545
8706
|
for (const line of input2.lines) {
|
|
8546
8707
|
const signature = line.trim();
|
|
8547
|
-
|
|
8708
|
+
const now = Date.now();
|
|
8709
|
+
if (!shouldPrintPlayProgressLine({
|
|
8710
|
+
signature,
|
|
8711
|
+
lastProgressSignature: input2.state.lastProgressSignature,
|
|
8712
|
+
lastProgressHeartbeatAt: input2.state.lastProgressHeartbeatAt,
|
|
8713
|
+
nowMs: now
|
|
8714
|
+
})) {
|
|
8548
8715
|
continue;
|
|
8549
8716
|
}
|
|
8550
8717
|
input2.state.lastProgressSignature = signature;
|
|
8718
|
+
input2.state.lastProgressHeartbeatAt = now;
|
|
8551
8719
|
input2.progress.writeLine(line);
|
|
8552
8720
|
}
|
|
8553
8721
|
}
|
|
8722
|
+
function getRunningHeartbeatLine(input2) {
|
|
8723
|
+
const status = getStatusFromLiveEvent(input2.event);
|
|
8724
|
+
if (status !== "queued" && status !== "running" && status !== "waiting") {
|
|
8725
|
+
return null;
|
|
8726
|
+
}
|
|
8727
|
+
const tableNamespace = extractTableNamespaceFromLiveEvent(input2.event);
|
|
8728
|
+
const target = tableNamespace ? formatProgressLabel(tableNamespace) : input2.playName;
|
|
8729
|
+
if (status === "queued") {
|
|
8730
|
+
return `queued ${target}: waiting for worker capacity`;
|
|
8731
|
+
}
|
|
8732
|
+
if (status === "waiting") {
|
|
8733
|
+
return `waiting ${target}: waiting on external work`;
|
|
8734
|
+
}
|
|
8735
|
+
return `running ${target}: still processing`;
|
|
8736
|
+
}
|
|
8737
|
+
function printPlayStatusHeartbeat(input2) {
|
|
8738
|
+
const now = Date.now();
|
|
8739
|
+
if (now - input2.state.lastStatusHeartbeatAt < PLAY_STATUS_HEARTBEAT_INTERVAL_MS) {
|
|
8740
|
+
return;
|
|
8741
|
+
}
|
|
8742
|
+
const line = getRunningHeartbeatLine({
|
|
8743
|
+
event: input2.event,
|
|
8744
|
+
playName: input2.playName
|
|
8745
|
+
});
|
|
8746
|
+
if (!line) {
|
|
8747
|
+
return;
|
|
8748
|
+
}
|
|
8749
|
+
input2.state.lastStatusHeartbeatAt = now;
|
|
8750
|
+
input2.progress.writeLine(line);
|
|
8751
|
+
}
|
|
8554
8752
|
function buildPlayDashboardUrl(baseUrl, playName) {
|
|
8555
8753
|
const trimmedBase = baseUrl.replace(/\/$/, "");
|
|
8556
8754
|
const encodedPlayName = encodeURIComponent(playName);
|
|
@@ -8633,11 +8831,20 @@ async function waitForPlayCompletionByStream(input2) {
|
|
|
8633
8831
|
progress: input2.progress
|
|
8634
8832
|
});
|
|
8635
8833
|
if (!input2.jsonOutput) {
|
|
8834
|
+
const progressLines = getProgressLinesFromLiveEvent(event);
|
|
8636
8835
|
printPlayProgressLines({
|
|
8637
|
-
lines:
|
|
8836
|
+
lines: progressLines,
|
|
8638
8837
|
state: input2.state,
|
|
8639
8838
|
progress: input2.progress
|
|
8640
8839
|
});
|
|
8840
|
+
if (progressLines.length === 0) {
|
|
8841
|
+
printPlayStatusHeartbeat({
|
|
8842
|
+
event,
|
|
8843
|
+
playName: input2.playName,
|
|
8844
|
+
state: input2.state,
|
|
8845
|
+
progress: input2.progress
|
|
8846
|
+
});
|
|
8847
|
+
}
|
|
8641
8848
|
}
|
|
8642
8849
|
const finalStatus = getFinalStatusFromLiveEvent(event);
|
|
8643
8850
|
if (finalStatus) {
|
|
@@ -8715,7 +8922,9 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
|
|
|
8715
8922
|
const state = {
|
|
8716
8923
|
lastLogIndex: 0,
|
|
8717
8924
|
emittedRunnerStarted: false,
|
|
8718
|
-
lastProgressSignature: null
|
|
8925
|
+
lastProgressSignature: null,
|
|
8926
|
+
lastProgressHeartbeatAt: 0,
|
|
8927
|
+
lastStatusHeartbeatAt: 0
|
|
8719
8928
|
};
|
|
8720
8929
|
const controller = new AbortController();
|
|
8721
8930
|
let timedOut = false;
|
|
@@ -8756,7 +8965,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
|
|
|
8756
8965
|
dashboardUrl,
|
|
8757
8966
|
noOpen: input2.noOpen
|
|
8758
8967
|
});
|
|
8759
|
-
input2.progress.phase(
|
|
8968
|
+
input2.progress.phase("running");
|
|
8760
8969
|
emittedDashboardUrl = true;
|
|
8761
8970
|
}
|
|
8762
8971
|
assertPlayWaitNotTimedOut({
|
|
@@ -8787,11 +8996,20 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
|
|
|
8787
8996
|
progress: input2.progress
|
|
8788
8997
|
});
|
|
8789
8998
|
if (!input2.jsonOutput) {
|
|
8999
|
+
const progressLines = getProgressLinesFromLiveEvent(event);
|
|
8790
9000
|
printPlayProgressLines({
|
|
8791
|
-
lines:
|
|
9001
|
+
lines: progressLines,
|
|
8792
9002
|
state,
|
|
8793
9003
|
progress: input2.progress
|
|
8794
9004
|
});
|
|
9005
|
+
if (progressLines.length === 0) {
|
|
9006
|
+
printPlayStatusHeartbeat({
|
|
9007
|
+
event,
|
|
9008
|
+
playName: input2.playName,
|
|
9009
|
+
state,
|
|
9010
|
+
progress: input2.progress
|
|
9011
|
+
});
|
|
9012
|
+
}
|
|
8795
9013
|
}
|
|
8796
9014
|
const finalStatus = getFinalStatusFromLiveEvent(event);
|
|
8797
9015
|
if (finalStatus) {
|
|
@@ -9391,6 +9609,17 @@ function getPlayRunPackage(status) {
|
|
|
9391
9609
|
const packaged = status.package;
|
|
9392
9610
|
return isPlayRunPackageValue(packaged) ? packaged : null;
|
|
9393
9611
|
}
|
|
9612
|
+
function withTerminalPlayIdentity(status, playName) {
|
|
9613
|
+
if (!playName.trim() || getPlayRunPackage(status)) {
|
|
9614
|
+
return status;
|
|
9615
|
+
}
|
|
9616
|
+
const record = status;
|
|
9617
|
+
const hasIdentity = typeof record.playName === "string" && record.playName.trim().length > 0 || typeof record.name === "string" && record.name.trim().length > 0 || Boolean(getStringField(record.run, "playName"));
|
|
9618
|
+
if (hasIdentity) {
|
|
9619
|
+
return status;
|
|
9620
|
+
}
|
|
9621
|
+
return { ...status, playName };
|
|
9622
|
+
}
|
|
9394
9623
|
function compactPlayStatus(status) {
|
|
9395
9624
|
const packaged = getPlayRunPackage(status);
|
|
9396
9625
|
if (packaged) {
|
|
@@ -9567,6 +9796,9 @@ function actionToCommand(action) {
|
|
|
9567
9796
|
if (record.kind === "deepline_run_inspect" && typeof record.runId === "string") {
|
|
9568
9797
|
return `deepline runs get ${record.runId} --json`;
|
|
9569
9798
|
}
|
|
9799
|
+
if (record.kind === "deepline_run_billing" && typeof record.runId === "string") {
|
|
9800
|
+
return `deepline runs get ${record.runId} --full --json | jq '.billing'`;
|
|
9801
|
+
}
|
|
9570
9802
|
if (record.kind === "deepline_run_export" && typeof record.runId === "string" && typeof record.datasetPath === "string") {
|
|
9571
9803
|
return `deepline runs export ${record.runId} --dataset ${shellSingleQuote(
|
|
9572
9804
|
record.datasetPath
|
|
@@ -9599,6 +9831,12 @@ function buildRunPackageTextLines(packaged) {
|
|
|
9599
9831
|
if (playName) {
|
|
9600
9832
|
lines.push(` play: ${playName}`);
|
|
9601
9833
|
}
|
|
9834
|
+
const next = packaged.next && typeof packaged.next === "object" && !Array.isArray(packaged.next) ? packaged.next : {};
|
|
9835
|
+
const billingCommand = actionToCommand(next.billing);
|
|
9836
|
+
if (billingCommand) {
|
|
9837
|
+
const costState = status === "completed" || status === "failed" || status === "cancelled" ? "finalizing" : "pending";
|
|
9838
|
+
lines.push(` cost: ${costState}`);
|
|
9839
|
+
}
|
|
9602
9840
|
for (const step of readRecordArray(packaged.steps).slice(0, 8)) {
|
|
9603
9841
|
const id = typeof step.id === "string" ? step.id : "step";
|
|
9604
9842
|
const kind = typeof step.kind === "string" ? step.kind : "step";
|
|
@@ -9615,12 +9853,12 @@ function buildRunPackageTextLines(packaged) {
|
|
|
9615
9853
|
);
|
|
9616
9854
|
}
|
|
9617
9855
|
}
|
|
9618
|
-
const next = packaged.next && typeof packaged.next === "object" && !Array.isArray(packaged.next) ? packaged.next : {};
|
|
9619
9856
|
const datasetActions = readFirstDatasetActions(packaged);
|
|
9620
9857
|
const inspectCommand = actionToCommand(next.inspect);
|
|
9621
9858
|
const queryCommand = actionToCommand(next.query) ?? actionToCommand(datasetActions.query);
|
|
9622
9859
|
const exportCommand = actionToCommand(next.export) ?? actionToCommand(datasetActions.exportCsv);
|
|
9623
9860
|
if (inspectCommand) lines.push(` inspect: ${inspectCommand}`);
|
|
9861
|
+
if (billingCommand) lines.push(` billing: ${billingCommand}`);
|
|
9624
9862
|
if (queryCommand) lines.push(` query: ${queryCommand}`);
|
|
9625
9863
|
if (exportCommand) lines.push(` export CSV: ${exportCommand}`);
|
|
9626
9864
|
return lines;
|
|
@@ -10662,11 +10900,14 @@ async function handleFileBackedRun(options) {
|
|
|
10662
10900
|
} else {
|
|
10663
10901
|
progress.fail();
|
|
10664
10902
|
}
|
|
10665
|
-
const outputStatus =
|
|
10666
|
-
|
|
10667
|
-
|
|
10668
|
-
|
|
10669
|
-
|
|
10903
|
+
const outputStatus = withTerminalPlayIdentity(
|
|
10904
|
+
await resolvePlayRunOutputStatus({
|
|
10905
|
+
client,
|
|
10906
|
+
status: finalStatus,
|
|
10907
|
+
fullJson: options.fullJson
|
|
10908
|
+
}),
|
|
10909
|
+
playName
|
|
10910
|
+
);
|
|
10670
10911
|
traceCliSync(
|
|
10671
10912
|
"cli.play_write_result",
|
|
10672
10913
|
{ targetKind: "file", playName },
|
|
@@ -10689,7 +10930,7 @@ async function handleFileBackedRun(options) {
|
|
|
10689
10930
|
dashboardUrl: resolvedDashboardUrl,
|
|
10690
10931
|
noOpen: options.noOpen
|
|
10691
10932
|
});
|
|
10692
|
-
progress.phase(
|
|
10933
|
+
progress.phase("started run");
|
|
10693
10934
|
progress.complete();
|
|
10694
10935
|
writeStartedPlayRun({
|
|
10695
10936
|
runId: started.workflowId,
|
|
@@ -10809,11 +11050,14 @@ async function handleNamedRun(options) {
|
|
|
10809
11050
|
} else {
|
|
10810
11051
|
progress.fail();
|
|
10811
11052
|
}
|
|
10812
|
-
const outputStatus =
|
|
10813
|
-
|
|
10814
|
-
|
|
10815
|
-
|
|
10816
|
-
|
|
11053
|
+
const outputStatus = withTerminalPlayIdentity(
|
|
11054
|
+
await resolvePlayRunOutputStatus({
|
|
11055
|
+
client,
|
|
11056
|
+
status: finalStatus,
|
|
11057
|
+
fullJson: options.fullJson
|
|
11058
|
+
}),
|
|
11059
|
+
playName
|
|
11060
|
+
);
|
|
10817
11061
|
traceCliSync(
|
|
10818
11062
|
"cli.play_write_result",
|
|
10819
11063
|
{ targetKind: "name", playName },
|
|
@@ -10836,7 +11080,7 @@ async function handleNamedRun(options) {
|
|
|
10836
11080
|
dashboardUrl: resolvedDashboardUrl,
|
|
10837
11081
|
noOpen: options.noOpen
|
|
10838
11082
|
});
|
|
10839
|
-
progress.phase(
|
|
11083
|
+
progress.phase("started run");
|
|
10840
11084
|
progress.complete();
|
|
10841
11085
|
writeStartedPlayRun({
|
|
10842
11086
|
runId: started.workflowId,
|
|
@@ -11324,16 +11568,19 @@ function parsePlaySearchOptions(args) {
|
|
|
11324
11568
|
const query = args[0]?.trim();
|
|
11325
11569
|
if (!query) {
|
|
11326
11570
|
throw new Error(
|
|
11327
|
-
"Usage: deepline plays search <query> [--compact] [--json]"
|
|
11571
|
+
"Usage: deepline plays search <query> [--all] [--compact] [--json]"
|
|
11328
11572
|
);
|
|
11329
11573
|
}
|
|
11330
11574
|
return {
|
|
11331
11575
|
query,
|
|
11332
11576
|
jsonOutput: argsWantJson(args),
|
|
11333
11577
|
compact: args.includes("--compact"),
|
|
11334
|
-
|
|
11578
|
+
scope: args.includes("--all") && !args.includes("--prebuilt") ? "all" : "prebuilt"
|
|
11335
11579
|
};
|
|
11336
11580
|
}
|
|
11581
|
+
function playSearchDisclaimer(scope) {
|
|
11582
|
+
return scope === "all" ? "Prebuilt-first search: Deepline-managed prebuilts are trusted, robust plays with maintained contracts, so they are listed before plays you created. Use created-play results only when you are specifically looking for one." : "Prebuilt-first search: Deepline-managed prebuilts are trusted, robust plays with maintained contracts. Plays you created are omitted by default; add --all only when you are specifically looking for one.";
|
|
11583
|
+
}
|
|
11337
11584
|
function printPlayDescription(play) {
|
|
11338
11585
|
const reference = formatPlayListReference(play);
|
|
11339
11586
|
const labels = [
|
|
@@ -11475,19 +11722,26 @@ async function handlePlaySearch(args) {
|
|
|
11475
11722
|
return 1;
|
|
11476
11723
|
}
|
|
11477
11724
|
const client = new DeeplineClient();
|
|
11478
|
-
const plays =
|
|
11725
|
+
const plays = await client.searchPlays({
|
|
11479
11726
|
query: options.query,
|
|
11480
|
-
compact: options.compact
|
|
11481
|
-
|
|
11482
|
-
|
|
11483
|
-
);
|
|
11727
|
+
compact: options.compact,
|
|
11728
|
+
scope: options.scope
|
|
11729
|
+
});
|
|
11730
|
+
const disclaimer = playSearchDisclaimer(options.scope);
|
|
11484
11731
|
if (options.jsonOutput) {
|
|
11485
|
-
const jsonPlays = options.
|
|
11732
|
+
const jsonPlays = options.scope === "prebuilt" ? plays.map((play) => ({
|
|
11486
11733
|
...play,
|
|
11487
11734
|
inputSchema: compactPlaySchema(play.inputSchema)
|
|
11488
11735
|
})) : plays;
|
|
11489
11736
|
process.stdout.write(
|
|
11490
11737
|
`${JSON.stringify({
|
|
11738
|
+
disclaimer,
|
|
11739
|
+
search_policy: {
|
|
11740
|
+
default_scope: "prebuilt",
|
|
11741
|
+
included_origins: options.scope === "all" ? ["prebuilt", "owned"] : ["prebuilt"],
|
|
11742
|
+
owned_plays_omitted: options.scope === "prebuilt",
|
|
11743
|
+
include_owned_flag: "--all"
|
|
11744
|
+
},
|
|
11491
11745
|
plays: jsonPlays,
|
|
11492
11746
|
total: jsonPlays.length,
|
|
11493
11747
|
truncated: false
|
|
@@ -11496,21 +11750,23 @@ async function handlePlaySearch(args) {
|
|
|
11496
11750
|
);
|
|
11497
11751
|
return 0;
|
|
11498
11752
|
}
|
|
11499
|
-
const displayPlays = options.
|
|
11753
|
+
const displayPlays = options.scope === "prebuilt" ? plays.slice(0, 5) : plays;
|
|
11754
|
+
process.stdout.write(`${disclaimer}
|
|
11755
|
+
`);
|
|
11500
11756
|
process.stdout.write(
|
|
11501
|
-
`${plays.length} plays found${options.
|
|
11757
|
+
`${plays.length} plays found${options.scope === "prebuilt" && plays.length > displayPlays.length ? `; showing top ${displayPlays.length}` : ""}:
|
|
11502
11758
|
|
|
11503
11759
|
`
|
|
11504
11760
|
);
|
|
11505
11761
|
for (const play of displayPlays) {
|
|
11506
|
-
if (options.
|
|
11762
|
+
if (options.scope === "prebuilt") {
|
|
11507
11763
|
printCompactPlaySearchResult(play);
|
|
11508
11764
|
} else {
|
|
11509
11765
|
printPlayDescription(play);
|
|
11510
11766
|
}
|
|
11511
11767
|
console.log("");
|
|
11512
11768
|
}
|
|
11513
|
-
if (options.
|
|
11769
|
+
if (options.scope === "prebuilt" && plays.length > displayPlays.length) {
|
|
11514
11770
|
console.log("Use --json for the full machine-readable result set.");
|
|
11515
11771
|
}
|
|
11516
11772
|
return 0;
|
|
@@ -11964,18 +12220,26 @@ Examples:
|
|
|
11964
12220
|
...options.json ? ["--json"] : []
|
|
11965
12221
|
]);
|
|
11966
12222
|
});
|
|
11967
|
-
const addPlaySearchCommand = (command) => command.description("Search
|
|
12223
|
+
const addPlaySearchCommand = (command) => command.description("Search Deepline prebuilt plays by task.").option(
|
|
12224
|
+
"--prebuilt",
|
|
12225
|
+
"Only show Deepline-managed prebuilt plays (default)"
|
|
12226
|
+
).option(
|
|
12227
|
+
"--all",
|
|
12228
|
+
"Also include plays you created after Deepline-managed prebuilts"
|
|
12229
|
+
).addHelpText(
|
|
11968
12230
|
"after",
|
|
11969
12231
|
`
|
|
11970
12232
|
Notes:
|
|
11971
|
-
Ranked discovery for workflows.
|
|
11972
|
-
|
|
11973
|
-
|
|
12233
|
+
Ranked discovery for workflows. Search defaults to Deepline-managed prebuilts
|
|
12234
|
+
because they are trusted, robust plays with maintained contracts. Use describe
|
|
12235
|
+
on a result before running it.
|
|
12236
|
+
Add --all only when you are specifically looking for a play you created.
|
|
11974
12237
|
The grep alias is the same ranked retrieval surface with a more literal name
|
|
11975
12238
|
for agents that are filtering the play registry.
|
|
11976
12239
|
|
|
11977
12240
|
Examples:
|
|
11978
12241
|
deepline plays search email
|
|
12242
|
+
deepline plays search email --all
|
|
11979
12243
|
deepline plays grep "linkedin to email" --compact --json
|
|
11980
12244
|
deepline plays describe person-linkedin-to-email --json
|
|
11981
12245
|
`
|
|
@@ -11983,6 +12247,7 @@ Examples:
|
|
|
11983
12247
|
process.exitCode = await handlePlaySearch([
|
|
11984
12248
|
query,
|
|
11985
12249
|
...options.prebuilt ? ["--prebuilt"] : [],
|
|
12250
|
+
...options.all ? ["--all"] : [],
|
|
11986
12251
|
...options.compact ? ["--compact"] : [],
|
|
11987
12252
|
...options.json ? ["--json"] : []
|
|
11988
12253
|
]);
|
|
@@ -13750,7 +14015,7 @@ async function readHiddenLine(prompt) {
|
|
|
13750
14015
|
if (typeof input.setRawMode === "function") input.setRawMode(true);
|
|
13751
14016
|
let value = "";
|
|
13752
14017
|
input.resume();
|
|
13753
|
-
return await new Promise((
|
|
14018
|
+
return await new Promise((resolve14, reject) => {
|
|
13754
14019
|
let settled = false;
|
|
13755
14020
|
const cleanup = () => {
|
|
13756
14021
|
input.off("data", onData);
|
|
@@ -13765,7 +14030,7 @@ async function readHiddenLine(prompt) {
|
|
|
13765
14030
|
settled = true;
|
|
13766
14031
|
output.write("\n");
|
|
13767
14032
|
cleanup();
|
|
13768
|
-
|
|
14033
|
+
resolve14(line);
|
|
13769
14034
|
};
|
|
13770
14035
|
const fail = (error) => {
|
|
13771
14036
|
if (settled) return;
|
|
@@ -13937,9 +14202,15 @@ Examples:
|
|
|
13937
14202
|
|
|
13938
14203
|
// src/cli/commands/tools.ts
|
|
13939
14204
|
import { Option } from "commander";
|
|
13940
|
-
import {
|
|
14205
|
+
import {
|
|
14206
|
+
chmodSync,
|
|
14207
|
+
existsSync as existsSync8,
|
|
14208
|
+
mkdtempSync,
|
|
14209
|
+
readFileSync as readFileSync7,
|
|
14210
|
+
writeFileSync as writeFileSync9
|
|
14211
|
+
} from "fs";
|
|
13941
14212
|
import { tmpdir as tmpdir4 } from "os";
|
|
13942
|
-
import { join as join10 } from "path";
|
|
14213
|
+
import { join as join10, resolve as resolve12 } from "path";
|
|
13943
14214
|
|
|
13944
14215
|
// src/tool-output.ts
|
|
13945
14216
|
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync8 } from "fs";
|
|
@@ -14530,7 +14801,13 @@ Examples:
|
|
|
14530
14801
|
).option(
|
|
14531
14802
|
"--json [payload]",
|
|
14532
14803
|
"Emit JSON output. Use `--input` or `--payload` for passing JSON params."
|
|
14533
|
-
).option(
|
|
14804
|
+
).option(
|
|
14805
|
+
"--input <payload>",
|
|
14806
|
+
"Merge a JSON object or @file path into the tool params"
|
|
14807
|
+
).option(
|
|
14808
|
+
"--payload <payload>",
|
|
14809
|
+
"Merge a JSON object or @file path into the tool params"
|
|
14810
|
+
).option(
|
|
14534
14811
|
"--output-format <format>",
|
|
14535
14812
|
"Output format: auto, csv, csv_file, json, or json_file"
|
|
14536
14813
|
).option(
|
|
@@ -15101,6 +15378,57 @@ function normalizeOutputFormat(raw) {
|
|
|
15101
15378
|
throw new Error(`Invalid value for --output-format: ${raw}`);
|
|
15102
15379
|
}
|
|
15103
15380
|
}
|
|
15381
|
+
function resolveAtFilePath(rawPath) {
|
|
15382
|
+
const trimmed = rawPath.trim();
|
|
15383
|
+
const resolved = resolve12(trimmed);
|
|
15384
|
+
if (existsSync8(resolved)) return resolved;
|
|
15385
|
+
if (process.platform !== "win32" && trimmed.includes("\\")) {
|
|
15386
|
+
const normalized = resolve12(trimmed.replace(/\\/g, "/"));
|
|
15387
|
+
if (existsSync8(normalized)) return normalized;
|
|
15388
|
+
}
|
|
15389
|
+
return resolved;
|
|
15390
|
+
}
|
|
15391
|
+
function readJsonArgument(raw, flagName) {
|
|
15392
|
+
if (!raw.startsWith("@")) return raw.replace(/^\uFEFF/, "");
|
|
15393
|
+
const filePath = raw.slice(1).trim();
|
|
15394
|
+
if (!filePath) {
|
|
15395
|
+
throw new Error(`Invalid ${flagName} value: empty @file path.`);
|
|
15396
|
+
}
|
|
15397
|
+
try {
|
|
15398
|
+
return readFileSync7(resolveAtFilePath(filePath), "utf8").replace(
|
|
15399
|
+
/^\uFEFF/,
|
|
15400
|
+
""
|
|
15401
|
+
);
|
|
15402
|
+
} catch (error) {
|
|
15403
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15404
|
+
throw new Error(
|
|
15405
|
+
`Failed to read ${flagName} file '${filePath}': ${message}`
|
|
15406
|
+
);
|
|
15407
|
+
}
|
|
15408
|
+
}
|
|
15409
|
+
function invalidJsonError(flagName, message) {
|
|
15410
|
+
const error = new Error(
|
|
15411
|
+
`Invalid JSON in ${flagName}: ${message}`
|
|
15412
|
+
);
|
|
15413
|
+
error.code = "INVALID_JSON";
|
|
15414
|
+
return error;
|
|
15415
|
+
}
|
|
15416
|
+
function parseJsonObjectArgument(raw, flagName) {
|
|
15417
|
+
let parsed;
|
|
15418
|
+
try {
|
|
15419
|
+
parsed = JSON.parse(readJsonArgument(raw, flagName));
|
|
15420
|
+
} catch (error) {
|
|
15421
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15422
|
+
if (message.startsWith("Failed to read ") || message.startsWith("Invalid ")) {
|
|
15423
|
+
throw error;
|
|
15424
|
+
}
|
|
15425
|
+
throw invalidJsonError(flagName, message);
|
|
15426
|
+
}
|
|
15427
|
+
if (!isRecord5(parsed)) {
|
|
15428
|
+
throw invalidJsonError(flagName, "expected an object.");
|
|
15429
|
+
}
|
|
15430
|
+
return parsed;
|
|
15431
|
+
}
|
|
15104
15432
|
function parseExecuteOptions(args) {
|
|
15105
15433
|
const toolId = args[0];
|
|
15106
15434
|
if (!toolId) {
|
|
@@ -15123,12 +15451,15 @@ function parseExecuteOptions(args) {
|
|
|
15123
15451
|
const next = args[index + 1];
|
|
15124
15452
|
outputFormat = "json";
|
|
15125
15453
|
if (next && !next.startsWith("--")) {
|
|
15126
|
-
Object.assign(
|
|
15454
|
+
Object.assign(
|
|
15455
|
+
params,
|
|
15456
|
+
parseJsonObjectArgument(args[++index], "--json")
|
|
15457
|
+
);
|
|
15127
15458
|
}
|
|
15128
15459
|
continue;
|
|
15129
15460
|
}
|
|
15130
15461
|
if ((arg === "--input" || arg === "--payload") && args[index + 1]) {
|
|
15131
|
-
Object.assign(params,
|
|
15462
|
+
Object.assign(params, parseJsonObjectArgument(args[++index], arg));
|
|
15132
15463
|
continue;
|
|
15133
15464
|
}
|
|
15134
15465
|
if (arg === "--output-format" && args[index + 1]) {
|
|
@@ -15448,8 +15779,8 @@ async function executeTool(args) {
|
|
|
15448
15779
|
|
|
15449
15780
|
// src/cli/commands/update.ts
|
|
15450
15781
|
import { spawn } from "child_process";
|
|
15451
|
-
import { existsSync as
|
|
15452
|
-
import { dirname as dirname9, join as join11, resolve as
|
|
15782
|
+
import { existsSync as existsSync9 } from "fs";
|
|
15783
|
+
import { dirname as dirname9, join as join11, resolve as resolve13 } from "path";
|
|
15453
15784
|
function posixShellQuote(value) {
|
|
15454
15785
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
15455
15786
|
}
|
|
@@ -15468,9 +15799,9 @@ function buildSourceUpdateCommand(sourceRoot) {
|
|
|
15468
15799
|
return `${cdCommand} && git fetch origin main --tags && git merge --ff-only origin/main`;
|
|
15469
15800
|
}
|
|
15470
15801
|
function findRepoBackedSdkRoot(startPath) {
|
|
15471
|
-
let current =
|
|
15802
|
+
let current = resolve13(startPath);
|
|
15472
15803
|
while (true) {
|
|
15473
|
-
if (
|
|
15804
|
+
if (existsSync9(join11(current, "sdk", "package.json")) && existsSync9(join11(current, "sdk", "bin", "deepline-dev.ts"))) {
|
|
15474
15805
|
return current;
|
|
15475
15806
|
}
|
|
15476
15807
|
const parent = dirname9(current);
|
|
@@ -15479,7 +15810,7 @@ function findRepoBackedSdkRoot(startPath) {
|
|
|
15479
15810
|
}
|
|
15480
15811
|
}
|
|
15481
15812
|
function resolveUpdatePlan() {
|
|
15482
|
-
const entrypoint = process.argv[1] ?
|
|
15813
|
+
const entrypoint = process.argv[1] ? resolve13(process.argv[1]) : "";
|
|
15483
15814
|
const sourceRoot = entrypoint ? findRepoBackedSdkRoot(dirname9(entrypoint)) : null;
|
|
15484
15815
|
if (sourceRoot) {
|
|
15485
15816
|
return {
|
|
@@ -15713,7 +16044,7 @@ function commandCompatibilityHint(currentFamily, commandName, baseUrl) {
|
|
|
15713
16044
|
lines.push(
|
|
15714
16045
|
"",
|
|
15715
16046
|
" To stay on the SDK CLI, install the SDK agent skill:",
|
|
15716
|
-
` ${skillsInstallCommand(baseUrl, "deepline-
|
|
16047
|
+
` ${skillsInstallCommand(baseUrl, "deepline-plays")}`,
|
|
15717
16048
|
" To use the legacy Python CLI instead:",
|
|
15718
16049
|
` ${legacyPythonInstallCommand(baseUrl)}`,
|
|
15719
16050
|
" `deepline update` updates this SDK CLI, but it will not switch CLI families."
|
|
@@ -15726,7 +16057,7 @@ function commandCompatibilityHint(currentFamily, commandName, baseUrl) {
|
|
|
15726
16057
|
"",
|
|
15727
16058
|
" To use SDK commands, install the SDK CLI and SDK agent skill:",
|
|
15728
16059
|
` ${sdkNpmGlobalInstallCommand()}`,
|
|
15729
|
-
` ${skillsInstallCommand(baseUrl, "deepline-
|
|
16060
|
+
` ${skillsInstallCommand(baseUrl, "deepline-plays")}`,
|
|
15730
16061
|
" `deepline update` updates this Python CLI and its skills, but it will not switch CLI families."
|
|
15731
16062
|
);
|
|
15732
16063
|
if (compatibility.python_alternative) {
|
|
@@ -15744,22 +16075,39 @@ function unknownCommandNameFromMessage(message) {
|
|
|
15744
16075
|
// src/cli/skills-sync.ts
|
|
15745
16076
|
import { spawn as spawn2, spawnSync } from "child_process";
|
|
15746
16077
|
import {
|
|
15747
|
-
existsSync as
|
|
16078
|
+
existsSync as existsSync10,
|
|
15748
16079
|
mkdirSync as mkdirSync5,
|
|
15749
16080
|
readdirSync as readdirSync2,
|
|
15750
|
-
readFileSync as
|
|
16081
|
+
readFileSync as readFileSync8,
|
|
15751
16082
|
statSync as statSync2,
|
|
15752
16083
|
writeFileSync as writeFileSync10
|
|
15753
16084
|
} from "fs";
|
|
15754
16085
|
import { homedir as homedir6 } from "os";
|
|
15755
16086
|
import { dirname as dirname10, join as join12 } from "path";
|
|
15756
16087
|
var CHECK_TIMEOUT_MS2 = 3e3;
|
|
15757
|
-
var SDK_SKILL_NAME = "deepline-
|
|
16088
|
+
var SDK_SKILL_NAME = "deepline-plays";
|
|
15758
16089
|
var attemptedSync = false;
|
|
15759
16090
|
function shouldSkipSkillsSync() {
|
|
15760
16091
|
const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
|
|
15761
16092
|
return value === "1" || value === "true" || value === "yes" || value === "on";
|
|
15762
16093
|
}
|
|
16094
|
+
function activePluginSkillsDir() {
|
|
16095
|
+
const pluginMode = process.env.DEEPLINE_PLUGIN_MODE?.trim().toLowerCase();
|
|
16096
|
+
if (pluginMode !== "true" && pluginMode !== "1" && pluginMode !== "yes" && pluginMode !== "on") {
|
|
16097
|
+
return "";
|
|
16098
|
+
}
|
|
16099
|
+
const dir = process.env.DEEPLINE_PLUGIN_SKILLS_DIR?.trim() ?? "";
|
|
16100
|
+
return dir && existsSync10(dir) ? dir : "";
|
|
16101
|
+
}
|
|
16102
|
+
function readPluginSkillsVersion() {
|
|
16103
|
+
const dir = activePluginSkillsDir();
|
|
16104
|
+
if (!dir) return "";
|
|
16105
|
+
try {
|
|
16106
|
+
return readFileSync8(join12(dir, ".version"), "utf-8").trim();
|
|
16107
|
+
} catch {
|
|
16108
|
+
return "";
|
|
16109
|
+
}
|
|
16110
|
+
}
|
|
15763
16111
|
function sdkSkillsVersionPath(baseUrl) {
|
|
15764
16112
|
const home = process.env.HOME?.trim() || homedir6();
|
|
15765
16113
|
return join12(
|
|
@@ -15772,10 +16120,12 @@ function sdkSkillsVersionPath(baseUrl) {
|
|
|
15772
16120
|
);
|
|
15773
16121
|
}
|
|
15774
16122
|
function readLocalSkillsVersion(baseUrl) {
|
|
16123
|
+
const pluginVersion = readPluginSkillsVersion();
|
|
16124
|
+
if (pluginVersion) return pluginVersion;
|
|
15775
16125
|
const path = sdkSkillsVersionPath(baseUrl);
|
|
15776
|
-
if (!
|
|
16126
|
+
if (!existsSync10(path)) return "";
|
|
15777
16127
|
try {
|
|
15778
|
-
return
|
|
16128
|
+
return readFileSync8(path, "utf-8").trim();
|
|
15779
16129
|
} catch {
|
|
15780
16130
|
return "";
|
|
15781
16131
|
}
|
|
@@ -15788,7 +16138,8 @@ function writeLocalSkillsVersion(baseUrl, version) {
|
|
|
15788
16138
|
}
|
|
15789
16139
|
function installedSdkSkillHasStalePositionalExecuteExamples() {
|
|
15790
16140
|
const home = process.env.HOME?.trim() || homedir6();
|
|
15791
|
-
const
|
|
16141
|
+
const pluginSkillsDir = activePluginSkillsDir();
|
|
16142
|
+
const roots = pluginSkillsDir ? [join12(pluginSkillsDir, SDK_SKILL_NAME)] : [
|
|
15792
16143
|
join12(home, ".claude", "skills", SDK_SKILL_NAME),
|
|
15793
16144
|
join12(home, ".agents", "skills", SDK_SKILL_NAME)
|
|
15794
16145
|
];
|
|
@@ -15808,14 +16159,14 @@ function installedSdkSkillHasStalePositionalExecuteExamples() {
|
|
|
15808
16159
|
continue;
|
|
15809
16160
|
}
|
|
15810
16161
|
if (!entry.endsWith(".md")) continue;
|
|
15811
|
-
const text =
|
|
16162
|
+
const text = readFileSync8(path, "utf-8");
|
|
15812
16163
|
if (staleMarkers.some((marker) => text.includes(marker))) return true;
|
|
15813
16164
|
}
|
|
15814
16165
|
return false;
|
|
15815
16166
|
};
|
|
15816
16167
|
for (const root of roots) {
|
|
15817
16168
|
try {
|
|
15818
|
-
if (
|
|
16169
|
+
if (existsSync10(root) && scan(root)) return true;
|
|
15819
16170
|
} catch {
|
|
15820
16171
|
continue;
|
|
15821
16172
|
}
|
|
@@ -15887,7 +16238,7 @@ function resolveSkillsInstallCommands(baseUrl) {
|
|
|
15887
16238
|
return [npxInstall];
|
|
15888
16239
|
}
|
|
15889
16240
|
function runOneSkillsInstall(install) {
|
|
15890
|
-
return new Promise((
|
|
16241
|
+
return new Promise((resolve14) => {
|
|
15891
16242
|
const child = spawn2(install.command, install.args, {
|
|
15892
16243
|
stdio: ["ignore", "ignore", "pipe"],
|
|
15893
16244
|
env: process.env
|
|
@@ -15897,7 +16248,7 @@ function runOneSkillsInstall(install) {
|
|
|
15897
16248
|
stderr += chunk.toString("utf-8");
|
|
15898
16249
|
});
|
|
15899
16250
|
child.on("error", (error) => {
|
|
15900
|
-
|
|
16251
|
+
resolve14({
|
|
15901
16252
|
ok: false,
|
|
15902
16253
|
detail: `failed to start ${install.command}: ${error.message}`,
|
|
15903
16254
|
manualCommand: install.manualCommand
|
|
@@ -15905,11 +16256,11 @@ function runOneSkillsInstall(install) {
|
|
|
15905
16256
|
});
|
|
15906
16257
|
child.on("close", (code) => {
|
|
15907
16258
|
if (code === 0) {
|
|
15908
|
-
|
|
16259
|
+
resolve14({ ok: true, detail: "", manualCommand: install.manualCommand });
|
|
15909
16260
|
return;
|
|
15910
16261
|
}
|
|
15911
16262
|
const detail = stderr.trim();
|
|
15912
|
-
|
|
16263
|
+
resolve14({
|
|
15913
16264
|
ok: false,
|
|
15914
16265
|
detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
|
|
15915
16266
|
manualCommand: install.manualCommand
|
|
@@ -15946,18 +16297,22 @@ function writeSdkSkillsStatusLine(line) {
|
|
|
15946
16297
|
async function syncSdkSkillsIfNeeded(baseUrl) {
|
|
15947
16298
|
if (attemptedSync || shouldSkipSkillsSync()) return;
|
|
15948
16299
|
attemptedSync = true;
|
|
16300
|
+
const usingPluginSkills = Boolean(activePluginSkillsDir());
|
|
15949
16301
|
const localVersion = readLocalSkillsVersion(baseUrl);
|
|
15950
16302
|
const update = await fetchSkillsUpdate(baseUrl, localVersion);
|
|
15951
16303
|
const hasStaleInstalledSkill = installedSdkSkillHasStalePositionalExecuteExamples();
|
|
16304
|
+
if (usingPluginSkills) {
|
|
16305
|
+
return;
|
|
16306
|
+
}
|
|
15952
16307
|
if (!update?.needsUpdate && !hasStaleInstalledSkill || !update?.remoteVersion) {
|
|
15953
16308
|
return;
|
|
15954
16309
|
}
|
|
15955
|
-
writeSdkSkillsStatusLine("SDK skills changed; syncing deepline-
|
|
16310
|
+
writeSdkSkillsStatusLine("SDK skills changed; syncing deepline-plays skill...");
|
|
15956
16311
|
const installed = await runSkillsInstall(baseUrl);
|
|
15957
16312
|
if (!installed) return;
|
|
15958
16313
|
if (installedSdkSkillHasStalePositionalExecuteExamples()) {
|
|
15959
16314
|
process.stderr.write(
|
|
15960
|
-
"SDK skills sync completed, but installed deepline-
|
|
16315
|
+
"SDK skills sync completed, but installed deepline-plays docs still contain stale positional ctx.tools.execute examples.\n"
|
|
15961
16316
|
);
|
|
15962
16317
|
return;
|
|
15963
16318
|
}
|