deepline 0.1.62 → 0.1.64
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 +702 -339
- package/dist/cli/index.mjs +727 -348
- package/dist/index.d.mts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +77 -51
- package/dist/index.mjs +77 -51
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +9 -10
- package/dist/repo/apps/play-runner-workers/src/entry.ts +55 -0
- 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 +25 -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/play-runtime/tool-result.ts +28 -15
- package/dist/repo/shared_libs/plays/dataset.ts +10 -11
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -57,7 +57,11 @@ var RateLimitError = class extends DeeplineError {
|
|
|
57
57
|
/** Milliseconds to wait before retrying, from the `Retry-After` response header. Defaults to 5000. */
|
|
58
58
|
retryAfterMs;
|
|
59
59
|
constructor(retryAfterMs = 5e3, message) {
|
|
60
|
-
super(
|
|
60
|
+
super(
|
|
61
|
+
message ?? `Rate limited. Retry after ${retryAfterMs}ms.`,
|
|
62
|
+
429,
|
|
63
|
+
"RATE_LIMIT"
|
|
64
|
+
);
|
|
61
65
|
this.name = "RateLimitError";
|
|
62
66
|
this.retryAfterMs = retryAfterMs;
|
|
63
67
|
}
|
|
@@ -220,10 +224,10 @@ function resolveConfig(options) {
|
|
|
220
224
|
|
|
221
225
|
// src/release.ts
|
|
222
226
|
var SDK_RELEASE = {
|
|
223
|
-
version: "0.1.
|
|
227
|
+
version: "0.1.64",
|
|
224
228
|
apiContract: "2026-05-play-bootstrap-dataset-summary",
|
|
225
229
|
supportPolicy: {
|
|
226
|
-
latest: "0.1.
|
|
230
|
+
latest: "0.1.64",
|
|
227
231
|
minimumSupported: "0.1.53",
|
|
228
232
|
deprecatedBelow: "0.1.53"
|
|
229
233
|
}
|
|
@@ -246,7 +250,7 @@ var HttpClient = class {
|
|
|
246
250
|
config;
|
|
247
251
|
authHeaders(extra) {
|
|
248
252
|
const headers = {
|
|
249
|
-
|
|
253
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
250
254
|
"User-Agent": `deepline-ts-sdk/${SDK_VERSION}`,
|
|
251
255
|
"X-Deepline-SDK-Version": SDK_VERSION,
|
|
252
256
|
"X-Deepline-API-Contract": SDK_API_CONTRACT,
|
|
@@ -929,31 +933,34 @@ var DeeplineClient = class {
|
|
|
929
933
|
* artifactStorageKey: 'plays/v1/orgs/acme/plays/my-play/artifacts/playgraph_abc123.json',
|
|
930
934
|
* });
|
|
931
935
|
* ```
|
|
932
|
-
|
|
936
|
+
*/
|
|
933
937
|
async startPlayRun(request) {
|
|
934
|
-
const response = await this.http.post(
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
938
|
+
const response = await this.http.post(
|
|
939
|
+
"/api/v2/plays/run",
|
|
940
|
+
{
|
|
941
|
+
...request.name ? { name: request.name } : {},
|
|
942
|
+
...request.revisionId ? { revisionId: request.revisionId } : {},
|
|
943
|
+
...request.artifactStorageKey ? { artifactStorageKey: request.artifactStorageKey } : {},
|
|
944
|
+
...request.sourceCode ? { sourceCode: request.sourceCode } : {},
|
|
945
|
+
...request.sourceFiles ? { sourceFiles: request.sourceFiles } : {},
|
|
946
|
+
..."staticPipeline" in request ? { staticPipeline: request.staticPipeline } : {},
|
|
947
|
+
...request.artifactHash ? { artifactHash: request.artifactHash } : {},
|
|
948
|
+
...request.graphHash ? { graphHash: request.graphHash } : {},
|
|
949
|
+
...request.runtimeArtifact ? { runtimeArtifact: request.runtimeArtifact } : {},
|
|
950
|
+
...request.compilerManifest ? { compilerManifest: request.compilerManifest } : {},
|
|
951
|
+
...request.inputFileUpload ? { inputFileUpload: request.inputFileUpload } : {},
|
|
952
|
+
...request.packagedFileUploads?.length ? { packagedFileUploads: request.packagedFileUploads } : {},
|
|
953
|
+
...request.input ? { input: request.input } : {},
|
|
954
|
+
...request.inputFile ? { inputFile: request.inputFile } : {},
|
|
955
|
+
...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
|
|
956
|
+
...request.force ? { force: true } : {},
|
|
957
|
+
...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
|
|
958
|
+
// Profile selection is the API's job, not the CLI's. The server
|
|
959
|
+
// hardcodes workers_edge as the default; tests that want a
|
|
960
|
+
// different profile pass `request.profile` explicitly.
|
|
961
|
+
...request.profile ? { profile: request.profile } : {}
|
|
962
|
+
}
|
|
963
|
+
);
|
|
957
964
|
return normalizePlayRunStart(response);
|
|
958
965
|
}
|
|
959
966
|
async *startPlayRunStream(request, options) {
|
|
@@ -1205,10 +1212,7 @@ var DeeplineClient = class {
|
|
|
1205
1212
|
}
|
|
1206
1213
|
return formData;
|
|
1207
1214
|
};
|
|
1208
|
-
const response = await this.http.postFormData(
|
|
1209
|
-
"/api/v2/plays/files/stage",
|
|
1210
|
-
buildFormData
|
|
1211
|
-
);
|
|
1215
|
+
const response = await this.http.postFormData("/api/v2/plays/files/stage", buildFormData);
|
|
1212
1216
|
return response.files;
|
|
1213
1217
|
}
|
|
1214
1218
|
async resolveStagedPlayFiles(files) {
|
|
@@ -1655,7 +1659,9 @@ var DeeplineClient = class {
|
|
|
1655
1659
|
}
|
|
1656
1660
|
options?.onProgress?.(status);
|
|
1657
1661
|
if (TERMINAL_PLAY_STATUSES.has(status.status)) {
|
|
1658
|
-
const finalStatus = await this.getPlayStatus(
|
|
1662
|
+
const finalStatus = await this.getPlayStatus(
|
|
1663
|
+
status.runId || workflowId
|
|
1664
|
+
).catch(() => status);
|
|
1659
1665
|
return playRunResultFromStatus(finalStatus, start, workflowId);
|
|
1660
1666
|
}
|
|
1661
1667
|
}
|
|
@@ -1946,11 +1952,9 @@ function openUrlMacos(targetUrl, allowFocus, runner = defaultBrowserCommandRunne
|
|
|
1946
1952
|
return true;
|
|
1947
1953
|
}
|
|
1948
1954
|
try {
|
|
1949
|
-
runner.execFileSync(
|
|
1950
|
-
"
|
|
1951
|
-
|
|
1952
|
-
{ stdio: "ignore" }
|
|
1953
|
-
);
|
|
1955
|
+
runner.execFileSync("open", [...allowFocus ? [] : ["-g"], targetUrl], {
|
|
1956
|
+
stdio: "ignore"
|
|
1957
|
+
});
|
|
1954
1958
|
return true;
|
|
1955
1959
|
} catch {
|
|
1956
1960
|
return false;
|
|
@@ -2144,7 +2148,10 @@ function createTimestampedName(prefix, extension) {
|
|
|
2144
2148
|
return `${prefix}-${timestamp}.${extension}`;
|
|
2145
2149
|
}
|
|
2146
2150
|
async function writeCsvRowsFile(prefix, rows) {
|
|
2147
|
-
const path = await writeOutputFile(
|
|
2151
|
+
const path = await writeOutputFile(
|
|
2152
|
+
createTimestampedName(prefix, "csv"),
|
|
2153
|
+
csvStringFromRows(rows)
|
|
2154
|
+
);
|
|
2148
2155
|
return path;
|
|
2149
2156
|
}
|
|
2150
2157
|
function clip(value, maxLength) {
|
|
@@ -2225,7 +2232,9 @@ function saveEnvValues(values, baseUrl) {
|
|
|
2225
2232
|
saveHostEnvValues(baseUrl, filtered);
|
|
2226
2233
|
}
|
|
2227
2234
|
async function httpJson(method, url, apiKey, body) {
|
|
2228
|
-
const headers = {
|
|
2235
|
+
const headers = {
|
|
2236
|
+
"Content-Type": "application/json"
|
|
2237
|
+
};
|
|
2229
2238
|
if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
|
|
2230
2239
|
let response = null;
|
|
2231
2240
|
let lastError = null;
|
|
@@ -2280,12 +2289,24 @@ function sleep3(ms) {
|
|
|
2280
2289
|
}
|
|
2281
2290
|
function printDeeplineLogo() {
|
|
2282
2291
|
if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
|
|
2283
|
-
console.log(
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
console.log(
|
|
2287
|
-
|
|
2288
|
-
|
|
2292
|
+
console.log(
|
|
2293
|
+
" \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"
|
|
2294
|
+
);
|
|
2295
|
+
console.log(
|
|
2296
|
+
" \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"
|
|
2297
|
+
);
|
|
2298
|
+
console.log(
|
|
2299
|
+
" \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"
|
|
2300
|
+
);
|
|
2301
|
+
console.log(
|
|
2302
|
+
" \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"
|
|
2303
|
+
);
|
|
2304
|
+
console.log(
|
|
2305
|
+
" \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"
|
|
2306
|
+
);
|
|
2307
|
+
console.log(
|
|
2308
|
+
" \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"
|
|
2309
|
+
);
|
|
2289
2310
|
console.log("");
|
|
2290
2311
|
return;
|
|
2291
2312
|
}
|
|
@@ -2319,7 +2340,12 @@ async function handleRegister(args) {
|
|
|
2319
2340
|
const payload = {};
|
|
2320
2341
|
if (orgName) payload.org_name = orgName;
|
|
2321
2342
|
if (agentName) payload.agent_name = agentName;
|
|
2322
|
-
const { status, data } = await httpJson(
|
|
2343
|
+
const { status, data } = await httpJson(
|
|
2344
|
+
"POST",
|
|
2345
|
+
`${baseUrl}/api/v2/auth/cli/register`,
|
|
2346
|
+
null,
|
|
2347
|
+
payload
|
|
2348
|
+
);
|
|
2323
2349
|
if (status >= 400) {
|
|
2324
2350
|
console.error(`Auth register failed (status ${status}).`);
|
|
2325
2351
|
if (data.error) console.error(String(data.error));
|
|
@@ -2329,9 +2355,12 @@ async function handleRegister(args) {
|
|
|
2329
2355
|
const claimToken = String(data.claim_token || "");
|
|
2330
2356
|
if (claimToken) {
|
|
2331
2357
|
savePendingClaimToken(baseUrl, claimToken);
|
|
2332
|
-
saveEnvValues(
|
|
2333
|
-
|
|
2334
|
-
|
|
2358
|
+
saveEnvValues(
|
|
2359
|
+
{
|
|
2360
|
+
[HOST_URL_ENV]: baseUrl
|
|
2361
|
+
},
|
|
2362
|
+
baseUrl
|
|
2363
|
+
);
|
|
2335
2364
|
}
|
|
2336
2365
|
if (claimUrl) {
|
|
2337
2366
|
console.log(" Opening approval page in your browser.");
|
|
@@ -2370,10 +2399,13 @@ async function handleRegister(args) {
|
|
|
2370
2399
|
if (state === "claimed") {
|
|
2371
2400
|
const apiKey = String(statusData.api_key || "");
|
|
2372
2401
|
if (apiKey) {
|
|
2373
|
-
saveEnvValues(
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2402
|
+
saveEnvValues(
|
|
2403
|
+
{
|
|
2404
|
+
[HOST_URL_ENV]: baseUrl,
|
|
2405
|
+
[API_KEY_ENV]: apiKey
|
|
2406
|
+
},
|
|
2407
|
+
baseUrl
|
|
2408
|
+
);
|
|
2377
2409
|
clearPendingClaimToken(baseUrl);
|
|
2378
2410
|
printClaimSuccessBanner(statusData);
|
|
2379
2411
|
return EXIT_OK;
|
|
@@ -2381,7 +2413,9 @@ async function handleRegister(args) {
|
|
|
2381
2413
|
}
|
|
2382
2414
|
if (state === "expired") {
|
|
2383
2415
|
clearPendingClaimToken(baseUrl);
|
|
2384
|
-
console.log(
|
|
2416
|
+
console.log(
|
|
2417
|
+
"That approval link expired. Please run: deepline auth register"
|
|
2418
|
+
);
|
|
2385
2419
|
return EXIT_AUTH;
|
|
2386
2420
|
}
|
|
2387
2421
|
await sleep3(2e3);
|
|
@@ -2432,10 +2466,13 @@ async function handleWait(args) {
|
|
|
2432
2466
|
if (state === "claimed") {
|
|
2433
2467
|
const apiKey = String(data.api_key || "");
|
|
2434
2468
|
if (apiKey) {
|
|
2435
|
-
saveEnvValues(
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2469
|
+
saveEnvValues(
|
|
2470
|
+
{
|
|
2471
|
+
[HOST_URL_ENV]: baseUrl,
|
|
2472
|
+
[API_KEY_ENV]: apiKey
|
|
2473
|
+
},
|
|
2474
|
+
baseUrl
|
|
2475
|
+
);
|
|
2439
2476
|
clearPendingClaimToken(baseUrl);
|
|
2440
2477
|
printClaimSuccessBanner(data);
|
|
2441
2478
|
return EXIT_OK;
|
|
@@ -2448,7 +2485,9 @@ async function handleWait(args) {
|
|
|
2448
2485
|
}
|
|
2449
2486
|
await sleep3(2e3);
|
|
2450
2487
|
}
|
|
2451
|
-
console.error(
|
|
2488
|
+
console.error(
|
|
2489
|
+
"Still pending. Approve the browser link, then run: deepline auth wait"
|
|
2490
|
+
);
|
|
2452
2491
|
return EXIT_AUTH;
|
|
2453
2492
|
}
|
|
2454
2493
|
async function handleStatus(args) {
|
|
@@ -2458,7 +2497,11 @@ async function handleStatus(args) {
|
|
|
2458
2497
|
let hostStatusPayload = null;
|
|
2459
2498
|
const hostLines = [];
|
|
2460
2499
|
try {
|
|
2461
|
-
const { status: hStatus, data: hData } = await httpJson(
|
|
2500
|
+
const { status: hStatus, data: hData } = await httpJson(
|
|
2501
|
+
"GET",
|
|
2502
|
+
`${baseUrl}/api/v2/health`,
|
|
2503
|
+
null
|
|
2504
|
+
);
|
|
2462
2505
|
if (hStatus === 200) {
|
|
2463
2506
|
hostStatusPayload = {
|
|
2464
2507
|
host: baseUrl,
|
|
@@ -2480,45 +2523,74 @@ async function handleStatus(args) {
|
|
|
2480
2523
|
const apiKey = resolveApiKeyForBaseUrl(baseUrl);
|
|
2481
2524
|
if (!apiKey) {
|
|
2482
2525
|
if (readPendingClaimToken(baseUrl)) {
|
|
2483
|
-
printCommandEnvelope(
|
|
2526
|
+
printCommandEnvelope(
|
|
2527
|
+
{
|
|
2528
|
+
...hostStatusPayload ?? { host: baseUrl },
|
|
2529
|
+
status: "pending",
|
|
2530
|
+
connected: false,
|
|
2531
|
+
next: "deepline auth wait",
|
|
2532
|
+
render: {
|
|
2533
|
+
sections: [
|
|
2534
|
+
{
|
|
2535
|
+
title: "auth status",
|
|
2536
|
+
lines: [...hostLines, "Status: pending"]
|
|
2537
|
+
}
|
|
2538
|
+
],
|
|
2539
|
+
actions: [{ label: "Run", command: "deepline auth wait" }]
|
|
2540
|
+
}
|
|
2541
|
+
},
|
|
2542
|
+
{ json: jsonOutput }
|
|
2543
|
+
);
|
|
2544
|
+
return EXIT_OK;
|
|
2545
|
+
}
|
|
2546
|
+
printCommandEnvelope(
|
|
2547
|
+
{
|
|
2484
2548
|
...hostStatusPayload ?? { host: baseUrl },
|
|
2485
|
-
status: "
|
|
2549
|
+
status: "not connected",
|
|
2486
2550
|
connected: false,
|
|
2487
|
-
next: "deepline auth
|
|
2551
|
+
next: "deepline auth register",
|
|
2488
2552
|
render: {
|
|
2489
|
-
sections: [
|
|
2490
|
-
|
|
2553
|
+
sections: [
|
|
2554
|
+
{
|
|
2555
|
+
title: "auth status",
|
|
2556
|
+
lines: [...hostLines, "Status: not connected"]
|
|
2557
|
+
}
|
|
2558
|
+
],
|
|
2559
|
+
actions: [{ label: "Run", command: "deepline auth register" }]
|
|
2491
2560
|
}
|
|
2492
|
-
},
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
printCommandEnvelope({
|
|
2496
|
-
...hostStatusPayload ?? { host: baseUrl },
|
|
2497
|
-
status: "not connected",
|
|
2498
|
-
connected: false,
|
|
2499
|
-
next: "deepline auth register",
|
|
2500
|
-
render: {
|
|
2501
|
-
sections: [{ title: "auth status", lines: [...hostLines, "Status: not connected"] }],
|
|
2502
|
-
actions: [{ label: "Run", command: "deepline auth register" }]
|
|
2503
|
-
}
|
|
2504
|
-
}, { json: jsonOutput });
|
|
2561
|
+
},
|
|
2562
|
+
{ json: jsonOutput }
|
|
2563
|
+
);
|
|
2505
2564
|
return EXIT_OK;
|
|
2506
2565
|
}
|
|
2507
|
-
const { status, data } = await httpJson(
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2566
|
+
const { status, data } = await httpJson(
|
|
2567
|
+
"POST",
|
|
2568
|
+
`${baseUrl}/api/v2/auth/cli/status`,
|
|
2569
|
+
apiKey,
|
|
2570
|
+
{
|
|
2571
|
+
api_key: apiKey,
|
|
2572
|
+
reveal
|
|
2573
|
+
}
|
|
2574
|
+
);
|
|
2511
2575
|
if (status === 401 || status === 403) {
|
|
2512
|
-
printCommandEnvelope(
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2576
|
+
printCommandEnvelope(
|
|
2577
|
+
{
|
|
2578
|
+
...hostStatusPayload ?? { host: baseUrl },
|
|
2579
|
+
status: "unauthorized",
|
|
2580
|
+
connected: false,
|
|
2581
|
+
next: "deepline auth register",
|
|
2582
|
+
render: {
|
|
2583
|
+
sections: [
|
|
2584
|
+
{
|
|
2585
|
+
title: "auth status",
|
|
2586
|
+
lines: [...hostLines, "Status: unauthorized"]
|
|
2587
|
+
}
|
|
2588
|
+
],
|
|
2589
|
+
actions: [{ label: "Run", command: "deepline auth register" }]
|
|
2590
|
+
}
|
|
2591
|
+
},
|
|
2592
|
+
{ json: jsonOutput }
|
|
2593
|
+
);
|
|
2522
2594
|
return EXIT_AUTH;
|
|
2523
2595
|
}
|
|
2524
2596
|
if (status >= 400) {
|
|
@@ -2545,35 +2617,44 @@ async function handleStatus(args) {
|
|
|
2545
2617
|
if (reveal) {
|
|
2546
2618
|
const apiKeyResp = String(data.api_key || apiKey);
|
|
2547
2619
|
if (apiKeyResp) {
|
|
2548
|
-
saveEnvValues(
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2620
|
+
saveEnvValues(
|
|
2621
|
+
{
|
|
2622
|
+
[HOST_URL_ENV]: baseUrl,
|
|
2623
|
+
[API_KEY_ENV]: apiKeyResp
|
|
2624
|
+
},
|
|
2625
|
+
baseUrl
|
|
2626
|
+
);
|
|
2552
2627
|
savedApiKeyPath = envFilePath(baseUrl);
|
|
2553
2628
|
}
|
|
2554
2629
|
}
|
|
2555
|
-
printCommandEnvelope(
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2630
|
+
printCommandEnvelope(
|
|
2631
|
+
{
|
|
2632
|
+
...payload,
|
|
2633
|
+
...savedApiKeyPath ? { saved_api_key_path: savedApiKeyPath } : {},
|
|
2634
|
+
render: {
|
|
2635
|
+
sections: [
|
|
2636
|
+
{
|
|
2637
|
+
title: "auth status",
|
|
2638
|
+
lines: [
|
|
2639
|
+
...hostLines,
|
|
2640
|
+
`Status: ${payload.status}`,
|
|
2641
|
+
`Rate limit tier: ${payload.rateLimitTier}`,
|
|
2642
|
+
...payload.workspace.name ? [`Workspace: ${payload.workspace.name}`] : [],
|
|
2643
|
+
...payload.workspace.slug ? [`Workspace slug: ${payload.workspace.slug}`] : [],
|
|
2644
|
+
...payload.workspace.id != null ? [`Org ID: ${payload.workspace.id}`] : [],
|
|
2645
|
+
...payload.user.id != null ? [`User ID: ${payload.user.id}`] : [],
|
|
2646
|
+
...payload.examples.length > 0 ? [
|
|
2647
|
+
"Examples:",
|
|
2648
|
+
...payload.examples.slice(0, 3).map((example) => ` ${String(example)}`)
|
|
2649
|
+
] : [],
|
|
2650
|
+
...savedApiKeyPath ? [`Saved API key to ${savedApiKeyPath}`] : []
|
|
2651
|
+
]
|
|
2652
|
+
}
|
|
2653
|
+
]
|
|
2654
|
+
}
|
|
2655
|
+
},
|
|
2656
|
+
{ json: jsonOutput }
|
|
2657
|
+
);
|
|
2577
2658
|
return EXIT_OK;
|
|
2578
2659
|
}
|
|
2579
2660
|
function registerAuthCommands(program) {
|
|
@@ -2593,7 +2674,9 @@ Notes:
|
|
|
2593
2674
|
Auth status shows the target host and active workspace without printing secrets.
|
|
2594
2675
|
`
|
|
2595
2676
|
);
|
|
2596
|
-
auth.command("register").description(
|
|
2677
|
+
auth.command("register").description(
|
|
2678
|
+
"Register this device and open the approval page in your browser."
|
|
2679
|
+
).addHelpText(
|
|
2597
2680
|
"after",
|
|
2598
2681
|
`
|
|
2599
2682
|
Notes:
|
|
@@ -2640,7 +2723,10 @@ Examples:
|
|
|
2640
2723
|
deepline auth status
|
|
2641
2724
|
deepline auth status --json
|
|
2642
2725
|
`
|
|
2643
|
-
).option(
|
|
2726
|
+
).option(
|
|
2727
|
+
"--reveal",
|
|
2728
|
+
"Persist the revealed API key back to the host auth file"
|
|
2729
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
2644
2730
|
process.exitCode = await handleStatus([
|
|
2645
2731
|
...options.reveal ? ["--reveal"] : [],
|
|
2646
2732
|
...options.json ? ["--json"] : []
|
|
@@ -2665,7 +2751,9 @@ function recentUsageLines(entries) {
|
|
|
2665
2751
|
const op = `${humanize(entry.provider)} ${humanize(entry.operation)}`.trim();
|
|
2666
2752
|
const charge = entry.billing_mode === "no_bill" ? "free" : `${entry.credits ?? 0} cr`;
|
|
2667
2753
|
const status = entry.status || "completed";
|
|
2668
|
-
lines.push(
|
|
2754
|
+
lines.push(
|
|
2755
|
+
`${op} | ${charge} | ${status} | ${entry.created_at || "unknown"}`
|
|
2756
|
+
);
|
|
2669
2757
|
}
|
|
2670
2758
|
return lines;
|
|
2671
2759
|
}
|
|
@@ -2719,16 +2807,21 @@ function defaultLedgerExportPath() {
|
|
|
2719
2807
|
}
|
|
2720
2808
|
async function handleBalance(options) {
|
|
2721
2809
|
const { http } = getAuthedHttpClient();
|
|
2722
|
-
const payload = await http.get(
|
|
2810
|
+
const payload = await http.get(
|
|
2811
|
+
"/api/v2/billing/balance"
|
|
2812
|
+
);
|
|
2723
2813
|
const status = String(payload.balance_status || "");
|
|
2724
2814
|
const lines = status === "no_billing" ? [
|
|
2725
2815
|
"Balance: 0 credits",
|
|
2726
2816
|
"Billing: No billing account or payment method set up for this workspace."
|
|
2727
2817
|
] : [`Balance: ${payload.balance ?? "(unknown)"} credits`];
|
|
2728
|
-
printCommandEnvelope(
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2818
|
+
printCommandEnvelope(
|
|
2819
|
+
{
|
|
2820
|
+
...payload,
|
|
2821
|
+
render: { sections: [{ title: "billing balance", lines }] }
|
|
2822
|
+
},
|
|
2823
|
+
{ json: options.json }
|
|
2824
|
+
);
|
|
2732
2825
|
return;
|
|
2733
2826
|
}
|
|
2734
2827
|
async function handleUsage(options) {
|
|
@@ -2737,7 +2830,9 @@ async function handleUsage(options) {
|
|
|
2737
2830
|
if (options.limit) params.set("recent_limit", options.limit);
|
|
2738
2831
|
if (options.offset) params.set("recent_offset", options.offset);
|
|
2739
2832
|
const suffix = Array.from(params).length > 0 ? `?${params.toString()}` : "";
|
|
2740
|
-
const payload = await http.get(
|
|
2833
|
+
const payload = await http.get(
|
|
2834
|
+
`/api/v2/billing/usage${suffix}`
|
|
2835
|
+
);
|
|
2741
2836
|
const usage = payload.usage ?? {};
|
|
2742
2837
|
const quota = payload.quota ?? {};
|
|
2743
2838
|
const recent = payload.recent ?? {};
|
|
@@ -2745,24 +2840,34 @@ async function handleUsage(options) {
|
|
|
2745
2840
|
`Balance: ${payload.balance ?? "(unknown)"}`,
|
|
2746
2841
|
`Last 30 days spent: ${usage.month_spent_credits ?? "(unknown)"}`,
|
|
2747
2842
|
`Monthly limit: ${quota.enabled ? quota.monthly_credits_limit ?? "(unknown)" : "off"}`,
|
|
2748
|
-
...recentUsageLines(
|
|
2843
|
+
...recentUsageLines(
|
|
2844
|
+
Array.isArray(recent.entries) ? recent.entries : []
|
|
2845
|
+
)
|
|
2749
2846
|
];
|
|
2750
|
-
printCommandEnvelope(
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2847
|
+
printCommandEnvelope(
|
|
2848
|
+
{
|
|
2849
|
+
...payload,
|
|
2850
|
+
render: { sections: [{ title: "billing usage", lines }] }
|
|
2851
|
+
},
|
|
2852
|
+
{ json: options.json }
|
|
2853
|
+
);
|
|
2754
2854
|
}
|
|
2755
2855
|
async function handleLimit(options) {
|
|
2756
2856
|
const { http } = getAuthedHttpClient();
|
|
2757
|
-
const payload = await http.get(
|
|
2857
|
+
const payload = await http.get(
|
|
2858
|
+
"/api/v2/billing/limit"
|
|
2859
|
+
);
|
|
2758
2860
|
const lines = payload.enabled ? [
|
|
2759
2861
|
`Monthly limit: ${payload.monthly_credits_limit ?? "(unknown)"}`,
|
|
2760
2862
|
`Remaining before cap: ${payload.remaining_credits ?? "(unknown)"}`
|
|
2761
2863
|
] : ["Monthly limit: off"];
|
|
2762
|
-
printCommandEnvelope(
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2864
|
+
printCommandEnvelope(
|
|
2865
|
+
{
|
|
2866
|
+
...payload,
|
|
2867
|
+
render: { sections: [{ title: "billing limit", lines }] }
|
|
2868
|
+
},
|
|
2869
|
+
{ json: options.json }
|
|
2870
|
+
);
|
|
2766
2871
|
}
|
|
2767
2872
|
async function handleSetLimit(credits, options) {
|
|
2768
2873
|
const { http } = getAuthedHttpClient();
|
|
@@ -2770,26 +2875,53 @@ async function handleSetLimit(credits, options) {
|
|
|
2770
2875
|
method: "PUT",
|
|
2771
2876
|
body: { monthly_credits_limit: Number.parseInt(credits, 10) }
|
|
2772
2877
|
});
|
|
2773
|
-
printCommandEnvelope(
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2878
|
+
printCommandEnvelope(
|
|
2879
|
+
{
|
|
2880
|
+
...payload,
|
|
2881
|
+
render: {
|
|
2882
|
+
sections: [
|
|
2883
|
+
{
|
|
2884
|
+
title: "billing limit",
|
|
2885
|
+
lines: [`Monthly billing limit set to ${credits} credits.`]
|
|
2886
|
+
}
|
|
2887
|
+
]
|
|
2888
|
+
}
|
|
2889
|
+
},
|
|
2890
|
+
{ json: options.json }
|
|
2891
|
+
);
|
|
2779
2892
|
}
|
|
2780
2893
|
async function handleLimitOff(options) {
|
|
2781
2894
|
const { http } = getAuthedHttpClient();
|
|
2782
|
-
const payload = await http.request("/api/v2/billing/limit", {
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2895
|
+
const payload = await http.request("/api/v2/billing/limit", {
|
|
2896
|
+
method: "DELETE"
|
|
2897
|
+
});
|
|
2898
|
+
printCommandEnvelope(
|
|
2899
|
+
{
|
|
2900
|
+
...payload,
|
|
2901
|
+
render: {
|
|
2902
|
+
sections: [
|
|
2903
|
+
{
|
|
2904
|
+
title: "billing limit",
|
|
2905
|
+
lines: ["Monthly billing limit is now off."]
|
|
2906
|
+
}
|
|
2907
|
+
]
|
|
2908
|
+
}
|
|
2909
|
+
},
|
|
2910
|
+
{ json: options.json }
|
|
2911
|
+
);
|
|
2787
2912
|
}
|
|
2788
2913
|
async function handleHistory(options) {
|
|
2789
2914
|
const { http } = getAuthedHttpClient();
|
|
2790
|
-
const windows = {
|
|
2915
|
+
const windows = {
|
|
2916
|
+
"1d": 86400,
|
|
2917
|
+
"1w": 604800,
|
|
2918
|
+
"1m": 2592e3,
|
|
2919
|
+
"1y": 31536e3
|
|
2920
|
+
};
|
|
2791
2921
|
const sinceAt = Math.max(0, Math.floor(Date.now() / 1e3) - windows[options.time]) * 1e3;
|
|
2792
|
-
const payload = await http.get(
|
|
2922
|
+
const payload = await http.get(
|
|
2923
|
+
`/api/v2/billing/ledger?since_at=${sinceAt}&limit=5000`
|
|
2924
|
+
);
|
|
2793
2925
|
const entries = Array.isArray(payload.entries) ? payload.entries : [];
|
|
2794
2926
|
const rows = entries.map((entry) => {
|
|
2795
2927
|
const metadata = entry.metadata ?? {};
|
|
@@ -2801,21 +2933,30 @@ async function handleHistory(options) {
|
|
|
2801
2933
|
operation: metadata.operation ?? ""
|
|
2802
2934
|
};
|
|
2803
2935
|
});
|
|
2804
|
-
const outputPath = await writeCsvRowsFile(
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2936
|
+
const outputPath = await writeCsvRowsFile(
|
|
2937
|
+
`billing-history-${options.time}`,
|
|
2938
|
+
rows
|
|
2939
|
+
);
|
|
2940
|
+
printCommandEnvelope(
|
|
2941
|
+
{
|
|
2942
|
+
output_path: outputPath,
|
|
2943
|
+
row_count: rows.length,
|
|
2944
|
+
time_window: options.time,
|
|
2945
|
+
render: {
|
|
2946
|
+
sections: [
|
|
2947
|
+
{
|
|
2948
|
+
title: "billing history",
|
|
2949
|
+
lines: [
|
|
2950
|
+
`Billing history written to ${outputPath}`,
|
|
2951
|
+
`${rows.length} row(s) exported.`
|
|
2952
|
+
]
|
|
2953
|
+
}
|
|
2954
|
+
]
|
|
2955
|
+
},
|
|
2956
|
+
local: { output_path: outputPath }
|
|
2816
2957
|
},
|
|
2817
|
-
|
|
2818
|
-
|
|
2958
|
+
{ json: options.json }
|
|
2959
|
+
);
|
|
2819
2960
|
}
|
|
2820
2961
|
async function handleLedgerExportAll(options) {
|
|
2821
2962
|
const { http } = getAuthedHttpClient();
|
|
@@ -2847,51 +2988,75 @@ async function handleLedgerExportAll(options) {
|
|
|
2847
2988
|
if (nextCursor === cursor) break;
|
|
2848
2989
|
cursor = nextCursor;
|
|
2849
2990
|
}
|
|
2850
|
-
printCommandEnvelope(
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2991
|
+
printCommandEnvelope(
|
|
2992
|
+
{
|
|
2993
|
+
output_path: outputPath,
|
|
2994
|
+
row_count: summary.row_count,
|
|
2995
|
+
net_delta_credits: summary.net_delta_credits,
|
|
2996
|
+
scope: "current_auth_context",
|
|
2997
|
+
render: {
|
|
2998
|
+
sections: [
|
|
2999
|
+
{
|
|
3000
|
+
title: "billing ledger",
|
|
3001
|
+
lines: [
|
|
3002
|
+
`Billing ledger written to ${outputPath}`,
|
|
3003
|
+
`${summary.row_count} row(s) exported for the current auth context.`,
|
|
3004
|
+
`Net ledger delta: ${summary.net_delta_credits} Deepline Credits`
|
|
3005
|
+
]
|
|
3006
|
+
}
|
|
3007
|
+
]
|
|
3008
|
+
},
|
|
3009
|
+
local: { output_path: outputPath }
|
|
2866
3010
|
},
|
|
2867
|
-
|
|
2868
|
-
|
|
3011
|
+
{ json: options.json }
|
|
3012
|
+
);
|
|
2869
3013
|
}
|
|
2870
3014
|
async function handleCheckout(options) {
|
|
2871
3015
|
const { http } = getAuthedHttpClient();
|
|
2872
|
-
const payload = await http.post(
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
3016
|
+
const payload = await http.post(
|
|
3017
|
+
"/api/v2/billing/checkout",
|
|
3018
|
+
{
|
|
3019
|
+
...options.tier ? { tierId: options.tier } : {},
|
|
3020
|
+
...options.credits ? { credits: Number.parseInt(options.credits, 10) } : {},
|
|
3021
|
+
...options.discountCode ? { discountCode: options.discountCode } : {}
|
|
3022
|
+
}
|
|
3023
|
+
);
|
|
2877
3024
|
const url = String(payload.url || payload.checkout_url || "");
|
|
2878
3025
|
if (!options.json && !options.noOpen && url) openInBrowser(url);
|
|
2879
|
-
printCommandEnvelope(
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
3026
|
+
printCommandEnvelope(
|
|
3027
|
+
{
|
|
3028
|
+
...payload,
|
|
3029
|
+
render: {
|
|
3030
|
+
sections: [
|
|
3031
|
+
{
|
|
3032
|
+
title: "billing checkout",
|
|
3033
|
+
lines: [url || "Checkout session created."]
|
|
3034
|
+
}
|
|
3035
|
+
]
|
|
3036
|
+
}
|
|
3037
|
+
},
|
|
3038
|
+
{ json: options.json }
|
|
3039
|
+
);
|
|
2883
3040
|
}
|
|
2884
3041
|
async function handleRedeemCode(code, options) {
|
|
2885
3042
|
const { http } = getAuthedHttpClient();
|
|
2886
|
-
const payload = await http.post(
|
|
2887
|
-
|
|
2888
|
-
|
|
3043
|
+
const payload = await http.post(
|
|
3044
|
+
"/api/v2/billing/checkout",
|
|
3045
|
+
{
|
|
3046
|
+
discountCode: code
|
|
3047
|
+
}
|
|
3048
|
+
);
|
|
2889
3049
|
const url = String(payload.url || payload.checkout_url || "");
|
|
2890
3050
|
if (!options.json && !options.noOpen && url) openInBrowser(url);
|
|
2891
|
-
printCommandEnvelope(
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
3051
|
+
printCommandEnvelope(
|
|
3052
|
+
{
|
|
3053
|
+
...payload,
|
|
3054
|
+
render: {
|
|
3055
|
+
sections: [{ title: "billing code", lines: [url || "Code redeemed."] }]
|
|
3056
|
+
}
|
|
3057
|
+
},
|
|
3058
|
+
{ json: options.json }
|
|
3059
|
+
);
|
|
2895
3060
|
}
|
|
2896
3061
|
function registerBillingCommands(program) {
|
|
2897
3062
|
const billing = program.command("billing").description("Inspect balance, usage, limits, and checkout flows.").addHelpText(
|
|
@@ -2999,7 +3164,10 @@ Examples:
|
|
|
2999
3164
|
deepline billing ledger export all
|
|
3000
3165
|
deepline billing ledger export all --json
|
|
3001
3166
|
`
|
|
3002
|
-
).option("--output <path>", "Write CSV to an explicit path").option(
|
|
3167
|
+
).option("--output <path>", "Write CSV to an explicit path").option(
|
|
3168
|
+
"--json",
|
|
3169
|
+
"Emit JSON output. Also automatic when stdout is piped"
|
|
3170
|
+
).action(handleLedgerExportAll)
|
|
3003
3171
|
)
|
|
3004
3172
|
);
|
|
3005
3173
|
billing.command("history").description("Export billing ledger history to CSV.").addHelpText(
|
|
@@ -3014,7 +3182,9 @@ Examples:
|
|
|
3014
3182
|
deepline billing history --time 1y --json
|
|
3015
3183
|
`
|
|
3016
3184
|
).requiredOption("--time <window>", "Rolling time window: 1d, 1w, 1m, or 1y").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleHistory);
|
|
3017
|
-
billing.command("checkout").description(
|
|
3185
|
+
billing.command("checkout").description(
|
|
3186
|
+
"Create a checkout session and optionally open it in your browser."
|
|
3187
|
+
).addHelpText(
|
|
3018
3188
|
"after",
|
|
3019
3189
|
`
|
|
3020
3190
|
Notes:
|
|
@@ -3060,12 +3230,18 @@ function formatDatasetExecutionStats(raw, denominator) {
|
|
|
3060
3230
|
readCount(raw.completed),
|
|
3061
3231
|
denominator
|
|
3062
3232
|
),
|
|
3063
|
-
"completed:reused": datasetSummaryPercentText(
|
|
3233
|
+
"completed:reused": datasetSummaryPercentText(
|
|
3234
|
+
readCount(raw.cached),
|
|
3235
|
+
denominator
|
|
3236
|
+
),
|
|
3064
3237
|
"skipped:condition": datasetSummaryPercentText(
|
|
3065
3238
|
readCount(raw.skipped),
|
|
3066
3239
|
denominator
|
|
3067
3240
|
),
|
|
3068
|
-
"skipped:missed": datasetSummaryPercentText(
|
|
3241
|
+
"skipped:missed": datasetSummaryPercentText(
|
|
3242
|
+
readCount(raw.missed),
|
|
3243
|
+
denominator
|
|
3244
|
+
),
|
|
3069
3245
|
failed: datasetSummaryPercentText(readCount(raw.failed), denominator)
|
|
3070
3246
|
};
|
|
3071
3247
|
}
|
|
@@ -3246,19 +3422,51 @@ function collectCanonicalRowsInfos(statusOrResult) {
|
|
|
3246
3422
|
const metadata = isRecord2(result._metadata) ? result._metadata : null;
|
|
3247
3423
|
const totalFromMetadata = metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count;
|
|
3248
3424
|
const candidates = [
|
|
3249
|
-
{
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3425
|
+
{
|
|
3426
|
+
source: "result.contacts",
|
|
3427
|
+
value: result.contacts,
|
|
3428
|
+
total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
|
|
3429
|
+
},
|
|
3430
|
+
{
|
|
3431
|
+
source: "result.previewRows",
|
|
3432
|
+
value: result.previewRows,
|
|
3433
|
+
total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
|
|
3434
|
+
},
|
|
3435
|
+
{
|
|
3436
|
+
source: "result.rows",
|
|
3437
|
+
value: result.rows,
|
|
3438
|
+
total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
|
|
3439
|
+
},
|
|
3440
|
+
{
|
|
3441
|
+
source: "result.results",
|
|
3442
|
+
value: result.results,
|
|
3443
|
+
total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
|
|
3444
|
+
}
|
|
3253
3445
|
];
|
|
3254
3446
|
if (isRecord2(result.output)) {
|
|
3255
3447
|
const outputMetadata = isRecord2(result.output._metadata) ? result.output._metadata : null;
|
|
3256
3448
|
const outputTotalFromMetadata = outputMetadata?.totalRows ?? outputMetadata?.rowCount ?? outputMetadata?.count;
|
|
3257
3449
|
candidates.push(
|
|
3258
|
-
{
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3450
|
+
{
|
|
3451
|
+
source: "result.output.contacts",
|
|
3452
|
+
value: result.output.contacts,
|
|
3453
|
+
total: outputTotalFromMetadata ?? result.output.totalRows ?? result.output.rowCount ?? result.output.count
|
|
3454
|
+
},
|
|
3455
|
+
{
|
|
3456
|
+
source: "result.output.previewRows",
|
|
3457
|
+
value: result.output.previewRows,
|
|
3458
|
+
total: outputTotalFromMetadata ?? result.output.totalRows ?? result.output.rowCount ?? result.output.count
|
|
3459
|
+
},
|
|
3460
|
+
{
|
|
3461
|
+
source: "result.output.rows",
|
|
3462
|
+
value: result.output.rows,
|
|
3463
|
+
total: outputTotalFromMetadata ?? result.output.totalRows ?? result.output.rowCount ?? result.output.count
|
|
3464
|
+
},
|
|
3465
|
+
{
|
|
3466
|
+
source: "result.output.results",
|
|
3467
|
+
value: result.output.results,
|
|
3468
|
+
total: outputTotalFromMetadata ?? result.output.totalRows ?? result.output.rowCount ?? result.output.count
|
|
3469
|
+
}
|
|
3262
3470
|
);
|
|
3263
3471
|
}
|
|
3264
3472
|
collectDatasetCandidates({
|
|
@@ -3396,7 +3604,8 @@ function compactCell(value) {
|
|
|
3396
3604
|
const parsed = parseJsonLike(value);
|
|
3397
3605
|
if (parsed === null || parsed === void 0) return "";
|
|
3398
3606
|
if (typeof parsed === "string") return compactScalar(parsed, 120);
|
|
3399
|
-
if (typeof parsed === "number" || typeof parsed === "boolean")
|
|
3607
|
+
if (typeof parsed === "number" || typeof parsed === "boolean")
|
|
3608
|
+
return String(parsed);
|
|
3400
3609
|
if (Array.isArray(parsed)) {
|
|
3401
3610
|
if (parsed.length === 0) return "";
|
|
3402
3611
|
if (parsed.slice(0, 3).every((item) => ["string", "number", "boolean"].includes(typeof item))) {
|
|
@@ -3410,7 +3619,15 @@ function compactCell(value) {
|
|
|
3410
3619
|
return compactCell(parsed[key]);
|
|
3411
3620
|
}
|
|
3412
3621
|
}
|
|
3413
|
-
const preferred = [
|
|
3622
|
+
const preferred = [
|
|
3623
|
+
"email",
|
|
3624
|
+
"status",
|
|
3625
|
+
"name",
|
|
3626
|
+
"full_name",
|
|
3627
|
+
"title",
|
|
3628
|
+
"domain",
|
|
3629
|
+
"linkedin_url"
|
|
3630
|
+
];
|
|
3414
3631
|
const parts = [];
|
|
3415
3632
|
for (const key of preferred) {
|
|
3416
3633
|
if (parsed[key] !== null && parsed[key] !== void 0 && parsed[key] !== "") {
|
|
@@ -3452,7 +3669,10 @@ function buildDatasetStats(rows, totalRows = rows.length, columns = inferColumns
|
|
|
3452
3669
|
};
|
|
3453
3670
|
const rawExecutionStats = executionStats?.columnStats[column];
|
|
3454
3671
|
if (rawExecutionStats) {
|
|
3455
|
-
stat3.execution = formatDatasetExecutionStats(
|
|
3672
|
+
stat3.execution = formatDatasetExecutionStats(
|
|
3673
|
+
rawExecutionStats,
|
|
3674
|
+
totalRows
|
|
3675
|
+
);
|
|
3456
3676
|
}
|
|
3457
3677
|
if (sampleValue !== void 0 && sampleValueType) {
|
|
3458
3678
|
stat3.sample_value = sampleValue;
|
|
@@ -3494,11 +3714,7 @@ function writeCanonicalRowsCsv(rowsInfo, outPath) {
|
|
|
3494
3714
|
const rows = dataExportRows(sanitized.rows);
|
|
3495
3715
|
const columns = dataExportColumns(rows, sanitized.columns);
|
|
3496
3716
|
const resolved = (0, import_node_path5.resolve)(outPath);
|
|
3497
|
-
(0, import_node_fs4.writeFileSync)(
|
|
3498
|
-
resolved,
|
|
3499
|
-
csvStringFromRows(rows, columns),
|
|
3500
|
-
"utf-8"
|
|
3501
|
-
);
|
|
3717
|
+
(0, import_node_fs4.writeFileSync)(resolved, csvStringFromRows(rows, columns), "utf-8");
|
|
3502
3718
|
return resolved;
|
|
3503
3719
|
}
|
|
3504
3720
|
|
|
@@ -3509,7 +3725,9 @@ function parseRowRange(raw) {
|
|
|
3509
3725
|
const start = Number.parseInt(startRaw ?? "", 10);
|
|
3510
3726
|
const end = Number.parseInt(endRaw ?? "", 10);
|
|
3511
3727
|
if (!Number.isFinite(start) || !Number.isFinite(end) || start < 0 || end < start) {
|
|
3512
|
-
throw new Error(
|
|
3728
|
+
throw new Error(
|
|
3729
|
+
`Invalid --rows value: ${source} (expected start:end, e.g. 0:19).`
|
|
3730
|
+
);
|
|
3513
3731
|
}
|
|
3514
3732
|
return [start, end];
|
|
3515
3733
|
}
|
|
@@ -3520,7 +3738,9 @@ function selectColumns(rows, rawColumns) {
|
|
|
3520
3738
|
if (!rawColumns?.trim()) return rows;
|
|
3521
3739
|
const requested = rawColumns.split(",").map((part) => part.trim()).filter(Boolean);
|
|
3522
3740
|
if (requested.length === 0) {
|
|
3523
|
-
throw new Error(
|
|
3741
|
+
throw new Error(
|
|
3742
|
+
"Invalid --columns value: provide at least one column name."
|
|
3743
|
+
);
|
|
3524
3744
|
}
|
|
3525
3745
|
const available = new Set(Object.keys(rows[0] ?? {}));
|
|
3526
3746
|
const missing = requested.filter((column) => !available.has(column));
|
|
@@ -3557,13 +3777,22 @@ function renderTable(rows, totalRows, verbose) {
|
|
|
3557
3777
|
return display.padEnd(widths[column]);
|
|
3558
3778
|
}).join(" | ")
|
|
3559
3779
|
);
|
|
3560
|
-
return [
|
|
3780
|
+
return [
|
|
3781
|
+
header,
|
|
3782
|
+
divider,
|
|
3783
|
+
...body,
|
|
3784
|
+
"",
|
|
3785
|
+
`showing ${rows.length} row(s) of ${totalRows}`
|
|
3786
|
+
].join("\n");
|
|
3561
3787
|
}
|
|
3562
3788
|
async function handleCsvShow(options) {
|
|
3563
3789
|
const csvPath = options.csv;
|
|
3564
3790
|
const [rowStart, rowEnd] = parseRowRange(options.rows);
|
|
3565
3791
|
const allRows = readCsvRows(csvPath);
|
|
3566
|
-
const selected = selectColumns(
|
|
3792
|
+
const selected = selectColumns(
|
|
3793
|
+
selectRows(allRows, rowStart, rowEnd),
|
|
3794
|
+
options.columns
|
|
3795
|
+
);
|
|
3567
3796
|
const format = options.format ?? "json";
|
|
3568
3797
|
if (options.summary) {
|
|
3569
3798
|
printJson(buildDatasetStats(selected, allRows.length));
|
|
@@ -3580,13 +3809,17 @@ async function handleCsvShow(options) {
|
|
|
3580
3809
|
process.stdout.write(`${columns.join(",")}
|
|
3581
3810
|
`);
|
|
3582
3811
|
for (const row of selected) {
|
|
3583
|
-
process.stdout.write(
|
|
3584
|
-
|
|
3812
|
+
process.stdout.write(
|
|
3813
|
+
`${columns.map((column) => JSON.stringify(row[column] ?? "")).join(",")}
|
|
3814
|
+
`
|
|
3815
|
+
);
|
|
3585
3816
|
}
|
|
3586
3817
|
return;
|
|
3587
3818
|
}
|
|
3588
|
-
process.stdout.write(
|
|
3589
|
-
|
|
3819
|
+
process.stdout.write(
|
|
3820
|
+
`${renderTable(selected, allRows.length, Boolean(options.verbose))}
|
|
3821
|
+
`
|
|
3822
|
+
);
|
|
3590
3823
|
}
|
|
3591
3824
|
function registerCsvCommands(program) {
|
|
3592
3825
|
const csv = program.command("csv").description("Inspect local CSV files.").addHelpText(
|
|
@@ -3619,12 +3852,7 @@ Examples:
|
|
|
3619
3852
|
// src/cli/commands/db.ts
|
|
3620
3853
|
var import_node_fs5 = require("fs");
|
|
3621
3854
|
var import_node_path6 = require("path");
|
|
3622
|
-
var CUSTOMER_DB_QUERY_FORMATS = /* @__PURE__ */ new Set([
|
|
3623
|
-
"table",
|
|
3624
|
-
"json",
|
|
3625
|
-
"csv",
|
|
3626
|
-
"markdown"
|
|
3627
|
-
]);
|
|
3855
|
+
var CUSTOMER_DB_QUERY_FORMATS = /* @__PURE__ */ new Set(["table", "json", "csv", "markdown"]);
|
|
3628
3856
|
function parsePositiveInteger(value, flagName) {
|
|
3629
3857
|
const parsed = Number.parseInt(value, 10);
|
|
3630
3858
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
@@ -3639,10 +3867,17 @@ function formatCell(value) {
|
|
|
3639
3867
|
}
|
|
3640
3868
|
function tableLines(result) {
|
|
3641
3869
|
const rows = dataExportRows(customerDbRows(result));
|
|
3642
|
-
const responseColumns = dataExportColumns(
|
|
3643
|
-
|
|
3870
|
+
const responseColumns = dataExportColumns(
|
|
3871
|
+
rows,
|
|
3872
|
+
customerDbColumnNames(result)
|
|
3873
|
+
);
|
|
3874
|
+
const businessColumns = responseColumns.filter(
|
|
3875
|
+
(column) => !column.startsWith("_")
|
|
3876
|
+
);
|
|
3644
3877
|
const columns = businessColumns.length > 0 ? businessColumns : responseColumns;
|
|
3645
|
-
const hiddenColumns = responseColumns.filter(
|
|
3878
|
+
const hiddenColumns = responseColumns.filter(
|
|
3879
|
+
(column) => !columns.includes(column)
|
|
3880
|
+
);
|
|
3646
3881
|
const lines = [
|
|
3647
3882
|
`${result.command} returned ${result.row_count_returned} row(s)` + (result.truncated ? " (truncated)" : "")
|
|
3648
3883
|
];
|
|
@@ -3650,7 +3885,9 @@ function tableLines(result) {
|
|
|
3650
3885
|
lines.push(
|
|
3651
3886
|
`Showing ${columns.length}/${responseColumns.length} columns; hidden metadata: ${hiddenColumns.join(", ")}`
|
|
3652
3887
|
);
|
|
3653
|
-
lines.push(
|
|
3888
|
+
lines.push(
|
|
3889
|
+
"Use --json or select metadata columns explicitly when you need run ids/errors/stages."
|
|
3890
|
+
);
|
|
3654
3891
|
}
|
|
3655
3892
|
if (rows.length === 0) {
|
|
3656
3893
|
return lines;
|
|
@@ -3664,7 +3901,9 @@ function tableLines(result) {
|
|
|
3664
3901
|
)
|
|
3665
3902
|
)
|
|
3666
3903
|
);
|
|
3667
|
-
lines.push(
|
|
3904
|
+
lines.push(
|
|
3905
|
+
columns.map((column, index) => column.padEnd(widths[index])).join(" ")
|
|
3906
|
+
);
|
|
3668
3907
|
lines.push(widths.map((width) => "-".repeat(width)).join(" "));
|
|
3669
3908
|
for (const row of rows) {
|
|
3670
3909
|
lines.push(
|
|
@@ -3740,10 +3979,12 @@ async function handleDbQuery(args) {
|
|
|
3740
3979
|
const explicitJsonOutput = args.includes("--json");
|
|
3741
3980
|
const client = new DeeplineClient();
|
|
3742
3981
|
const result = await client.queryCustomerDb({ sql, maxRows });
|
|
3743
|
-
const toolCommand = `deepline tools execute query_customer_db --payload ${JSON.stringify(
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3982
|
+
const toolCommand = `deepline tools execute query_customer_db --payload ${JSON.stringify(
|
|
3983
|
+
{
|
|
3984
|
+
sql,
|
|
3985
|
+
...maxRows ? { max_rows: maxRows } : {}
|
|
3986
|
+
}
|
|
3987
|
+
)} --json`;
|
|
3747
3988
|
if (format === "csv") {
|
|
3748
3989
|
if (outPath) {
|
|
3749
3990
|
const exportedPath = writeCustomerDbCsv(result, outPath);
|
|
@@ -3771,7 +4012,10 @@ async function handleDbQuery(args) {
|
|
|
3771
4012
|
}),
|
|
3772
4013
|
{
|
|
3773
4014
|
json: explicitJsonOutput,
|
|
3774
|
-
text: dataExportCsvString(
|
|
4015
|
+
text: dataExportCsvString(
|
|
4016
|
+
customerDbRows(result),
|
|
4017
|
+
customerDbColumnNames(result)
|
|
4018
|
+
)
|
|
3775
4019
|
}
|
|
3776
4020
|
);
|
|
3777
4021
|
return 0;
|
|
@@ -3813,14 +4057,17 @@ async function handleDbQuery(args) {
|
|
|
3813
4057
|
);
|
|
3814
4058
|
return 0;
|
|
3815
4059
|
}
|
|
3816
|
-
printCommandEnvelope(
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
4060
|
+
printCommandEnvelope(
|
|
4061
|
+
{
|
|
4062
|
+
...result,
|
|
4063
|
+
next: { toolEquivalent: toolCommand },
|
|
4064
|
+
render: {
|
|
4065
|
+
sections: [{ title: "customer db query", lines: tableLines(result) }],
|
|
4066
|
+
actions: [{ label: "Tool equivalent", command: toolCommand }]
|
|
4067
|
+
}
|
|
4068
|
+
},
|
|
4069
|
+
{ json: jsonOutput || format === "json" }
|
|
4070
|
+
);
|
|
3824
4071
|
return 0;
|
|
3825
4072
|
}
|
|
3826
4073
|
function registerDbCommands(program) {
|
|
@@ -3856,7 +4103,10 @@ Examples:
|
|
|
3856
4103
|
deepline db query --sql "select * from contacts limit 20" --format csv --out contacts.csv
|
|
3857
4104
|
deepline db query --sql "select domain, name from companies limit 20" --format markdown
|
|
3858
4105
|
`
|
|
3859
|
-
).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(
|
|
4106
|
+
).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(
|
|
4107
|
+
"--json",
|
|
4108
|
+
"Emit raw JSON response. Also automatic when stdout is piped"
|
|
4109
|
+
).action(async (options) => {
|
|
3860
4110
|
process.exitCode = await handleDbQuery([
|
|
3861
4111
|
"--sql",
|
|
3862
4112
|
options.sql,
|
|
@@ -3877,12 +4127,17 @@ async function handleFeedback(text, options) {
|
|
|
3877
4127
|
...options.command ? { command: options.command } : {},
|
|
3878
4128
|
...options.payload ? { payload: options.payload } : {}
|
|
3879
4129
|
});
|
|
3880
|
-
printCommandEnvelope(
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
4130
|
+
printCommandEnvelope(
|
|
4131
|
+
{
|
|
4132
|
+
...response,
|
|
4133
|
+
render: {
|
|
4134
|
+
sections: [
|
|
4135
|
+
{ title: "feedback", lines: ["Feedback submitted. Thank you."] }
|
|
4136
|
+
]
|
|
4137
|
+
}
|
|
4138
|
+
},
|
|
4139
|
+
{ json: options.json }
|
|
4140
|
+
);
|
|
3886
4141
|
}
|
|
3887
4142
|
function registerFeedbackCommands(program) {
|
|
3888
4143
|
const feedback = program.command("feedback").description("Submit CLI feedback to Deepline.").addHelpText(
|
|
@@ -3925,76 +4180,106 @@ async function handleOrgList(options) {
|
|
|
3925
4180
|
const config = resolveConfig();
|
|
3926
4181
|
const http = new HttpClient(config);
|
|
3927
4182
|
const payload = await fetchOrganizations(http, config.apiKey);
|
|
3928
|
-
printCommandEnvelope(
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
4183
|
+
printCommandEnvelope(
|
|
4184
|
+
{
|
|
4185
|
+
...payload,
|
|
4186
|
+
render: {
|
|
4187
|
+
sections: [
|
|
4188
|
+
{
|
|
4189
|
+
title: "Your organizations:",
|
|
4190
|
+
lines: orgListLines(payload.organizations)
|
|
4191
|
+
}
|
|
4192
|
+
]
|
|
4193
|
+
}
|
|
4194
|
+
},
|
|
4195
|
+
{ json: options.json }
|
|
4196
|
+
);
|
|
3934
4197
|
}
|
|
3935
4198
|
async function handleOrgSwitch(selection, options) {
|
|
3936
4199
|
const config = resolveConfig();
|
|
3937
4200
|
const http = new HttpClient(config);
|
|
3938
4201
|
const payload = await fetchOrganizations(http, config.apiKey);
|
|
3939
4202
|
if (!selection && !options.orgId) {
|
|
3940
|
-
printCommandEnvelope(
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
4203
|
+
printCommandEnvelope(
|
|
4204
|
+
{
|
|
4205
|
+
...payload,
|
|
4206
|
+
next: { switch: "deepline org switch <number>" },
|
|
4207
|
+
render: {
|
|
4208
|
+
sections: [
|
|
4209
|
+
{
|
|
4210
|
+
title: "Your organizations:",
|
|
4211
|
+
lines: orgListLines(payload.organizations)
|
|
4212
|
+
}
|
|
4213
|
+
],
|
|
4214
|
+
actions: [{ label: "Run", command: "deepline org switch <number>" }]
|
|
4215
|
+
}
|
|
4216
|
+
},
|
|
4217
|
+
{ json: options.json }
|
|
4218
|
+
);
|
|
3948
4219
|
return;
|
|
3949
4220
|
}
|
|
3950
|
-
let target = payload.organizations.find(
|
|
4221
|
+
let target = payload.organizations.find(
|
|
4222
|
+
(org) => org.org_id === options.orgId
|
|
4223
|
+
);
|
|
3951
4224
|
if (!target && selection) {
|
|
3952
4225
|
const index = Number.parseInt(selection, 10);
|
|
3953
4226
|
if (Number.isFinite(index) && index >= 1 && index <= payload.organizations.length) {
|
|
3954
4227
|
target = payload.organizations[index - 1];
|
|
3955
4228
|
} else {
|
|
3956
|
-
target = payload.organizations.find(
|
|
4229
|
+
target = payload.organizations.find(
|
|
4230
|
+
(org) => org.name === selection || org.org_id === selection
|
|
4231
|
+
);
|
|
3957
4232
|
}
|
|
3958
4233
|
}
|
|
3959
4234
|
if (!target) {
|
|
3960
4235
|
throw new Error("Could not resolve the selected organization.");
|
|
3961
4236
|
}
|
|
3962
4237
|
if (target.is_current) {
|
|
3963
|
-
printCommandEnvelope(
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
4238
|
+
printCommandEnvelope(
|
|
4239
|
+
{
|
|
4240
|
+
ok: true,
|
|
4241
|
+
unchanged: true,
|
|
4242
|
+
organization: target,
|
|
4243
|
+
render: {
|
|
4244
|
+
sections: [
|
|
4245
|
+
{ title: "org switch", lines: [`Already on ${target.name}.`] }
|
|
4246
|
+
]
|
|
4247
|
+
}
|
|
4248
|
+
},
|
|
4249
|
+
{ json: options.json }
|
|
4250
|
+
);
|
|
3969
4251
|
return;
|
|
3970
4252
|
}
|
|
3971
|
-
const switched = await http.post(
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
);
|
|
4253
|
+
const switched = await http.post("/api/v2/auth/cli/switch", {
|
|
4254
|
+
api_key: config.apiKey,
|
|
4255
|
+
org_id: target.org_id
|
|
4256
|
+
});
|
|
3975
4257
|
saveHostEnvValues(config.baseUrl, {
|
|
3976
4258
|
DEEPLINE_API_KEY: switched.api_key,
|
|
3977
4259
|
DEEPLINE_ACTIVE_ORG_ID: switched.org_id,
|
|
3978
4260
|
DEEPLINE_ACTIVE_ORG_NAME: switched.org_name
|
|
3979
4261
|
});
|
|
3980
4262
|
const { api_key: _apiKey, ...publicSwitched } = switched;
|
|
3981
|
-
printCommandEnvelope(
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
4263
|
+
printCommandEnvelope(
|
|
4264
|
+
{
|
|
4265
|
+
ok: true,
|
|
4266
|
+
host_env_path: hostEnvFilePath(config.baseUrl),
|
|
4267
|
+
...publicSwitched,
|
|
4268
|
+
api_key_saved: true,
|
|
4269
|
+
render: {
|
|
4270
|
+
sections: [
|
|
4271
|
+
{
|
|
4272
|
+
title: "org switch",
|
|
4273
|
+
lines: [
|
|
4274
|
+
`Switched to ${switched.org_name}.`,
|
|
4275
|
+
`Saved host auth in ${hostEnvFilePath(config.baseUrl)}`
|
|
4276
|
+
]
|
|
4277
|
+
}
|
|
4278
|
+
]
|
|
4279
|
+
}
|
|
4280
|
+
},
|
|
4281
|
+
{ json: options.json }
|
|
4282
|
+
);
|
|
3998
4283
|
}
|
|
3999
4284
|
function registerOrgCommands(program) {
|
|
4000
4285
|
const org = program.command("org").description("List and switch organizations.").addHelpText(
|
|
@@ -4021,7 +4306,9 @@ Examples:
|
|
|
4021
4306
|
deepline org list --json
|
|
4022
4307
|
`
|
|
4023
4308
|
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgList);
|
|
4024
|
-
org.command("switch [selection]").description(
|
|
4309
|
+
org.command("switch [selection]").description(
|
|
4310
|
+
"Switch to another organization and save the new API key in the host auth file."
|
|
4311
|
+
).addHelpText(
|
|
4025
4312
|
"after",
|
|
4026
4313
|
`
|
|
4027
4314
|
Notes:
|
|
@@ -5234,7 +5521,17 @@ function resolveExecutionProfile(override) {
|
|
|
5234
5521
|
var import_node_crypto2 = require("crypto");
|
|
5235
5522
|
var import_promises4 = require("fs/promises");
|
|
5236
5523
|
var import_node_path8 = require("path");
|
|
5237
|
-
var SOURCE_EXTENSIONS2 = [
|
|
5524
|
+
var SOURCE_EXTENSIONS2 = [
|
|
5525
|
+
".ts",
|
|
5526
|
+
".tsx",
|
|
5527
|
+
".mts",
|
|
5528
|
+
".cts",
|
|
5529
|
+
".js",
|
|
5530
|
+
".jsx",
|
|
5531
|
+
".mjs",
|
|
5532
|
+
".cjs",
|
|
5533
|
+
".json"
|
|
5534
|
+
];
|
|
5238
5535
|
function sha2562(buffer) {
|
|
5239
5536
|
return (0, import_node_crypto2.createHash)("sha256").update(buffer).digest("hex");
|
|
5240
5537
|
}
|
|
@@ -5258,7 +5555,9 @@ function unquoteStringLiteral2(literal) {
|
|
|
5258
5555
|
return null;
|
|
5259
5556
|
}
|
|
5260
5557
|
try {
|
|
5261
|
-
return JSON.parse(
|
|
5558
|
+
return JSON.parse(
|
|
5559
|
+
quote === '"' ? trimmed : `"${trimmed.slice(1, -1).replace(/"/g, '\\"')}"`
|
|
5560
|
+
);
|
|
5262
5561
|
} catch {
|
|
5263
5562
|
return trimmed.slice(1, -1);
|
|
5264
5563
|
}
|
|
@@ -5319,7 +5618,9 @@ function resolveStringExpression(expression, constants) {
|
|
|
5319
5618
|
}
|
|
5320
5619
|
const parts = splitTopLevelPlus(value);
|
|
5321
5620
|
if (parts) {
|
|
5322
|
-
const resolved = parts.map(
|
|
5621
|
+
const resolved = parts.map(
|
|
5622
|
+
(part) => resolveStringExpression(part, constants)
|
|
5623
|
+
);
|
|
5323
5624
|
return resolved.every((part) => part != null) ? resolved.join("") : null;
|
|
5324
5625
|
}
|
|
5325
5626
|
return null;
|
|
@@ -5327,7 +5628,9 @@ function resolveStringExpression(expression, constants) {
|
|
|
5327
5628
|
function collectTopLevelStringConstants(sourceCode) {
|
|
5328
5629
|
const constants = /* @__PURE__ */ new Map();
|
|
5329
5630
|
const source = stripCommentsToSpaces2(sourceCode);
|
|
5330
|
-
for (const match of source.matchAll(
|
|
5631
|
+
for (const match of source.matchAll(
|
|
5632
|
+
/(?:^|\n)\s*const\s+([A-Za-z_$][\w$]*)\s*=\s*([^;\n]+)/g
|
|
5633
|
+
)) {
|
|
5331
5634
|
const resolved = resolveStringExpression(match[2], constants);
|
|
5332
5635
|
if (resolved != null) {
|
|
5333
5636
|
constants.set(match[1], resolved);
|
|
@@ -5416,7 +5719,9 @@ function localImportSpecifiers(sourceCode) {
|
|
|
5416
5719
|
)) {
|
|
5417
5720
|
if (match[1]?.startsWith(".")) specifiers.push(match[1]);
|
|
5418
5721
|
}
|
|
5419
|
-
for (const match of source.matchAll(
|
|
5722
|
+
for (const match of source.matchAll(
|
|
5723
|
+
/\brequire\s*\(\s*(['"])(\.[^'"]*)\1\s*\)/g
|
|
5724
|
+
)) {
|
|
5420
5725
|
specifiers.push(match[2]);
|
|
5421
5726
|
}
|
|
5422
5727
|
return specifiers;
|
|
@@ -5438,18 +5743,26 @@ async function resolveLocalImport2(fromFile, specifier) {
|
|
|
5438
5743
|
const candidates = [base];
|
|
5439
5744
|
const explicitExtension = (0, import_node_path8.extname)(base).toLowerCase();
|
|
5440
5745
|
if (!explicitExtension) {
|
|
5441
|
-
candidates.push(
|
|
5442
|
-
|
|
5746
|
+
candidates.push(
|
|
5747
|
+
...SOURCE_EXTENSIONS2.map((extension) => `${base}${extension}`)
|
|
5748
|
+
);
|
|
5749
|
+
candidates.push(
|
|
5750
|
+
...SOURCE_EXTENSIONS2.map((extension) => (0, import_node_path8.join)(base, `index${extension}`))
|
|
5751
|
+
);
|
|
5443
5752
|
} else if ([".js", ".jsx", ".mjs", ".cjs"].includes(explicitExtension)) {
|
|
5444
5753
|
const stem = base.slice(0, -explicitExtension.length);
|
|
5445
|
-
candidates.push(
|
|
5754
|
+
candidates.push(
|
|
5755
|
+
...SOURCE_EXTENSIONS2.map((extension) => `${stem}${extension}`)
|
|
5756
|
+
);
|
|
5446
5757
|
}
|
|
5447
5758
|
for (const candidate of candidates) {
|
|
5448
5759
|
if (await fileExists2(candidate)) {
|
|
5449
5760
|
return candidate;
|
|
5450
5761
|
}
|
|
5451
5762
|
}
|
|
5452
|
-
throw new Error(
|
|
5763
|
+
throw new Error(
|
|
5764
|
+
`Could not resolve local import "${specifier}" from ${fromFile}`
|
|
5765
|
+
);
|
|
5453
5766
|
}
|
|
5454
5767
|
async function discoverPackagedLocalFiles(entryFile) {
|
|
5455
5768
|
const absoluteEntryFile = (0, import_node_path8.resolve)(entryFile);
|
|
@@ -5467,12 +5780,17 @@ async function discoverPackagedLocalFiles(entryFile) {
|
|
|
5467
5780
|
const scanSource = stripCommentsToSpaces2(sourceCode);
|
|
5468
5781
|
const constants = collectTopLevelStringConstants(sourceCode);
|
|
5469
5782
|
const childVisits = [];
|
|
5470
|
-
for (const match of scanSource.matchAll(
|
|
5783
|
+
for (const match of scanSource.matchAll(
|
|
5784
|
+
/\b([A-Za-z_$][\w$]*)\s*\.\s*csv\b/g
|
|
5785
|
+
)) {
|
|
5471
5786
|
const target = match[1];
|
|
5472
5787
|
if (target !== "ctx" && !target.endsWith("Ctx")) {
|
|
5473
5788
|
continue;
|
|
5474
5789
|
}
|
|
5475
|
-
const openParen = findCallOpenParen(
|
|
5790
|
+
const openParen = findCallOpenParen(
|
|
5791
|
+
scanSource,
|
|
5792
|
+
match.index + match[0].length
|
|
5793
|
+
);
|
|
5476
5794
|
if (openParen < 0) {
|
|
5477
5795
|
continue;
|
|
5478
5796
|
}
|
|
@@ -9264,7 +9582,9 @@ function buildRunPackageTextLines(packaged) {
|
|
|
9264
9582
|
lines.push(` ${kind} ${id}: ${stepStatus}${rowCount}`);
|
|
9265
9583
|
lines.push(...formatPackageDatasetSummaryLines(output?.summary));
|
|
9266
9584
|
if (previewRows !== null) {
|
|
9267
|
-
lines.push(
|
|
9585
|
+
lines.push(
|
|
9586
|
+
` preview=${previewRows}${preview?.truncated ? " truncated" : ""}`
|
|
9587
|
+
);
|
|
9268
9588
|
}
|
|
9269
9589
|
}
|
|
9270
9590
|
const next = packaged.next && typeof packaged.next === "object" && !Array.isArray(packaged.next) ? packaged.next : {};
|
|
@@ -11066,7 +11386,9 @@ function matchesPlayGrepQuery(value, query, mode) {
|
|
|
11066
11386
|
async function handlePlayGrep(args) {
|
|
11067
11387
|
const query = args[0]?.trim();
|
|
11068
11388
|
if (!query) {
|
|
11069
|
-
console.error(
|
|
11389
|
+
console.error(
|
|
11390
|
+
"Usage: deepline plays grep <query> [--mode all|any|phrase] [--compact] [--json]"
|
|
11391
|
+
);
|
|
11070
11392
|
return 1;
|
|
11071
11393
|
}
|
|
11072
11394
|
let mode = "all";
|
|
@@ -11099,13 +11421,15 @@ async function handlePlayGrep(args) {
|
|
|
11099
11421
|
)
|
|
11100
11422
|
).map((play) => summarizePlayListItemForCli(play, { compact }));
|
|
11101
11423
|
if (argsWantJson(args)) {
|
|
11102
|
-
process.stdout.write(
|
|
11103
|
-
|
|
11104
|
-
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
|
-
|
|
11424
|
+
process.stdout.write(
|
|
11425
|
+
`${JSON.stringify({
|
|
11426
|
+
plays,
|
|
11427
|
+
count: plays.length,
|
|
11428
|
+
query,
|
|
11429
|
+
grep: { mode, terms: parsePlayGrepTerms(query, mode) }
|
|
11430
|
+
})}
|
|
11431
|
+
`
|
|
11432
|
+
);
|
|
11109
11433
|
return 0;
|
|
11110
11434
|
}
|
|
11111
11435
|
process.stdout.write(`${plays.length} plays found:
|
|
@@ -11768,7 +12092,9 @@ function normalizeRows(value) {
|
|
|
11768
12092
|
});
|
|
11769
12093
|
}
|
|
11770
12094
|
function candidateRoots(payload) {
|
|
11771
|
-
const roots = [
|
|
12095
|
+
const roots = [
|
|
12096
|
+
{ path: null, value: payload }
|
|
12097
|
+
];
|
|
11772
12098
|
if (isPlainObject(payload) && isPlainObject(payload.toolResponse)) {
|
|
11773
12099
|
roots.push({ path: "toolResponse", value: payload.toolResponse });
|
|
11774
12100
|
if (Object.prototype.hasOwnProperty.call(payload.toolResponse, "raw")) {
|
|
@@ -11795,7 +12121,9 @@ function candidateRoots(payload) {
|
|
|
11795
12121
|
function findBestArrayCandidate(value, pathPrefix = "", depth = 0) {
|
|
11796
12122
|
if (depth > 5) return null;
|
|
11797
12123
|
const directRows = normalizeRows(value);
|
|
11798
|
-
const hasObjectRow = directRows?.some(
|
|
12124
|
+
const hasObjectRow = directRows?.some(
|
|
12125
|
+
(row) => Object.keys(row).some((key) => key !== "value")
|
|
12126
|
+
) ?? false;
|
|
11799
12127
|
let best = directRows && directRows.length > 0 && hasObjectRow ? { path: pathPrefix, rows: directRows } : null;
|
|
11800
12128
|
if (!isPlainObject(value)) {
|
|
11801
12129
|
return best;
|
|
@@ -11811,7 +12139,9 @@ function findBestArrayCandidate(value, pathPrefix = "", depth = 0) {
|
|
|
11811
12139
|
return best;
|
|
11812
12140
|
}
|
|
11813
12141
|
function tryConvertToList(payload, options) {
|
|
11814
|
-
const listExtractorPaths = Array.isArray(options?.listExtractorPaths) ? options?.listExtractorPaths.filter(
|
|
12142
|
+
const listExtractorPaths = Array.isArray(options?.listExtractorPaths) ? options?.listExtractorPaths.filter(
|
|
12143
|
+
(entry) => typeof entry === "string" && entry.trim().length > 0
|
|
12144
|
+
) : [];
|
|
11815
12145
|
if (listExtractorPaths.length > 0) {
|
|
11816
12146
|
for (const root of candidateRoots(payload)) {
|
|
11817
12147
|
for (const extractorPath of listExtractorPaths) {
|
|
@@ -11877,7 +12207,9 @@ function writeCsvOutputFile(rows, stem) {
|
|
|
11877
12207
|
const previewColumns = columns.slice(0, 5);
|
|
11878
12208
|
const preview = [
|
|
11879
12209
|
previewColumns.join(","),
|
|
11880
|
-
...previewRows.map(
|
|
12210
|
+
...previewRows.map(
|
|
12211
|
+
(row) => previewColumns.map((column) => escapeCell(row[column])).join(",")
|
|
12212
|
+
)
|
|
11881
12213
|
].join("\n");
|
|
11882
12214
|
return {
|
|
11883
12215
|
path: outputPath,
|
|
@@ -11890,9 +12222,11 @@ function extractSummaryFields(payload) {
|
|
|
11890
12222
|
const candidates = candidateRoots(payload);
|
|
11891
12223
|
for (const candidate of candidates) {
|
|
11892
12224
|
if (!isPlainObject(candidate.value)) continue;
|
|
11893
|
-
const summaryEntries = Object.entries(candidate.value).filter(
|
|
11894
|
-
|
|
11895
|
-
|
|
12225
|
+
const summaryEntries = Object.entries(candidate.value).filter(
|
|
12226
|
+
([, value]) => {
|
|
12227
|
+
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
12228
|
+
}
|
|
12229
|
+
);
|
|
11896
12230
|
if (summaryEntries.length === 0) continue;
|
|
11897
12231
|
return Object.fromEntries(summaryEntries);
|
|
11898
12232
|
}
|
|
@@ -12422,8 +12756,16 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
|
|
|
12422
12756
|
arrayField(toolExecutionResult, "extractedValues", "extracted_values")
|
|
12423
12757
|
);
|
|
12424
12758
|
const cost = recordField(tool, "cost");
|
|
12425
|
-
const deeplineCredits = numberField(
|
|
12426
|
-
|
|
12759
|
+
const deeplineCredits = numberField(
|
|
12760
|
+
tool,
|
|
12761
|
+
"deeplineCreditsPerPricingUnit",
|
|
12762
|
+
"deepline_credits_per_pricing_unit"
|
|
12763
|
+
);
|
|
12764
|
+
const deeplineUsdPerPricingUnit = numberField(
|
|
12765
|
+
tool,
|
|
12766
|
+
"deeplineUsdPerPricingUnit",
|
|
12767
|
+
"deepline_usd_per_pricing_unit"
|
|
12768
|
+
);
|
|
12427
12769
|
const starterScript = seedToolListScript({
|
|
12428
12770
|
toolId,
|
|
12429
12771
|
payload: samplePayloadForInputFields(inputFields),
|
|
@@ -12511,7 +12853,9 @@ function printCompactToolContract(tool, requestedToolId) {
|
|
|
12511
12853
|
if (starterPath) {
|
|
12512
12854
|
console.log("");
|
|
12513
12855
|
console.log(`Starter script: ${starterPath}`);
|
|
12514
|
-
console.log(
|
|
12856
|
+
console.log(
|
|
12857
|
+
"Copy it into your project and replace the sample input with the proven probe payload."
|
|
12858
|
+
);
|
|
12515
12859
|
}
|
|
12516
12860
|
if (listGetters.length || valueGetters.length) {
|
|
12517
12861
|
console.log("");
|
|
@@ -12674,7 +13018,9 @@ function playResultExpression(entry) {
|
|
|
12674
13018
|
}
|
|
12675
13019
|
function toolMetadataJsonForDescribe(tool, requestedToolId) {
|
|
12676
13020
|
const toolId = String(tool.toolId || requestedToolId);
|
|
12677
|
-
const inputFields = toolInputFieldsForDisplay(
|
|
13021
|
+
const inputFields = toolInputFieldsForDisplay(
|
|
13022
|
+
recordField(tool, "inputSchema", "input_schema")
|
|
13023
|
+
);
|
|
12678
13024
|
const starterScript = seedToolListScript({
|
|
12679
13025
|
toolId,
|
|
12680
13026
|
payload: samplePayloadForInputFields(inputFields),
|
|
@@ -12699,7 +13045,9 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
|
|
|
12699
13045
|
toolId,
|
|
12700
13046
|
provider: tool.provider,
|
|
12701
13047
|
displayName: tool.displayName,
|
|
12702
|
-
usageGuidance: usageGuidanceWithAccessDefaults(
|
|
13048
|
+
usageGuidance: usageGuidanceWithAccessDefaults(
|
|
13049
|
+
recordField(tool, "usageGuidance", "usage_guidance")
|
|
13050
|
+
),
|
|
12703
13051
|
runtimeOutputHelp: {
|
|
12704
13052
|
contract: "tools describe shows declared schema and Deepline getters; it is not an observed provider response.",
|
|
12705
13053
|
getterScope: "extractedValues/extractedLists .get() only works for declared Deepline getters listed in usageGuidance.toolExecutionResult.",
|
|
@@ -13314,8 +13662,10 @@ async function handleUpdate(options) {
|
|
|
13314
13662
|
printCommandEnvelope({ ...plan, render }, { json: false });
|
|
13315
13663
|
return 0;
|
|
13316
13664
|
}
|
|
13317
|
-
process.stderr.write(
|
|
13318
|
-
`
|
|
13665
|
+
process.stderr.write(
|
|
13666
|
+
`Updating Deepline SDK/CLI with: ${plan.manualCommand}
|
|
13667
|
+
`
|
|
13668
|
+
);
|
|
13319
13669
|
return runCommand(plan.command, plan.args);
|
|
13320
13670
|
}
|
|
13321
13671
|
function registerUpdateCommand(program) {
|
|
@@ -13352,7 +13702,14 @@ function shouldSkipSkillsSync() {
|
|
|
13352
13702
|
}
|
|
13353
13703
|
function sdkSkillsVersionPath(baseUrl) {
|
|
13354
13704
|
const home = process.env.HOME?.trim() || (0, import_node_os8.homedir)();
|
|
13355
|
-
return (0, import_node_path15.join)(
|
|
13705
|
+
return (0, import_node_path15.join)(
|
|
13706
|
+
home,
|
|
13707
|
+
".local",
|
|
13708
|
+
"deepline",
|
|
13709
|
+
baseUrlSlug(baseUrl),
|
|
13710
|
+
"sdk-skills",
|
|
13711
|
+
".version"
|
|
13712
|
+
);
|
|
13356
13713
|
}
|
|
13357
13714
|
function readLocalSkillsVersion(baseUrl) {
|
|
13358
13715
|
const path = sdkSkillsVersionPath(baseUrl);
|
|
@@ -13434,7 +13791,10 @@ async function fetchSkillsUpdate(baseUrl, localVersion) {
|
|
|
13434
13791
|
}
|
|
13435
13792
|
}
|
|
13436
13793
|
function buildSkillsInstallArgs(baseUrl) {
|
|
13437
|
-
const packageUrl = new URL(
|
|
13794
|
+
const packageUrl = new URL(
|
|
13795
|
+
"/.well-known/skills/index.json",
|
|
13796
|
+
baseUrl
|
|
13797
|
+
).toString();
|
|
13438
13798
|
return [
|
|
13439
13799
|
"--yes",
|
|
13440
13800
|
"skills",
|
|
@@ -13450,7 +13810,10 @@ function buildSkillsInstallArgs(baseUrl) {
|
|
|
13450
13810
|
];
|
|
13451
13811
|
}
|
|
13452
13812
|
function buildBunxSkillsInstallArgs(baseUrl) {
|
|
13453
|
-
const packageUrl = new URL(
|
|
13813
|
+
const packageUrl = new URL(
|
|
13814
|
+
"/.well-known/skills/index.json",
|
|
13815
|
+
baseUrl
|
|
13816
|
+
).toString();
|
|
13454
13817
|
return [
|
|
13455
13818
|
"--bun",
|
|
13456
13819
|
"skills",
|