deepline 0.1.63 → 0.1.65
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 +933 -533
- package/dist/cli/index.mjs +837 -421
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +102 -49
- package/dist/index.mjs +98 -45
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +9 -10
- package/dist/repo/apps/play-runner-workers/src/runtime/dataset-handles.ts +36 -27
- package/dist/repo/apps/play-runner-workers/src/runtime/tool-http-errors.ts +5 -2
- package/dist/repo/sdk/src/client.ts +71 -63
- package/dist/repo/sdk/src/errors.ts +5 -1
- package/dist/repo/sdk/src/http.ts +69 -17
- package/dist/repo/sdk/src/plays/local-file-discovery.ts +93 -24
- package/dist/repo/sdk/src/release.ts +2 -2
- package/dist/repo/sdk/src/tool-output.ts +40 -20
- package/dist/repo/shared_libs/play-runtime/batch-runtime.ts +10 -3
- package/dist/repo/shared_libs/play-runtime/batching-types.ts +15 -4
- package/dist/repo/shared_libs/play-runtime/coordinator-headers.ts +2 -1
- package/dist/repo/shared_libs/play-runtime/dedup-backend.ts +0 -0
- package/dist/repo/shared_libs/play-runtime/default-batch-strategies.ts +3 -4
- package/dist/repo/shared_libs/play-runtime/run-failure.ts +1 -3
- package/dist/repo/shared_libs/play-runtime/step-lifecycle-tracker.ts +4 -1
- package/dist/repo/shared_libs/play-runtime/tool-batch-executor.ts +4 -1
- package/dist/repo/shared_libs/plays/dataset.ts +10 -11
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli/index.ts
|
|
4
4
|
import { mkdtemp, rm, writeFile as writeFile4 } from "fs/promises";
|
|
5
|
-
import { join as
|
|
5
|
+
import { join as join12 } from "path";
|
|
6
6
|
import { tmpdir as tmpdir4 } from "os";
|
|
7
7
|
import { Command as Command3 } from "commander";
|
|
8
8
|
|
|
@@ -34,7 +34,11 @@ var RateLimitError = class extends DeeplineError {
|
|
|
34
34
|
/** Milliseconds to wait before retrying, from the `Retry-After` response header. Defaults to 5000. */
|
|
35
35
|
retryAfterMs;
|
|
36
36
|
constructor(retryAfterMs = 5e3, message) {
|
|
37
|
-
super(
|
|
37
|
+
super(
|
|
38
|
+
message ?? `Rate limited. Retry after ${retryAfterMs}ms.`,
|
|
39
|
+
429,
|
|
40
|
+
"RATE_LIMIT"
|
|
41
|
+
);
|
|
38
42
|
this.name = "RateLimitError";
|
|
39
43
|
this.retryAfterMs = retryAfterMs;
|
|
40
44
|
}
|
|
@@ -195,12 +199,17 @@ function resolveConfig(options) {
|
|
|
195
199
|
};
|
|
196
200
|
}
|
|
197
201
|
|
|
202
|
+
// src/http.ts
|
|
203
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
204
|
+
import { homedir as homedir2 } from "os";
|
|
205
|
+
import { join as join2 } from "path";
|
|
206
|
+
|
|
198
207
|
// src/release.ts
|
|
199
208
|
var SDK_RELEASE = {
|
|
200
|
-
version: "0.1.
|
|
209
|
+
version: "0.1.65",
|
|
201
210
|
apiContract: "2026-05-play-bootstrap-dataset-summary",
|
|
202
211
|
supportPolicy: {
|
|
203
|
-
latest: "0.1.
|
|
212
|
+
latest: "0.1.65",
|
|
204
213
|
minimumSupported: "0.1.53",
|
|
205
214
|
deprecatedBelow: "0.1.53"
|
|
206
215
|
}
|
|
@@ -216,19 +225,51 @@ var COORDINATOR_URL_OVERRIDE_HEADER = "x-deepline-coordinator-url";
|
|
|
216
225
|
var WORKER_CALLBACK_URL_OVERRIDE_HEADER = "x-deepline-worker-callback-url";
|
|
217
226
|
|
|
218
227
|
// src/http.ts
|
|
228
|
+
var MAX_DIAGNOSTIC_HEADER_LENGTH = 120;
|
|
219
229
|
var HttpClient = class {
|
|
220
230
|
constructor(config) {
|
|
221
231
|
this.config = config;
|
|
222
232
|
}
|
|
223
233
|
config;
|
|
234
|
+
cleanDiagnosticHeader(value) {
|
|
235
|
+
const normalized = String(value ?? "").replace(/[\u0000-\u001f\u007f]/g, " ").trim().slice(0, MAX_DIAGNOSTIC_HEADER_LENGTH);
|
|
236
|
+
return normalized || null;
|
|
237
|
+
}
|
|
238
|
+
readSkillsVersionHeader() {
|
|
239
|
+
const explicit = this.cleanDiagnosticHeader(
|
|
240
|
+
process.env.DEEPLINE_SKILLS_VERSION
|
|
241
|
+
);
|
|
242
|
+
if (explicit) return explicit;
|
|
243
|
+
try {
|
|
244
|
+
const versionPath = join2(
|
|
245
|
+
process.env.HOME?.trim() || homedir2(),
|
|
246
|
+
".local",
|
|
247
|
+
"deepline",
|
|
248
|
+
baseUrlSlug(this.config.baseUrl),
|
|
249
|
+
"sdk-skills",
|
|
250
|
+
".version"
|
|
251
|
+
);
|
|
252
|
+
if (!existsSync2(versionPath)) return null;
|
|
253
|
+
return this.cleanDiagnosticHeader(readFileSync2(versionPath, "utf-8"));
|
|
254
|
+
} catch {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
224
258
|
authHeaders(extra) {
|
|
225
259
|
const headers = {
|
|
226
|
-
|
|
260
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
227
261
|
"User-Agent": `deepline-ts-sdk/${SDK_VERSION}`,
|
|
262
|
+
"X-Deepline-Client-Family": "sdk",
|
|
263
|
+
"X-Deepline-CLI-Family": "sdk",
|
|
264
|
+
"X-Deepline-CLI-Version": SDK_VERSION,
|
|
228
265
|
"X-Deepline-SDK-Version": SDK_VERSION,
|
|
229
266
|
"X-Deepline-API-Contract": SDK_API_CONTRACT,
|
|
230
267
|
...extra
|
|
231
268
|
};
|
|
269
|
+
const skillsVersion = this.readSkillsVersionHeader();
|
|
270
|
+
if (skillsVersion) {
|
|
271
|
+
headers["X-Deepline-Skills-Version"] = skillsVersion;
|
|
272
|
+
}
|
|
232
273
|
const bypassToken = typeof process !== "undefined" ? process.env?.VERCEL_PROTECTION_BYPASS_TOKEN : void 0;
|
|
233
274
|
if (bypassToken) {
|
|
234
275
|
headers["x-vercel-protection-bypass"] = bypassToken;
|
|
@@ -906,31 +947,34 @@ var DeeplineClient = class {
|
|
|
906
947
|
* artifactStorageKey: 'plays/v1/orgs/acme/plays/my-play/artifacts/playgraph_abc123.json',
|
|
907
948
|
* });
|
|
908
949
|
* ```
|
|
909
|
-
|
|
950
|
+
*/
|
|
910
951
|
async startPlayRun(request) {
|
|
911
|
-
const response = await this.http.post(
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
952
|
+
const response = await this.http.post(
|
|
953
|
+
"/api/v2/plays/run",
|
|
954
|
+
{
|
|
955
|
+
...request.name ? { name: request.name } : {},
|
|
956
|
+
...request.revisionId ? { revisionId: request.revisionId } : {},
|
|
957
|
+
...request.artifactStorageKey ? { artifactStorageKey: request.artifactStorageKey } : {},
|
|
958
|
+
...request.sourceCode ? { sourceCode: request.sourceCode } : {},
|
|
959
|
+
...request.sourceFiles ? { sourceFiles: request.sourceFiles } : {},
|
|
960
|
+
..."staticPipeline" in request ? { staticPipeline: request.staticPipeline } : {},
|
|
961
|
+
...request.artifactHash ? { artifactHash: request.artifactHash } : {},
|
|
962
|
+
...request.graphHash ? { graphHash: request.graphHash } : {},
|
|
963
|
+
...request.runtimeArtifact ? { runtimeArtifact: request.runtimeArtifact } : {},
|
|
964
|
+
...request.compilerManifest ? { compilerManifest: request.compilerManifest } : {},
|
|
965
|
+
...request.inputFileUpload ? { inputFileUpload: request.inputFileUpload } : {},
|
|
966
|
+
...request.packagedFileUploads?.length ? { packagedFileUploads: request.packagedFileUploads } : {},
|
|
967
|
+
...request.input ? { input: request.input } : {},
|
|
968
|
+
...request.inputFile ? { inputFile: request.inputFile } : {},
|
|
969
|
+
...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
|
|
970
|
+
...request.force ? { force: true } : {},
|
|
971
|
+
...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
|
|
972
|
+
// Profile selection is the API's job, not the CLI's. The server
|
|
973
|
+
// hardcodes workers_edge as the default; tests that want a
|
|
974
|
+
// different profile pass `request.profile` explicitly.
|
|
975
|
+
...request.profile ? { profile: request.profile } : {}
|
|
976
|
+
}
|
|
977
|
+
);
|
|
934
978
|
return normalizePlayRunStart(response);
|
|
935
979
|
}
|
|
936
980
|
async *startPlayRunStream(request, options) {
|
|
@@ -1182,10 +1226,7 @@ var DeeplineClient = class {
|
|
|
1182
1226
|
}
|
|
1183
1227
|
return formData;
|
|
1184
1228
|
};
|
|
1185
|
-
const response = await this.http.postFormData(
|
|
1186
|
-
"/api/v2/plays/files/stage",
|
|
1187
|
-
buildFormData
|
|
1188
|
-
);
|
|
1229
|
+
const response = await this.http.postFormData("/api/v2/plays/files/stage", buildFormData);
|
|
1189
1230
|
return response.files;
|
|
1190
1231
|
}
|
|
1191
1232
|
async resolveStagedPlayFiles(files) {
|
|
@@ -1632,7 +1673,9 @@ var DeeplineClient = class {
|
|
|
1632
1673
|
}
|
|
1633
1674
|
options?.onProgress?.(status);
|
|
1634
1675
|
if (TERMINAL_PLAY_STATUSES.has(status.status)) {
|
|
1635
|
-
const finalStatus = await this.getPlayStatus(
|
|
1676
|
+
const finalStatus = await this.getPlayStatus(
|
|
1677
|
+
status.runId || workflowId
|
|
1678
|
+
).catch(() => status);
|
|
1636
1679
|
return playRunResultFromStatus(finalStatus, start, workflowId);
|
|
1637
1680
|
}
|
|
1638
1681
|
}
|
|
@@ -1715,20 +1758,21 @@ async function enforceSdkCompatibility(baseUrl) {
|
|
|
1715
1758
|
}
|
|
1716
1759
|
|
|
1717
1760
|
// src/cli/commands/auth.ts
|
|
1718
|
-
import {
|
|
1761
|
+
import {
|
|
1762
|
+
existsSync as existsSync4,
|
|
1763
|
+
mkdirSync as mkdirSync3,
|
|
1764
|
+
readFileSync as readFileSync4,
|
|
1765
|
+
rmSync,
|
|
1766
|
+
writeFileSync as writeFileSync3
|
|
1767
|
+
} from "fs";
|
|
1719
1768
|
import { hostname } from "os";
|
|
1720
1769
|
import { dirname as dirname3 } from "path";
|
|
1721
1770
|
|
|
1722
1771
|
// src/cli/utils.ts
|
|
1723
|
-
import {
|
|
1724
|
-
existsSync as existsSync2,
|
|
1725
|
-
mkdirSync as mkdirSync2,
|
|
1726
|
-
readFileSync as readFileSync2,
|
|
1727
|
-
writeFileSync as writeFileSync2
|
|
1728
|
-
} from "fs";
|
|
1772
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
1729
1773
|
import { mkdir, writeFile } from "fs/promises";
|
|
1730
|
-
import { homedir as
|
|
1731
|
-
import { dirname as dirname2, join as
|
|
1774
|
+
import { homedir as homedir3 } from "os";
|
|
1775
|
+
import { dirname as dirname2, join as join3, resolve as resolve2 } from "path";
|
|
1732
1776
|
import * as childProcess from "child_process";
|
|
1733
1777
|
import { parse } from "csv-parse/sync";
|
|
1734
1778
|
import { stringify } from "csv-stringify/sync";
|
|
@@ -1741,13 +1785,13 @@ function getAuthedHttpClient() {
|
|
|
1741
1785
|
async function writeOutputFile(filename, content) {
|
|
1742
1786
|
const outputDir = resolve2(process.cwd(), "deepline", "data");
|
|
1743
1787
|
await mkdir(outputDir, { recursive: true });
|
|
1744
|
-
const fullPath =
|
|
1788
|
+
const fullPath = join3(outputDir, filename);
|
|
1745
1789
|
await writeFile(fullPath, content, "utf-8");
|
|
1746
1790
|
return fullPath;
|
|
1747
1791
|
}
|
|
1748
1792
|
function browserFocusStateFile() {
|
|
1749
|
-
const homeDir = process.env.HOME ||
|
|
1750
|
-
return
|
|
1793
|
+
const homeDir = process.env.HOME || homedir3();
|
|
1794
|
+
return join3(
|
|
1751
1795
|
homeDir,
|
|
1752
1796
|
".local",
|
|
1753
1797
|
"deepline",
|
|
@@ -1761,8 +1805,8 @@ function claimBrowserFocus(now = Date.now()) {
|
|
|
1761
1805
|
try {
|
|
1762
1806
|
mkdirSync2(dirname2(statePath), { recursive: true });
|
|
1763
1807
|
let lastFocusedAt = 0;
|
|
1764
|
-
if (
|
|
1765
|
-
const payload = JSON.parse(
|
|
1808
|
+
if (existsSync3(statePath)) {
|
|
1809
|
+
const payload = JSON.parse(readFileSync3(statePath, "utf-8"));
|
|
1766
1810
|
const value = payload.lastFocusedAt ?? payload.last_focused_at;
|
|
1767
1811
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1768
1812
|
lastFocusedAt = value;
|
|
@@ -1808,7 +1852,7 @@ function readDefaultMacBrowserBundleId(runner = defaultBrowserCommandRunner) {
|
|
|
1808
1852
|
"/usr/bin/defaults",
|
|
1809
1853
|
[
|
|
1810
1854
|
"read",
|
|
1811
|
-
`${
|
|
1855
|
+
`${homedir3()}/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist`,
|
|
1812
1856
|
"LSHandlers"
|
|
1813
1857
|
],
|
|
1814
1858
|
{ encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }
|
|
@@ -1928,11 +1972,9 @@ function openUrlMacos(targetUrl, allowFocus, runner = defaultBrowserCommandRunne
|
|
|
1928
1972
|
return true;
|
|
1929
1973
|
}
|
|
1930
1974
|
try {
|
|
1931
|
-
runner.execFileSync(
|
|
1932
|
-
"
|
|
1933
|
-
|
|
1934
|
-
{ stdio: "ignore" }
|
|
1935
|
-
);
|
|
1975
|
+
runner.execFileSync("open", [...allowFocus ? [] : ["-g"], targetUrl], {
|
|
1976
|
+
stdio: "ignore"
|
|
1977
|
+
});
|
|
1936
1978
|
return true;
|
|
1937
1979
|
} catch {
|
|
1938
1980
|
return false;
|
|
@@ -1969,11 +2011,11 @@ function collectLocalEnvInfo() {
|
|
|
1969
2011
|
return {
|
|
1970
2012
|
os: `${process.platform} ${process.arch}`,
|
|
1971
2013
|
node_version: process.version,
|
|
1972
|
-
home_dir:
|
|
2014
|
+
home_dir: homedir3()
|
|
1973
2015
|
};
|
|
1974
2016
|
}
|
|
1975
2017
|
function readCsvRows(csvPath) {
|
|
1976
|
-
const raw =
|
|
2018
|
+
const raw = readFileSync3(resolve2(csvPath), "utf-8");
|
|
1977
2019
|
return parse(raw, {
|
|
1978
2020
|
columns: true,
|
|
1979
2021
|
skip_empty_lines: true
|
|
@@ -2126,7 +2168,10 @@ function createTimestampedName(prefix, extension) {
|
|
|
2126
2168
|
return `${prefix}-${timestamp}.${extension}`;
|
|
2127
2169
|
}
|
|
2128
2170
|
async function writeCsvRowsFile(prefix, rows) {
|
|
2129
|
-
const path = await writeOutputFile(
|
|
2171
|
+
const path = await writeOutputFile(
|
|
2172
|
+
createTimestampedName(prefix, "csv"),
|
|
2173
|
+
csvStringFromRows(rows)
|
|
2174
|
+
);
|
|
2130
2175
|
return path;
|
|
2131
2176
|
}
|
|
2132
2177
|
function clip(value, maxLength) {
|
|
@@ -2178,7 +2223,7 @@ function pendingClaimTokenPath(baseUrl) {
|
|
|
2178
2223
|
function savePendingClaimToken(baseUrl, claimToken) {
|
|
2179
2224
|
const filePath = pendingClaimTokenPath(baseUrl);
|
|
2180
2225
|
const dir = dirname3(filePath);
|
|
2181
|
-
if (!
|
|
2226
|
+
if (!existsSync4(dir)) {
|
|
2182
2227
|
mkdirSync3(dir, { recursive: true });
|
|
2183
2228
|
}
|
|
2184
2229
|
writeFileSync3(filePath, `${claimToken}
|
|
@@ -2186,9 +2231,9 @@ function savePendingClaimToken(baseUrl, claimToken) {
|
|
|
2186
2231
|
}
|
|
2187
2232
|
function readPendingClaimToken(baseUrl) {
|
|
2188
2233
|
const filePath = pendingClaimTokenPath(baseUrl);
|
|
2189
|
-
if (!
|
|
2234
|
+
if (!existsSync4(filePath)) return "";
|
|
2190
2235
|
try {
|
|
2191
|
-
return
|
|
2236
|
+
return readFileSync4(filePath, "utf-8").trim();
|
|
2192
2237
|
} catch {
|
|
2193
2238
|
return "";
|
|
2194
2239
|
}
|
|
@@ -2207,7 +2252,9 @@ function saveEnvValues(values, baseUrl) {
|
|
|
2207
2252
|
saveHostEnvValues(baseUrl, filtered);
|
|
2208
2253
|
}
|
|
2209
2254
|
async function httpJson(method, url, apiKey, body) {
|
|
2210
|
-
const headers = {
|
|
2255
|
+
const headers = {
|
|
2256
|
+
"Content-Type": "application/json"
|
|
2257
|
+
};
|
|
2211
2258
|
if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
|
|
2212
2259
|
let response = null;
|
|
2213
2260
|
let lastError = null;
|
|
@@ -2262,12 +2309,24 @@ function sleep3(ms) {
|
|
|
2262
2309
|
}
|
|
2263
2310
|
function printDeeplineLogo() {
|
|
2264
2311
|
if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
|
|
2265
|
-
console.log(
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
console.log(
|
|
2269
|
-
|
|
2270
|
-
|
|
2312
|
+
console.log(
|
|
2313
|
+
" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557"
|
|
2314
|
+
);
|
|
2315
|
+
console.log(
|
|
2316
|
+
" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D"
|
|
2317
|
+
);
|
|
2318
|
+
console.log(
|
|
2319
|
+
" \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2557"
|
|
2320
|
+
);
|
|
2321
|
+
console.log(
|
|
2322
|
+
" \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D"
|
|
2323
|
+
);
|
|
2324
|
+
console.log(
|
|
2325
|
+
" \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557"
|
|
2326
|
+
);
|
|
2327
|
+
console.log(
|
|
2328
|
+
" \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
|
|
2329
|
+
);
|
|
2271
2330
|
console.log("");
|
|
2272
2331
|
return;
|
|
2273
2332
|
}
|
|
@@ -2301,7 +2360,12 @@ async function handleRegister(args) {
|
|
|
2301
2360
|
const payload = {};
|
|
2302
2361
|
if (orgName) payload.org_name = orgName;
|
|
2303
2362
|
if (agentName) payload.agent_name = agentName;
|
|
2304
|
-
const { status, data } = await httpJson(
|
|
2363
|
+
const { status, data } = await httpJson(
|
|
2364
|
+
"POST",
|
|
2365
|
+
`${baseUrl}/api/v2/auth/cli/register`,
|
|
2366
|
+
null,
|
|
2367
|
+
payload
|
|
2368
|
+
);
|
|
2305
2369
|
if (status >= 400) {
|
|
2306
2370
|
console.error(`Auth register failed (status ${status}).`);
|
|
2307
2371
|
if (data.error) console.error(String(data.error));
|
|
@@ -2311,9 +2375,12 @@ async function handleRegister(args) {
|
|
|
2311
2375
|
const claimToken = String(data.claim_token || "");
|
|
2312
2376
|
if (claimToken) {
|
|
2313
2377
|
savePendingClaimToken(baseUrl, claimToken);
|
|
2314
|
-
saveEnvValues(
|
|
2315
|
-
|
|
2316
|
-
|
|
2378
|
+
saveEnvValues(
|
|
2379
|
+
{
|
|
2380
|
+
[HOST_URL_ENV]: baseUrl
|
|
2381
|
+
},
|
|
2382
|
+
baseUrl
|
|
2383
|
+
);
|
|
2317
2384
|
}
|
|
2318
2385
|
if (claimUrl) {
|
|
2319
2386
|
console.log(" Opening approval page in your browser.");
|
|
@@ -2352,10 +2419,13 @@ async function handleRegister(args) {
|
|
|
2352
2419
|
if (state === "claimed") {
|
|
2353
2420
|
const apiKey = String(statusData.api_key || "");
|
|
2354
2421
|
if (apiKey) {
|
|
2355
|
-
saveEnvValues(
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2422
|
+
saveEnvValues(
|
|
2423
|
+
{
|
|
2424
|
+
[HOST_URL_ENV]: baseUrl,
|
|
2425
|
+
[API_KEY_ENV]: apiKey
|
|
2426
|
+
},
|
|
2427
|
+
baseUrl
|
|
2428
|
+
);
|
|
2359
2429
|
clearPendingClaimToken(baseUrl);
|
|
2360
2430
|
printClaimSuccessBanner(statusData);
|
|
2361
2431
|
return EXIT_OK;
|
|
@@ -2363,7 +2433,9 @@ async function handleRegister(args) {
|
|
|
2363
2433
|
}
|
|
2364
2434
|
if (state === "expired") {
|
|
2365
2435
|
clearPendingClaimToken(baseUrl);
|
|
2366
|
-
console.log(
|
|
2436
|
+
console.log(
|
|
2437
|
+
"That approval link expired. Please run: deepline auth register"
|
|
2438
|
+
);
|
|
2367
2439
|
return EXIT_AUTH;
|
|
2368
2440
|
}
|
|
2369
2441
|
await sleep3(2e3);
|
|
@@ -2414,10 +2486,13 @@ async function handleWait(args) {
|
|
|
2414
2486
|
if (state === "claimed") {
|
|
2415
2487
|
const apiKey = String(data.api_key || "");
|
|
2416
2488
|
if (apiKey) {
|
|
2417
|
-
saveEnvValues(
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2489
|
+
saveEnvValues(
|
|
2490
|
+
{
|
|
2491
|
+
[HOST_URL_ENV]: baseUrl,
|
|
2492
|
+
[API_KEY_ENV]: apiKey
|
|
2493
|
+
},
|
|
2494
|
+
baseUrl
|
|
2495
|
+
);
|
|
2421
2496
|
clearPendingClaimToken(baseUrl);
|
|
2422
2497
|
printClaimSuccessBanner(data);
|
|
2423
2498
|
return EXIT_OK;
|
|
@@ -2430,7 +2505,9 @@ async function handleWait(args) {
|
|
|
2430
2505
|
}
|
|
2431
2506
|
await sleep3(2e3);
|
|
2432
2507
|
}
|
|
2433
|
-
console.error(
|
|
2508
|
+
console.error(
|
|
2509
|
+
"Still pending. Approve the browser link, then run: deepline auth wait"
|
|
2510
|
+
);
|
|
2434
2511
|
return EXIT_AUTH;
|
|
2435
2512
|
}
|
|
2436
2513
|
async function handleStatus(args) {
|
|
@@ -2440,7 +2517,11 @@ async function handleStatus(args) {
|
|
|
2440
2517
|
let hostStatusPayload = null;
|
|
2441
2518
|
const hostLines = [];
|
|
2442
2519
|
try {
|
|
2443
|
-
const { status: hStatus, data: hData } = await httpJson(
|
|
2520
|
+
const { status: hStatus, data: hData } = await httpJson(
|
|
2521
|
+
"GET",
|
|
2522
|
+
`${baseUrl}/api/v2/health`,
|
|
2523
|
+
null
|
|
2524
|
+
);
|
|
2444
2525
|
if (hStatus === 200) {
|
|
2445
2526
|
hostStatusPayload = {
|
|
2446
2527
|
host: baseUrl,
|
|
@@ -2462,45 +2543,74 @@ async function handleStatus(args) {
|
|
|
2462
2543
|
const apiKey = resolveApiKeyForBaseUrl(baseUrl);
|
|
2463
2544
|
if (!apiKey) {
|
|
2464
2545
|
if (readPendingClaimToken(baseUrl)) {
|
|
2465
|
-
printCommandEnvelope(
|
|
2546
|
+
printCommandEnvelope(
|
|
2547
|
+
{
|
|
2548
|
+
...hostStatusPayload ?? { host: baseUrl },
|
|
2549
|
+
status: "pending",
|
|
2550
|
+
connected: false,
|
|
2551
|
+
next: "deepline auth wait",
|
|
2552
|
+
render: {
|
|
2553
|
+
sections: [
|
|
2554
|
+
{
|
|
2555
|
+
title: "auth status",
|
|
2556
|
+
lines: [...hostLines, "Status: pending"]
|
|
2557
|
+
}
|
|
2558
|
+
],
|
|
2559
|
+
actions: [{ label: "Run", command: "deepline auth wait" }]
|
|
2560
|
+
}
|
|
2561
|
+
},
|
|
2562
|
+
{ json: jsonOutput }
|
|
2563
|
+
);
|
|
2564
|
+
return EXIT_OK;
|
|
2565
|
+
}
|
|
2566
|
+
printCommandEnvelope(
|
|
2567
|
+
{
|
|
2466
2568
|
...hostStatusPayload ?? { host: baseUrl },
|
|
2467
|
-
status: "
|
|
2569
|
+
status: "not connected",
|
|
2468
2570
|
connected: false,
|
|
2469
|
-
next: "deepline auth
|
|
2571
|
+
next: "deepline auth register",
|
|
2470
2572
|
render: {
|
|
2471
|
-
sections: [
|
|
2472
|
-
|
|
2573
|
+
sections: [
|
|
2574
|
+
{
|
|
2575
|
+
title: "auth status",
|
|
2576
|
+
lines: [...hostLines, "Status: not connected"]
|
|
2577
|
+
}
|
|
2578
|
+
],
|
|
2579
|
+
actions: [{ label: "Run", command: "deepline auth register" }]
|
|
2473
2580
|
}
|
|
2474
|
-
},
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
printCommandEnvelope({
|
|
2478
|
-
...hostStatusPayload ?? { host: baseUrl },
|
|
2479
|
-
status: "not connected",
|
|
2480
|
-
connected: false,
|
|
2481
|
-
next: "deepline auth register",
|
|
2482
|
-
render: {
|
|
2483
|
-
sections: [{ title: "auth status", lines: [...hostLines, "Status: not connected"] }],
|
|
2484
|
-
actions: [{ label: "Run", command: "deepline auth register" }]
|
|
2485
|
-
}
|
|
2486
|
-
}, { json: jsonOutput });
|
|
2581
|
+
},
|
|
2582
|
+
{ json: jsonOutput }
|
|
2583
|
+
);
|
|
2487
2584
|
return EXIT_OK;
|
|
2488
2585
|
}
|
|
2489
|
-
const { status, data } = await httpJson(
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2586
|
+
const { status, data } = await httpJson(
|
|
2587
|
+
"POST",
|
|
2588
|
+
`${baseUrl}/api/v2/auth/cli/status`,
|
|
2589
|
+
apiKey,
|
|
2590
|
+
{
|
|
2591
|
+
api_key: apiKey,
|
|
2592
|
+
reveal
|
|
2593
|
+
}
|
|
2594
|
+
);
|
|
2493
2595
|
if (status === 401 || status === 403) {
|
|
2494
|
-
printCommandEnvelope(
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2596
|
+
printCommandEnvelope(
|
|
2597
|
+
{
|
|
2598
|
+
...hostStatusPayload ?? { host: baseUrl },
|
|
2599
|
+
status: "unauthorized",
|
|
2600
|
+
connected: false,
|
|
2601
|
+
next: "deepline auth register",
|
|
2602
|
+
render: {
|
|
2603
|
+
sections: [
|
|
2604
|
+
{
|
|
2605
|
+
title: "auth status",
|
|
2606
|
+
lines: [...hostLines, "Status: unauthorized"]
|
|
2607
|
+
}
|
|
2608
|
+
],
|
|
2609
|
+
actions: [{ label: "Run", command: "deepline auth register" }]
|
|
2610
|
+
}
|
|
2611
|
+
},
|
|
2612
|
+
{ json: jsonOutput }
|
|
2613
|
+
);
|
|
2504
2614
|
return EXIT_AUTH;
|
|
2505
2615
|
}
|
|
2506
2616
|
if (status >= 400) {
|
|
@@ -2527,35 +2637,44 @@ async function handleStatus(args) {
|
|
|
2527
2637
|
if (reveal) {
|
|
2528
2638
|
const apiKeyResp = String(data.api_key || apiKey);
|
|
2529
2639
|
if (apiKeyResp) {
|
|
2530
|
-
saveEnvValues(
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2640
|
+
saveEnvValues(
|
|
2641
|
+
{
|
|
2642
|
+
[HOST_URL_ENV]: baseUrl,
|
|
2643
|
+
[API_KEY_ENV]: apiKeyResp
|
|
2644
|
+
},
|
|
2645
|
+
baseUrl
|
|
2646
|
+
);
|
|
2534
2647
|
savedApiKeyPath = envFilePath(baseUrl);
|
|
2535
2648
|
}
|
|
2536
2649
|
}
|
|
2537
|
-
printCommandEnvelope(
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2650
|
+
printCommandEnvelope(
|
|
2651
|
+
{
|
|
2652
|
+
...payload,
|
|
2653
|
+
...savedApiKeyPath ? { saved_api_key_path: savedApiKeyPath } : {},
|
|
2654
|
+
render: {
|
|
2655
|
+
sections: [
|
|
2656
|
+
{
|
|
2657
|
+
title: "auth status",
|
|
2658
|
+
lines: [
|
|
2659
|
+
...hostLines,
|
|
2660
|
+
`Status: ${payload.status}`,
|
|
2661
|
+
`Rate limit tier: ${payload.rateLimitTier}`,
|
|
2662
|
+
...payload.workspace.name ? [`Workspace: ${payload.workspace.name}`] : [],
|
|
2663
|
+
...payload.workspace.slug ? [`Workspace slug: ${payload.workspace.slug}`] : [],
|
|
2664
|
+
...payload.workspace.id != null ? [`Org ID: ${payload.workspace.id}`] : [],
|
|
2665
|
+
...payload.user.id != null ? [`User ID: ${payload.user.id}`] : [],
|
|
2666
|
+
...payload.examples.length > 0 ? [
|
|
2667
|
+
"Examples:",
|
|
2668
|
+
...payload.examples.slice(0, 3).map((example) => ` ${String(example)}`)
|
|
2669
|
+
] : [],
|
|
2670
|
+
...savedApiKeyPath ? [`Saved API key to ${savedApiKeyPath}`] : []
|
|
2671
|
+
]
|
|
2672
|
+
}
|
|
2673
|
+
]
|
|
2674
|
+
}
|
|
2675
|
+
},
|
|
2676
|
+
{ json: jsonOutput }
|
|
2677
|
+
);
|
|
2559
2678
|
return EXIT_OK;
|
|
2560
2679
|
}
|
|
2561
2680
|
function registerAuthCommands(program) {
|
|
@@ -2575,7 +2694,9 @@ Notes:
|
|
|
2575
2694
|
Auth status shows the target host and active workspace without printing secrets.
|
|
2576
2695
|
`
|
|
2577
2696
|
);
|
|
2578
|
-
auth.command("register").description(
|
|
2697
|
+
auth.command("register").description(
|
|
2698
|
+
"Register this device and open the approval page in your browser."
|
|
2699
|
+
).addHelpText(
|
|
2579
2700
|
"after",
|
|
2580
2701
|
`
|
|
2581
2702
|
Notes:
|
|
@@ -2622,7 +2743,10 @@ Examples:
|
|
|
2622
2743
|
deepline auth status
|
|
2623
2744
|
deepline auth status --json
|
|
2624
2745
|
`
|
|
2625
|
-
).option(
|
|
2746
|
+
).option(
|
|
2747
|
+
"--reveal",
|
|
2748
|
+
"Persist the revealed API key back to the host auth file"
|
|
2749
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
2626
2750
|
process.exitCode = await handleStatus([
|
|
2627
2751
|
...options.reveal ? ["--reveal"] : [],
|
|
2628
2752
|
...options.json ? ["--json"] : []
|
|
@@ -2647,7 +2771,9 @@ function recentUsageLines(entries) {
|
|
|
2647
2771
|
const op = `${humanize(entry.provider)} ${humanize(entry.operation)}`.trim();
|
|
2648
2772
|
const charge = entry.billing_mode === "no_bill" ? "free" : `${entry.credits ?? 0} cr`;
|
|
2649
2773
|
const status = entry.status || "completed";
|
|
2650
|
-
lines.push(
|
|
2774
|
+
lines.push(
|
|
2775
|
+
`${op} | ${charge} | ${status} | ${entry.created_at || "unknown"}`
|
|
2776
|
+
);
|
|
2651
2777
|
}
|
|
2652
2778
|
return lines;
|
|
2653
2779
|
}
|
|
@@ -2701,16 +2827,21 @@ function defaultLedgerExportPath() {
|
|
|
2701
2827
|
}
|
|
2702
2828
|
async function handleBalance(options) {
|
|
2703
2829
|
const { http } = getAuthedHttpClient();
|
|
2704
|
-
const payload = await http.get(
|
|
2830
|
+
const payload = await http.get(
|
|
2831
|
+
"/api/v2/billing/balance"
|
|
2832
|
+
);
|
|
2705
2833
|
const status = String(payload.balance_status || "");
|
|
2706
2834
|
const lines = status === "no_billing" ? [
|
|
2707
2835
|
"Balance: 0 credits",
|
|
2708
2836
|
"Billing: No billing account or payment method set up for this workspace."
|
|
2709
2837
|
] : [`Balance: ${payload.balance ?? "(unknown)"} credits`];
|
|
2710
|
-
printCommandEnvelope(
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2838
|
+
printCommandEnvelope(
|
|
2839
|
+
{
|
|
2840
|
+
...payload,
|
|
2841
|
+
render: { sections: [{ title: "billing balance", lines }] }
|
|
2842
|
+
},
|
|
2843
|
+
{ json: options.json }
|
|
2844
|
+
);
|
|
2714
2845
|
return;
|
|
2715
2846
|
}
|
|
2716
2847
|
async function handleUsage(options) {
|
|
@@ -2719,7 +2850,9 @@ async function handleUsage(options) {
|
|
|
2719
2850
|
if (options.limit) params.set("recent_limit", options.limit);
|
|
2720
2851
|
if (options.offset) params.set("recent_offset", options.offset);
|
|
2721
2852
|
const suffix = Array.from(params).length > 0 ? `?${params.toString()}` : "";
|
|
2722
|
-
const payload = await http.get(
|
|
2853
|
+
const payload = await http.get(
|
|
2854
|
+
`/api/v2/billing/usage${suffix}`
|
|
2855
|
+
);
|
|
2723
2856
|
const usage = payload.usage ?? {};
|
|
2724
2857
|
const quota = payload.quota ?? {};
|
|
2725
2858
|
const recent = payload.recent ?? {};
|
|
@@ -2727,24 +2860,34 @@ async function handleUsage(options) {
|
|
|
2727
2860
|
`Balance: ${payload.balance ?? "(unknown)"}`,
|
|
2728
2861
|
`Last 30 days spent: ${usage.month_spent_credits ?? "(unknown)"}`,
|
|
2729
2862
|
`Monthly limit: ${quota.enabled ? quota.monthly_credits_limit ?? "(unknown)" : "off"}`,
|
|
2730
|
-
...recentUsageLines(
|
|
2863
|
+
...recentUsageLines(
|
|
2864
|
+
Array.isArray(recent.entries) ? recent.entries : []
|
|
2865
|
+
)
|
|
2731
2866
|
];
|
|
2732
|
-
printCommandEnvelope(
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2867
|
+
printCommandEnvelope(
|
|
2868
|
+
{
|
|
2869
|
+
...payload,
|
|
2870
|
+
render: { sections: [{ title: "billing usage", lines }] }
|
|
2871
|
+
},
|
|
2872
|
+
{ json: options.json }
|
|
2873
|
+
);
|
|
2736
2874
|
}
|
|
2737
2875
|
async function handleLimit(options) {
|
|
2738
2876
|
const { http } = getAuthedHttpClient();
|
|
2739
|
-
const payload = await http.get(
|
|
2877
|
+
const payload = await http.get(
|
|
2878
|
+
"/api/v2/billing/limit"
|
|
2879
|
+
);
|
|
2740
2880
|
const lines = payload.enabled ? [
|
|
2741
2881
|
`Monthly limit: ${payload.monthly_credits_limit ?? "(unknown)"}`,
|
|
2742
2882
|
`Remaining before cap: ${payload.remaining_credits ?? "(unknown)"}`
|
|
2743
2883
|
] : ["Monthly limit: off"];
|
|
2744
|
-
printCommandEnvelope(
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2884
|
+
printCommandEnvelope(
|
|
2885
|
+
{
|
|
2886
|
+
...payload,
|
|
2887
|
+
render: { sections: [{ title: "billing limit", lines }] }
|
|
2888
|
+
},
|
|
2889
|
+
{ json: options.json }
|
|
2890
|
+
);
|
|
2748
2891
|
}
|
|
2749
2892
|
async function handleSetLimit(credits, options) {
|
|
2750
2893
|
const { http } = getAuthedHttpClient();
|
|
@@ -2752,26 +2895,53 @@ async function handleSetLimit(credits, options) {
|
|
|
2752
2895
|
method: "PUT",
|
|
2753
2896
|
body: { monthly_credits_limit: Number.parseInt(credits, 10) }
|
|
2754
2897
|
});
|
|
2755
|
-
printCommandEnvelope(
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2898
|
+
printCommandEnvelope(
|
|
2899
|
+
{
|
|
2900
|
+
...payload,
|
|
2901
|
+
render: {
|
|
2902
|
+
sections: [
|
|
2903
|
+
{
|
|
2904
|
+
title: "billing limit",
|
|
2905
|
+
lines: [`Monthly billing limit set to ${credits} credits.`]
|
|
2906
|
+
}
|
|
2907
|
+
]
|
|
2908
|
+
}
|
|
2909
|
+
},
|
|
2910
|
+
{ json: options.json }
|
|
2911
|
+
);
|
|
2761
2912
|
}
|
|
2762
2913
|
async function handleLimitOff(options) {
|
|
2763
2914
|
const { http } = getAuthedHttpClient();
|
|
2764
|
-
const payload = await http.request("/api/v2/billing/limit", {
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2915
|
+
const payload = await http.request("/api/v2/billing/limit", {
|
|
2916
|
+
method: "DELETE"
|
|
2917
|
+
});
|
|
2918
|
+
printCommandEnvelope(
|
|
2919
|
+
{
|
|
2920
|
+
...payload,
|
|
2921
|
+
render: {
|
|
2922
|
+
sections: [
|
|
2923
|
+
{
|
|
2924
|
+
title: "billing limit",
|
|
2925
|
+
lines: ["Monthly billing limit is now off."]
|
|
2926
|
+
}
|
|
2927
|
+
]
|
|
2928
|
+
}
|
|
2929
|
+
},
|
|
2930
|
+
{ json: options.json }
|
|
2931
|
+
);
|
|
2769
2932
|
}
|
|
2770
2933
|
async function handleHistory(options) {
|
|
2771
2934
|
const { http } = getAuthedHttpClient();
|
|
2772
|
-
const windows = {
|
|
2935
|
+
const windows = {
|
|
2936
|
+
"1d": 86400,
|
|
2937
|
+
"1w": 604800,
|
|
2938
|
+
"1m": 2592e3,
|
|
2939
|
+
"1y": 31536e3
|
|
2940
|
+
};
|
|
2773
2941
|
const sinceAt = Math.max(0, Math.floor(Date.now() / 1e3) - windows[options.time]) * 1e3;
|
|
2774
|
-
const payload = await http.get(
|
|
2942
|
+
const payload = await http.get(
|
|
2943
|
+
`/api/v2/billing/ledger?since_at=${sinceAt}&limit=5000`
|
|
2944
|
+
);
|
|
2775
2945
|
const entries = Array.isArray(payload.entries) ? payload.entries : [];
|
|
2776
2946
|
const rows = entries.map((entry) => {
|
|
2777
2947
|
const metadata = entry.metadata ?? {};
|
|
@@ -2783,21 +2953,30 @@ async function handleHistory(options) {
|
|
|
2783
2953
|
operation: metadata.operation ?? ""
|
|
2784
2954
|
};
|
|
2785
2955
|
});
|
|
2786
|
-
const outputPath = await writeCsvRowsFile(
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2956
|
+
const outputPath = await writeCsvRowsFile(
|
|
2957
|
+
`billing-history-${options.time}`,
|
|
2958
|
+
rows
|
|
2959
|
+
);
|
|
2960
|
+
printCommandEnvelope(
|
|
2961
|
+
{
|
|
2962
|
+
output_path: outputPath,
|
|
2963
|
+
row_count: rows.length,
|
|
2964
|
+
time_window: options.time,
|
|
2965
|
+
render: {
|
|
2966
|
+
sections: [
|
|
2967
|
+
{
|
|
2968
|
+
title: "billing history",
|
|
2969
|
+
lines: [
|
|
2970
|
+
`Billing history written to ${outputPath}`,
|
|
2971
|
+
`${rows.length} row(s) exported.`
|
|
2972
|
+
]
|
|
2973
|
+
}
|
|
2974
|
+
]
|
|
2975
|
+
},
|
|
2976
|
+
local: { output_path: outputPath }
|
|
2798
2977
|
},
|
|
2799
|
-
|
|
2800
|
-
|
|
2978
|
+
{ json: options.json }
|
|
2979
|
+
);
|
|
2801
2980
|
}
|
|
2802
2981
|
async function handleLedgerExportAll(options) {
|
|
2803
2982
|
const { http } = getAuthedHttpClient();
|
|
@@ -2829,51 +3008,75 @@ async function handleLedgerExportAll(options) {
|
|
|
2829
3008
|
if (nextCursor === cursor) break;
|
|
2830
3009
|
cursor = nextCursor;
|
|
2831
3010
|
}
|
|
2832
|
-
printCommandEnvelope(
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
3011
|
+
printCommandEnvelope(
|
|
3012
|
+
{
|
|
3013
|
+
output_path: outputPath,
|
|
3014
|
+
row_count: summary.row_count,
|
|
3015
|
+
net_delta_credits: summary.net_delta_credits,
|
|
3016
|
+
scope: "current_auth_context",
|
|
3017
|
+
render: {
|
|
3018
|
+
sections: [
|
|
3019
|
+
{
|
|
3020
|
+
title: "billing ledger",
|
|
3021
|
+
lines: [
|
|
3022
|
+
`Billing ledger written to ${outputPath}`,
|
|
3023
|
+
`${summary.row_count} row(s) exported for the current auth context.`,
|
|
3024
|
+
`Net ledger delta: ${summary.net_delta_credits} Deepline Credits`
|
|
3025
|
+
]
|
|
3026
|
+
}
|
|
3027
|
+
]
|
|
3028
|
+
},
|
|
3029
|
+
local: { output_path: outputPath }
|
|
2848
3030
|
},
|
|
2849
|
-
|
|
2850
|
-
|
|
3031
|
+
{ json: options.json }
|
|
3032
|
+
);
|
|
2851
3033
|
}
|
|
2852
3034
|
async function handleCheckout(options) {
|
|
2853
3035
|
const { http } = getAuthedHttpClient();
|
|
2854
|
-
const payload = await http.post(
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
3036
|
+
const payload = await http.post(
|
|
3037
|
+
"/api/v2/billing/checkout",
|
|
3038
|
+
{
|
|
3039
|
+
...options.tier ? { tierId: options.tier } : {},
|
|
3040
|
+
...options.credits ? { credits: Number.parseInt(options.credits, 10) } : {},
|
|
3041
|
+
...options.discountCode ? { discountCode: options.discountCode } : {}
|
|
3042
|
+
}
|
|
3043
|
+
);
|
|
2859
3044
|
const url = String(payload.url || payload.checkout_url || "");
|
|
2860
3045
|
if (!options.json && !options.noOpen && url) openInBrowser(url);
|
|
2861
|
-
printCommandEnvelope(
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
3046
|
+
printCommandEnvelope(
|
|
3047
|
+
{
|
|
3048
|
+
...payload,
|
|
3049
|
+
render: {
|
|
3050
|
+
sections: [
|
|
3051
|
+
{
|
|
3052
|
+
title: "billing checkout",
|
|
3053
|
+
lines: [url || "Checkout session created."]
|
|
3054
|
+
}
|
|
3055
|
+
]
|
|
3056
|
+
}
|
|
3057
|
+
},
|
|
3058
|
+
{ json: options.json }
|
|
3059
|
+
);
|
|
2865
3060
|
}
|
|
2866
3061
|
async function handleRedeemCode(code, options) {
|
|
2867
3062
|
const { http } = getAuthedHttpClient();
|
|
2868
|
-
const payload = await http.post(
|
|
2869
|
-
|
|
2870
|
-
|
|
3063
|
+
const payload = await http.post(
|
|
3064
|
+
"/api/v2/billing/checkout",
|
|
3065
|
+
{
|
|
3066
|
+
discountCode: code
|
|
3067
|
+
}
|
|
3068
|
+
);
|
|
2871
3069
|
const url = String(payload.url || payload.checkout_url || "");
|
|
2872
3070
|
if (!options.json && !options.noOpen && url) openInBrowser(url);
|
|
2873
|
-
printCommandEnvelope(
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
3071
|
+
printCommandEnvelope(
|
|
3072
|
+
{
|
|
3073
|
+
...payload,
|
|
3074
|
+
render: {
|
|
3075
|
+
sections: [{ title: "billing code", lines: [url || "Code redeemed."] }]
|
|
3076
|
+
}
|
|
3077
|
+
},
|
|
3078
|
+
{ json: options.json }
|
|
3079
|
+
);
|
|
2877
3080
|
}
|
|
2878
3081
|
function registerBillingCommands(program) {
|
|
2879
3082
|
const billing = program.command("billing").description("Inspect balance, usage, limits, and checkout flows.").addHelpText(
|
|
@@ -2981,7 +3184,10 @@ Examples:
|
|
|
2981
3184
|
deepline billing ledger export all
|
|
2982
3185
|
deepline billing ledger export all --json
|
|
2983
3186
|
`
|
|
2984
|
-
).option("--output <path>", "Write CSV to an explicit path").option(
|
|
3187
|
+
).option("--output <path>", "Write CSV to an explicit path").option(
|
|
3188
|
+
"--json",
|
|
3189
|
+
"Emit JSON output. Also automatic when stdout is piped"
|
|
3190
|
+
).action(handleLedgerExportAll)
|
|
2985
3191
|
)
|
|
2986
3192
|
);
|
|
2987
3193
|
billing.command("history").description("Export billing ledger history to CSV.").addHelpText(
|
|
@@ -2996,7 +3202,9 @@ Examples:
|
|
|
2996
3202
|
deepline billing history --time 1y --json
|
|
2997
3203
|
`
|
|
2998
3204
|
).requiredOption("--time <window>", "Rolling time window: 1d, 1w, 1m, or 1y").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleHistory);
|
|
2999
|
-
billing.command("checkout").description(
|
|
3205
|
+
billing.command("checkout").description(
|
|
3206
|
+
"Create a checkout session and optionally open it in your browser."
|
|
3207
|
+
).addHelpText(
|
|
3000
3208
|
"after",
|
|
3001
3209
|
`
|
|
3002
3210
|
Notes:
|
|
@@ -3042,12 +3250,18 @@ function formatDatasetExecutionStats(raw, denominator) {
|
|
|
3042
3250
|
readCount(raw.completed),
|
|
3043
3251
|
denominator
|
|
3044
3252
|
),
|
|
3045
|
-
"completed:reused": datasetSummaryPercentText(
|
|
3253
|
+
"completed:reused": datasetSummaryPercentText(
|
|
3254
|
+
readCount(raw.cached),
|
|
3255
|
+
denominator
|
|
3256
|
+
),
|
|
3046
3257
|
"skipped:condition": datasetSummaryPercentText(
|
|
3047
3258
|
readCount(raw.skipped),
|
|
3048
3259
|
denominator
|
|
3049
3260
|
),
|
|
3050
|
-
"skipped:missed": datasetSummaryPercentText(
|
|
3261
|
+
"skipped:missed": datasetSummaryPercentText(
|
|
3262
|
+
readCount(raw.missed),
|
|
3263
|
+
denominator
|
|
3264
|
+
),
|
|
3051
3265
|
failed: datasetSummaryPercentText(readCount(raw.failed), denominator)
|
|
3052
3266
|
};
|
|
3053
3267
|
}
|
|
@@ -3228,19 +3442,51 @@ function collectCanonicalRowsInfos(statusOrResult) {
|
|
|
3228
3442
|
const metadata = isRecord2(result._metadata) ? result._metadata : null;
|
|
3229
3443
|
const totalFromMetadata = metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count;
|
|
3230
3444
|
const candidates = [
|
|
3231
|
-
{
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3445
|
+
{
|
|
3446
|
+
source: "result.contacts",
|
|
3447
|
+
value: result.contacts,
|
|
3448
|
+
total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
|
|
3449
|
+
},
|
|
3450
|
+
{
|
|
3451
|
+
source: "result.previewRows",
|
|
3452
|
+
value: result.previewRows,
|
|
3453
|
+
total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
|
|
3454
|
+
},
|
|
3455
|
+
{
|
|
3456
|
+
source: "result.rows",
|
|
3457
|
+
value: result.rows,
|
|
3458
|
+
total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
|
|
3459
|
+
},
|
|
3460
|
+
{
|
|
3461
|
+
source: "result.results",
|
|
3462
|
+
value: result.results,
|
|
3463
|
+
total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
|
|
3464
|
+
}
|
|
3235
3465
|
];
|
|
3236
3466
|
if (isRecord2(result.output)) {
|
|
3237
3467
|
const outputMetadata = isRecord2(result.output._metadata) ? result.output._metadata : null;
|
|
3238
3468
|
const outputTotalFromMetadata = outputMetadata?.totalRows ?? outputMetadata?.rowCount ?? outputMetadata?.count;
|
|
3239
3469
|
candidates.push(
|
|
3240
|
-
{
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3470
|
+
{
|
|
3471
|
+
source: "result.output.contacts",
|
|
3472
|
+
value: result.output.contacts,
|
|
3473
|
+
total: outputTotalFromMetadata ?? result.output.totalRows ?? result.output.rowCount ?? result.output.count
|
|
3474
|
+
},
|
|
3475
|
+
{
|
|
3476
|
+
source: "result.output.previewRows",
|
|
3477
|
+
value: result.output.previewRows,
|
|
3478
|
+
total: outputTotalFromMetadata ?? result.output.totalRows ?? result.output.rowCount ?? result.output.count
|
|
3479
|
+
},
|
|
3480
|
+
{
|
|
3481
|
+
source: "result.output.rows",
|
|
3482
|
+
value: result.output.rows,
|
|
3483
|
+
total: outputTotalFromMetadata ?? result.output.totalRows ?? result.output.rowCount ?? result.output.count
|
|
3484
|
+
},
|
|
3485
|
+
{
|
|
3486
|
+
source: "result.output.results",
|
|
3487
|
+
value: result.output.results,
|
|
3488
|
+
total: outputTotalFromMetadata ?? result.output.totalRows ?? result.output.rowCount ?? result.output.count
|
|
3489
|
+
}
|
|
3244
3490
|
);
|
|
3245
3491
|
}
|
|
3246
3492
|
collectDatasetCandidates({
|
|
@@ -3378,7 +3624,8 @@ function compactCell(value) {
|
|
|
3378
3624
|
const parsed = parseJsonLike(value);
|
|
3379
3625
|
if (parsed === null || parsed === void 0) return "";
|
|
3380
3626
|
if (typeof parsed === "string") return compactScalar(parsed, 120);
|
|
3381
|
-
if (typeof parsed === "number" || typeof parsed === "boolean")
|
|
3627
|
+
if (typeof parsed === "number" || typeof parsed === "boolean")
|
|
3628
|
+
return String(parsed);
|
|
3382
3629
|
if (Array.isArray(parsed)) {
|
|
3383
3630
|
if (parsed.length === 0) return "";
|
|
3384
3631
|
if (parsed.slice(0, 3).every((item) => ["string", "number", "boolean"].includes(typeof item))) {
|
|
@@ -3392,7 +3639,15 @@ function compactCell(value) {
|
|
|
3392
3639
|
return compactCell(parsed[key]);
|
|
3393
3640
|
}
|
|
3394
3641
|
}
|
|
3395
|
-
const preferred = [
|
|
3642
|
+
const preferred = [
|
|
3643
|
+
"email",
|
|
3644
|
+
"status",
|
|
3645
|
+
"name",
|
|
3646
|
+
"full_name",
|
|
3647
|
+
"title",
|
|
3648
|
+
"domain",
|
|
3649
|
+
"linkedin_url"
|
|
3650
|
+
];
|
|
3396
3651
|
const parts = [];
|
|
3397
3652
|
for (const key of preferred) {
|
|
3398
3653
|
if (parsed[key] !== null && parsed[key] !== void 0 && parsed[key] !== "") {
|
|
@@ -3434,7 +3689,10 @@ function buildDatasetStats(rows, totalRows = rows.length, columns = inferColumns
|
|
|
3434
3689
|
};
|
|
3435
3690
|
const rawExecutionStats = executionStats?.columnStats[column];
|
|
3436
3691
|
if (rawExecutionStats) {
|
|
3437
|
-
stat3.execution = formatDatasetExecutionStats(
|
|
3692
|
+
stat3.execution = formatDatasetExecutionStats(
|
|
3693
|
+
rawExecutionStats,
|
|
3694
|
+
totalRows
|
|
3695
|
+
);
|
|
3438
3696
|
}
|
|
3439
3697
|
if (sampleValue !== void 0 && sampleValueType) {
|
|
3440
3698
|
stat3.sample_value = sampleValue;
|
|
@@ -3476,11 +3734,7 @@ function writeCanonicalRowsCsv(rowsInfo, outPath) {
|
|
|
3476
3734
|
const rows = dataExportRows(sanitized.rows);
|
|
3477
3735
|
const columns = dataExportColumns(rows, sanitized.columns);
|
|
3478
3736
|
const resolved = resolve4(outPath);
|
|
3479
|
-
writeFileSync4(
|
|
3480
|
-
resolved,
|
|
3481
|
-
csvStringFromRows(rows, columns),
|
|
3482
|
-
"utf-8"
|
|
3483
|
-
);
|
|
3737
|
+
writeFileSync4(resolved, csvStringFromRows(rows, columns), "utf-8");
|
|
3484
3738
|
return resolved;
|
|
3485
3739
|
}
|
|
3486
3740
|
|
|
@@ -3491,7 +3745,9 @@ function parseRowRange(raw) {
|
|
|
3491
3745
|
const start = Number.parseInt(startRaw ?? "", 10);
|
|
3492
3746
|
const end = Number.parseInt(endRaw ?? "", 10);
|
|
3493
3747
|
if (!Number.isFinite(start) || !Number.isFinite(end) || start < 0 || end < start) {
|
|
3494
|
-
throw new Error(
|
|
3748
|
+
throw new Error(
|
|
3749
|
+
`Invalid --rows value: ${source} (expected start:end, e.g. 0:19).`
|
|
3750
|
+
);
|
|
3495
3751
|
}
|
|
3496
3752
|
return [start, end];
|
|
3497
3753
|
}
|
|
@@ -3502,7 +3758,9 @@ function selectColumns(rows, rawColumns) {
|
|
|
3502
3758
|
if (!rawColumns?.trim()) return rows;
|
|
3503
3759
|
const requested = rawColumns.split(",").map((part) => part.trim()).filter(Boolean);
|
|
3504
3760
|
if (requested.length === 0) {
|
|
3505
|
-
throw new Error(
|
|
3761
|
+
throw new Error(
|
|
3762
|
+
"Invalid --columns value: provide at least one column name."
|
|
3763
|
+
);
|
|
3506
3764
|
}
|
|
3507
3765
|
const available = new Set(Object.keys(rows[0] ?? {}));
|
|
3508
3766
|
const missing = requested.filter((column) => !available.has(column));
|
|
@@ -3539,13 +3797,22 @@ function renderTable(rows, totalRows, verbose) {
|
|
|
3539
3797
|
return display.padEnd(widths[column]);
|
|
3540
3798
|
}).join(" | ")
|
|
3541
3799
|
);
|
|
3542
|
-
return [
|
|
3800
|
+
return [
|
|
3801
|
+
header,
|
|
3802
|
+
divider,
|
|
3803
|
+
...body,
|
|
3804
|
+
"",
|
|
3805
|
+
`showing ${rows.length} row(s) of ${totalRows}`
|
|
3806
|
+
].join("\n");
|
|
3543
3807
|
}
|
|
3544
3808
|
async function handleCsvShow(options) {
|
|
3545
3809
|
const csvPath = options.csv;
|
|
3546
3810
|
const [rowStart, rowEnd] = parseRowRange(options.rows);
|
|
3547
3811
|
const allRows = readCsvRows(csvPath);
|
|
3548
|
-
const selected = selectColumns(
|
|
3812
|
+
const selected = selectColumns(
|
|
3813
|
+
selectRows(allRows, rowStart, rowEnd),
|
|
3814
|
+
options.columns
|
|
3815
|
+
);
|
|
3549
3816
|
const format = options.format ?? "json";
|
|
3550
3817
|
if (options.summary) {
|
|
3551
3818
|
printJson(buildDatasetStats(selected, allRows.length));
|
|
@@ -3562,13 +3829,17 @@ async function handleCsvShow(options) {
|
|
|
3562
3829
|
process.stdout.write(`${columns.join(",")}
|
|
3563
3830
|
`);
|
|
3564
3831
|
for (const row of selected) {
|
|
3565
|
-
process.stdout.write(
|
|
3566
|
-
|
|
3832
|
+
process.stdout.write(
|
|
3833
|
+
`${columns.map((column) => JSON.stringify(row[column] ?? "")).join(",")}
|
|
3834
|
+
`
|
|
3835
|
+
);
|
|
3567
3836
|
}
|
|
3568
3837
|
return;
|
|
3569
3838
|
}
|
|
3570
|
-
process.stdout.write(
|
|
3571
|
-
|
|
3839
|
+
process.stdout.write(
|
|
3840
|
+
`${renderTable(selected, allRows.length, Boolean(options.verbose))}
|
|
3841
|
+
`
|
|
3842
|
+
);
|
|
3572
3843
|
}
|
|
3573
3844
|
function registerCsvCommands(program) {
|
|
3574
3845
|
const csv = program.command("csv").description("Inspect local CSV files.").addHelpText(
|
|
@@ -3601,12 +3872,7 @@ Examples:
|
|
|
3601
3872
|
// src/cli/commands/db.ts
|
|
3602
3873
|
import { writeFileSync as writeFileSync5 } from "fs";
|
|
3603
3874
|
import { resolve as resolve5 } from "path";
|
|
3604
|
-
var CUSTOMER_DB_QUERY_FORMATS = /* @__PURE__ */ new Set([
|
|
3605
|
-
"table",
|
|
3606
|
-
"json",
|
|
3607
|
-
"csv",
|
|
3608
|
-
"markdown"
|
|
3609
|
-
]);
|
|
3875
|
+
var CUSTOMER_DB_QUERY_FORMATS = /* @__PURE__ */ new Set(["table", "json", "csv", "markdown"]);
|
|
3610
3876
|
function parsePositiveInteger(value, flagName) {
|
|
3611
3877
|
const parsed = Number.parseInt(value, 10);
|
|
3612
3878
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
@@ -3621,10 +3887,17 @@ function formatCell(value) {
|
|
|
3621
3887
|
}
|
|
3622
3888
|
function tableLines(result) {
|
|
3623
3889
|
const rows = dataExportRows(customerDbRows(result));
|
|
3624
|
-
const responseColumns = dataExportColumns(
|
|
3625
|
-
|
|
3890
|
+
const responseColumns = dataExportColumns(
|
|
3891
|
+
rows,
|
|
3892
|
+
customerDbColumnNames(result)
|
|
3893
|
+
);
|
|
3894
|
+
const businessColumns = responseColumns.filter(
|
|
3895
|
+
(column) => !column.startsWith("_")
|
|
3896
|
+
);
|
|
3626
3897
|
const columns = businessColumns.length > 0 ? businessColumns : responseColumns;
|
|
3627
|
-
const hiddenColumns = responseColumns.filter(
|
|
3898
|
+
const hiddenColumns = responseColumns.filter(
|
|
3899
|
+
(column) => !columns.includes(column)
|
|
3900
|
+
);
|
|
3628
3901
|
const lines = [
|
|
3629
3902
|
`${result.command} returned ${result.row_count_returned} row(s)` + (result.truncated ? " (truncated)" : "")
|
|
3630
3903
|
];
|
|
@@ -3632,7 +3905,9 @@ function tableLines(result) {
|
|
|
3632
3905
|
lines.push(
|
|
3633
3906
|
`Showing ${columns.length}/${responseColumns.length} columns; hidden metadata: ${hiddenColumns.join(", ")}`
|
|
3634
3907
|
);
|
|
3635
|
-
lines.push(
|
|
3908
|
+
lines.push(
|
|
3909
|
+
"Use --json or select metadata columns explicitly when you need run ids/errors/stages."
|
|
3910
|
+
);
|
|
3636
3911
|
}
|
|
3637
3912
|
if (rows.length === 0) {
|
|
3638
3913
|
return lines;
|
|
@@ -3646,7 +3921,9 @@ function tableLines(result) {
|
|
|
3646
3921
|
)
|
|
3647
3922
|
)
|
|
3648
3923
|
);
|
|
3649
|
-
lines.push(
|
|
3924
|
+
lines.push(
|
|
3925
|
+
columns.map((column, index) => column.padEnd(widths[index])).join(" ")
|
|
3926
|
+
);
|
|
3650
3927
|
lines.push(widths.map((width) => "-".repeat(width)).join(" "));
|
|
3651
3928
|
for (const row of rows) {
|
|
3652
3929
|
lines.push(
|
|
@@ -3722,10 +3999,12 @@ async function handleDbQuery(args) {
|
|
|
3722
3999
|
const explicitJsonOutput = args.includes("--json");
|
|
3723
4000
|
const client = new DeeplineClient();
|
|
3724
4001
|
const result = await client.queryCustomerDb({ sql, maxRows });
|
|
3725
|
-
const toolCommand = `deepline tools execute query_customer_db --payload ${JSON.stringify(
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
4002
|
+
const toolCommand = `deepline tools execute query_customer_db --payload ${JSON.stringify(
|
|
4003
|
+
{
|
|
4004
|
+
sql,
|
|
4005
|
+
...maxRows ? { max_rows: maxRows } : {}
|
|
4006
|
+
}
|
|
4007
|
+
)} --json`;
|
|
3729
4008
|
if (format === "csv") {
|
|
3730
4009
|
if (outPath) {
|
|
3731
4010
|
const exportedPath = writeCustomerDbCsv(result, outPath);
|
|
@@ -3753,7 +4032,10 @@ async function handleDbQuery(args) {
|
|
|
3753
4032
|
}),
|
|
3754
4033
|
{
|
|
3755
4034
|
json: explicitJsonOutput,
|
|
3756
|
-
text: dataExportCsvString(
|
|
4035
|
+
text: dataExportCsvString(
|
|
4036
|
+
customerDbRows(result),
|
|
4037
|
+
customerDbColumnNames(result)
|
|
4038
|
+
)
|
|
3757
4039
|
}
|
|
3758
4040
|
);
|
|
3759
4041
|
return 0;
|
|
@@ -3795,14 +4077,17 @@ async function handleDbQuery(args) {
|
|
|
3795
4077
|
);
|
|
3796
4078
|
return 0;
|
|
3797
4079
|
}
|
|
3798
|
-
printCommandEnvelope(
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
4080
|
+
printCommandEnvelope(
|
|
4081
|
+
{
|
|
4082
|
+
...result,
|
|
4083
|
+
next: { toolEquivalent: toolCommand },
|
|
4084
|
+
render: {
|
|
4085
|
+
sections: [{ title: "customer db query", lines: tableLines(result) }],
|
|
4086
|
+
actions: [{ label: "Tool equivalent", command: toolCommand }]
|
|
4087
|
+
}
|
|
4088
|
+
},
|
|
4089
|
+
{ json: jsonOutput || format === "json" }
|
|
4090
|
+
);
|
|
3806
4091
|
return 0;
|
|
3807
4092
|
}
|
|
3808
4093
|
function registerDbCommands(program) {
|
|
@@ -3838,7 +4123,10 @@ Examples:
|
|
|
3838
4123
|
deepline db query --sql "select * from contacts limit 20" --format csv --out contacts.csv
|
|
3839
4124
|
deepline db query --sql "select domain, name from companies limit 20" --format markdown
|
|
3840
4125
|
`
|
|
3841
|
-
).requiredOption("--sql <sql>", "SQL statement").option("--max-rows <n>", "Maximum returned rows").option("--format <format>", "Output format: table, json, csv, or markdown").option("--out <path>", "Write csv or markdown output to a file").option(
|
|
4126
|
+
).requiredOption("--sql <sql>", "SQL statement").option("--max-rows <n>", "Maximum returned rows").option("--format <format>", "Output format: table, json, csv, or markdown").option("--out <path>", "Write csv or markdown output to a file").option(
|
|
4127
|
+
"--json",
|
|
4128
|
+
"Emit raw JSON response. Also automatic when stdout is piped"
|
|
4129
|
+
).action(async (options) => {
|
|
3842
4130
|
process.exitCode = await handleDbQuery([
|
|
3843
4131
|
"--sql",
|
|
3844
4132
|
options.sql,
|
|
@@ -3859,12 +4147,17 @@ async function handleFeedback(text, options) {
|
|
|
3859
4147
|
...options.command ? { command: options.command } : {},
|
|
3860
4148
|
...options.payload ? { payload: options.payload } : {}
|
|
3861
4149
|
});
|
|
3862
|
-
printCommandEnvelope(
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
4150
|
+
printCommandEnvelope(
|
|
4151
|
+
{
|
|
4152
|
+
...response,
|
|
4153
|
+
render: {
|
|
4154
|
+
sections: [
|
|
4155
|
+
{ title: "feedback", lines: ["Feedback submitted. Thank you."] }
|
|
4156
|
+
]
|
|
4157
|
+
}
|
|
4158
|
+
},
|
|
4159
|
+
{ json: options.json }
|
|
4160
|
+
);
|
|
3868
4161
|
}
|
|
3869
4162
|
function registerFeedbackCommands(program) {
|
|
3870
4163
|
const feedback = program.command("feedback").description("Submit CLI feedback to Deepline.").addHelpText(
|
|
@@ -3907,76 +4200,106 @@ async function handleOrgList(options) {
|
|
|
3907
4200
|
const config = resolveConfig();
|
|
3908
4201
|
const http = new HttpClient(config);
|
|
3909
4202
|
const payload = await fetchOrganizations(http, config.apiKey);
|
|
3910
|
-
printCommandEnvelope(
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
4203
|
+
printCommandEnvelope(
|
|
4204
|
+
{
|
|
4205
|
+
...payload,
|
|
4206
|
+
render: {
|
|
4207
|
+
sections: [
|
|
4208
|
+
{
|
|
4209
|
+
title: "Your organizations:",
|
|
4210
|
+
lines: orgListLines(payload.organizations)
|
|
4211
|
+
}
|
|
4212
|
+
]
|
|
4213
|
+
}
|
|
4214
|
+
},
|
|
4215
|
+
{ json: options.json }
|
|
4216
|
+
);
|
|
3916
4217
|
}
|
|
3917
4218
|
async function handleOrgSwitch(selection, options) {
|
|
3918
4219
|
const config = resolveConfig();
|
|
3919
4220
|
const http = new HttpClient(config);
|
|
3920
4221
|
const payload = await fetchOrganizations(http, config.apiKey);
|
|
3921
4222
|
if (!selection && !options.orgId) {
|
|
3922
|
-
printCommandEnvelope(
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
4223
|
+
printCommandEnvelope(
|
|
4224
|
+
{
|
|
4225
|
+
...payload,
|
|
4226
|
+
next: { switch: "deepline org switch <number>" },
|
|
4227
|
+
render: {
|
|
4228
|
+
sections: [
|
|
4229
|
+
{
|
|
4230
|
+
title: "Your organizations:",
|
|
4231
|
+
lines: orgListLines(payload.organizations)
|
|
4232
|
+
}
|
|
4233
|
+
],
|
|
4234
|
+
actions: [{ label: "Run", command: "deepline org switch <number>" }]
|
|
4235
|
+
}
|
|
4236
|
+
},
|
|
4237
|
+
{ json: options.json }
|
|
4238
|
+
);
|
|
3930
4239
|
return;
|
|
3931
4240
|
}
|
|
3932
|
-
let target = payload.organizations.find(
|
|
4241
|
+
let target = payload.organizations.find(
|
|
4242
|
+
(org) => org.org_id === options.orgId
|
|
4243
|
+
);
|
|
3933
4244
|
if (!target && selection) {
|
|
3934
4245
|
const index = Number.parseInt(selection, 10);
|
|
3935
4246
|
if (Number.isFinite(index) && index >= 1 && index <= payload.organizations.length) {
|
|
3936
4247
|
target = payload.organizations[index - 1];
|
|
3937
4248
|
} else {
|
|
3938
|
-
target = payload.organizations.find(
|
|
4249
|
+
target = payload.organizations.find(
|
|
4250
|
+
(org) => org.name === selection || org.org_id === selection
|
|
4251
|
+
);
|
|
3939
4252
|
}
|
|
3940
4253
|
}
|
|
3941
4254
|
if (!target) {
|
|
3942
4255
|
throw new Error("Could not resolve the selected organization.");
|
|
3943
4256
|
}
|
|
3944
4257
|
if (target.is_current) {
|
|
3945
|
-
printCommandEnvelope(
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
4258
|
+
printCommandEnvelope(
|
|
4259
|
+
{
|
|
4260
|
+
ok: true,
|
|
4261
|
+
unchanged: true,
|
|
4262
|
+
organization: target,
|
|
4263
|
+
render: {
|
|
4264
|
+
sections: [
|
|
4265
|
+
{ title: "org switch", lines: [`Already on ${target.name}.`] }
|
|
4266
|
+
]
|
|
4267
|
+
}
|
|
4268
|
+
},
|
|
4269
|
+
{ json: options.json }
|
|
4270
|
+
);
|
|
3951
4271
|
return;
|
|
3952
4272
|
}
|
|
3953
|
-
const switched = await http.post(
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
);
|
|
4273
|
+
const switched = await http.post("/api/v2/auth/cli/switch", {
|
|
4274
|
+
api_key: config.apiKey,
|
|
4275
|
+
org_id: target.org_id
|
|
4276
|
+
});
|
|
3957
4277
|
saveHostEnvValues(config.baseUrl, {
|
|
3958
4278
|
DEEPLINE_API_KEY: switched.api_key,
|
|
3959
4279
|
DEEPLINE_ACTIVE_ORG_ID: switched.org_id,
|
|
3960
4280
|
DEEPLINE_ACTIVE_ORG_NAME: switched.org_name
|
|
3961
4281
|
});
|
|
3962
4282
|
const { api_key: _apiKey, ...publicSwitched } = switched;
|
|
3963
|
-
printCommandEnvelope(
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
4283
|
+
printCommandEnvelope(
|
|
4284
|
+
{
|
|
4285
|
+
ok: true,
|
|
4286
|
+
host_env_path: hostEnvFilePath(config.baseUrl),
|
|
4287
|
+
...publicSwitched,
|
|
4288
|
+
api_key_saved: true,
|
|
4289
|
+
render: {
|
|
4290
|
+
sections: [
|
|
4291
|
+
{
|
|
4292
|
+
title: "org switch",
|
|
4293
|
+
lines: [
|
|
4294
|
+
`Switched to ${switched.org_name}.`,
|
|
4295
|
+
`Saved host auth in ${hostEnvFilePath(config.baseUrl)}`
|
|
4296
|
+
]
|
|
4297
|
+
}
|
|
4298
|
+
]
|
|
4299
|
+
}
|
|
4300
|
+
},
|
|
4301
|
+
{ json: options.json }
|
|
4302
|
+
);
|
|
3980
4303
|
}
|
|
3981
4304
|
function registerOrgCommands(program) {
|
|
3982
4305
|
const org = program.command("org").description("List and switch organizations.").addHelpText(
|
|
@@ -4003,7 +4326,9 @@ Examples:
|
|
|
4003
4326
|
deepline org list --json
|
|
4004
4327
|
`
|
|
4005
4328
|
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgList);
|
|
4006
|
-
org.command("switch [selection]").description(
|
|
4329
|
+
org.command("switch [selection]").description(
|
|
4330
|
+
"Switch to another organization and save the new API key in the host auth file."
|
|
4331
|
+
).addHelpText(
|
|
4007
4332
|
"after",
|
|
4008
4333
|
`
|
|
4009
4334
|
Notes:
|
|
@@ -4021,23 +4346,23 @@ Examples:
|
|
|
4021
4346
|
// src/cli/commands/play.ts
|
|
4022
4347
|
import { createHash as createHash3 } from "crypto";
|
|
4023
4348
|
import {
|
|
4024
|
-
existsSync as
|
|
4025
|
-
readFileSync as
|
|
4349
|
+
existsSync as existsSync7,
|
|
4350
|
+
readFileSync as readFileSync6,
|
|
4026
4351
|
readdirSync,
|
|
4027
4352
|
realpathSync,
|
|
4028
4353
|
writeFileSync as writeFileSync6
|
|
4029
4354
|
} from "fs";
|
|
4030
|
-
import { basename as basename3, dirname as dirname8, join as
|
|
4355
|
+
import { basename as basename3, dirname as dirname8, join as join7, resolve as resolve10 } from "path";
|
|
4031
4356
|
|
|
4032
4357
|
// src/plays/bundle-play-file.ts
|
|
4033
4358
|
import { tmpdir as tmpdir2 } from "os";
|
|
4034
|
-
import { dirname as dirname7, join as
|
|
4359
|
+
import { dirname as dirname7, join as join6, resolve as resolve8 } from "path";
|
|
4035
4360
|
import { fileURLToPath } from "url";
|
|
4036
|
-
import { existsSync as
|
|
4361
|
+
import { existsSync as existsSync6 } from "fs";
|
|
4037
4362
|
|
|
4038
4363
|
// ../shared_libs/plays/bundling/index.ts
|
|
4039
4364
|
import { createHash } from "crypto";
|
|
4040
|
-
import { existsSync as
|
|
4365
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
|
|
4041
4366
|
import { mkdir as mkdir3, readFile, realpath, stat, writeFile as writeFile3 } from "fs/promises";
|
|
4042
4367
|
import { tmpdir } from "os";
|
|
4043
4368
|
import {
|
|
@@ -4045,7 +4370,7 @@ import {
|
|
|
4045
4370
|
dirname as dirname5,
|
|
4046
4371
|
extname,
|
|
4047
4372
|
isAbsolute,
|
|
4048
|
-
join as
|
|
4373
|
+
join as join4,
|
|
4049
4374
|
resolve as resolve6
|
|
4050
4375
|
} from "path";
|
|
4051
4376
|
import { builtinModules } from "module";
|
|
@@ -4106,7 +4431,7 @@ function buildPlayContractCompatibility(input) {
|
|
|
4106
4431
|
var PLAY_BUNDLE_CACHE_VERSION = 24;
|
|
4107
4432
|
var MAX_PLAY_BUNDLE_BYTES = 30 * 1024 * 1024;
|
|
4108
4433
|
var MAX_ESM_WORKERS_BUNDLE_BYTES = 115e4;
|
|
4109
|
-
var PLAY_ARTIFACT_CACHE_DIR =
|
|
4434
|
+
var PLAY_ARTIFACT_CACHE_DIR = join4(
|
|
4110
4435
|
tmpdir(),
|
|
4111
4436
|
`deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION}`
|
|
4112
4437
|
);
|
|
@@ -4326,7 +4651,7 @@ function extractDefinedPlayName(sourceCode) {
|
|
|
4326
4651
|
}
|
|
4327
4652
|
function readPackageVersionFromPackageJson(packageJsonPath, packageName) {
|
|
4328
4653
|
try {
|
|
4329
|
-
const packageJson = JSON.parse(
|
|
4654
|
+
const packageJson = JSON.parse(readFileSync5(packageJsonPath, "utf-8"));
|
|
4330
4655
|
if (packageJson.name === packageName && typeof packageJson.version === "string") {
|
|
4331
4656
|
return packageJson.version;
|
|
4332
4657
|
}
|
|
@@ -4338,13 +4663,13 @@ function readPackageVersionFromPackageJson(packageJsonPath, packageName) {
|
|
|
4338
4663
|
function findPackageJsonPathFrom(startDir, packageName) {
|
|
4339
4664
|
let current = resolve6(startDir);
|
|
4340
4665
|
while (true) {
|
|
4341
|
-
const packageJsonPath =
|
|
4666
|
+
const packageJsonPath = join4(
|
|
4342
4667
|
current,
|
|
4343
4668
|
"node_modules",
|
|
4344
4669
|
packageName,
|
|
4345
4670
|
"package.json"
|
|
4346
4671
|
);
|
|
4347
|
-
if (
|
|
4672
|
+
if (existsSync5(packageJsonPath)) {
|
|
4348
4673
|
return packageJsonPath;
|
|
4349
4674
|
}
|
|
4350
4675
|
const parent = dirname5(current);
|
|
@@ -4369,16 +4694,16 @@ function findPackageJsonPath(packageName, fromFile, adapter) {
|
|
|
4369
4694
|
const packageJsonPath = findPackageJsonPathFrom(normalized, packageName);
|
|
4370
4695
|
if (packageJsonPath) return packageJsonPath;
|
|
4371
4696
|
}
|
|
4372
|
-
const adapterNodeModulesPackageJson =
|
|
4697
|
+
const adapterNodeModulesPackageJson = join4(
|
|
4373
4698
|
adapter.nodeModulesDir,
|
|
4374
4699
|
packageName,
|
|
4375
4700
|
"package.json"
|
|
4376
4701
|
);
|
|
4377
|
-
return
|
|
4702
|
+
return existsSync5(adapterNodeModulesPackageJson) ? adapterNodeModulesPackageJson : null;
|
|
4378
4703
|
}
|
|
4379
4704
|
function localSdkAliasPlugin(adapter, options) {
|
|
4380
4705
|
const entryFile = options?.workersRuntime ? adapter.sdkWorkersEntryFile : adapter.sdkEntryFile;
|
|
4381
|
-
if (!
|
|
4706
|
+
if (!existsSync5(entryFile)) {
|
|
4382
4707
|
return null;
|
|
4383
4708
|
}
|
|
4384
4709
|
return {
|
|
@@ -4388,7 +4713,7 @@ function localSdkAliasPlugin(adapter, options) {
|
|
|
4388
4713
|
path: entryFile
|
|
4389
4714
|
}));
|
|
4390
4715
|
buildContext.onResolve({ filter: /^deepline\/helpers$/ }, () => ({
|
|
4391
|
-
path:
|
|
4716
|
+
path: join4(adapter.sdkSourceRoot, "helpers.ts")
|
|
4392
4717
|
}));
|
|
4393
4718
|
}
|
|
4394
4719
|
};
|
|
@@ -4619,7 +4944,7 @@ async function resolveLocalImport(fromFile, specifier) {
|
|
|
4619
4944
|
...SOURCE_EXTENSIONS.map((extension) => `${base}${extension}`)
|
|
4620
4945
|
);
|
|
4621
4946
|
candidates.push(
|
|
4622
|
-
...SOURCE_EXTENSIONS.map((extension) =>
|
|
4947
|
+
...SOURCE_EXTENSIONS.map((extension) => join4(base, `index${extension}`))
|
|
4623
4948
|
);
|
|
4624
4949
|
} else if ([".js", ".jsx", ".mjs", ".cjs"].includes(explicitExtension)) {
|
|
4625
4950
|
const stem = base.slice(0, -explicitExtension.length);
|
|
@@ -4638,9 +4963,9 @@ async function resolveLocalImport(fromFile, specifier) {
|
|
|
4638
4963
|
}
|
|
4639
4964
|
function resolvePackageImport(specifier, fromFile, adapter) {
|
|
4640
4965
|
const packageName = getPackageName(specifier);
|
|
4641
|
-
if (packageName === "deepline" &&
|
|
4966
|
+
if (packageName === "deepline" && existsSync5(adapter.sdkPackageJson)) {
|
|
4642
4967
|
const packageJson = JSON.parse(
|
|
4643
|
-
|
|
4968
|
+
readFileSync5(adapter.sdkPackageJson, "utf-8")
|
|
4644
4969
|
);
|
|
4645
4970
|
return {
|
|
4646
4971
|
name: "deepline",
|
|
@@ -4787,7 +5112,7 @@ async function computeWorkersHarnessFingerprintWithAdapter(adapter) {
|
|
|
4787
5112
|
const parts = [];
|
|
4788
5113
|
for (const name of tsFiles) {
|
|
4789
5114
|
const contents = await readFile(
|
|
4790
|
-
|
|
5115
|
+
join4(adapter.workersHarnessFilesDir, name),
|
|
4791
5116
|
"utf-8"
|
|
4792
5117
|
);
|
|
4793
5118
|
parts.push({ name, hash: sha256(contents) });
|
|
@@ -4795,7 +5120,7 @@ async function computeWorkersHarnessFingerprintWithAdapter(adapter) {
|
|
|
4795
5120
|
return sha256(JSON.stringify(parts));
|
|
4796
5121
|
}
|
|
4797
5122
|
function artifactCachePath(graphHash, artifactKind, adapter) {
|
|
4798
|
-
return
|
|
5123
|
+
return join4(
|
|
4799
5124
|
adapter.cacheDir ?? PLAY_ARTIFACT_CACHE_DIR,
|
|
4800
5125
|
`${graphHash}.${artifactKind}.json`
|
|
4801
5126
|
);
|
|
@@ -5228,8 +5553,26 @@ function resolveExecutionProfile(override) {
|
|
|
5228
5553
|
// src/plays/local-file-discovery.ts
|
|
5229
5554
|
import { createHash as createHash2 } from "crypto";
|
|
5230
5555
|
import { readFile as readFile2, stat as stat2 } from "fs/promises";
|
|
5231
|
-
import {
|
|
5232
|
-
|
|
5556
|
+
import {
|
|
5557
|
+
basename as basename2,
|
|
5558
|
+
dirname as dirname6,
|
|
5559
|
+
extname as extname2,
|
|
5560
|
+
isAbsolute as isAbsolute2,
|
|
5561
|
+
join as join5,
|
|
5562
|
+
relative,
|
|
5563
|
+
resolve as resolve7
|
|
5564
|
+
} from "path";
|
|
5565
|
+
var SOURCE_EXTENSIONS2 = [
|
|
5566
|
+
".ts",
|
|
5567
|
+
".tsx",
|
|
5568
|
+
".mts",
|
|
5569
|
+
".cts",
|
|
5570
|
+
".js",
|
|
5571
|
+
".jsx",
|
|
5572
|
+
".mjs",
|
|
5573
|
+
".cjs",
|
|
5574
|
+
".json"
|
|
5575
|
+
];
|
|
5233
5576
|
function sha2562(buffer) {
|
|
5234
5577
|
return createHash2("sha256").update(buffer).digest("hex");
|
|
5235
5578
|
}
|
|
@@ -5253,7 +5596,9 @@ function unquoteStringLiteral2(literal) {
|
|
|
5253
5596
|
return null;
|
|
5254
5597
|
}
|
|
5255
5598
|
try {
|
|
5256
|
-
return JSON.parse(
|
|
5599
|
+
return JSON.parse(
|
|
5600
|
+
quote === '"' ? trimmed : `"${trimmed.slice(1, -1).replace(/"/g, '\\"')}"`
|
|
5601
|
+
);
|
|
5257
5602
|
} catch {
|
|
5258
5603
|
return trimmed.slice(1, -1);
|
|
5259
5604
|
}
|
|
@@ -5314,7 +5659,9 @@ function resolveStringExpression(expression, constants) {
|
|
|
5314
5659
|
}
|
|
5315
5660
|
const parts = splitTopLevelPlus(value);
|
|
5316
5661
|
if (parts) {
|
|
5317
|
-
const resolved = parts.map(
|
|
5662
|
+
const resolved = parts.map(
|
|
5663
|
+
(part) => resolveStringExpression(part, constants)
|
|
5664
|
+
);
|
|
5318
5665
|
return resolved.every((part) => part != null) ? resolved.join("") : null;
|
|
5319
5666
|
}
|
|
5320
5667
|
return null;
|
|
@@ -5322,7 +5669,9 @@ function resolveStringExpression(expression, constants) {
|
|
|
5322
5669
|
function collectTopLevelStringConstants(sourceCode) {
|
|
5323
5670
|
const constants = /* @__PURE__ */ new Map();
|
|
5324
5671
|
const source = stripCommentsToSpaces2(sourceCode);
|
|
5325
|
-
for (const match of source.matchAll(
|
|
5672
|
+
for (const match of source.matchAll(
|
|
5673
|
+
/(?:^|\n)\s*const\s+([A-Za-z_$][\w$]*)\s*=\s*([^;\n]+)/g
|
|
5674
|
+
)) {
|
|
5326
5675
|
const resolved = resolveStringExpression(match[2], constants);
|
|
5327
5676
|
if (resolved != null) {
|
|
5328
5677
|
constants.set(match[1], resolved);
|
|
@@ -5411,7 +5760,9 @@ function localImportSpecifiers(sourceCode) {
|
|
|
5411
5760
|
)) {
|
|
5412
5761
|
if (match[1]?.startsWith(".")) specifiers.push(match[1]);
|
|
5413
5762
|
}
|
|
5414
|
-
for (const match of source.matchAll(
|
|
5763
|
+
for (const match of source.matchAll(
|
|
5764
|
+
/\brequire\s*\(\s*(['"])(\.[^'"]*)\1\s*\)/g
|
|
5765
|
+
)) {
|
|
5415
5766
|
specifiers.push(match[2]);
|
|
5416
5767
|
}
|
|
5417
5768
|
return specifiers;
|
|
@@ -5433,18 +5784,26 @@ async function resolveLocalImport2(fromFile, specifier) {
|
|
|
5433
5784
|
const candidates = [base];
|
|
5434
5785
|
const explicitExtension = extname2(base).toLowerCase();
|
|
5435
5786
|
if (!explicitExtension) {
|
|
5436
|
-
candidates.push(
|
|
5437
|
-
|
|
5787
|
+
candidates.push(
|
|
5788
|
+
...SOURCE_EXTENSIONS2.map((extension) => `${base}${extension}`)
|
|
5789
|
+
);
|
|
5790
|
+
candidates.push(
|
|
5791
|
+
...SOURCE_EXTENSIONS2.map((extension) => join5(base, `index${extension}`))
|
|
5792
|
+
);
|
|
5438
5793
|
} else if ([".js", ".jsx", ".mjs", ".cjs"].includes(explicitExtension)) {
|
|
5439
5794
|
const stem = base.slice(0, -explicitExtension.length);
|
|
5440
|
-
candidates.push(
|
|
5795
|
+
candidates.push(
|
|
5796
|
+
...SOURCE_EXTENSIONS2.map((extension) => `${stem}${extension}`)
|
|
5797
|
+
);
|
|
5441
5798
|
}
|
|
5442
5799
|
for (const candidate of candidates) {
|
|
5443
5800
|
if (await fileExists2(candidate)) {
|
|
5444
5801
|
return candidate;
|
|
5445
5802
|
}
|
|
5446
5803
|
}
|
|
5447
|
-
throw new Error(
|
|
5804
|
+
throw new Error(
|
|
5805
|
+
`Could not resolve local import "${specifier}" from ${fromFile}`
|
|
5806
|
+
);
|
|
5448
5807
|
}
|
|
5449
5808
|
async function discoverPackagedLocalFiles(entryFile) {
|
|
5450
5809
|
const absoluteEntryFile = resolve7(entryFile);
|
|
@@ -5462,12 +5821,17 @@ async function discoverPackagedLocalFiles(entryFile) {
|
|
|
5462
5821
|
const scanSource = stripCommentsToSpaces2(sourceCode);
|
|
5463
5822
|
const constants = collectTopLevelStringConstants(sourceCode);
|
|
5464
5823
|
const childVisits = [];
|
|
5465
|
-
for (const match of scanSource.matchAll(
|
|
5824
|
+
for (const match of scanSource.matchAll(
|
|
5825
|
+
/\b([A-Za-z_$][\w$]*)\s*\.\s*csv\b/g
|
|
5826
|
+
)) {
|
|
5466
5827
|
const target = match[1];
|
|
5467
5828
|
if (target !== "ctx" && !target.endsWith("Ctx")) {
|
|
5468
5829
|
continue;
|
|
5469
5830
|
}
|
|
5470
|
-
const openParen = findCallOpenParen(
|
|
5831
|
+
const openParen = findCallOpenParen(
|
|
5832
|
+
scanSource,
|
|
5833
|
+
match.index + match[0].length
|
|
5834
|
+
);
|
|
5471
5835
|
if (openParen < 0) {
|
|
5472
5836
|
continue;
|
|
5473
5837
|
}
|
|
@@ -5527,11 +5891,11 @@ var PLAY_BUNDLE_CACHE_VERSION2 = 30;
|
|
|
5527
5891
|
var MODULE_DIR = dirname7(fileURLToPath(import.meta.url));
|
|
5528
5892
|
var SDK_PACKAGE_ROOT = resolve8(MODULE_DIR, "..", "..");
|
|
5529
5893
|
var SOURCE_REPO_ROOT = resolve8(SDK_PACKAGE_ROOT, "..");
|
|
5530
|
-
var HAS_SOURCE_BUNDLING_SOURCES =
|
|
5894
|
+
var HAS_SOURCE_BUNDLING_SOURCES = existsSync6(
|
|
5531
5895
|
resolve8(SOURCE_REPO_ROOT, "apps", "play-runner-workers", "src", "entry.ts")
|
|
5532
5896
|
);
|
|
5533
5897
|
var PACKAGED_REPO_ROOT = resolve8(SDK_PACKAGE_ROOT, "dist", "repo");
|
|
5534
|
-
var HAS_PACKAGED_BUNDLING_SOURCES =
|
|
5898
|
+
var HAS_PACKAGED_BUNDLING_SOURCES = existsSync6(
|
|
5535
5899
|
resolve8(PACKAGED_REPO_ROOT, "apps", "play-runner-workers", "src", "entry.ts")
|
|
5536
5900
|
);
|
|
5537
5901
|
var PROJECT_ROOT = HAS_SOURCE_BUNDLING_SOURCES ? SOURCE_REPO_ROOT : HAS_PACKAGED_BUNDLING_SOURCES ? PACKAGED_REPO_ROOT : resolve8(SDK_PACKAGE_ROOT, "..");
|
|
@@ -5577,14 +5941,14 @@ function createSdkPlayBundlingAdapter() {
|
|
|
5577
5941
|
return {
|
|
5578
5942
|
projectRoot: PROJECT_ROOT,
|
|
5579
5943
|
nodeModulesDir: resolve8(PROJECT_ROOT, "node_modules"),
|
|
5580
|
-
cacheDir:
|
|
5944
|
+
cacheDir: join6(
|
|
5581
5945
|
tmpdir2(),
|
|
5582
5946
|
`deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION2}`
|
|
5583
5947
|
),
|
|
5584
5948
|
sdkSourceRoot: SDK_SOURCE_ROOT,
|
|
5585
5949
|
sdkPackageJson: SDK_PACKAGE_JSON,
|
|
5586
5950
|
sdkEntryFile: SDK_ENTRY_FILE,
|
|
5587
|
-
sdkTypesEntryFile: HAS_SOURCE_BUNDLING_SOURCES || !
|
|
5951
|
+
sdkTypesEntryFile: HAS_SOURCE_BUNDLING_SOURCES || !existsSync6(SDK_TYPES_ENTRY_FILE) ? SDK_ENTRY_FILE : SDK_TYPES_ENTRY_FILE,
|
|
5588
5952
|
sdkWorkersEntryFile: SDK_WORKERS_ENTRY_FILE,
|
|
5589
5953
|
workersHarnessEntryFile: WORKERS_HARNESS_ENTRY_FILE,
|
|
5590
5954
|
workersHarnessFilesDir: WORKERS_HARNESS_FILES_DIR,
|
|
@@ -7558,8 +7922,8 @@ function materializeRemotePlaySource(input) {
|
|
|
7558
7922
|
return null;
|
|
7559
7923
|
}
|
|
7560
7924
|
const outputPath = input.outPath ?? defaultMaterializedPlayPath(input.playName);
|
|
7561
|
-
if (
|
|
7562
|
-
const existingSource =
|
|
7925
|
+
if (existsSync7(outputPath)) {
|
|
7926
|
+
const existingSource = readFileSync6(outputPath, "utf-8");
|
|
7563
7927
|
if (existingSource === input.sourceCode) {
|
|
7564
7928
|
return { path: outputPath, status: "unchanged", created: false };
|
|
7565
7929
|
}
|
|
@@ -7611,7 +7975,7 @@ function extractPlayName(code, filePath) {
|
|
|
7611
7975
|
throw buildMissingDefinePlayError(filePath);
|
|
7612
7976
|
}
|
|
7613
7977
|
function isFileTarget(target) {
|
|
7614
|
-
return
|
|
7978
|
+
return existsSync7(resolve10(target));
|
|
7615
7979
|
}
|
|
7616
7980
|
function looksLikeRunId(target) {
|
|
7617
7981
|
return /^play\/[^/]+\/run\/[^/]+/.test(target.trim());
|
|
@@ -7640,7 +8004,7 @@ function parsePositiveInteger3(value, flagName) {
|
|
|
7640
8004
|
return parsed;
|
|
7641
8005
|
}
|
|
7642
8006
|
function parseJsonInput(raw) {
|
|
7643
|
-
const source = raw.startsWith("@") ?
|
|
8007
|
+
const source = raw.startsWith("@") ? readFileSync6(resolve10(raw.slice(1)), "utf-8") : raw;
|
|
7644
8008
|
const parsed = JSON.parse(source);
|
|
7645
8009
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
7646
8010
|
throw new Error("--input must be a JSON object.");
|
|
@@ -7742,7 +8106,7 @@ function fileInputBindingsFromStaticPipeline(staticPipeline) {
|
|
|
7742
8106
|
function isLocalFilePathValue(value) {
|
|
7743
8107
|
if (typeof value !== "string" || !value.trim()) return false;
|
|
7744
8108
|
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value.trim())) return false;
|
|
7745
|
-
return
|
|
8109
|
+
return existsSync7(resolve10(value));
|
|
7746
8110
|
}
|
|
7747
8111
|
function inputContainsLocalFilePath(value) {
|
|
7748
8112
|
if (isLocalFilePathValue(value)) {
|
|
@@ -7803,7 +8167,7 @@ async function stageFileInputArgs(input) {
|
|
|
7803
8167
|
};
|
|
7804
8168
|
}
|
|
7805
8169
|
function stageFile(logicalPath, absolutePath) {
|
|
7806
|
-
const buffer =
|
|
8170
|
+
const buffer = readFileSync6(absolutePath);
|
|
7807
8171
|
return {
|
|
7808
8172
|
logicalPath,
|
|
7809
8173
|
contentBase64: buffer.toString("base64"),
|
|
@@ -9258,7 +9622,9 @@ function buildRunPackageTextLines(packaged) {
|
|
|
9258
9622
|
lines.push(` ${kind} ${id}: ${stepStatus}${rowCount}`);
|
|
9259
9623
|
lines.push(...formatPackageDatasetSummaryLines(output?.summary));
|
|
9260
9624
|
if (previewRows !== null) {
|
|
9261
|
-
lines.push(
|
|
9625
|
+
lines.push(
|
|
9626
|
+
` preview=${previewRows}${preview?.truncated ? " truncated" : ""}`
|
|
9627
|
+
);
|
|
9262
9628
|
}
|
|
9263
9629
|
}
|
|
9264
9630
|
const next = packaged.next && typeof packaged.next === "object" && !Array.isArray(packaged.next) ? packaged.next : {};
|
|
@@ -10037,7 +10403,7 @@ async function handlePlayCheck(args) {
|
|
|
10037
10403
|
return 1;
|
|
10038
10404
|
}
|
|
10039
10405
|
const absolutePlayPath = resolve10(options.target);
|
|
10040
|
-
const sourceCode =
|
|
10406
|
+
const sourceCode = readFileSync6(absolutePlayPath, "utf-8");
|
|
10041
10407
|
let graph;
|
|
10042
10408
|
try {
|
|
10043
10409
|
graph = await collectBundledPlayGraph(absolutePlayPath);
|
|
@@ -10121,7 +10487,7 @@ async function handleFileBackedRun(options) {
|
|
|
10121
10487
|
const sourceCode = traceCliSync(
|
|
10122
10488
|
"cli.play_file_read_source",
|
|
10123
10489
|
{ targetKind: "file" },
|
|
10124
|
-
() =>
|
|
10490
|
+
() => readFileSync6(absolutePlayPath, "utf-8")
|
|
10125
10491
|
);
|
|
10126
10492
|
const runtimeInput = options.input ? { ...options.input } : {};
|
|
10127
10493
|
let graph;
|
|
@@ -10408,7 +10774,7 @@ async function handlePlayRun(args) {
|
|
|
10408
10774
|
const resolved = resolve10(options.target.path);
|
|
10409
10775
|
console.error(`File not found: ${resolved}`);
|
|
10410
10776
|
const dir = dirname8(resolved);
|
|
10411
|
-
if (
|
|
10777
|
+
if (existsSync7(dir)) {
|
|
10412
10778
|
const base = basename3(resolved);
|
|
10413
10779
|
try {
|
|
10414
10780
|
const siblings = readdirSync(dir).filter(
|
|
@@ -10417,7 +10783,7 @@ async function handlePlayRun(args) {
|
|
|
10417
10783
|
if (siblings.length > 0) {
|
|
10418
10784
|
console.error(`Did you mean one of these?`);
|
|
10419
10785
|
for (const s of siblings.slice(0, 5)) {
|
|
10420
|
-
console.error(` ${
|
|
10786
|
+
console.error(` ${join7(dir, s)}`);
|
|
10421
10787
|
}
|
|
10422
10788
|
}
|
|
10423
10789
|
} catch {
|
|
@@ -10755,7 +11121,7 @@ async function handlePlayGet(args) {
|
|
|
10755
11121
|
outPath = resolve10(args[++index]);
|
|
10756
11122
|
}
|
|
10757
11123
|
}
|
|
10758
|
-
const playName = isFileTarget(target) ? extractPlayName(
|
|
11124
|
+
const playName = isFileTarget(target) ? extractPlayName(readFileSync6(resolve10(target), "utf-8"), resolve10(target)) : parseReferencedPlayTarget2(target).playName;
|
|
10759
11125
|
const detail = isFileTarget(target) ? await client.getPlay(playName) : await assertCanonicalNamedPlayReference(client, target);
|
|
10760
11126
|
const resolvedSource = detail.play.workingRevision?.sourceCode ?? detail.play.liveRevision?.sourceCode ?? detail.play.currentRevision?.sourceCode ?? detail.play.sourceCode ?? "";
|
|
10761
11127
|
const materializedFile = outPath ? materializeRemotePlaySource({
|
|
@@ -11060,7 +11426,9 @@ function matchesPlayGrepQuery(value, query, mode) {
|
|
|
11060
11426
|
async function handlePlayGrep(args) {
|
|
11061
11427
|
const query = args[0]?.trim();
|
|
11062
11428
|
if (!query) {
|
|
11063
|
-
console.error(
|
|
11429
|
+
console.error(
|
|
11430
|
+
"Usage: deepline plays grep <query> [--mode all|any|phrase] [--compact] [--json]"
|
|
11431
|
+
);
|
|
11064
11432
|
return 1;
|
|
11065
11433
|
}
|
|
11066
11434
|
let mode = "all";
|
|
@@ -11093,13 +11461,15 @@ async function handlePlayGrep(args) {
|
|
|
11093
11461
|
)
|
|
11094
11462
|
).map((play) => summarizePlayListItemForCli(play, { compact }));
|
|
11095
11463
|
if (argsWantJson(args)) {
|
|
11096
|
-
process.stdout.write(
|
|
11097
|
-
|
|
11098
|
-
|
|
11099
|
-
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
|
|
11464
|
+
process.stdout.write(
|
|
11465
|
+
`${JSON.stringify({
|
|
11466
|
+
plays,
|
|
11467
|
+
count: plays.length,
|
|
11468
|
+
query,
|
|
11469
|
+
grep: { mode, terms: parsePlayGrepTerms(query, mode) }
|
|
11470
|
+
})}
|
|
11471
|
+
`
|
|
11472
|
+
);
|
|
11103
11473
|
return 0;
|
|
11104
11474
|
}
|
|
11105
11475
|
process.stdout.write(`${plays.length} plays found:
|
|
@@ -11735,12 +12105,12 @@ Examples:
|
|
|
11735
12105
|
import { Option } from "commander";
|
|
11736
12106
|
import { chmodSync, mkdtempSync, writeFileSync as writeFileSync8 } from "fs";
|
|
11737
12107
|
import { tmpdir as tmpdir3 } from "os";
|
|
11738
|
-
import { join as
|
|
12108
|
+
import { join as join9 } from "path";
|
|
11739
12109
|
|
|
11740
12110
|
// src/tool-output.ts
|
|
11741
12111
|
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync7 } from "fs";
|
|
11742
|
-
import { homedir as
|
|
11743
|
-
import { join as
|
|
12112
|
+
import { homedir as homedir4 } from "os";
|
|
12113
|
+
import { join as join8 } from "path";
|
|
11744
12114
|
function isPlainObject(value) {
|
|
11745
12115
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
11746
12116
|
}
|
|
@@ -11762,7 +12132,9 @@ function normalizeRows(value) {
|
|
|
11762
12132
|
});
|
|
11763
12133
|
}
|
|
11764
12134
|
function candidateRoots(payload) {
|
|
11765
|
-
const roots = [
|
|
12135
|
+
const roots = [
|
|
12136
|
+
{ path: null, value: payload }
|
|
12137
|
+
];
|
|
11766
12138
|
if (isPlainObject(payload) && isPlainObject(payload.toolResponse)) {
|
|
11767
12139
|
roots.push({ path: "toolResponse", value: payload.toolResponse });
|
|
11768
12140
|
if (Object.prototype.hasOwnProperty.call(payload.toolResponse, "raw")) {
|
|
@@ -11789,7 +12161,9 @@ function candidateRoots(payload) {
|
|
|
11789
12161
|
function findBestArrayCandidate(value, pathPrefix = "", depth = 0) {
|
|
11790
12162
|
if (depth > 5) return null;
|
|
11791
12163
|
const directRows = normalizeRows(value);
|
|
11792
|
-
const hasObjectRow = directRows?.some(
|
|
12164
|
+
const hasObjectRow = directRows?.some(
|
|
12165
|
+
(row) => Object.keys(row).some((key) => key !== "value")
|
|
12166
|
+
) ?? false;
|
|
11793
12167
|
let best = directRows && directRows.length > 0 && hasObjectRow ? { path: pathPrefix, rows: directRows } : null;
|
|
11794
12168
|
if (!isPlainObject(value)) {
|
|
11795
12169
|
return best;
|
|
@@ -11805,7 +12179,9 @@ function findBestArrayCandidate(value, pathPrefix = "", depth = 0) {
|
|
|
11805
12179
|
return best;
|
|
11806
12180
|
}
|
|
11807
12181
|
function tryConvertToList(payload, options) {
|
|
11808
|
-
const listExtractorPaths = Array.isArray(options?.listExtractorPaths) ? options?.listExtractorPaths.filter(
|
|
12182
|
+
const listExtractorPaths = Array.isArray(options?.listExtractorPaths) ? options?.listExtractorPaths.filter(
|
|
12183
|
+
(entry) => typeof entry === "string" && entry.trim().length > 0
|
|
12184
|
+
) : [];
|
|
11809
12185
|
if (listExtractorPaths.length > 0) {
|
|
11810
12186
|
for (const root of candidateRoots(payload)) {
|
|
11811
12187
|
for (const extractorPath of listExtractorPaths) {
|
|
@@ -11830,19 +12206,19 @@ function tryConvertToList(payload, options) {
|
|
|
11830
12206
|
return null;
|
|
11831
12207
|
}
|
|
11832
12208
|
function ensureOutputDir() {
|
|
11833
|
-
const outputDir =
|
|
12209
|
+
const outputDir = join8(homedir4(), ".local", "share", "deepline", "data");
|
|
11834
12210
|
mkdirSync4(outputDir, { recursive: true });
|
|
11835
12211
|
return outputDir;
|
|
11836
12212
|
}
|
|
11837
12213
|
function writeJsonOutputFile(payload, stem) {
|
|
11838
12214
|
const outputDir = ensureOutputDir();
|
|
11839
|
-
const outputPath =
|
|
12215
|
+
const outputPath = join8(outputDir, `${stem}_${Date.now()}.json`);
|
|
11840
12216
|
writeFileSync7(outputPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
11841
12217
|
return outputPath;
|
|
11842
12218
|
}
|
|
11843
12219
|
function writeCsvOutputFile(rows, stem) {
|
|
11844
12220
|
const outputDir = ensureOutputDir();
|
|
11845
|
-
const outputPath =
|
|
12221
|
+
const outputPath = join8(outputDir, `${stem}_${Date.now()}.csv`);
|
|
11846
12222
|
const seen = /* @__PURE__ */ new Set();
|
|
11847
12223
|
const columns = [];
|
|
11848
12224
|
for (const row of rows) {
|
|
@@ -11871,7 +12247,9 @@ function writeCsvOutputFile(rows, stem) {
|
|
|
11871
12247
|
const previewColumns = columns.slice(0, 5);
|
|
11872
12248
|
const preview = [
|
|
11873
12249
|
previewColumns.join(","),
|
|
11874
|
-
...previewRows.map(
|
|
12250
|
+
...previewRows.map(
|
|
12251
|
+
(row) => previewColumns.map((column) => escapeCell(row[column])).join(",")
|
|
12252
|
+
)
|
|
11875
12253
|
].join("\n");
|
|
11876
12254
|
return {
|
|
11877
12255
|
path: outputPath,
|
|
@@ -11884,9 +12262,11 @@ function extractSummaryFields(payload) {
|
|
|
11884
12262
|
const candidates = candidateRoots(payload);
|
|
11885
12263
|
for (const candidate of candidates) {
|
|
11886
12264
|
if (!isPlainObject(candidate.value)) continue;
|
|
11887
|
-
const summaryEntries = Object.entries(candidate.value).filter(
|
|
11888
|
-
|
|
11889
|
-
|
|
12265
|
+
const summaryEntries = Object.entries(candidate.value).filter(
|
|
12266
|
+
([, value]) => {
|
|
12267
|
+
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
12268
|
+
}
|
|
12269
|
+
);
|
|
11890
12270
|
if (summaryEntries.length === 0) continue;
|
|
11891
12271
|
return Object.fromEntries(summaryEntries);
|
|
11892
12272
|
}
|
|
@@ -12416,8 +12796,16 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
|
|
|
12416
12796
|
arrayField(toolExecutionResult, "extractedValues", "extracted_values")
|
|
12417
12797
|
);
|
|
12418
12798
|
const cost = recordField(tool, "cost");
|
|
12419
|
-
const deeplineCredits = numberField(
|
|
12420
|
-
|
|
12799
|
+
const deeplineCredits = numberField(
|
|
12800
|
+
tool,
|
|
12801
|
+
"deeplineCreditsPerPricingUnit",
|
|
12802
|
+
"deepline_credits_per_pricing_unit"
|
|
12803
|
+
);
|
|
12804
|
+
const deeplineUsdPerPricingUnit = numberField(
|
|
12805
|
+
tool,
|
|
12806
|
+
"deeplineUsdPerPricingUnit",
|
|
12807
|
+
"deepline_usd_per_pricing_unit"
|
|
12808
|
+
);
|
|
12421
12809
|
const starterScript = seedToolListScript({
|
|
12422
12810
|
toolId,
|
|
12423
12811
|
payload: samplePayloadForInputFields(inputFields),
|
|
@@ -12505,7 +12893,9 @@ function printCompactToolContract(tool, requestedToolId) {
|
|
|
12505
12893
|
if (starterPath) {
|
|
12506
12894
|
console.log("");
|
|
12507
12895
|
console.log(`Starter script: ${starterPath}`);
|
|
12508
|
-
console.log(
|
|
12896
|
+
console.log(
|
|
12897
|
+
"Copy it into your project and replace the sample input with the proven probe payload."
|
|
12898
|
+
);
|
|
12509
12899
|
}
|
|
12510
12900
|
if (listGetters.length || valueGetters.length) {
|
|
12511
12901
|
console.log("");
|
|
@@ -12668,7 +13058,9 @@ function playResultExpression(entry) {
|
|
|
12668
13058
|
}
|
|
12669
13059
|
function toolMetadataJsonForDescribe(tool, requestedToolId) {
|
|
12670
13060
|
const toolId = String(tool.toolId || requestedToolId);
|
|
12671
|
-
const inputFields = toolInputFieldsForDisplay(
|
|
13061
|
+
const inputFields = toolInputFieldsForDisplay(
|
|
13062
|
+
recordField(tool, "inputSchema", "input_schema")
|
|
13063
|
+
);
|
|
12672
13064
|
const starterScript = seedToolListScript({
|
|
12673
13065
|
toolId,
|
|
12674
13066
|
payload: samplePayloadForInputFields(inputFields),
|
|
@@ -12693,7 +13085,9 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
|
|
|
12693
13085
|
toolId,
|
|
12694
13086
|
provider: tool.provider,
|
|
12695
13087
|
displayName: tool.displayName,
|
|
12696
|
-
usageGuidance: usageGuidanceWithAccessDefaults(
|
|
13088
|
+
usageGuidance: usageGuidanceWithAccessDefaults(
|
|
13089
|
+
recordField(tool, "usageGuidance", "usage_guidance")
|
|
13090
|
+
),
|
|
12697
13091
|
runtimeOutputHelp: {
|
|
12698
13092
|
contract: "tools describe shows declared schema and Deepline getters; it is not an observed provider response.",
|
|
12699
13093
|
getterScope: "extractedValues/extractedLists .get() only works for declared Deepline getters listed in usageGuidance.toolExecutionResult.",
|
|
@@ -12915,9 +13309,9 @@ function powerShellQuote(value) {
|
|
|
12915
13309
|
function seedToolListScript(input) {
|
|
12916
13310
|
const stem = safeFileStem(input.toolId);
|
|
12917
13311
|
const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
|
|
12918
|
-
const scriptDir = mkdtempSync(
|
|
13312
|
+
const scriptDir = mkdtempSync(join9(tmpdir3(), "deepline-workflow-seed-"));
|
|
12919
13313
|
chmodSync(scriptDir, 448);
|
|
12920
|
-
const scriptPath =
|
|
13314
|
+
const scriptPath = join9(scriptDir, fileName);
|
|
12921
13315
|
const projectDir = `deepline/projects/${stem}-workflow`;
|
|
12922
13316
|
const playName = `${stem}-workflow`;
|
|
12923
13317
|
const sampleRows = input.rows.length > 0 ? `${JSON.stringify(input.rows.slice(0, 2)).replace(/\]$/, "")}, ...]` : "[]";
|
|
@@ -13208,8 +13602,8 @@ async function executeTool(args) {
|
|
|
13208
13602
|
|
|
13209
13603
|
// src/cli/commands/update.ts
|
|
13210
13604
|
import { spawn } from "child_process";
|
|
13211
|
-
import { existsSync as
|
|
13212
|
-
import { dirname as dirname9, join as
|
|
13605
|
+
import { existsSync as existsSync8 } from "fs";
|
|
13606
|
+
import { dirname as dirname9, join as join10, resolve as resolve11 } from "path";
|
|
13213
13607
|
function posixShellQuote(value) {
|
|
13214
13608
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
13215
13609
|
}
|
|
@@ -13230,7 +13624,7 @@ function buildSourceUpdateCommand(sourceRoot) {
|
|
|
13230
13624
|
function findRepoBackedSdkRoot(startPath) {
|
|
13231
13625
|
let current = resolve11(startPath);
|
|
13232
13626
|
while (true) {
|
|
13233
|
-
if (
|
|
13627
|
+
if (existsSync8(join10(current, "sdk", "package.json")) && existsSync8(join10(current, "sdk", "bin", "deepline-dev.ts"))) {
|
|
13234
13628
|
return current;
|
|
13235
13629
|
}
|
|
13236
13630
|
const parent = dirname9(current);
|
|
@@ -13308,8 +13702,10 @@ async function handleUpdate(options) {
|
|
|
13308
13702
|
printCommandEnvelope({ ...plan, render }, { json: false });
|
|
13309
13703
|
return 0;
|
|
13310
13704
|
}
|
|
13311
|
-
process.stderr.write(
|
|
13312
|
-
`
|
|
13705
|
+
process.stderr.write(
|
|
13706
|
+
`Updating Deepline SDK/CLI with: ${plan.manualCommand}
|
|
13707
|
+
`
|
|
13708
|
+
);
|
|
13313
13709
|
return runCommand(plan.command, plan.args);
|
|
13314
13710
|
}
|
|
13315
13711
|
function registerUpdateCommand(program) {
|
|
@@ -13333,9 +13729,16 @@ Examples:
|
|
|
13333
13729
|
|
|
13334
13730
|
// src/cli/skills-sync.ts
|
|
13335
13731
|
import { spawn as spawn2, spawnSync } from "child_process";
|
|
13336
|
-
import {
|
|
13337
|
-
|
|
13338
|
-
|
|
13732
|
+
import {
|
|
13733
|
+
existsSync as existsSync9,
|
|
13734
|
+
mkdirSync as mkdirSync5,
|
|
13735
|
+
readdirSync as readdirSync2,
|
|
13736
|
+
readFileSync as readFileSync7,
|
|
13737
|
+
statSync as statSync2,
|
|
13738
|
+
writeFileSync as writeFileSync9
|
|
13739
|
+
} from "fs";
|
|
13740
|
+
import { homedir as homedir5 } from "os";
|
|
13741
|
+
import { dirname as dirname10, join as join11 } from "path";
|
|
13339
13742
|
var CHECK_TIMEOUT_MS2 = 3e3;
|
|
13340
13743
|
var SDK_SKILL_NAME = "deepline-sdk";
|
|
13341
13744
|
var SKILL_AGENTS = ["codex", "claude-code", "cursor"];
|
|
@@ -13345,14 +13748,21 @@ function shouldSkipSkillsSync() {
|
|
|
13345
13748
|
return value === "1" || value === "true" || value === "yes" || value === "on";
|
|
13346
13749
|
}
|
|
13347
13750
|
function sdkSkillsVersionPath(baseUrl) {
|
|
13348
|
-
const home = process.env.HOME?.trim() ||
|
|
13349
|
-
return
|
|
13751
|
+
const home = process.env.HOME?.trim() || homedir5();
|
|
13752
|
+
return join11(
|
|
13753
|
+
home,
|
|
13754
|
+
".local",
|
|
13755
|
+
"deepline",
|
|
13756
|
+
baseUrlSlug(baseUrl),
|
|
13757
|
+
"sdk-skills",
|
|
13758
|
+
".version"
|
|
13759
|
+
);
|
|
13350
13760
|
}
|
|
13351
13761
|
function readLocalSkillsVersion(baseUrl) {
|
|
13352
13762
|
const path = sdkSkillsVersionPath(baseUrl);
|
|
13353
|
-
if (!
|
|
13763
|
+
if (!existsSync9(path)) return "";
|
|
13354
13764
|
try {
|
|
13355
|
-
return
|
|
13765
|
+
return readFileSync7(path, "utf-8").trim();
|
|
13356
13766
|
} catch {
|
|
13357
13767
|
return "";
|
|
13358
13768
|
}
|
|
@@ -13364,10 +13774,10 @@ function writeLocalSkillsVersion(baseUrl, version) {
|
|
|
13364
13774
|
`, "utf-8");
|
|
13365
13775
|
}
|
|
13366
13776
|
function installedSdkSkillHasStalePositionalExecuteExamples() {
|
|
13367
|
-
const home = process.env.HOME?.trim() ||
|
|
13777
|
+
const home = process.env.HOME?.trim() || homedir5();
|
|
13368
13778
|
const roots = [
|
|
13369
|
-
|
|
13370
|
-
|
|
13779
|
+
join11(home, ".claude", "skills", SDK_SKILL_NAME),
|
|
13780
|
+
join11(home, ".agents", "skills", SDK_SKILL_NAME)
|
|
13371
13781
|
];
|
|
13372
13782
|
const staleMarkers = [
|
|
13373
13783
|
"ctx.tools.execute(key",
|
|
@@ -13378,21 +13788,21 @@ function installedSdkSkillHasStalePositionalExecuteExamples() {
|
|
|
13378
13788
|
];
|
|
13379
13789
|
const scan = (dir) => {
|
|
13380
13790
|
for (const entry of readdirSync2(dir)) {
|
|
13381
|
-
const path =
|
|
13791
|
+
const path = join11(dir, entry);
|
|
13382
13792
|
const stat3 = statSync2(path);
|
|
13383
13793
|
if (stat3.isDirectory()) {
|
|
13384
13794
|
if (scan(path)) return true;
|
|
13385
13795
|
continue;
|
|
13386
13796
|
}
|
|
13387
13797
|
if (!entry.endsWith(".md")) continue;
|
|
13388
|
-
const text =
|
|
13798
|
+
const text = readFileSync7(path, "utf-8");
|
|
13389
13799
|
if (staleMarkers.some((marker) => text.includes(marker))) return true;
|
|
13390
13800
|
}
|
|
13391
13801
|
return false;
|
|
13392
13802
|
};
|
|
13393
13803
|
for (const root of roots) {
|
|
13394
13804
|
try {
|
|
13395
|
-
if (
|
|
13805
|
+
if (existsSync9(root) && scan(root)) return true;
|
|
13396
13806
|
} catch {
|
|
13397
13807
|
continue;
|
|
13398
13808
|
}
|
|
@@ -13428,7 +13838,10 @@ async function fetchSkillsUpdate(baseUrl, localVersion) {
|
|
|
13428
13838
|
}
|
|
13429
13839
|
}
|
|
13430
13840
|
function buildSkillsInstallArgs(baseUrl) {
|
|
13431
|
-
const packageUrl = new URL(
|
|
13841
|
+
const packageUrl = new URL(
|
|
13842
|
+
"/.well-known/skills/index.json",
|
|
13843
|
+
baseUrl
|
|
13844
|
+
).toString();
|
|
13432
13845
|
return [
|
|
13433
13846
|
"--yes",
|
|
13434
13847
|
"skills",
|
|
@@ -13444,7 +13857,10 @@ function buildSkillsInstallArgs(baseUrl) {
|
|
|
13444
13857
|
];
|
|
13445
13858
|
}
|
|
13446
13859
|
function buildBunxSkillsInstallArgs(baseUrl) {
|
|
13447
|
-
const packageUrl = new URL(
|
|
13860
|
+
const packageUrl = new URL(
|
|
13861
|
+
"/.well-known/skills/index.json",
|
|
13862
|
+
baseUrl
|
|
13863
|
+
).toString();
|
|
13448
13864
|
return [
|
|
13449
13865
|
"--bun",
|
|
13450
13866
|
"skills",
|
|
@@ -13588,8 +14004,8 @@ function shouldDeferSkillsSyncForCommand() {
|
|
|
13588
14004
|
return (command === "play" || command === "plays") && subcommand === "run" && args.includes("--json");
|
|
13589
14005
|
}
|
|
13590
14006
|
async function runPlayRunnerHealthCheck() {
|
|
13591
|
-
const dir = await mkdtemp(
|
|
13592
|
-
const file =
|
|
14007
|
+
const dir = await mkdtemp(join12(tmpdir4(), "deepline-health-play-"));
|
|
14008
|
+
const file = join12(dir, "health-check.play.ts");
|
|
13593
14009
|
try {
|
|
13594
14010
|
await writeFile4(
|
|
13595
14011
|
file,
|