deepline 0.1.48 → 0.1.49
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 +859 -258
- package/dist/cli/index.mjs +859 -258
- package/dist/index.d.mts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +53 -8
- package/dist/index.mjs +53 -8
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +5 -2
- package/dist/repo/apps/play-runner-workers/src/entry.ts +3 -0
- package/dist/repo/sdk/src/client.ts +29 -4
- package/dist/repo/sdk/src/version.ts +1 -1
- package/dist/repo/shared_libs/play-runtime/tool-result.ts +34 -3
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -24,7 +24,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/cli/index.ts
|
|
27
|
-
var
|
|
27
|
+
var import_promises5 = require("fs/promises");
|
|
28
|
+
var import_node_path15 = require("path");
|
|
29
|
+
var import_node_os9 = require("os");
|
|
30
|
+
var import_commander3 = require("commander");
|
|
28
31
|
|
|
29
32
|
// src/config.ts
|
|
30
33
|
var import_node_fs = require("fs");
|
|
@@ -216,7 +219,7 @@ function resolveConfig(options) {
|
|
|
216
219
|
}
|
|
217
220
|
|
|
218
221
|
// src/version.ts
|
|
219
|
-
var SDK_VERSION = "0.1.
|
|
222
|
+
var SDK_VERSION = "0.1.49";
|
|
220
223
|
var SDK_API_CONTRACT = "2026-05-stripe-promo-checkout";
|
|
221
224
|
|
|
222
225
|
// ../shared_libs/play-runtime/coordinator-headers.ts
|
|
@@ -736,9 +739,18 @@ var DeeplineClient = class {
|
|
|
736
739
|
* console.log(`Found ${searchTools.length} search tools`);
|
|
737
740
|
* ```
|
|
738
741
|
*/
|
|
739
|
-
async listTools() {
|
|
742
|
+
async listTools(options) {
|
|
743
|
+
const params = new URLSearchParams();
|
|
744
|
+
if (options?.categories?.trim()) {
|
|
745
|
+
params.set("categories", options.categories.trim());
|
|
746
|
+
}
|
|
747
|
+
if (options?.grep?.trim()) {
|
|
748
|
+
params.set("grep", options.grep.trim());
|
|
749
|
+
params.set("grep_mode", options.grepMode ?? "all");
|
|
750
|
+
}
|
|
751
|
+
const suffix = params.toString() ? `?${params.toString()}` : "";
|
|
740
752
|
const res = await this.http.get(
|
|
741
|
-
|
|
753
|
+
`/api/v2/tools${suffix}`
|
|
742
754
|
);
|
|
743
755
|
return res.tools;
|
|
744
756
|
}
|
|
@@ -1373,9 +1385,17 @@ var DeeplineClient = class {
|
|
|
1373
1385
|
options?.reason ? { reason: options.reason } : {}
|
|
1374
1386
|
);
|
|
1375
1387
|
}
|
|
1376
|
-
async listPlays() {
|
|
1388
|
+
async listPlays(options) {
|
|
1389
|
+
const params = new URLSearchParams();
|
|
1390
|
+
if (options?.origin) params.set("origin", options.origin);
|
|
1391
|
+
if (options?.grep?.trim()) {
|
|
1392
|
+
params.set("grep", options.grep.trim());
|
|
1393
|
+
params.set("grep_mode", options.grepMode ?? "all");
|
|
1394
|
+
params.set("limit", "60");
|
|
1395
|
+
}
|
|
1396
|
+
const suffix = params.toString() ? `?${params.toString()}` : "";
|
|
1377
1397
|
const response = await this.http.get(
|
|
1378
|
-
|
|
1398
|
+
`/api/v2/plays${suffix}`
|
|
1379
1399
|
);
|
|
1380
1400
|
return response.plays ?? [];
|
|
1381
1401
|
}
|
|
@@ -5683,6 +5703,16 @@ function extractPlayName(code, filePath) {
|
|
|
5683
5703
|
function isFileTarget(target) {
|
|
5684
5704
|
return (0, import_node_fs8.existsSync)((0, import_node_path10.resolve)(target));
|
|
5685
5705
|
}
|
|
5706
|
+
function looksLikeRunId(target) {
|
|
5707
|
+
return /^play\/[^/]+\/run\/[^/]+/.test(target.trim());
|
|
5708
|
+
}
|
|
5709
|
+
function formatPlayCommandReceivedRunIdError(input) {
|
|
5710
|
+
return `\`deepline plays ${input.command} <run-id>\` expects a play name, but this looks like a run id.
|
|
5711
|
+
Use:
|
|
5712
|
+
deepline runs get ${input.runId} --json
|
|
5713
|
+
deepline runs logs ${input.runId} --json
|
|
5714
|
+
deepline runs export ${input.runId} --out output.csv`;
|
|
5715
|
+
}
|
|
5686
5716
|
function looksLikeFilePath(target) {
|
|
5687
5717
|
if (target.trim().toLowerCase().startsWith("prebuilt/")) {
|
|
5688
5718
|
return false;
|
|
@@ -6109,6 +6139,69 @@ function describeLiveEventPhase(event) {
|
|
|
6109
6139
|
}
|
|
6110
6140
|
return null;
|
|
6111
6141
|
}
|
|
6142
|
+
function formatProgressLabel(raw) {
|
|
6143
|
+
const value = typeof raw === "string" && raw.trim() ? raw.trim() : "step";
|
|
6144
|
+
return value.replace(/^map:/, "").replace(/^tool:/, "");
|
|
6145
|
+
}
|
|
6146
|
+
function formatProgressCounts(input) {
|
|
6147
|
+
const completed = typeof input.completed === "number" && Number.isFinite(input.completed) ? input.completed : null;
|
|
6148
|
+
const total = typeof input.total === "number" && Number.isFinite(input.total) ? input.total : null;
|
|
6149
|
+
if (completed === null || total === null || total <= 0) {
|
|
6150
|
+
return null;
|
|
6151
|
+
}
|
|
6152
|
+
const percent = Math.max(0, Math.min(100, Math.round(completed / total * 100)));
|
|
6153
|
+
const failed = typeof input.failed === "number" && Number.isFinite(input.failed) && input.failed > 0 ? `, failed ${formatInteger(input.failed)}` : "";
|
|
6154
|
+
return `${formatInteger(completed)}/${formatInteger(total)} (${percent}%)${failed}`;
|
|
6155
|
+
}
|
|
6156
|
+
function getProgressLinesFromLiveEvent(event) {
|
|
6157
|
+
const payload = getEventPayload(event);
|
|
6158
|
+
if (event.type === "play.step.progress") {
|
|
6159
|
+
const counts = formatProgressCounts({
|
|
6160
|
+
completed: payload.completed,
|
|
6161
|
+
total: payload.total,
|
|
6162
|
+
failed: payload.failed
|
|
6163
|
+
});
|
|
6164
|
+
if (!counts) return [];
|
|
6165
|
+
return [`progress ${formatProgressLabel(payload.stepId)}: ${counts}`];
|
|
6166
|
+
}
|
|
6167
|
+
if (event.type !== "play.run.snapshot" && event.type !== "play.run.final_status") {
|
|
6168
|
+
return [];
|
|
6169
|
+
}
|
|
6170
|
+
const nodeStates = Array.isArray(payload.nodeStates) ? payload.nodeStates : Array.isArray(payload.steps) ? payload.steps : [];
|
|
6171
|
+
const lines = [];
|
|
6172
|
+
for (const state of nodeStates) {
|
|
6173
|
+
if (!state || typeof state !== "object" || Array.isArray(state)) {
|
|
6174
|
+
continue;
|
|
6175
|
+
}
|
|
6176
|
+
const record = state;
|
|
6177
|
+
const progress = record.progress && typeof record.progress === "object" && !Array.isArray(record.progress) ? record.progress : null;
|
|
6178
|
+
if (!progress) {
|
|
6179
|
+
continue;
|
|
6180
|
+
}
|
|
6181
|
+
const counts = formatProgressCounts({
|
|
6182
|
+
completed: progress.completed,
|
|
6183
|
+
total: progress.total,
|
|
6184
|
+
failed: progress.failed
|
|
6185
|
+
});
|
|
6186
|
+
if (!counts) {
|
|
6187
|
+
continue;
|
|
6188
|
+
}
|
|
6189
|
+
lines.push(
|
|
6190
|
+
`progress ${formatProgressLabel(record.nodeId ?? progress.artifactTableNamespace)}: ${counts}`
|
|
6191
|
+
);
|
|
6192
|
+
}
|
|
6193
|
+
return lines;
|
|
6194
|
+
}
|
|
6195
|
+
function printPlayProgressLines(input) {
|
|
6196
|
+
for (const line of input.lines) {
|
|
6197
|
+
const signature = line.trim();
|
|
6198
|
+
if (!signature || input.state.lastProgressSignature === signature) {
|
|
6199
|
+
continue;
|
|
6200
|
+
}
|
|
6201
|
+
input.state.lastProgressSignature = signature;
|
|
6202
|
+
input.progress.writeLine(line);
|
|
6203
|
+
}
|
|
6204
|
+
}
|
|
6112
6205
|
function buildPlayDashboardUrl(baseUrl, playName) {
|
|
6113
6206
|
const trimmedBase = baseUrl.replace(/\/$/, "");
|
|
6114
6207
|
const encodedPlayName = encodeURIComponent(playName);
|
|
@@ -6182,6 +6275,13 @@ async function waitForPlayCompletionByStream(input) {
|
|
|
6182
6275
|
state: input.state,
|
|
6183
6276
|
progress: input.progress
|
|
6184
6277
|
});
|
|
6278
|
+
if (!input.jsonOutput) {
|
|
6279
|
+
printPlayProgressLines({
|
|
6280
|
+
lines: getProgressLinesFromLiveEvent(event),
|
|
6281
|
+
state: input.state,
|
|
6282
|
+
progress: input.progress
|
|
6283
|
+
});
|
|
6284
|
+
}
|
|
6185
6285
|
const status = getStatusFromLiveEvent(event);
|
|
6186
6286
|
if (status && TERMINAL_PLAY_STATUSES2.has(status)) {
|
|
6187
6287
|
const finalStatus = await input.client.getPlayStatus(input.workflowId, {
|
|
@@ -6250,7 +6350,8 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
6250
6350
|
);
|
|
6251
6351
|
const state = {
|
|
6252
6352
|
lastLogIndex: 0,
|
|
6253
|
-
emittedRunnerStarted: false
|
|
6353
|
+
emittedRunnerStarted: false,
|
|
6354
|
+
lastProgressSignature: null
|
|
6254
6355
|
};
|
|
6255
6356
|
const controller = new AbortController();
|
|
6256
6357
|
let timedOut = false;
|
|
@@ -6278,11 +6379,6 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
6278
6379
|
}
|
|
6279
6380
|
const workflowId = lastKnownWorkflowId || "pending";
|
|
6280
6381
|
if (workflowId !== "pending" && !emittedDashboardUrl) {
|
|
6281
|
-
openPlayDashboard({
|
|
6282
|
-
dashboardUrl,
|
|
6283
|
-
jsonOutput: input.jsonOutput,
|
|
6284
|
-
noOpen: input.noOpen
|
|
6285
|
-
});
|
|
6286
6382
|
if (!input.jsonOutput) {
|
|
6287
6383
|
writeStartedPlayRun({
|
|
6288
6384
|
runId: workflowId,
|
|
@@ -6292,6 +6388,11 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
6292
6388
|
progress: input.progress
|
|
6293
6389
|
});
|
|
6294
6390
|
}
|
|
6391
|
+
openPlayDashboard({
|
|
6392
|
+
dashboardUrl,
|
|
6393
|
+
jsonOutput: input.jsonOutput,
|
|
6394
|
+
noOpen: input.noOpen
|
|
6395
|
+
});
|
|
6295
6396
|
input.progress.phase(`loading play on ${dashboardUrl}`);
|
|
6296
6397
|
emittedDashboardUrl = true;
|
|
6297
6398
|
}
|
|
@@ -6314,6 +6415,13 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
6314
6415
|
state,
|
|
6315
6416
|
progress: input.progress
|
|
6316
6417
|
});
|
|
6418
|
+
if (!input.jsonOutput) {
|
|
6419
|
+
printPlayProgressLines({
|
|
6420
|
+
lines: getProgressLinesFromLiveEvent(event),
|
|
6421
|
+
state,
|
|
6422
|
+
progress: input.progress
|
|
6423
|
+
});
|
|
6424
|
+
}
|
|
6317
6425
|
const finalStatus = getFinalStatusFromLiveEvent(event);
|
|
6318
6426
|
if (finalStatus) {
|
|
6319
6427
|
recordCliTrace({
|
|
@@ -6582,6 +6690,7 @@ function buildRunNextCommands(status) {
|
|
|
6582
6690
|
const commands = {
|
|
6583
6691
|
get: `deepline runs get ${runId} --json`,
|
|
6584
6692
|
full: `deepline runs get ${runId} --full --json`,
|
|
6693
|
+
export: `deepline runs export ${runId} --out output.csv`,
|
|
6585
6694
|
stop: `deepline runs stop ${runId} --reason "stale lock" --json`,
|
|
6586
6695
|
logs: `deepline runs logs ${runId} --out run.log --json`
|
|
6587
6696
|
};
|
|
@@ -6714,6 +6823,32 @@ function formatInsufficientCreditsMessage(input) {
|
|
|
6714
6823
|
const addSuffix = billingUrl && recommended !== "-" ? ` Add >=${recommended} at ${billingUrl}.` : billingUrl ? ` Add credits at ${billingUrl}.` : "";
|
|
6715
6824
|
return `Workspace balance ${balance} < required ${required} for ${operation}${workspaceSuffix}.${addSuffix}`;
|
|
6716
6825
|
}
|
|
6826
|
+
function buildInsufficientCreditsSummaryLines(input) {
|
|
6827
|
+
const progress = input.status.progress;
|
|
6828
|
+
const rowsInfo = extractCanonicalRowsInfo(input.status);
|
|
6829
|
+
const completed = getNumericField(progress, "completed") ?? getNumericField(progress, "completedRows") ?? rowsInfo?.rows.length ?? null;
|
|
6830
|
+
const total = getNumericField(progress, "total") ?? getNumericField(progress, "totalRows") ?? rowsInfo?.totalRows ?? null;
|
|
6831
|
+
const lines = [
|
|
6832
|
+
" status: stopped_insufficient_credits",
|
|
6833
|
+
completed === null ? " completed rows: unknown" : ` completed rows: ${formatInteger(completed)}${total !== null ? ` of ${formatInteger(total)}` : ""}`,
|
|
6834
|
+
" reusable receipts: yes; rerun after adding credits to continue from completed provider work"
|
|
6835
|
+
];
|
|
6836
|
+
const billingUrl = getStringField(input.billing, "billing_url");
|
|
6837
|
+
const recommended = formatCreditAmount(
|
|
6838
|
+
input.billing.recommended_add_credits ?? input.billing.needed_credits
|
|
6839
|
+
);
|
|
6840
|
+
if (billingUrl) {
|
|
6841
|
+
lines.push(
|
|
6842
|
+
recommended !== "-" ? ` add credits: add >=${recommended} at ${billingUrl}` : ` add credits: ${billingUrl}`
|
|
6843
|
+
);
|
|
6844
|
+
}
|
|
6845
|
+
const runId = input.status.runId?.trim();
|
|
6846
|
+
if (runId) {
|
|
6847
|
+
lines.push(` inspect: deepline runs get ${runId} --json`);
|
|
6848
|
+
lines.push(` export partial: deepline runs export ${runId} --out output.csv`);
|
|
6849
|
+
}
|
|
6850
|
+
return lines;
|
|
6851
|
+
}
|
|
6717
6852
|
function formatPlayErrorForDisplay(status, error) {
|
|
6718
6853
|
if (!error) {
|
|
6719
6854
|
return null;
|
|
@@ -6904,6 +7039,19 @@ function formatDatasetStatsLines(datasetStats) {
|
|
|
6904
7039
|
}
|
|
6905
7040
|
return lines;
|
|
6906
7041
|
}
|
|
7042
|
+
function buildJsonRunResultRenderLines(status) {
|
|
7043
|
+
const publicStatus = status.status ?? "running";
|
|
7044
|
+
const runId = status.runId ?? "unknown";
|
|
7045
|
+
const lines = [`${publicStatus} ${runId}`];
|
|
7046
|
+
const progressError = status.progress?.error;
|
|
7047
|
+
if (typeof progressError === "string") {
|
|
7048
|
+
const billing = extractBillingForStatus(status, progressError);
|
|
7049
|
+
if (isInsufficientCreditsBilling(billing)) {
|
|
7050
|
+
lines.push(...buildInsufficientCreditsSummaryLines({ status, billing }));
|
|
7051
|
+
}
|
|
7052
|
+
}
|
|
7053
|
+
return lines;
|
|
7054
|
+
}
|
|
6907
7055
|
function writePlayResult(status, jsonOutput, options) {
|
|
6908
7056
|
if (jsonOutput) {
|
|
6909
7057
|
const payload2 = options?.fullJson ? enrichPlayStatusWithDatasetStats(status) : compactPlayStatus(status);
|
|
@@ -6913,9 +7061,7 @@ function writePlayResult(status, jsonOutput, options) {
|
|
|
6913
7061
|
sections: [
|
|
6914
7062
|
{
|
|
6915
7063
|
title: "run result",
|
|
6916
|
-
lines:
|
|
6917
|
-
`${status.status ?? "running"} ${status.runId ?? "unknown"}`
|
|
6918
|
-
]
|
|
7064
|
+
lines: buildJsonRunResultRenderLines(status)
|
|
6919
7065
|
}
|
|
6920
7066
|
]
|
|
6921
7067
|
}
|
|
@@ -6942,6 +7088,10 @@ function writePlayResult(status, jsonOutput, options) {
|
|
|
6942
7088
|
lines.push(...formatDatasetStatsLines(datasetStats));
|
|
6943
7089
|
const progressError = status.progress?.error;
|
|
6944
7090
|
if (progressError && typeof progressError === "string") {
|
|
7091
|
+
const billing = extractBillingForStatus(status, progressError);
|
|
7092
|
+
if (isInsufficientCreditsBilling(billing)) {
|
|
7093
|
+
lines.push(...buildInsufficientCreditsSummaryLines({ status, billing }));
|
|
7094
|
+
}
|
|
6945
7095
|
const displayError = formatPlayErrorForDisplay(status, progressError) ?? progressError;
|
|
6946
7096
|
lines.push(` error: ${displayError.slice(0, 200)}`);
|
|
6947
7097
|
}
|
|
@@ -7321,24 +7471,31 @@ function writeStartedPlayRun(input) {
|
|
|
7321
7471
|
workflowId: input.runId,
|
|
7322
7472
|
name: input.playName,
|
|
7323
7473
|
status: input.status ?? "started",
|
|
7324
|
-
dashboardUrl: input.dashboardUrl
|
|
7474
|
+
dashboardUrl: input.dashboardUrl,
|
|
7475
|
+
next: {
|
|
7476
|
+
inspect: `deepline runs get ${input.runId} --json`,
|
|
7477
|
+
full: `deepline runs get ${input.runId} --full --json`,
|
|
7478
|
+
logs: `deepline runs logs ${input.runId} --json`,
|
|
7479
|
+
export: `deepline runs export ${input.runId} --out output.csv`,
|
|
7480
|
+
stop: `deepline runs stop ${input.runId} --reason "stale lock" --json`
|
|
7481
|
+
}
|
|
7325
7482
|
};
|
|
7483
|
+
const lines = [
|
|
7484
|
+
`Started ${input.playName}`,
|
|
7485
|
+
` run id: ${input.runId}`,
|
|
7486
|
+
` inspect: deepline runs get ${input.runId} --json`,
|
|
7487
|
+
` full debug: deepline runs get ${input.runId} --full --json`,
|
|
7488
|
+
` logs: deepline runs logs ${input.runId} --json`,
|
|
7489
|
+
` export after completion: deepline runs export ${input.runId} --out output.csv`,
|
|
7490
|
+
` stop run: deepline runs stop ${input.runId} --reason "stale lock" --json`
|
|
7491
|
+
];
|
|
7326
7492
|
if (input.jsonOutput) {
|
|
7327
7493
|
printCommandEnvelope({
|
|
7328
7494
|
...payload,
|
|
7329
|
-
render: { sections: [{ title: "play run", lines
|
|
7495
|
+
render: { sections: [{ title: "play run", lines }] }
|
|
7330
7496
|
}, { json: true });
|
|
7331
7497
|
return;
|
|
7332
7498
|
}
|
|
7333
|
-
const lines = [
|
|
7334
|
-
`Started ${input.playName}`,
|
|
7335
|
-
` run id: ${input.runId}`,
|
|
7336
|
-
` get status: deepline runs get ${input.runId} --json`,
|
|
7337
|
-
` logs: deepline runs logs ${input.runId} --json`,
|
|
7338
|
-
` stop run: deepline runs stop ${input.runId} --reason "stale lock" --json`,
|
|
7339
|
-
` result JSON: deepline runs get ${input.runId} --json`,
|
|
7340
|
-
` full debug JSON: deepline runs get ${input.runId} --full --json`
|
|
7341
|
-
];
|
|
7342
7499
|
if (input.dashboardUrl) {
|
|
7343
7500
|
lines.push(` play page: ${input.dashboardUrl}`);
|
|
7344
7501
|
}
|
|
@@ -7354,13 +7511,13 @@ function writeStartedPlayRun(input) {
|
|
|
7354
7511
|
` });
|
|
7355
7512
|
}
|
|
7356
7513
|
function parsePlayRunOptions(args) {
|
|
7357
|
-
const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--
|
|
7514
|
+
const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--<input> value]\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotency, tool call id, and ctx.map guidance.";
|
|
7358
7515
|
let filePath = null;
|
|
7359
7516
|
let playName = null;
|
|
7360
7517
|
let input = null;
|
|
7361
7518
|
let revisionId = null;
|
|
7362
7519
|
let revisionSelector = null;
|
|
7363
|
-
const watch = args.includes("--
|
|
7520
|
+
const watch = !args.includes("--no-wait");
|
|
7364
7521
|
let jsonOutput = watch ? args.includes("--json") : argsWantJson(args);
|
|
7365
7522
|
const emitLogs = !jsonOutput || args.includes("--logs");
|
|
7366
7523
|
const force = args.includes("--force");
|
|
@@ -7406,7 +7563,7 @@ function parsePlayRunOptions(args) {
|
|
|
7406
7563
|
waitTimeoutMs = parsePositiveInteger2(args[++index], arg);
|
|
7407
7564
|
continue;
|
|
7408
7565
|
}
|
|
7409
|
-
if (arg === "--json" || arg === "--wait" || arg === "--tail" || arg === "--watch" || arg === "--logs" || arg === "--force" || arg === "--no-open") {
|
|
7566
|
+
if (arg === "--json" || arg === "--wait" || arg === "--tail" || arg === "--watch" || arg === "--no-wait" || arg === "--logs" || arg === "--force" || arg === "--no-open") {
|
|
7410
7567
|
if (arg === "--watch") {
|
|
7411
7568
|
continue;
|
|
7412
7569
|
}
|
|
@@ -8262,6 +8419,12 @@ async function handlePlayGet(args) {
|
|
|
8262
8419
|
console.error("Usage: deepline play get <play-file.ts|play-name> [--json]");
|
|
8263
8420
|
return 1;
|
|
8264
8421
|
}
|
|
8422
|
+
if (looksLikeRunId(target)) {
|
|
8423
|
+
console.error(
|
|
8424
|
+
formatPlayCommandReceivedRunIdError({ command: "get", runId: target })
|
|
8425
|
+
);
|
|
8426
|
+
return 2;
|
|
8427
|
+
}
|
|
8265
8428
|
const client = new DeeplineClient();
|
|
8266
8429
|
const explicitJson = args.includes("--json");
|
|
8267
8430
|
const sourceOutput = args.includes("--source");
|
|
@@ -8376,8 +8539,20 @@ async function handlePlayVersions(args) {
|
|
|
8376
8539
|
}
|
|
8377
8540
|
async function handlePlayList(args) {
|
|
8378
8541
|
const jsonOutput = argsWantJson(args);
|
|
8542
|
+
const originArgIndex = args.findIndex((arg) => arg === "--origin");
|
|
8543
|
+
const rawOrigin = originArgIndex >= 0 ? args[originArgIndex + 1] : void 0;
|
|
8544
|
+
if (rawOrigin && rawOrigin !== "prebuilt" && rawOrigin !== "owned") {
|
|
8545
|
+
throw new Error(`Invalid value for --origin: ${rawOrigin}`);
|
|
8546
|
+
}
|
|
8547
|
+
const origin = rawOrigin;
|
|
8379
8548
|
const client = new DeeplineClient();
|
|
8380
|
-
const plays = await client.listPlays(
|
|
8549
|
+
const plays = (await client.listPlays({
|
|
8550
|
+
...origin ? { origin } : {}
|
|
8551
|
+
})).filter((play) => {
|
|
8552
|
+
if (!origin) return true;
|
|
8553
|
+
const isPrebuilt = play.origin === "prebuilt" || play.ownerType === "deepline";
|
|
8554
|
+
return origin === "prebuilt" ? isPrebuilt : !isPrebuilt;
|
|
8555
|
+
});
|
|
8381
8556
|
if (jsonOutput) {
|
|
8382
8557
|
process.stdout.write(`${JSON.stringify(plays)}
|
|
8383
8558
|
`);
|
|
@@ -8480,6 +8655,54 @@ function printPlayDescription(play) {
|
|
|
8480
8655
|
);
|
|
8481
8656
|
}
|
|
8482
8657
|
}
|
|
8658
|
+
function compactPlaySchema(schema) {
|
|
8659
|
+
if (!schema) return null;
|
|
8660
|
+
const fields = Array.isArray(schema.fields) ? schema.fields.map(
|
|
8661
|
+
(field) => field && typeof field === "object" ? {
|
|
8662
|
+
name: String(field.name ?? ""),
|
|
8663
|
+
type: field.type ?? void 0,
|
|
8664
|
+
required: field.required ?? void 0
|
|
8665
|
+
} : null
|
|
8666
|
+
).filter((field) => Boolean(field?.name)) : [];
|
|
8667
|
+
return fields.length > 0 ? { fields } : schema;
|
|
8668
|
+
}
|
|
8669
|
+
function playSchemaMetadata(schema, key) {
|
|
8670
|
+
if (!schema || typeof schema !== "object" || Array.isArray(schema)) return null;
|
|
8671
|
+
const value = schema[key];
|
|
8672
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
8673
|
+
}
|
|
8674
|
+
function playRunCommand(play, options) {
|
|
8675
|
+
const target = play.reference || play.name;
|
|
8676
|
+
if (options?.csvInput) {
|
|
8677
|
+
const inputField = typeof options.csvInput.inputField === "string" && options.csvInput.inputField.trim() ? options.csvInput.inputField.trim() : "csv";
|
|
8678
|
+
return `deepline plays run ${target} --input '${JSON.stringify({ [inputField]: "leads.csv" })}' --watch`;
|
|
8679
|
+
}
|
|
8680
|
+
return `deepline plays run ${target} --input '{...}' --watch`;
|
|
8681
|
+
}
|
|
8682
|
+
function summarizePlayListItemForCli(play, options) {
|
|
8683
|
+
const aliases = play.aliases?.length ? play.aliases : [play.name];
|
|
8684
|
+
const csvInput = playSchemaMetadata(play.inputSchema, "csvInput");
|
|
8685
|
+
const rowOutputSchema = playSchemaMetadata(play.outputSchema, "rowOutputSchema");
|
|
8686
|
+
const runCommand2 = playRunCommand(play, { csvInput });
|
|
8687
|
+
return {
|
|
8688
|
+
name: play.name,
|
|
8689
|
+
...play.reference ? { reference: play.reference } : {},
|
|
8690
|
+
...play.displayName ? { displayName: play.displayName } : {},
|
|
8691
|
+
origin: play.origin,
|
|
8692
|
+
ownerType: play.ownerType,
|
|
8693
|
+
canEdit: play.canEdit,
|
|
8694
|
+
canClone: play.canClone,
|
|
8695
|
+
aliases,
|
|
8696
|
+
inputSchema: options?.compact ? compactPlaySchema(play.inputSchema) : play.inputSchema ?? null,
|
|
8697
|
+
outputSchema: options?.compact ? compactPlaySchema(play.outputSchema) : play.outputSchema ?? null,
|
|
8698
|
+
...csvInput ? { csvInput } : {},
|
|
8699
|
+
...rowOutputSchema ? { rowOutputSchema } : {},
|
|
8700
|
+
runCommand: runCommand2,
|
|
8701
|
+
examples: [runCommand2],
|
|
8702
|
+
currentPublishedVersion: play.currentPublishedVersion ?? null,
|
|
8703
|
+
isDraftDirty: play.isDraftDirty
|
|
8704
|
+
};
|
|
8705
|
+
}
|
|
8483
8706
|
async function handlePlaySearch(args) {
|
|
8484
8707
|
let options;
|
|
8485
8708
|
try {
|
|
@@ -8501,6 +8724,100 @@ async function handlePlaySearch(args) {
|
|
|
8501
8724
|
}
|
|
8502
8725
|
process.stdout.write(`${plays.length} plays found:
|
|
8503
8726
|
|
|
8727
|
+
`);
|
|
8728
|
+
for (const play of plays) {
|
|
8729
|
+
printPlayDescription(play);
|
|
8730
|
+
console.log("");
|
|
8731
|
+
}
|
|
8732
|
+
return 0;
|
|
8733
|
+
}
|
|
8734
|
+
function normalizePlayGrepText(value) {
|
|
8735
|
+
if (value === null || value === void 0) return "";
|
|
8736
|
+
if (typeof value === "string") return value.toLowerCase();
|
|
8737
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
8738
|
+
return String(value).toLowerCase();
|
|
8739
|
+
}
|
|
8740
|
+
if (Array.isArray(value)) return value.map(normalizePlayGrepText).join(" ");
|
|
8741
|
+
if (typeof value === "object") {
|
|
8742
|
+
return Object.values(value).map(normalizePlayGrepText).join(" ");
|
|
8743
|
+
}
|
|
8744
|
+
return "";
|
|
8745
|
+
}
|
|
8746
|
+
function parsePlayGrepTerms(query, mode) {
|
|
8747
|
+
const trimmed = query.trim().toLowerCase();
|
|
8748
|
+
if (!trimmed) return [];
|
|
8749
|
+
if (mode === "phrase") return [trimmed];
|
|
8750
|
+
const matches = trimmed.match(/"([^"]+)"|'([^']+)'|\S+/g) ?? [];
|
|
8751
|
+
return matches.map((term) => term.replace(/^["']|["']$/g, "").trim()).filter(Boolean);
|
|
8752
|
+
}
|
|
8753
|
+
function matchesPlayGrepQuery(value, query, mode) {
|
|
8754
|
+
const terms = parsePlayGrepTerms(query, mode);
|
|
8755
|
+
if (terms.length === 0) return true;
|
|
8756
|
+
const haystack = normalizePlayGrepText(value);
|
|
8757
|
+
if (mode === "any") return terms.some((term) => haystack.includes(term));
|
|
8758
|
+
return terms.every((term) => haystack.includes(term));
|
|
8759
|
+
}
|
|
8760
|
+
async function handlePlayGrep(args) {
|
|
8761
|
+
const query = args[0]?.trim();
|
|
8762
|
+
if (!query) {
|
|
8763
|
+
console.error("Usage: deepline plays grep <query> [--origin prebuilt|owned] [--compact] [--json]");
|
|
8764
|
+
return 1;
|
|
8765
|
+
}
|
|
8766
|
+
let origin;
|
|
8767
|
+
let mode = "all";
|
|
8768
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
8769
|
+
const arg = args[index];
|
|
8770
|
+
if (arg === "--origin" && args[index + 1]) {
|
|
8771
|
+
const rawOrigin = args[++index].trim().toLowerCase();
|
|
8772
|
+
if (rawOrigin !== "prebuilt" && rawOrigin !== "owned") {
|
|
8773
|
+
throw new Error(`Invalid value for --origin: ${rawOrigin}`);
|
|
8774
|
+
}
|
|
8775
|
+
origin = rawOrigin;
|
|
8776
|
+
}
|
|
8777
|
+
if (arg === "--mode" && args[index + 1]) {
|
|
8778
|
+
const rawMode = args[++index].trim().toLowerCase();
|
|
8779
|
+
mode = rawMode === "any" || rawMode === "phrase" ? rawMode : "all";
|
|
8780
|
+
}
|
|
8781
|
+
}
|
|
8782
|
+
const compact = args.includes("--compact");
|
|
8783
|
+
const client = new DeeplineClient();
|
|
8784
|
+
const plays = (await client.listPlays({
|
|
8785
|
+
grep: query,
|
|
8786
|
+
grepMode: mode,
|
|
8787
|
+
...origin ? { origin } : {}
|
|
8788
|
+
})).filter((play) => {
|
|
8789
|
+
if (!origin) return true;
|
|
8790
|
+
const isPrebuilt = play.origin === "prebuilt" || play.ownerType === "deepline";
|
|
8791
|
+
return origin === "prebuilt" ? isPrebuilt : !isPrebuilt;
|
|
8792
|
+
}).filter(
|
|
8793
|
+
(play) => matchesPlayGrepQuery(
|
|
8794
|
+
{
|
|
8795
|
+
name: play.name,
|
|
8796
|
+
reference: play.reference,
|
|
8797
|
+
displayName: play.displayName,
|
|
8798
|
+
origin: play.origin,
|
|
8799
|
+
ownerType: play.ownerType,
|
|
8800
|
+
aliases: play.aliases,
|
|
8801
|
+
inputSchema: play.inputSchema,
|
|
8802
|
+
outputSchema: play.outputSchema
|
|
8803
|
+
},
|
|
8804
|
+
query,
|
|
8805
|
+
mode
|
|
8806
|
+
)
|
|
8807
|
+
).map((play) => summarizePlayListItemForCli(play, { compact }));
|
|
8808
|
+
if (argsWantJson(args)) {
|
|
8809
|
+
process.stdout.write(`${JSON.stringify({
|
|
8810
|
+
plays,
|
|
8811
|
+
count: plays.length,
|
|
8812
|
+
query,
|
|
8813
|
+
grep: { mode, terms: parsePlayGrepTerms(query, mode) },
|
|
8814
|
+
filters: { origin: origin ?? null }
|
|
8815
|
+
})}
|
|
8816
|
+
`);
|
|
8817
|
+
return 0;
|
|
8818
|
+
}
|
|
8819
|
+
process.stdout.write(`${plays.length} plays found:
|
|
8820
|
+
|
|
8504
8821
|
`);
|
|
8505
8822
|
for (const play of plays) {
|
|
8506
8823
|
printPlayDescription(play);
|
|
@@ -8516,6 +8833,15 @@ async function handlePlayDescribe(args) {
|
|
|
8516
8833
|
);
|
|
8517
8834
|
return 1;
|
|
8518
8835
|
}
|
|
8836
|
+
if (looksLikeRunId(playName)) {
|
|
8837
|
+
console.error(
|
|
8838
|
+
formatPlayCommandReceivedRunIdError({
|
|
8839
|
+
command: "describe",
|
|
8840
|
+
runId: playName
|
|
8841
|
+
})
|
|
8842
|
+
);
|
|
8843
|
+
return 2;
|
|
8844
|
+
}
|
|
8519
8845
|
const client = new DeeplineClient();
|
|
8520
8846
|
await assertCanonicalNamedPlayReference(client, playName);
|
|
8521
8847
|
const play = await client.describePlay(
|
|
@@ -8672,7 +8998,7 @@ Common commands:
|
|
|
8672
8998
|
deepline plays search email --json
|
|
8673
8999
|
deepline plays describe person-linkedin-to-email --json
|
|
8674
9000
|
deepline plays check my.play.ts
|
|
8675
|
-
deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
|
|
9001
|
+
deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
|
|
8676
9002
|
deepline plays set-live my.play.ts --json
|
|
8677
9003
|
deepline plays get person-linkedin-to-email --json
|
|
8678
9004
|
`
|
|
@@ -8703,8 +9029,10 @@ Notes:
|
|
|
8703
9029
|
Unknown --foo value and --foo.bar value flags are passed into play input.
|
|
8704
9030
|
Example: --limit 5 becomes input.limit = 5.
|
|
8705
9031
|
File args accept local paths; the CLI stages files before submit.
|
|
8706
|
-
|
|
8707
|
-
--wait
|
|
9032
|
+
By default, run waits for completion and prints logs, previews, stats, and
|
|
9033
|
+
next commands. --watch and --wait are accepted compatibility aliases for the
|
|
9034
|
+
default behavior. Use --no-wait only when you intentionally want
|
|
9035
|
+
a fire-and-forget run id.
|
|
8708
9036
|
The play page opens in your browser as soon as the run starts; use --no-open
|
|
8709
9037
|
to only print the URL.
|
|
8710
9038
|
--force supersedes active runs; it does not bypass completed reuse.
|
|
@@ -8732,17 +9060,18 @@ Idempotent execution:
|
|
|
8732
9060
|
.run({ key: 'domain', staleAfterSeconds: 86400 })
|
|
8733
9061
|
|
|
8734
9062
|
Examples:
|
|
8735
|
-
deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
|
|
8736
|
-
deepline plays run my.play.ts --input @input.json --
|
|
8737
|
-
deepline plays run person-linkedin-to-email --input '{"linkedin_url":"..."}'
|
|
8738
|
-
deepline plays run cto-search.play.ts --limit 5
|
|
9063
|
+
deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
|
|
9064
|
+
deepline plays run my.play.ts --input @input.json --json
|
|
9065
|
+
deepline plays run person-linkedin-to-email --input '{"linkedin_url":"..."}'
|
|
9066
|
+
deepline plays run cto-search.play.ts --limit 5
|
|
9067
|
+
deepline plays run long-background-play --no-wait
|
|
8739
9068
|
deepline runs export <run-id> --out output.csv
|
|
8740
9069
|
deepline runs get <run-id>
|
|
8741
9070
|
`
|
|
8742
9071
|
).option("--file <path>", "Local play file to run").option("--name <name>", "Saved play name to run").option("-i, --input <json>", "Input JSON object or @file path").option("--live", "Run the current live revision explicitly").option("--latest", "Run the newest saved revision, even if it is not live").option(
|
|
8743
9072
|
"--revision-id <id>",
|
|
8744
9073
|
"Run a specific saved revision instead of the live revision"
|
|
8745
|
-
).option("--watch", "
|
|
9074
|
+
).option("--watch", "Compatibility alias; run waits by default").option("--wait", "Compatibility alias; run waits by default").option("--no-wait", "Start the run and return immediately").option(
|
|
8746
9075
|
"--logs",
|
|
8747
9076
|
"When output is non-interactive, stream play logs to stderr while waiting"
|
|
8748
9077
|
).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Supersede any active runs for this play").option("--no-open", "Print the play page URL without opening a browser").option("--json", "Emit JSON output").addHelpText(
|
|
@@ -8775,6 +9104,7 @@ Pass-through input flags:
|
|
|
8775
9104
|
...options.live ? ["--live"] : [],
|
|
8776
9105
|
...options.latest ? ["--latest"] : [],
|
|
8777
9106
|
...options.revisionId ? ["--revision-id", options.revisionId] : [],
|
|
9107
|
+
...options.wait === false ? ["--no-wait"] : [],
|
|
8778
9108
|
...options.watch || options.wait ? ["--watch"] : [],
|
|
8779
9109
|
...options.logs ? ["--logs"] : [],
|
|
8780
9110
|
...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
|
|
@@ -8815,24 +9145,27 @@ Notes:
|
|
|
8815
9145
|
|
|
8816
9146
|
Examples:
|
|
8817
9147
|
deepline plays list
|
|
8818
|
-
deepline plays list --json
|
|
9148
|
+
deepline plays list --origin prebuilt --json
|
|
8819
9149
|
deepline plays search email --origin prebuilt --json
|
|
8820
9150
|
`
|
|
8821
|
-
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
9151
|
+
).option("--origin <origin>", "Filter to prebuilt or owned plays").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
8822
9152
|
process.exitCode = await handlePlayList([
|
|
9153
|
+
...options.origin ? ["--origin", options.origin] : [],
|
|
8823
9154
|
...options.json ? ["--json"] : []
|
|
8824
9155
|
]);
|
|
8825
9156
|
});
|
|
8826
|
-
|
|
9157
|
+
const addPlaySearchCommand = (command) => command.description("Search saved and prebuilt plays.").addHelpText(
|
|
8827
9158
|
"after",
|
|
8828
9159
|
`
|
|
8829
9160
|
Notes:
|
|
8830
9161
|
Ranked discovery for workflows. Use --origin prebuilt or --origin owned when
|
|
8831
9162
|
you need to narrow results. Use describe on a result before running it.
|
|
9163
|
+
The grep alias is the same ranked retrieval surface with a more literal name
|
|
9164
|
+
for agents that are filtering the play registry.
|
|
8832
9165
|
|
|
8833
9166
|
Examples:
|
|
8834
9167
|
deepline plays search email
|
|
8835
|
-
deepline plays
|
|
9168
|
+
deepline plays grep "linkedin to email" --origin prebuilt --compact --json
|
|
8836
9169
|
deepline plays describe person-linkedin-to-email --json
|
|
8837
9170
|
`
|
|
8838
9171
|
).option("--origin <origin>", "Filter to prebuilt or owned plays").option("--compact", "Emit compact schemas").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
|
|
@@ -8843,6 +9176,30 @@ Examples:
|
|
|
8843
9176
|
...options.json ? ["--json"] : []
|
|
8844
9177
|
]);
|
|
8845
9178
|
});
|
|
9179
|
+
addPlaySearchCommand(play.command("search <query>"));
|
|
9180
|
+
play.command("grep <query>").description("Literal grep over play names, aliases, schemas, and descriptions.").addHelpText(
|
|
9181
|
+
"after",
|
|
9182
|
+
`
|
|
9183
|
+
Notes:
|
|
9184
|
+
Literal registry filtering. Terms are matched case-insensitively against play
|
|
9185
|
+
names, references, display names, aliases, ownership, and schemas. Use
|
|
9186
|
+
--mode phrase for exact phrase matching, --mode any for OR, and the default
|
|
9187
|
+
--mode all for AND.
|
|
9188
|
+
|
|
9189
|
+
Examples:
|
|
9190
|
+
deepline plays grep email --origin prebuilt --json
|
|
9191
|
+
deepline plays grep "company contact" --origin prebuilt --mode all --json
|
|
9192
|
+
deepline plays describe prebuilt/company-to-contact --json
|
|
9193
|
+
`
|
|
9194
|
+
).option("--origin <origin>", "Filter to prebuilt or owned plays").option("--compact", "Emit compact schemas").option("--mode <mode>", "Grep matching mode: all, any, or phrase").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
|
|
9195
|
+
process.exitCode = await handlePlayGrep([
|
|
9196
|
+
query,
|
|
9197
|
+
...options.origin ? ["--origin", options.origin] : [],
|
|
9198
|
+
...options.compact ? ["--compact"] : [],
|
|
9199
|
+
...options.mode ? ["--mode", options.mode] : [],
|
|
9200
|
+
...options.json ? ["--json"] : []
|
|
9201
|
+
]);
|
|
9202
|
+
});
|
|
8846
9203
|
play.command("describe <target>").description("Describe a play contract and how to run it.").addHelpText(
|
|
8847
9204
|
"after",
|
|
8848
9205
|
`
|
|
@@ -8871,7 +9228,7 @@ Notes:
|
|
|
8871
9228
|
Examples:
|
|
8872
9229
|
deepline plays versions --name my-play
|
|
8873
9230
|
deepline plays versions --name my-play --json
|
|
8874
|
-
deepline plays run my-play --revision-id <revision-id>
|
|
9231
|
+
deepline plays run my-play --revision-id <revision-id>
|
|
8875
9232
|
`
|
|
8876
9233
|
).option("--name <name>", "Saved play name").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
8877
9234
|
process.exitCode = await handlePlayVersions([
|
|
@@ -9073,6 +9430,7 @@ Examples:
|
|
|
9073
9430
|
}
|
|
9074
9431
|
|
|
9075
9432
|
// src/cli/commands/tools.ts
|
|
9433
|
+
var import_commander2 = require("commander");
|
|
9076
9434
|
var import_node_fs10 = require("fs");
|
|
9077
9435
|
var import_node_os7 = require("os");
|
|
9078
9436
|
var import_node_path12 = require("path");
|
|
@@ -9257,9 +9615,42 @@ function toListedTool(tool) {
|
|
|
9257
9615
|
executeCommand: `deepline tools execute ${tool.toolId}`
|
|
9258
9616
|
};
|
|
9259
9617
|
}
|
|
9618
|
+
function normalizeGrepText(value) {
|
|
9619
|
+
if (value === null || value === void 0) return "";
|
|
9620
|
+
if (typeof value === "string") return value.toLowerCase();
|
|
9621
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
9622
|
+
return String(value).toLowerCase();
|
|
9623
|
+
}
|
|
9624
|
+
if (Array.isArray(value)) return value.map(normalizeGrepText).join(" ");
|
|
9625
|
+
if (typeof value === "object") {
|
|
9626
|
+
return Object.values(value).map(normalizeGrepText).join(" ");
|
|
9627
|
+
}
|
|
9628
|
+
return "";
|
|
9629
|
+
}
|
|
9630
|
+
function parseGrepTerms(query, mode) {
|
|
9631
|
+
const trimmed = query.trim().toLowerCase();
|
|
9632
|
+
if (!trimmed) return [];
|
|
9633
|
+
if (mode === "phrase") return [trimmed];
|
|
9634
|
+
const matches = trimmed.match(/"([^"]+)"|'([^']+)'|\S+/g) ?? [];
|
|
9635
|
+
return matches.map((term) => term.replace(/^["']|["']$/g, "").trim()).filter(Boolean);
|
|
9636
|
+
}
|
|
9637
|
+
function matchesGrepQuery(value, query, mode) {
|
|
9638
|
+
const terms = parseGrepTerms(query, mode);
|
|
9639
|
+
if (terms.length === 0) return true;
|
|
9640
|
+
const haystack = normalizeGrepText(value);
|
|
9641
|
+
if (mode === "any") return terms.some((term) => haystack.includes(term));
|
|
9642
|
+
return terms.every((term) => haystack.includes(term));
|
|
9643
|
+
}
|
|
9260
9644
|
async function listTools(args) {
|
|
9261
9645
|
const client = new DeeplineClient();
|
|
9262
|
-
const
|
|
9646
|
+
const categoryArgIndex = args.findIndex((arg) => arg === "--categories");
|
|
9647
|
+
const categoryFilter = categoryArgIndex >= 0 ? args[categoryArgIndex + 1] : "";
|
|
9648
|
+
const requestedCategories = categoryFilter ? categoryFilter.split(",").map((item) => item.trim()).filter(Boolean) : [];
|
|
9649
|
+
const items = (await client.listTools({
|
|
9650
|
+
...categoryFilter ? { categories: categoryFilter } : {}
|
|
9651
|
+
})).map(toListedTool).filter(
|
|
9652
|
+
(item) => requestedCategories.length === 0 || requestedCategories.some((category) => item.categories.includes(category))
|
|
9653
|
+
);
|
|
9263
9654
|
const render = {
|
|
9264
9655
|
sections: [
|
|
9265
9656
|
{
|
|
@@ -9282,6 +9673,9 @@ async function listTools(args) {
|
|
|
9282
9673
|
{
|
|
9283
9674
|
tools: items,
|
|
9284
9675
|
count: items.length,
|
|
9676
|
+
filters: {
|
|
9677
|
+
categories: requestedCategories
|
|
9678
|
+
},
|
|
9285
9679
|
commandTemplates: TOOL_COMMAND_TEMPLATES,
|
|
9286
9680
|
render
|
|
9287
9681
|
},
|
|
@@ -9308,6 +9702,56 @@ async function searchTools(queryInput, options = {}) {
|
|
|
9308
9702
|
});
|
|
9309
9703
|
return 0;
|
|
9310
9704
|
}
|
|
9705
|
+
async function grepTools(queryInput, options = {}) {
|
|
9706
|
+
const query = queryInput.trim();
|
|
9707
|
+
if (!query) {
|
|
9708
|
+
console.error("Usage: deepline tools grep <query> [--json]");
|
|
9709
|
+
return 1;
|
|
9710
|
+
}
|
|
9711
|
+
const client = new DeeplineClient();
|
|
9712
|
+
const requestedCategories = options.categories ? options.categories.split(",").map((item) => item.trim()).filter(Boolean) : [];
|
|
9713
|
+
const mode = options.mode ?? "all";
|
|
9714
|
+
const tools = (await client.listTools({
|
|
9715
|
+
grep: query,
|
|
9716
|
+
grepMode: mode,
|
|
9717
|
+
...options.categories ? { categories: options.categories } : {}
|
|
9718
|
+
})).map(toListedTool).filter(
|
|
9719
|
+
(item) => requestedCategories.length === 0 || requestedCategories.some((category) => item.categories.includes(category))
|
|
9720
|
+
).filter(
|
|
9721
|
+
(item) => matchesGrepQuery(
|
|
9722
|
+
{
|
|
9723
|
+
id: item.toolId,
|
|
9724
|
+
toolId: item.toolId,
|
|
9725
|
+
provider: item.provider,
|
|
9726
|
+
displayName: item.displayName,
|
|
9727
|
+
description: item.description,
|
|
9728
|
+
categories: item.categories,
|
|
9729
|
+
operation: item.operation,
|
|
9730
|
+
operationAliases: item.operationAliases,
|
|
9731
|
+
inputFields: item.inputFields
|
|
9732
|
+
},
|
|
9733
|
+
query,
|
|
9734
|
+
mode
|
|
9735
|
+
)
|
|
9736
|
+
);
|
|
9737
|
+
printCommandEnvelope(
|
|
9738
|
+
{
|
|
9739
|
+
tools,
|
|
9740
|
+
count: tools.length,
|
|
9741
|
+
query,
|
|
9742
|
+
grep: {
|
|
9743
|
+
mode,
|
|
9744
|
+
terms: parseGrepTerms(query, mode)
|
|
9745
|
+
},
|
|
9746
|
+
filters: {
|
|
9747
|
+
categories: requestedCategories
|
|
9748
|
+
},
|
|
9749
|
+
commandTemplates: TOOL_COMMAND_TEMPLATES
|
|
9750
|
+
},
|
|
9751
|
+
{ json: options.json || shouldEmitJson() }
|
|
9752
|
+
);
|
|
9753
|
+
return 0;
|
|
9754
|
+
}
|
|
9311
9755
|
function playIdentifiers(play) {
|
|
9312
9756
|
return [play.name, play.reference, ...play.aliases ?? []].filter((value) => Boolean(value?.trim())).map((value) => value.trim());
|
|
9313
9757
|
}
|
|
@@ -9377,24 +9821,27 @@ Notes:
|
|
|
9377
9821
|
|
|
9378
9822
|
Examples:
|
|
9379
9823
|
deepline tools list
|
|
9380
|
-
deepline tools list --json
|
|
9824
|
+
deepline tools list --categories email_finder --json
|
|
9381
9825
|
deepline tools search email --json
|
|
9382
9826
|
`
|
|
9383
|
-
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
9827
|
+
).option("--categories <categories>", "Comma-separated categories to filter inventory").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
9384
9828
|
process.exitCode = await listTools([
|
|
9829
|
+
...options.categories ? ["--categories", options.categories] : [],
|
|
9385
9830
|
...options.json ? ["--json"] : []
|
|
9386
9831
|
]);
|
|
9387
9832
|
});
|
|
9388
|
-
|
|
9833
|
+
const addToolSearchCommand = (command) => command.description("Search available tools.").addHelpText(
|
|
9389
9834
|
"after",
|
|
9390
9835
|
`
|
|
9391
9836
|
Notes:
|
|
9392
9837
|
Ranked discovery for atomic provider/API operations. Results include tool ids
|
|
9393
9838
|
that can be passed to deepline tools describe or deepline tools execute.
|
|
9839
|
+
The grep alias is the same ranked retrieval surface with a more literal name
|
|
9840
|
+
for agents that are filtering a registry rather than choosing a workflow.
|
|
9394
9841
|
|
|
9395
9842
|
Examples:
|
|
9396
9843
|
deepline tools search email
|
|
9397
|
-
deepline tools
|
|
9844
|
+
deepline tools grep "company enrichment" --categories enrichment --json
|
|
9398
9845
|
deepline tools search verifier --search-mode v2 --json
|
|
9399
9846
|
`
|
|
9400
9847
|
).option("--categories <categories>", "Comma-separated categories to filter ranked search").option("--search_terms <terms>", "Structured search terms for ranked search").option("--search-terms <terms>", "Structured search terms for ranked search").option("--search-mode <mode>", "Ranked search mode: v1 or v2").option("--include-search-debug", "Include ranked search debug metadata").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
|
|
@@ -9406,24 +9853,55 @@ Examples:
|
|
|
9406
9853
|
includeSearchDebug: Boolean(options.includeSearchDebug)
|
|
9407
9854
|
});
|
|
9408
9855
|
});
|
|
9856
|
+
addToolSearchCommand(tools.command("search <query>"));
|
|
9857
|
+
tools.command("grep <query>").description("Literal grep over tool ids, descriptions, categories, and input fields.").addHelpText(
|
|
9858
|
+
"after",
|
|
9859
|
+
`
|
|
9860
|
+
Notes:
|
|
9861
|
+
Literal registry filtering. Terms are matched case-insensitively against tool
|
|
9862
|
+
ids, provider, display name, description, categories, aliases, and input
|
|
9863
|
+
fields. Use --mode phrase for exact phrase matching, --mode any for OR, and
|
|
9864
|
+
the default --mode all for AND.
|
|
9865
|
+
|
|
9866
|
+
Examples:
|
|
9867
|
+
deepline tools grep email --categories email_finder --json
|
|
9868
|
+
deepline tools grep "phone validate" --mode all --json
|
|
9869
|
+
deepline tools grep hunter --mode phrase --json
|
|
9870
|
+
`
|
|
9871
|
+
).option("--categories <categories>", "Comma-separated categories to filter inventory").option("--mode <mode>", "Grep matching mode: all, any, or phrase").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
|
|
9872
|
+
const mode = options.mode === "any" || options.mode === "phrase" ? options.mode : "all";
|
|
9873
|
+
process.exitCode = await grepTools(query, {
|
|
9874
|
+
json: options.json,
|
|
9875
|
+
categories: options.categories,
|
|
9876
|
+
mode
|
|
9877
|
+
});
|
|
9878
|
+
});
|
|
9409
9879
|
const addToolMetadataCommand = (command) => command.description("Show metadata for a tool.").addHelpText(
|
|
9410
9880
|
"after",
|
|
9411
9881
|
`
|
|
9412
9882
|
Notes:
|
|
9413
|
-
Shows the
|
|
9414
|
-
|
|
9415
|
-
|
|
9883
|
+
Shows the compact agent contract by default: what the tool does, cost,
|
|
9884
|
+
required inputs, play getters, and a runnable ctx.tools.execute snippet.
|
|
9885
|
+
Use --json for the full metadata/debug payload.
|
|
9416
9886
|
|
|
9417
9887
|
Examples:
|
|
9418
9888
|
deepline tools describe hunter_email_verifier
|
|
9419
|
-
deepline tools describe hunter_email_verifier --
|
|
9889
|
+
deepline tools describe hunter_email_verifier --pricing-only
|
|
9890
|
+
deepline tools describe hunter_email_verifier --schema-only
|
|
9891
|
+
deepline tools describe hunter_email_verifier --examples-only
|
|
9892
|
+
deepline tools describe hunter_email_verifier --json
|
|
9420
9893
|
deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
|
|
9421
9894
|
`
|
|
9422
|
-
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (toolId, options) => {
|
|
9423
|
-
process.exitCode = await getTool(
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9895
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--pricing-only", "Only print pricing and billing semantics").option("--schema-only", "Only print input schema fields").option("--examples-only", "Only print runnable examples and sample payloads").option("--getters-only", "Only print extracted list/value getters").addOption(new import_commander2.Option("--compact", "Compatibility alias for the default compact view").hideHelp()).addOption(new import_commander2.Option("--contract-json", "Compatibility alias for compact contract JSON").hideHelp()).action(async (toolId, options) => {
|
|
9896
|
+
process.exitCode = await getTool(toolId, {
|
|
9897
|
+
json: Boolean(options.json),
|
|
9898
|
+
compact: Boolean(options.compact),
|
|
9899
|
+
contractJson: Boolean(options.contractJson),
|
|
9900
|
+
pricingOnly: Boolean(options.pricingOnly),
|
|
9901
|
+
schemaOnly: Boolean(options.schemaOnly),
|
|
9902
|
+
examplesOnly: Boolean(options.examplesOnly),
|
|
9903
|
+
gettersOnly: Boolean(options.gettersOnly)
|
|
9904
|
+
});
|
|
9427
9905
|
});
|
|
9428
9906
|
addToolMetadataCommand(tools.command("describe <toolId>"));
|
|
9429
9907
|
tools.command("get <toolId>").description("Deprecated. Use tools describe.").addHelpText(
|
|
@@ -9476,8 +9954,7 @@ Examples:
|
|
|
9476
9954
|
process.exitCode = await executeTool(args);
|
|
9477
9955
|
});
|
|
9478
9956
|
}
|
|
9479
|
-
async function getTool(
|
|
9480
|
-
const toolId = args[0];
|
|
9957
|
+
async function getTool(toolId, options = {}) {
|
|
9481
9958
|
if (!toolId) {
|
|
9482
9959
|
console.error("Usage: deepline tools get <toolId> [--json]");
|
|
9483
9960
|
return 1;
|
|
@@ -9494,14 +9971,264 @@ async function getTool(args) {
|
|
|
9494
9971
|
}
|
|
9495
9972
|
throw error;
|
|
9496
9973
|
}
|
|
9497
|
-
if (
|
|
9974
|
+
if (options.contractJson) {
|
|
9975
|
+
process.stdout.write(`${JSON.stringify(toolContractJsonForDescribe(tool, toolId))}
|
|
9976
|
+
`);
|
|
9977
|
+
return 0;
|
|
9978
|
+
}
|
|
9979
|
+
const emitJson = options.json === true;
|
|
9980
|
+
if (emitJson) {
|
|
9498
9981
|
process.stdout.write(`${JSON.stringify(toolMetadataJsonForDescribe(tool, toolId))}
|
|
9499
9982
|
`);
|
|
9500
9983
|
return 0;
|
|
9501
9984
|
}
|
|
9502
|
-
|
|
9985
|
+
const onlyModes = [
|
|
9986
|
+
options.pricingOnly,
|
|
9987
|
+
options.schemaOnly,
|
|
9988
|
+
options.examplesOnly,
|
|
9989
|
+
options.gettersOnly
|
|
9990
|
+
].filter(Boolean).length;
|
|
9991
|
+
if (onlyModes > 1) {
|
|
9992
|
+
console.error("Use only one of --pricing-only, --schema-only, --examples-only, or --getters-only.");
|
|
9993
|
+
return 2;
|
|
9994
|
+
}
|
|
9995
|
+
if (options.pricingOnly) {
|
|
9996
|
+
printToolPricingOnly(tool, toolId);
|
|
9997
|
+
return 0;
|
|
9998
|
+
}
|
|
9999
|
+
if (options.schemaOnly) {
|
|
10000
|
+
printToolSchemaOnly(tool, toolId);
|
|
10001
|
+
return 0;
|
|
10002
|
+
}
|
|
10003
|
+
if (options.examplesOnly) {
|
|
10004
|
+
printToolExamplesOnly(tool, toolId);
|
|
10005
|
+
return 0;
|
|
10006
|
+
}
|
|
10007
|
+
if (options.gettersOnly) {
|
|
10008
|
+
printToolGettersOnly(tool, toolId);
|
|
10009
|
+
return 0;
|
|
10010
|
+
}
|
|
10011
|
+
if (options.compact) {
|
|
10012
|
+
printCompactToolContract(tool, toolId);
|
|
10013
|
+
return 0;
|
|
10014
|
+
}
|
|
10015
|
+
if (shouldEmitJson()) {
|
|
10016
|
+
process.stdout.write(`${JSON.stringify(toolMetadataJsonForDescribe(tool, toolId))}
|
|
10017
|
+
`);
|
|
10018
|
+
return 0;
|
|
10019
|
+
}
|
|
10020
|
+
printCompactToolContract(tool, toolId);
|
|
9503
10021
|
return 0;
|
|
9504
10022
|
}
|
|
10023
|
+
function toolContractJsonForDescribe(tool, requestedToolId) {
|
|
10024
|
+
const toolId = String(tool.toolId || requestedToolId);
|
|
10025
|
+
const inputFields = toolInputFieldsForDisplay(recordField(tool, "inputSchema", "input_schema"));
|
|
10026
|
+
const usageGuidance = recordField(tool, "usageGuidance", "usage_guidance");
|
|
10027
|
+
const toolExecutionResult = recordField(usageGuidance, "toolExecutionResult", "tool_execution_result");
|
|
10028
|
+
const extractedLists = extractionContractEntries(
|
|
10029
|
+
arrayField(toolExecutionResult, "extractedLists", "extracted_lists")
|
|
10030
|
+
);
|
|
10031
|
+
const extractedValues = extractionContractEntries(
|
|
10032
|
+
arrayField(toolExecutionResult, "extractedValues", "extracted_values")
|
|
10033
|
+
);
|
|
10034
|
+
const cost = recordField(tool, "cost");
|
|
10035
|
+
const deeplineCredits = numberField(tool, "deeplineCreditsPerPricingUnit", "deepline_credits_per_pricing_unit");
|
|
10036
|
+
const deeplineUsdPerPricingUnit = numberField(tool, "deeplineUsdPerPricingUnit", "deepline_usd_per_pricing_unit");
|
|
10037
|
+
return {
|
|
10038
|
+
schemaVersion: 1,
|
|
10039
|
+
toolId,
|
|
10040
|
+
provider: tool.provider,
|
|
10041
|
+
displayName: tool.displayName,
|
|
10042
|
+
description: tool.description,
|
|
10043
|
+
categories: tool.categories,
|
|
10044
|
+
inputFields: inputFields.map((field) => ({
|
|
10045
|
+
name: field.name,
|
|
10046
|
+
type: field.type ?? "unknown",
|
|
10047
|
+
required: Boolean(field.required),
|
|
10048
|
+
...field.description ? { description: field.description } : {},
|
|
10049
|
+
...Object.prototype.hasOwnProperty.call(field, "default") ? { default: field.default } : {}
|
|
10050
|
+
})),
|
|
10051
|
+
cost: {
|
|
10052
|
+
pricingModel: stringField(cost, "pricingModel", "pricing_model") || null,
|
|
10053
|
+
billingMode: stringField(cost, "billingMode", "billing_mode") || null,
|
|
10054
|
+
deeplineCreditsPerPricingUnit: deeplineCredits,
|
|
10055
|
+
deeplineUsdPerPricingUnit
|
|
10056
|
+
},
|
|
10057
|
+
getters: {
|
|
10058
|
+
extractedLists,
|
|
10059
|
+
extractedValues
|
|
10060
|
+
},
|
|
10061
|
+
executeCommand: `deepline tools execute ${toolId} --input '{...}' --json`
|
|
10062
|
+
};
|
|
10063
|
+
}
|
|
10064
|
+
function extractionContractEntries(entries) {
|
|
10065
|
+
return entries.flatMap((entry) => {
|
|
10066
|
+
if (!isRecord4(entry)) return [];
|
|
10067
|
+
const name = stringField(entry, "name");
|
|
10068
|
+
const expression = stringField(entry, "expression");
|
|
10069
|
+
return name && expression ? [{ name, expression }] : [];
|
|
10070
|
+
});
|
|
10071
|
+
}
|
|
10072
|
+
function printCompactToolContract(tool, requestedToolId) {
|
|
10073
|
+
const contract = toolContractJsonForDescribe(tool, requestedToolId);
|
|
10074
|
+
const cost = isRecord4(contract.cost) ? contract.cost : {};
|
|
10075
|
+
const getters = isRecord4(contract.getters) ? contract.getters : {};
|
|
10076
|
+
const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
|
|
10077
|
+
const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
|
|
10078
|
+
const inputFields = Array.isArray(contract.inputFields) ? contract.inputFields : [];
|
|
10079
|
+
console.log(String(contract.toolId));
|
|
10080
|
+
if (contract.displayName) console.log(`Best for: ${contract.displayName}`);
|
|
10081
|
+
if (typeof contract.description === "string" && contract.description.trim()) {
|
|
10082
|
+
console.log(`Description: ${contract.description.trim()}`);
|
|
10083
|
+
}
|
|
10084
|
+
if (Array.isArray(contract.categories) && contract.categories.length) {
|
|
10085
|
+
console.log(`Tags: ${contract.categories.join(", ")}`);
|
|
10086
|
+
}
|
|
10087
|
+
printToolPricingOnly(tool, requestedToolId, { heading: "Cost" });
|
|
10088
|
+
if (inputFields.length) {
|
|
10089
|
+
console.log("");
|
|
10090
|
+
console.log("Inputs:");
|
|
10091
|
+
for (const field of inputFields) {
|
|
10092
|
+
if (!isRecord4(field)) continue;
|
|
10093
|
+
const name = stringField(field, "name");
|
|
10094
|
+
if (!name) continue;
|
|
10095
|
+
const required = field.required ? "*" : "";
|
|
10096
|
+
const type = stringField(field, "type") || "unknown";
|
|
10097
|
+
const description = stringField(field, "description");
|
|
10098
|
+
console.log(`- ${name}${required}: ${type}${description ? ` - ${description}` : ""}`);
|
|
10099
|
+
}
|
|
10100
|
+
}
|
|
10101
|
+
console.log("");
|
|
10102
|
+
printToolExamplesOnly(tool, requestedToolId, { includeSamples: false });
|
|
10103
|
+
if (listGetters.length || valueGetters.length) {
|
|
10104
|
+
console.log("");
|
|
10105
|
+
console.log("Getters:");
|
|
10106
|
+
if (listGetters.length) console.log("Lists:");
|
|
10107
|
+
for (const entry of listGetters) {
|
|
10108
|
+
if (isRecord4(entry)) console.log(`- ${stringField(entry, "name")}: ${playResultExpression(entry)}`);
|
|
10109
|
+
}
|
|
10110
|
+
if (valueGetters.length) console.log("Values:");
|
|
10111
|
+
for (const entry of valueGetters) {
|
|
10112
|
+
if (isRecord4(entry)) console.log(`- ${stringField(entry, "name")}: ${playResultExpression(entry)}`);
|
|
10113
|
+
}
|
|
10114
|
+
}
|
|
10115
|
+
console.log("");
|
|
10116
|
+
console.log(`More: deepline tools describe ${contract.toolId} --pricing-only | --schema-only | --examples-only | --getters-only | --json`);
|
|
10117
|
+
}
|
|
10118
|
+
function printToolPricingOnly(tool, requestedToolId, options = {}) {
|
|
10119
|
+
const contract = toolContractJsonForDescribe(tool, requestedToolId);
|
|
10120
|
+
const cost = isRecord4(contract.cost) ? contract.cost : {};
|
|
10121
|
+
const pricingModel = stringField(cost, "pricingModel") || "unknown";
|
|
10122
|
+
const billingMode = stringField(cost, "billingMode") || "unknown";
|
|
10123
|
+
const unit = pricingModel === "per_page" ? "page" : pricingModel === "per_result" ? "result" : pricingModel === "fixed" ? "call" : pricingModel.replace(/^per_/, "") || "unit";
|
|
10124
|
+
const credits = numberField(cost, "deeplineCreditsPerPricingUnit");
|
|
10125
|
+
const usd = numberField(cost, "deeplineUsdPerPricingUnit");
|
|
10126
|
+
const price = credits !== null ? `${formatDecimal(credits)} Deepline credits${usd !== null ? ` / ${formatUsd(usd)}` : ""} per ${unit}` : "pricing unavailable";
|
|
10127
|
+
console.log(`${options.heading ?? `Pricing: ${contract.toolId}`}: ${price}`);
|
|
10128
|
+
console.log(`Billing: ${billingMode}`);
|
|
10129
|
+
}
|
|
10130
|
+
function printToolSchemaOnly(tool, requestedToolId) {
|
|
10131
|
+
const contract = toolContractJsonForDescribe(tool, requestedToolId);
|
|
10132
|
+
const inputFields = Array.isArray(contract.inputFields) ? contract.inputFields : [];
|
|
10133
|
+
console.log(`Schema: ${contract.toolId}`);
|
|
10134
|
+
if (!inputFields.length) {
|
|
10135
|
+
console.log("Inputs: none");
|
|
10136
|
+
return;
|
|
10137
|
+
}
|
|
10138
|
+
console.log("Inputs:");
|
|
10139
|
+
for (const field of inputFields) {
|
|
10140
|
+
if (!isRecord4(field)) continue;
|
|
10141
|
+
const name = stringField(field, "name");
|
|
10142
|
+
if (!name) continue;
|
|
10143
|
+
const required = field.required ? "*" : "";
|
|
10144
|
+
const type = stringField(field, "type") || "unknown";
|
|
10145
|
+
const description = stringField(field, "description");
|
|
10146
|
+
const defaultSuffix = Object.prototype.hasOwnProperty.call(field, "default") ? ` default=${JSON.stringify(field.default)}` : "";
|
|
10147
|
+
console.log(`- ${name}${required}: ${type}${defaultSuffix}${description ? ` - ${description}` : ""}`);
|
|
10148
|
+
}
|
|
10149
|
+
}
|
|
10150
|
+
function printToolExamplesOnly(tool, requestedToolId, options = {}) {
|
|
10151
|
+
const contract = toolContractJsonForDescribe(tool, requestedToolId);
|
|
10152
|
+
const toolId = String(contract.toolId);
|
|
10153
|
+
const inputFields = Array.isArray(contract.inputFields) ? contract.inputFields : [];
|
|
10154
|
+
const sampleInput = Object.fromEntries(
|
|
10155
|
+
inputFields.slice(0, 4).flatMap((field) => {
|
|
10156
|
+
if (!isRecord4(field)) return [];
|
|
10157
|
+
const name = stringField(field, "name");
|
|
10158
|
+
if (!name) return [];
|
|
10159
|
+
return [[name, sampleValueForField(field)]];
|
|
10160
|
+
})
|
|
10161
|
+
);
|
|
10162
|
+
console.log(`Use in a play:`);
|
|
10163
|
+
console.log("```ts");
|
|
10164
|
+
console.log("const result = await ctx.tools.execute({");
|
|
10165
|
+
console.log(` id: '${stableStepIdForTool(toolId)}',`);
|
|
10166
|
+
console.log(` tool: '${toolId}',`);
|
|
10167
|
+
console.log(` input: ${JSON.stringify(sampleInput || {}, null, 2).replace(/\n/g, "\n ")},`);
|
|
10168
|
+
console.log("});");
|
|
10169
|
+
const getters = isRecord4(contract.getters) ? contract.getters : {};
|
|
10170
|
+
const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
|
|
10171
|
+
const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
|
|
10172
|
+
const firstGetter = [...valueGetters, ...listGetters].find(isRecord4);
|
|
10173
|
+
if (firstGetter) {
|
|
10174
|
+
const name = stringField(firstGetter, "name") || "value";
|
|
10175
|
+
const expression = stringField(firstGetter, "expression");
|
|
10176
|
+
if (expression) console.log(`const ${safeIdentifier(name)} = ${expression.replace(/^toolExecutionResult\./, "result.")};`);
|
|
10177
|
+
}
|
|
10178
|
+
console.log("```");
|
|
10179
|
+
if (options.includeSamples !== false) {
|
|
10180
|
+
const samples = recordField(tool, "samples");
|
|
10181
|
+
printSamples(samples);
|
|
10182
|
+
}
|
|
10183
|
+
}
|
|
10184
|
+
function printToolGettersOnly(tool, requestedToolId) {
|
|
10185
|
+
const contract = toolContractJsonForDescribe(tool, requestedToolId);
|
|
10186
|
+
const getters = isRecord4(contract.getters) ? contract.getters : {};
|
|
10187
|
+
const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
|
|
10188
|
+
const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
|
|
10189
|
+
console.log(`Getters: ${contract.toolId}`);
|
|
10190
|
+
if (!listGetters.length && !valueGetters.length) {
|
|
10191
|
+
console.log("No generated getters declared. Use --json only if you need raw metadata.");
|
|
10192
|
+
return;
|
|
10193
|
+
}
|
|
10194
|
+
if (listGetters.length) {
|
|
10195
|
+
console.log("Lists:");
|
|
10196
|
+
for (const entry of listGetters) {
|
|
10197
|
+
if (isRecord4(entry)) console.log(`- ${stringField(entry, "name")}: ${playResultExpression(entry)}`);
|
|
10198
|
+
}
|
|
10199
|
+
}
|
|
10200
|
+
if (valueGetters.length) {
|
|
10201
|
+
console.log("Values:");
|
|
10202
|
+
for (const entry of valueGetters) {
|
|
10203
|
+
if (isRecord4(entry)) console.log(`- ${stringField(entry, "name")}: ${playResultExpression(entry)}`);
|
|
10204
|
+
}
|
|
10205
|
+
}
|
|
10206
|
+
}
|
|
10207
|
+
function sampleValueForField(field) {
|
|
10208
|
+
const name = stringField(field, "name").toLowerCase();
|
|
10209
|
+
const type = stringField(field, "type").toLowerCase();
|
|
10210
|
+
if (Object.prototype.hasOwnProperty.call(field, "default")) return field.default;
|
|
10211
|
+
if (name.includes("email")) return "ada@example.com";
|
|
10212
|
+
if (name.includes("domain") || name.includes("website")) return "example.com";
|
|
10213
|
+
if (name.includes("first")) return "Ada";
|
|
10214
|
+
if (name.includes("last")) return "Lovelace";
|
|
10215
|
+
if (name.includes("name")) return "Ada Lovelace";
|
|
10216
|
+
if (type === "integer" || type === "number") return 1;
|
|
10217
|
+
if (type === "boolean") return true;
|
|
10218
|
+
if (type === "array") return [];
|
|
10219
|
+
if (type === "object") return {};
|
|
10220
|
+
return "...";
|
|
10221
|
+
}
|
|
10222
|
+
function stableStepIdForTool(toolId) {
|
|
10223
|
+
return toolId.replace(/^[a-z0-9]+_/, "").replace(/[^a-z0-9_]+/gi, "_") || "tool_call";
|
|
10224
|
+
}
|
|
10225
|
+
function safeIdentifier(name) {
|
|
10226
|
+
const cleaned = name.replace(/[^a-zA-Z0-9_$]+/g, "_").replace(/^[^a-zA-Z_$]+/, "");
|
|
10227
|
+
return cleaned || "value";
|
|
10228
|
+
}
|
|
10229
|
+
function playResultExpression(entry) {
|
|
10230
|
+
return stringField(entry, "expression").replace(/^toolExecutionResult\./, "result.");
|
|
10231
|
+
}
|
|
9505
10232
|
function toolMetadataJsonForDescribe(tool, requestedToolId) {
|
|
9506
10233
|
const toolId = String(tool.toolId || requestedToolId);
|
|
9507
10234
|
const {
|
|
@@ -9532,152 +10259,6 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
|
|
|
9532
10259
|
}
|
|
9533
10260
|
};
|
|
9534
10261
|
}
|
|
9535
|
-
function printToolDetails(tool, requestedToolId) {
|
|
9536
|
-
const toolId = String(tool.toolId || requestedToolId);
|
|
9537
|
-
const operation = typeof tool.operation === "string" ? tool.operation : "";
|
|
9538
|
-
const displayBase = operation && operation.startsWith(`${tool.provider}_`) ? operation.slice(String(tool.provider).length + 1) : operation ? `${tool.provider} ${operation}`.trim() : toolId;
|
|
9539
|
-
const displayName = titleCase(displayBase || String(tool.displayName || toolId));
|
|
9540
|
-
const cost = isRecord4(tool.cost) ? tool.cost : null;
|
|
9541
|
-
const pricing = recordField(tool, "pricing");
|
|
9542
|
-
const deeplineCredits = numberField(tool, "deeplineCreditsPerPricingUnit", "deepline_credits_per_pricing_unit");
|
|
9543
|
-
const deeplineUsdPerPricingUnit = numberField(tool, "deeplineUsdPerPricingUnit", "deepline_usd_per_pricing_unit");
|
|
9544
|
-
const billingSource = stringField(tool, "billingSource", "billing_source");
|
|
9545
|
-
const billingSourceLabel = stringField(tool, "billingSourceLabel", "billing_source_label");
|
|
9546
|
-
const estimatedCreditsRange = stringField(tool, "estimatedCreditsRange", "estimated_credits_range");
|
|
9547
|
-
const estimatedUsdRange = stringField(tool, "estimatedUsdRange", "estimated_usd_range");
|
|
9548
|
-
const estimateModelVersion = stringField(tool, "estimateModelVersion", "estimate_model_version");
|
|
9549
|
-
const estimateBasedOnTools = arrayField(tool, "estimateBasedOnTools", "estimate_based_on_tools").map((item) => String(item).trim()).filter(Boolean);
|
|
9550
|
-
const stepContributions = arrayField(tool, "stepContributions", "step_contributions");
|
|
9551
|
-
const playExpansion = recordField(tool, "playExpansion", "play_expansion");
|
|
9552
|
-
const samples = recordField(tool, "samples");
|
|
9553
|
-
const usageGuidance = recordField(tool, "usageGuidance", "usage_guidance");
|
|
9554
|
-
console.log(`Tool: ${toolId}`);
|
|
9555
|
-
console.log(" Runtime output help:");
|
|
9556
|
-
console.log(" describe shows declared schema/getters, not an observed provider response");
|
|
9557
|
-
console.log(` observe actual shape: deepline tools execute ${toolId} --input '{...}' --json`);
|
|
9558
|
-
console.log(" for play getter bugs: run the play, then use the db query commands printed by runs get");
|
|
9559
|
-
if (displayName) {
|
|
9560
|
-
console.log(" Display name:");
|
|
9561
|
-
console.log(` ${displayName}`);
|
|
9562
|
-
}
|
|
9563
|
-
if (tool.categories.length > 0) {
|
|
9564
|
-
console.log(" Categories:");
|
|
9565
|
-
console.log(` ${tool.categories.join(", ")}`);
|
|
9566
|
-
}
|
|
9567
|
-
const printedCost = printToolCost({
|
|
9568
|
-
pricing,
|
|
9569
|
-
cost,
|
|
9570
|
-
billingSource,
|
|
9571
|
-
deeplineCredits,
|
|
9572
|
-
deeplineUsdPerPricingUnit
|
|
9573
|
-
});
|
|
9574
|
-
if (!printedCost && ["run_javascript", "call_local_codex", "call_local_claude_code"].includes(toolId)) {
|
|
9575
|
-
console.log(" Cost: free");
|
|
9576
|
-
}
|
|
9577
|
-
if (billingSourceLabel) {
|
|
9578
|
-
console.log(` Billing source: ${billingSourceLabel}`);
|
|
9579
|
-
}
|
|
9580
|
-
if (estimatedCreditsRange) {
|
|
9581
|
-
const usdSuffix = estimatedUsdRange ? ` (~${estimatedUsdRange})` : "";
|
|
9582
|
-
console.log(` Estimated play spend: ${estimatedCreditsRange}${usdSuffix}`);
|
|
9583
|
-
if (estimateModelVersion) console.log(` model: ${estimateModelVersion}`);
|
|
9584
|
-
if (estimateBasedOnTools.length) console.log(` based on: ${estimateBasedOnTools.join(", ")}`);
|
|
9585
|
-
if (stepContributions.length) {
|
|
9586
|
-
console.log(" step contributions:");
|
|
9587
|
-
for (const item of stepContributions) {
|
|
9588
|
-
if (!isRecord4(item)) continue;
|
|
9589
|
-
const stepTool = typeof item.tool === "string" ? item.tool.trim() : "";
|
|
9590
|
-
const low = typeof item.lowCredits === "number" ? item.lowCredits : null;
|
|
9591
|
-
const high = typeof item.highCredits === "number" ? item.highCredits : null;
|
|
9592
|
-
const lowUsd = typeof item.lowUsd === "number" ? item.lowUsd : null;
|
|
9593
|
-
const highUsd = typeof item.highUsd === "number" ? item.highUsd : null;
|
|
9594
|
-
if (!stepTool || low === null || high === null) continue;
|
|
9595
|
-
const stepUsdSuffix = lowUsd !== null && highUsd !== null ? ` (~${formatUsd(lowUsd)}-${formatUsd(highUsd)})` : "";
|
|
9596
|
-
console.log(` - ${stepTool}: ${formatDecimal(low)}-${formatDecimal(high)} credits${stepUsdSuffix}`);
|
|
9597
|
-
}
|
|
9598
|
-
}
|
|
9599
|
-
}
|
|
9600
|
-
if (playExpansion && Object.keys(playExpansion).length > 0) {
|
|
9601
|
-
const group = typeof playExpansion.group === "string" ? playExpansion.group.trim() : "";
|
|
9602
|
-
console.log(" Play expansion:");
|
|
9603
|
-
if (group) console.log(` group: ${group}`);
|
|
9604
|
-
}
|
|
9605
|
-
const fields = toolInputFieldsForDisplay(recordField(tool, "inputSchema", "input_schema"));
|
|
9606
|
-
if (fields.length) {
|
|
9607
|
-
console.log(" Inputs (operation-specific):");
|
|
9608
|
-
for (const field of fields) {
|
|
9609
|
-
const name = String(field.name || "");
|
|
9610
|
-
const typeName = String(field.type || "unknown");
|
|
9611
|
-
const requiredLabel = field.required ? "required" : "optional";
|
|
9612
|
-
const defaultSuffix = Object.prototype.hasOwnProperty.call(field, "default") ? `, default: ${JSON.stringify(field.default)}` : "";
|
|
9613
|
-
const desc = typeof field.description === "string" && field.description.trim() ? ` - ${field.description.trim()}` : "";
|
|
9614
|
-
console.log(` - ${name} (${typeName}, ${requiredLabel}${defaultSuffix})${desc}`);
|
|
9615
|
-
}
|
|
9616
|
-
console.log(" Tip: pass --payload with a JSON object.");
|
|
9617
|
-
}
|
|
9618
|
-
printSamples(samples);
|
|
9619
|
-
printUsageGuidance(usageGuidance);
|
|
9620
|
-
if (isPlayTool(tool)) {
|
|
9621
|
-
console.log(" Play contract:");
|
|
9622
|
-
console.log(" - This is a deepline-native waterfall; the returned rows are extracted by target getters, not by hand-authored payload shape.");
|
|
9623
|
-
if (playExpansion && typeof playExpansion.group === "string" && playExpansion.group.trim()) {
|
|
9624
|
-
console.log(` - Output alias/runtime group is: ${playExpansion.group.trim()}`);
|
|
9625
|
-
}
|
|
9626
|
-
const toolExecutionResult = recordField(usageGuidance, "toolExecutionResult");
|
|
9627
|
-
const extractedValues = arrayField(toolExecutionResult, "extractedValues", "extracted_values");
|
|
9628
|
-
const targets = extractedValues.map((entry) => isRecord4(entry) && typeof entry.name === "string" ? entry.name : "").filter(Boolean).sort();
|
|
9629
|
-
if (targets.length) {
|
|
9630
|
-
console.log(` - Built-in extract targets: ${targets.join(", ")}`);
|
|
9631
|
-
}
|
|
9632
|
-
}
|
|
9633
|
-
console.log("");
|
|
9634
|
-
console.log("Usage:");
|
|
9635
|
-
const requestPayload = samplePayload(samples, "request");
|
|
9636
|
-
if (isPlayTool(tool)) {
|
|
9637
|
-
if (requestPayload !== void 0) {
|
|
9638
|
-
console.log(` deepline enrich --with '${JSON.stringify({ alias: "result", tool: toolId, payload: requestPayload })}'`);
|
|
9639
|
-
} else {
|
|
9640
|
-
console.log(` deepline enrich --with '{"alias":"result","tool":"${toolId}","payload":{...}}'`);
|
|
9641
|
-
}
|
|
9642
|
-
} else if (requestPayload !== void 0) {
|
|
9643
|
-
console.log(` deepline tools execute ${toolId} --payload '${JSON.stringify(requestPayload)}'`);
|
|
9644
|
-
} else {
|
|
9645
|
-
console.log(` deepline tools execute ${toolId} --payload '{...}'`);
|
|
9646
|
-
}
|
|
9647
|
-
console.log(" deepline tools describe <tool_id> --json");
|
|
9648
|
-
}
|
|
9649
|
-
function printUsageGuidance(usageGuidance) {
|
|
9650
|
-
if (Object.keys(usageGuidance).length === 0) return;
|
|
9651
|
-
const execute = stringField(usageGuidance, "execute");
|
|
9652
|
-
const toolExecutionResult = recordField(usageGuidance, "toolExecutionResult", "tool_execution_result");
|
|
9653
|
-
const toolResponse = recordField(toolExecutionResult, "toolResponse", "tool_response");
|
|
9654
|
-
const extractedLists = arrayField(toolExecutionResult, "extractedLists", "extracted_lists");
|
|
9655
|
-
const extractedValues = arrayField(toolExecutionResult, "extractedValues", "extracted_values");
|
|
9656
|
-
console.log(" Usage guidance:");
|
|
9657
|
-
if (execute) console.log(` ${execute}`);
|
|
9658
|
-
const raw = stringField(toolResponse, "raw");
|
|
9659
|
-
const meta = stringField(toolResponse, "meta");
|
|
9660
|
-
if (raw) console.log(` Raw tool response: ${raw}`);
|
|
9661
|
-
if (meta) console.log(` Tool response metadata: ${meta}`);
|
|
9662
|
-
printExtractions("Extracted lists", extractedLists);
|
|
9663
|
-
printExtractions("Extracted values", extractedValues);
|
|
9664
|
-
}
|
|
9665
|
-
function printExtractions(label, entries) {
|
|
9666
|
-
if (!entries.length) return;
|
|
9667
|
-
console.log(` ${label}:`);
|
|
9668
|
-
for (const entry of entries) {
|
|
9669
|
-
if (!isRecord4(entry)) continue;
|
|
9670
|
-
const name = stringField(entry, "name");
|
|
9671
|
-
const expression = stringField(entry, "expression");
|
|
9672
|
-
const details = recordField(entry, "details");
|
|
9673
|
-
const rawToolOutputPaths = arrayField(details, "rawToolOutputPaths", "raw_tool_output_paths").map((value) => typeof value === "string" ? value.trim() : "").filter(Boolean);
|
|
9674
|
-
const candidatePaths = arrayField(details, "candidatePaths", "candidate_paths").map((value) => typeof value === "string" ? value.trim() : "").filter(Boolean);
|
|
9675
|
-
if (!name || !expression) continue;
|
|
9676
|
-
const paths = candidatePaths.length ? candidatePaths : rawToolOutputPaths;
|
|
9677
|
-
const pathSuffix = paths.length ? ` from ${paths.join(", ")}` : "";
|
|
9678
|
-
console.log(` - ${name}: ${expression}${pathSuffix}`);
|
|
9679
|
-
}
|
|
9680
|
-
}
|
|
9681
10262
|
function singleLineText(value, maxLength = 260) {
|
|
9682
10263
|
if (typeof value !== "string") return "";
|
|
9683
10264
|
const text = value.replace(/\s+/g, " ").trim();
|
|
@@ -9694,42 +10275,6 @@ function formatListedToolCost(tool) {
|
|
|
9694
10275
|
const displayText = stringField(pricing, "displayText", "display_text");
|
|
9695
10276
|
return displayText ? `Cost: ${displayText}` : "";
|
|
9696
10277
|
}
|
|
9697
|
-
function printToolCost(input) {
|
|
9698
|
-
const { pricing, cost, billingSource, deeplineCredits, deeplineUsdPerPricingUnit } = input;
|
|
9699
|
-
if (billingSource === "own_provider_credentials") {
|
|
9700
|
-
console.log(" Cost: free through Deepline");
|
|
9701
|
-
return true;
|
|
9702
|
-
}
|
|
9703
|
-
const displayText = stringField(pricing, "displayText", "display_text");
|
|
9704
|
-
if (displayText) {
|
|
9705
|
-
console.log(` Cost: ${displayText}`);
|
|
9706
|
-
const details = arrayField(pricing, "details").map((item) => String(item).trim()).filter(Boolean);
|
|
9707
|
-
if (details.length) {
|
|
9708
|
-
console.log(" notes:");
|
|
9709
|
-
for (const detail of details) console.log(` - ${detail}`);
|
|
9710
|
-
}
|
|
9711
|
-
return true;
|
|
9712
|
-
}
|
|
9713
|
-
const pricingModel = cost ? typeof cost.pricingModel === "string" ? cost.pricingModel : typeof cost.pricing_model === "string" ? cost.pricing_model : "" : "";
|
|
9714
|
-
const billingMode = cost ? typeof cost.billingMode === "string" ? cost.billingMode : typeof cost.billing_mode === "string" ? cost.billing_mode : "" : "";
|
|
9715
|
-
if (deeplineCredits === 0) {
|
|
9716
|
-
console.log(" Cost: Free");
|
|
9717
|
-
return true;
|
|
9718
|
-
}
|
|
9719
|
-
if (pricingModel && deeplineCredits !== null) {
|
|
9720
|
-
const unit = pricingModel === "per_page" ? "page" : pricingModel === "per_result" ? "result" : "call";
|
|
9721
|
-
const usdText = deeplineUsdPerPricingUnit !== null ? ` / ${formatUsd(deeplineUsdPerPricingUnit)}` : "";
|
|
9722
|
-
const billingSuffix = billingMode ? ` (${billingMode})` : "";
|
|
9723
|
-
console.log(` Cost: ${formatDecimal(deeplineCredits)} Deepline credits${usdText} per ${unit}${billingSuffix}`);
|
|
9724
|
-
return true;
|
|
9725
|
-
}
|
|
9726
|
-
const summary = stringField(pricing, "summary");
|
|
9727
|
-
if (summary) {
|
|
9728
|
-
console.log(` Cost: ${summary}`);
|
|
9729
|
-
return true;
|
|
9730
|
-
}
|
|
9731
|
-
return false;
|
|
9732
|
-
}
|
|
9733
10278
|
function toolInputFieldsForDisplay(inputSchema) {
|
|
9734
10279
|
if (Array.isArray(inputSchema.fields)) return inputSchema.fields.filter(isRecord4);
|
|
9735
10280
|
const jsonSchema = isRecord4(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
|
|
@@ -9780,17 +10325,6 @@ function listExtractorPathsFromUsageGuidance(tool) {
|
|
|
9780
10325
|
).filter(Boolean);
|
|
9781
10326
|
});
|
|
9782
10327
|
}
|
|
9783
|
-
function isPlayTool(tool) {
|
|
9784
|
-
const provider = typeof tool.provider === "string" ? tool.provider : "";
|
|
9785
|
-
return provider === "deepline_native" && Boolean(recordField(tool, "playExpansion", "play_expansion"));
|
|
9786
|
-
}
|
|
9787
|
-
function titleCase(value) {
|
|
9788
|
-
return value.replace(/[_-]+/g, " ").split(" ").filter(Boolean).map((part) => {
|
|
9789
|
-
const lower = part.toLowerCase();
|
|
9790
|
-
const special = { linkedin: "LinkedIn", crm: "CRM", api: "API" };
|
|
9791
|
-
return special[lower] ?? `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`;
|
|
9792
|
-
}).join(" ");
|
|
9793
|
-
}
|
|
9794
10328
|
function formatDecimal(value) {
|
|
9795
10329
|
const text = value.toFixed(12).replace(/0+$/, "").replace(/\.$/, "");
|
|
9796
10330
|
return text || "0";
|
|
@@ -10550,6 +11084,61 @@ function shouldDeferSkillsSyncForCommand() {
|
|
|
10550
11084
|
const subcommand = args[1];
|
|
10551
11085
|
return (command === "play" || command === "plays") && subcommand === "run" && args.includes("--json");
|
|
10552
11086
|
}
|
|
11087
|
+
async function runPlayRunnerHealthCheck() {
|
|
11088
|
+
const dir = await (0, import_promises5.mkdtemp)((0, import_node_path15.join)((0, import_node_os9.tmpdir)(), "deepline-health-play-"));
|
|
11089
|
+
const file = (0, import_node_path15.join)(dir, "health-check.play.ts");
|
|
11090
|
+
try {
|
|
11091
|
+
await (0, import_promises5.writeFile)(
|
|
11092
|
+
file,
|
|
11093
|
+
[
|
|
11094
|
+
"import { definePlay } from 'deepline';",
|
|
11095
|
+
"",
|
|
11096
|
+
"export default definePlay('health-check', async (ctx) => {",
|
|
11097
|
+
" const rows = await ctx",
|
|
11098
|
+
" .map('health_rows', [{ id: 'a' }, { id: 'b' }])",
|
|
11099
|
+
" .step('echo', (row) => ({ ok: true, id: row.id }))",
|
|
11100
|
+
" .run({ key: 'id' });",
|
|
11101
|
+
" return { ok: true, rows, source: 'deepline health --play-runner' };",
|
|
11102
|
+
"});",
|
|
11103
|
+
""
|
|
11104
|
+
].join("\n"),
|
|
11105
|
+
"utf8"
|
|
11106
|
+
);
|
|
11107
|
+
let capturedOutput = "";
|
|
11108
|
+
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
11109
|
+
process.stdout.write = ((chunk, ...args) => {
|
|
11110
|
+
capturedOutput += typeof chunk === "string" ? chunk : String(chunk);
|
|
11111
|
+
return true;
|
|
11112
|
+
});
|
|
11113
|
+
let exitCode = 1;
|
|
11114
|
+
try {
|
|
11115
|
+
exitCode = await handlePlayRun([
|
|
11116
|
+
file,
|
|
11117
|
+
"--input",
|
|
11118
|
+
"{}",
|
|
11119
|
+
"--watch",
|
|
11120
|
+
"--no-open",
|
|
11121
|
+
"--json"
|
|
11122
|
+
]);
|
|
11123
|
+
} finally {
|
|
11124
|
+
process.stdout.write = originalWrite;
|
|
11125
|
+
}
|
|
11126
|
+
if (exitCode !== 0) {
|
|
11127
|
+
throw new Error(
|
|
11128
|
+
`play runner canary exited ${exitCode}: ${capturedOutput.slice(0, 1e3)}`
|
|
11129
|
+
);
|
|
11130
|
+
}
|
|
11131
|
+
return {
|
|
11132
|
+
status: "ok",
|
|
11133
|
+
playRunner: {
|
|
11134
|
+
status: "ok",
|
|
11135
|
+
check: "no-provider local play run completed"
|
|
11136
|
+
}
|
|
11137
|
+
};
|
|
11138
|
+
} finally {
|
|
11139
|
+
await (0, import_promises5.rm)(dir, { recursive: true, force: true });
|
|
11140
|
+
}
|
|
11141
|
+
}
|
|
10553
11142
|
async function main() {
|
|
10554
11143
|
const mainStartedAt = Date.now();
|
|
10555
11144
|
recordCliTrace({
|
|
@@ -10561,7 +11150,7 @@ async function main() {
|
|
|
10561
11150
|
if (printStartupPhase) {
|
|
10562
11151
|
progress?.phase("loading deepline cli");
|
|
10563
11152
|
}
|
|
10564
|
-
const program = new
|
|
11153
|
+
const program = new import_commander3.Command();
|
|
10565
11154
|
program.name("deepline").description("Deepline CLI (TypeScript SDK)").version(SDK_VERSION, "-v, --version", "Show version").showHelpAfterError().showSuggestionAfterError(true).addHelpText(
|
|
10566
11155
|
"after",
|
|
10567
11156
|
`
|
|
@@ -10570,7 +11159,7 @@ Common commands:
|
|
|
10570
11159
|
deepline auth status --json
|
|
10571
11160
|
deepline plays search email --json
|
|
10572
11161
|
deepline plays describe person-linkedin-to-email --json
|
|
10573
|
-
deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
|
|
11162
|
+
deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
|
|
10574
11163
|
deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
|
|
10575
11164
|
deepline update
|
|
10576
11165
|
|
|
@@ -10626,18 +11215,30 @@ Exit codes:
|
|
|
10626
11215
|
registerDbCommands(program);
|
|
10627
11216
|
registerFeedbackCommands(program);
|
|
10628
11217
|
registerUpdateCommand(program);
|
|
10629
|
-
program.command("health").description("Check server health.").option("--json", "Force JSON output.").
|
|
11218
|
+
program.command("health").description("Check server health.").option("--json", "Force JSON output.").option(
|
|
11219
|
+
"--play-runner",
|
|
11220
|
+
"Run a tiny no-provider play to verify the full play execution plane."
|
|
11221
|
+
).addHelpText(
|
|
10630
11222
|
"after",
|
|
10631
11223
|
`
|
|
10632
11224
|
Notes:
|
|
10633
11225
|
Read-only connectivity check for the configured Deepline host. Prints the raw
|
|
10634
11226
|
server health payload as JSON.
|
|
11227
|
+
Add --play-runner to verify bundling, coordinator dispatch, runtime callbacks,
|
|
11228
|
+
and run streaming with a tiny no-provider play.
|
|
10635
11229
|
|
|
10636
11230
|
Examples:
|
|
10637
11231
|
deepline health
|
|
11232
|
+
deepline health --play-runner
|
|
10638
11233
|
`
|
|
10639
|
-
).action(async () => {
|
|
11234
|
+
).action(async (options) => {
|
|
10640
11235
|
try {
|
|
11236
|
+
if (options.playRunner) {
|
|
11237
|
+
const data2 = await runPlayRunnerHealthCheck();
|
|
11238
|
+
process.stdout.write(`${JSON.stringify(data2, null, 2)}
|
|
11239
|
+
`);
|
|
11240
|
+
return;
|
|
11241
|
+
}
|
|
10641
11242
|
const client = new DeeplineClient();
|
|
10642
11243
|
const data = await client.health();
|
|
10643
11244
|
process.stdout.write(`${JSON.stringify(data, null, 2)}
|