deepline 0.1.106 → 0.1.107
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 +404 -34
- package/dist/cli/index.mjs +400 -30
- package/dist/index.js +13 -3
- package/dist/index.mjs +13 -3
- package/dist/repo/sdk/src/release.ts +47 -7
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -242,12 +242,22 @@ var SDK_RELEASE = {
|
|
|
242
242
|
// 0.1.105 ships the billing catalog surface: billing plans, subscribe,
|
|
243
243
|
// subscription status/cancel, invoices, and the client.billing namespace.
|
|
244
244
|
// 0.1.106 ships play cell provenance metadata and v2 preview retry hardening.
|
|
245
|
-
|
|
245
|
+
// 0.1.107 ships the v2 quickstart command, the deepline-plays-quickstart
|
|
246
|
+
// skill on the sdk sync surface, and the people-search-to-email prebuilt.
|
|
247
|
+
version: "0.1.107",
|
|
246
248
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
247
249
|
supportPolicy: {
|
|
248
|
-
latest: "0.1.
|
|
250
|
+
latest: "0.1.107",
|
|
249
251
|
minimumSupported: "0.1.53",
|
|
250
|
-
deprecatedBelow: "0.1.53"
|
|
252
|
+
deprecatedBelow: "0.1.53",
|
|
253
|
+
commandMinimumSupported: [
|
|
254
|
+
{
|
|
255
|
+
command: "enrich",
|
|
256
|
+
minimumSupported: "0.1.106",
|
|
257
|
+
reason: "Older SDK CLI enrich generated stale play source for the current dataset API."
|
|
258
|
+
}
|
|
259
|
+
],
|
|
260
|
+
autoUpdatePatchLag: 2
|
|
251
261
|
}
|
|
252
262
|
};
|
|
253
263
|
|
|
@@ -3169,7 +3179,7 @@ function shouldSkipCompatibilityCheck() {
|
|
|
3169
3179
|
const value = process.env.DEEPLINE_SKIP_SDK_COMPAT_CHECK?.trim().toLowerCase();
|
|
3170
3180
|
return value === "1" || value === "true" || value === "yes";
|
|
3171
3181
|
}
|
|
3172
|
-
async function checkSdkCompatibility(baseUrl) {
|
|
3182
|
+
async function checkSdkCompatibility(baseUrl, options = {}) {
|
|
3173
3183
|
if (shouldSkipCompatibilityCheck()) {
|
|
3174
3184
|
return { response: null, error: null };
|
|
3175
3185
|
}
|
|
@@ -3178,6 +3188,9 @@ async function checkSdkCompatibility(baseUrl) {
|
|
|
3178
3188
|
try {
|
|
3179
3189
|
const url = new URL("/api/v2/sdk/compat", baseUrl);
|
|
3180
3190
|
url.searchParams.set("version", SDK_VERSION);
|
|
3191
|
+
if (options.command?.trim()) {
|
|
3192
|
+
url.searchParams.set("command", options.command.trim());
|
|
3193
|
+
}
|
|
3181
3194
|
const response = await fetch(url, {
|
|
3182
3195
|
method: "GET",
|
|
3183
3196
|
headers: {
|
|
@@ -3198,9 +3211,8 @@ async function checkSdkCompatibility(baseUrl) {
|
|
|
3198
3211
|
clearTimeout(timeout);
|
|
3199
3212
|
}
|
|
3200
3213
|
}
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
if (error || !response) {
|
|
3214
|
+
function enforceSdkCompatibilityResponse(response) {
|
|
3215
|
+
if (!response) {
|
|
3204
3216
|
return;
|
|
3205
3217
|
}
|
|
3206
3218
|
if (response.update_required) {
|
|
@@ -17951,6 +17963,244 @@ Examples:
|
|
|
17951
17963
|
).option("--org-id <id>", "Switch using an explicit organization id").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgSwitch);
|
|
17952
17964
|
}
|
|
17953
17965
|
|
|
17966
|
+
// src/cli/commands/quickstart.ts
|
|
17967
|
+
var import_node_child_process = require("child_process");
|
|
17968
|
+
var import_node_crypto4 = require("crypto");
|
|
17969
|
+
var import_node_http = require("http");
|
|
17970
|
+
var EXIT_OK2 = 0;
|
|
17971
|
+
var EXIT_AUTH2 = 1;
|
|
17972
|
+
var EXIT_SERVER3 = 2;
|
|
17973
|
+
var MAX_PROMPT_LENGTH = 8e3;
|
|
17974
|
+
var MAX_BODY_BYTES = 64 * 1024;
|
|
17975
|
+
function shellQuote(arg) {
|
|
17976
|
+
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
17977
|
+
}
|
|
17978
|
+
function hasClaudeBinary() {
|
|
17979
|
+
try {
|
|
17980
|
+
const result = (0, import_node_child_process.spawnSync)("claude", ["--version"], {
|
|
17981
|
+
stdio: "ignore",
|
|
17982
|
+
shell: process.platform === "win32"
|
|
17983
|
+
});
|
|
17984
|
+
return result.status === 0;
|
|
17985
|
+
} catch {
|
|
17986
|
+
return false;
|
|
17987
|
+
}
|
|
17988
|
+
}
|
|
17989
|
+
function launchClaude(prompt) {
|
|
17990
|
+
return new Promise((resolve16) => {
|
|
17991
|
+
const child = (0, import_node_child_process.spawn)("claude", [prompt], {
|
|
17992
|
+
stdio: "inherit",
|
|
17993
|
+
shell: process.platform === "win32"
|
|
17994
|
+
});
|
|
17995
|
+
child.on("error", () => resolve16(EXIT_SERVER3));
|
|
17996
|
+
child.on("close", (status) => resolve16(status ?? EXIT_OK2));
|
|
17997
|
+
});
|
|
17998
|
+
}
|
|
17999
|
+
function readBody(req) {
|
|
18000
|
+
return new Promise((resolve16, reject) => {
|
|
18001
|
+
let raw = "";
|
|
18002
|
+
req.setEncoding("utf8");
|
|
18003
|
+
req.on("data", (chunk) => {
|
|
18004
|
+
raw += chunk;
|
|
18005
|
+
if (raw.length > MAX_BODY_BYTES) {
|
|
18006
|
+
reject(new Error("Request body too large."));
|
|
18007
|
+
req.destroy();
|
|
18008
|
+
}
|
|
18009
|
+
});
|
|
18010
|
+
req.on("end", () => resolve16(raw));
|
|
18011
|
+
req.on("error", reject);
|
|
18012
|
+
});
|
|
18013
|
+
}
|
|
18014
|
+
function writeJson(res, status, payload) {
|
|
18015
|
+
res.writeHead(status, { "content-type": "application/json" });
|
|
18016
|
+
res.end(JSON.stringify(payload));
|
|
18017
|
+
}
|
|
18018
|
+
function startCallbackServer(input2) {
|
|
18019
|
+
const server = (0, import_node_http.createServer)((req, res) => {
|
|
18020
|
+
res.setHeader("Access-Control-Allow-Origin", req.headers.origin ?? "*");
|
|
18021
|
+
res.setHeader("Vary", "Origin");
|
|
18022
|
+
res.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
|
|
18023
|
+
res.setHeader("Access-Control-Allow-Headers", "content-type");
|
|
18024
|
+
res.setHeader("Access-Control-Allow-Private-Network", "true");
|
|
18025
|
+
res.setHeader("Access-Control-Max-Age", "600");
|
|
18026
|
+
if (req.method === "OPTIONS") {
|
|
18027
|
+
res.writeHead(204);
|
|
18028
|
+
res.end();
|
|
18029
|
+
return;
|
|
18030
|
+
}
|
|
18031
|
+
if (req.method !== "POST" || req.url !== "/submit") {
|
|
18032
|
+
writeJson(res, 404, { error: "Not found." });
|
|
18033
|
+
return;
|
|
18034
|
+
}
|
|
18035
|
+
void readBody(req).then((raw) => {
|
|
18036
|
+
let body = null;
|
|
18037
|
+
try {
|
|
18038
|
+
body = JSON.parse(raw);
|
|
18039
|
+
} catch {
|
|
18040
|
+
body = null;
|
|
18041
|
+
}
|
|
18042
|
+
const state = typeof body?.state === "string" ? body.state : "";
|
|
18043
|
+
const prompt = typeof body?.prompt === "string" ? body.prompt.trim() : "";
|
|
18044
|
+
const workflowId = typeof body?.workflow_id === "string" && body.workflow_id.trim() ? body.workflow_id.trim() : null;
|
|
18045
|
+
if (!state || state !== input2.state) {
|
|
18046
|
+
writeJson(res, 403, { error: "Invalid quickstart state token." });
|
|
18047
|
+
return;
|
|
18048
|
+
}
|
|
18049
|
+
if (!prompt) {
|
|
18050
|
+
writeJson(res, 400, { error: "prompt is required." });
|
|
18051
|
+
return;
|
|
18052
|
+
}
|
|
18053
|
+
if (prompt.length > MAX_PROMPT_LENGTH) {
|
|
18054
|
+
writeJson(res, 400, {
|
|
18055
|
+
error: `prompt exceeds ${MAX_PROMPT_LENGTH} characters.`
|
|
18056
|
+
});
|
|
18057
|
+
return;
|
|
18058
|
+
}
|
|
18059
|
+
writeJson(res, 200, { ok: true });
|
|
18060
|
+
setImmediate(() => input2.onSelection({ prompt, workflowId }));
|
|
18061
|
+
}).catch(() => {
|
|
18062
|
+
writeJson(res, 400, { error: "Invalid request body." });
|
|
18063
|
+
});
|
|
18064
|
+
});
|
|
18065
|
+
return new Promise((resolve16, reject) => {
|
|
18066
|
+
server.once("error", reject);
|
|
18067
|
+
server.listen(0, "127.0.0.1", () => {
|
|
18068
|
+
const address = server.address();
|
|
18069
|
+
if (!address || typeof address === "string") {
|
|
18070
|
+
reject(new Error("Failed to bind quickstart callback server."));
|
|
18071
|
+
return;
|
|
18072
|
+
}
|
|
18073
|
+
resolve16({ server, port: address.port });
|
|
18074
|
+
});
|
|
18075
|
+
});
|
|
18076
|
+
}
|
|
18077
|
+
async function handleQuickstart(options) {
|
|
18078
|
+
const jsonOutput = shouldEmitJson(options.json === true);
|
|
18079
|
+
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
18080
|
+
const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
18081
|
+
let apiKey = resolveApiKeyForBaseUrl(baseUrl);
|
|
18082
|
+
if (!apiKey) {
|
|
18083
|
+
if (interactive) {
|
|
18084
|
+
console.error("Not connected yet \u2014 registering this device first.");
|
|
18085
|
+
const registerExit = await handleRegister([]);
|
|
18086
|
+
if (registerExit !== EXIT_OK2) return registerExit;
|
|
18087
|
+
apiKey = resolveApiKeyForBaseUrl(baseUrl);
|
|
18088
|
+
}
|
|
18089
|
+
if (!apiKey) {
|
|
18090
|
+
console.error("Not connected. Run: deepline auth register");
|
|
18091
|
+
return EXIT_AUTH2;
|
|
18092
|
+
}
|
|
18093
|
+
}
|
|
18094
|
+
const state = (0, import_node_crypto4.randomBytes)(32).toString("hex");
|
|
18095
|
+
let resolveSelection;
|
|
18096
|
+
const selectionPromise = new Promise((resolve16) => {
|
|
18097
|
+
resolveSelection = resolve16;
|
|
18098
|
+
});
|
|
18099
|
+
let callback;
|
|
18100
|
+
try {
|
|
18101
|
+
callback = await startCallbackServer({
|
|
18102
|
+
state,
|
|
18103
|
+
onSelection: (selection) => resolveSelection(selection)
|
|
18104
|
+
});
|
|
18105
|
+
} catch (error) {
|
|
18106
|
+
console.error(
|
|
18107
|
+
`Could not start the local quickstart listener: ${error instanceof Error ? error.message : String(error)}`
|
|
18108
|
+
);
|
|
18109
|
+
return EXIT_SERVER3;
|
|
18110
|
+
}
|
|
18111
|
+
const quickstartUrl = `${baseUrl}/cli/quickstart?cb=${callback.port}&state=${state}`;
|
|
18112
|
+
console.error(" Opening the recipe picker in your browser.");
|
|
18113
|
+
console.error(` If it didn't open, cmd+click: ${quickstartUrl}`);
|
|
18114
|
+
if (options.open !== false) {
|
|
18115
|
+
openInBrowser(quickstartUrl);
|
|
18116
|
+
}
|
|
18117
|
+
const timeoutSeconds = Number.parseInt(options.timeout ?? "300", 10);
|
|
18118
|
+
const timeoutMs = (Number.isFinite(timeoutSeconds) && timeoutSeconds > 0 ? timeoutSeconds : 300) * 1e3;
|
|
18119
|
+
const timeoutHandle = setTimeout(
|
|
18120
|
+
() => resolveSelection("timeout"),
|
|
18121
|
+
timeoutMs
|
|
18122
|
+
);
|
|
18123
|
+
const progress = createCliProgress(!jsonOutput);
|
|
18124
|
+
progress.phase("waiting for your pick in the browser (Ctrl+C to skip)");
|
|
18125
|
+
const onSigint = () => resolveSelection("sigint");
|
|
18126
|
+
process.once("SIGINT", onSigint);
|
|
18127
|
+
const outcome = await selectionPromise;
|
|
18128
|
+
clearTimeout(timeoutHandle);
|
|
18129
|
+
process.removeListener("SIGINT", onSigint);
|
|
18130
|
+
callback.server.close();
|
|
18131
|
+
if (outcome === "sigint") {
|
|
18132
|
+
progress.fail();
|
|
18133
|
+
console.error("\nSkipped \u2014 run `deepline quickstart` anytime.");
|
|
18134
|
+
return EXIT_OK2;
|
|
18135
|
+
}
|
|
18136
|
+
if (outcome === "timeout") {
|
|
18137
|
+
progress.fail();
|
|
18138
|
+
console.error(
|
|
18139
|
+
"Timed out waiting for a selection. Run: deepline quickstart"
|
|
18140
|
+
);
|
|
18141
|
+
return EXIT_AUTH2;
|
|
18142
|
+
}
|
|
18143
|
+
progress.complete();
|
|
18144
|
+
const { prompt, workflowId } = outcome;
|
|
18145
|
+
const claudeCommand = `claude ${shellQuote(prompt)}`;
|
|
18146
|
+
const claudeAvailable = hasClaudeBinary();
|
|
18147
|
+
const willLaunch = options.launch !== false && !jsonOutput && interactive && claudeAvailable;
|
|
18148
|
+
printCommandEnvelope(
|
|
18149
|
+
{
|
|
18150
|
+
status: "submitted",
|
|
18151
|
+
workflowId,
|
|
18152
|
+
prompt,
|
|
18153
|
+
claudeCommand,
|
|
18154
|
+
url: quickstartUrl,
|
|
18155
|
+
launched: willLaunch,
|
|
18156
|
+
render: {
|
|
18157
|
+
sections: [
|
|
18158
|
+
{
|
|
18159
|
+
title: "quickstart",
|
|
18160
|
+
lines: [
|
|
18161
|
+
...workflowId ? [`Recipe: ${workflowId}`] : [],
|
|
18162
|
+
willLaunch ? "Launching Claude Code with your recipe..." : claudeAvailable ? "Run the command below to start your recipe." : "Claude Code not found. Install it (https://code.claude.com/docs/en/overview), then run the command below."
|
|
18163
|
+
]
|
|
18164
|
+
}
|
|
18165
|
+
],
|
|
18166
|
+
actions: [{ label: "Run", command: claudeCommand }]
|
|
18167
|
+
}
|
|
18168
|
+
},
|
|
18169
|
+
{ json: jsonOutput }
|
|
18170
|
+
);
|
|
18171
|
+
if (willLaunch) {
|
|
18172
|
+
return launchClaude(prompt);
|
|
18173
|
+
}
|
|
18174
|
+
return EXIT_OK2;
|
|
18175
|
+
}
|
|
18176
|
+
function registerQuickstartCommands(program) {
|
|
18177
|
+
program.command("quickstart").description(
|
|
18178
|
+
"Pick a starter recipe in the browser and launch it with Claude Code."
|
|
18179
|
+
).addHelpText(
|
|
18180
|
+
"after",
|
|
18181
|
+
`
|
|
18182
|
+
Notes:
|
|
18183
|
+
Opens the hosted recipe picker in your browser. The picker sends your
|
|
18184
|
+
selection back to a temporary listener on 127.0.0.1, so the browser must run
|
|
18185
|
+
on the same machine as the CLI. Once a recipe arrives, the CLI prints the
|
|
18186
|
+
matching claude command and, when Claude Code is installed and the shell is
|
|
18187
|
+
interactive, launches it directly. Press Ctrl+C while waiting to skip.
|
|
18188
|
+
|
|
18189
|
+
Examples:
|
|
18190
|
+
deepline quickstart
|
|
18191
|
+
deepline quickstart --no-open
|
|
18192
|
+
deepline quickstart --no-launch --json
|
|
18193
|
+
deepline quickstart --timeout 120
|
|
18194
|
+
`
|
|
18195
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--no-open", "Do not open the browser; print the URL only").option("--no-launch", "Print the claude command instead of launching it").option(
|
|
18196
|
+
"--timeout <seconds>",
|
|
18197
|
+
"Maximum seconds to wait for a selection",
|
|
18198
|
+
"300"
|
|
18199
|
+
).action(async (options) => {
|
|
18200
|
+
process.exitCode = await handleQuickstart(options);
|
|
18201
|
+
});
|
|
18202
|
+
}
|
|
18203
|
+
|
|
17954
18204
|
// src/cli/commands/secrets.ts
|
|
17955
18205
|
var import_node_process = require("process");
|
|
17956
18206
|
var hiddenInputBuffer = "";
|
|
@@ -18168,7 +18418,7 @@ var import_node_fs11 = require("fs");
|
|
|
18168
18418
|
var import_node_os8 = require("os");
|
|
18169
18419
|
var import_node_path14 = require("path");
|
|
18170
18420
|
var import_node_zlib = require("zlib");
|
|
18171
|
-
var
|
|
18421
|
+
var import_node_crypto5 = require("crypto");
|
|
18172
18422
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
18173
18423
|
var MAX_SESSION_UPLOAD_BYTES = 35e5;
|
|
18174
18424
|
var MAX_DIRECT_SESSION_DECODED_BYTES = 50 * 1024 * 1024;
|
|
@@ -18431,7 +18681,7 @@ async function uploadPayload(path, payload) {
|
|
|
18431
18681
|
return await http.post(path, payload);
|
|
18432
18682
|
}
|
|
18433
18683
|
async function uploadChunkedSessions(sessions, options) {
|
|
18434
|
-
const uploadId = (0,
|
|
18684
|
+
const uploadId = (0, import_node_crypto5.randomUUID)();
|
|
18435
18685
|
for (const session of sessions) {
|
|
18436
18686
|
const bytes = Buffer.from(session.encodedContent, "base64");
|
|
18437
18687
|
const chunks = [];
|
|
@@ -19955,7 +20205,7 @@ function parseExecuteOptions(args) {
|
|
|
19955
20205
|
function safeFileStem(value) {
|
|
19956
20206
|
return value.trim().replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "tool";
|
|
19957
20207
|
}
|
|
19958
|
-
function
|
|
20208
|
+
function shellQuote2(value) {
|
|
19959
20209
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
19960
20210
|
}
|
|
19961
20211
|
function powerShellQuote(value) {
|
|
@@ -20007,7 +20257,7 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
|
|
|
20007
20257
|
path: scriptPath,
|
|
20008
20258
|
sourceCode: script,
|
|
20009
20259
|
projectDir,
|
|
20010
|
-
macCopyCommand: `mkdir -p ${
|
|
20260
|
+
macCopyCommand: `mkdir -p ${shellQuote2(projectDir)} && cp ${shellQuote2(scriptPath)} ${shellQuote2(`${projectDir}/${fileName}`)}`,
|
|
20011
20261
|
windowsCopyCommand: `New-Item -ItemType Directory -Force -Path ${powerShellQuote(projectDir.replace(/\//g, "\\"))} | Out-Null; Copy-Item -LiteralPath ${powerShellQuote(scriptPath)} -Destination ${powerShellQuote(`${projectDir.replace(/\//g, "\\")}\\${fileName}`)}`
|
|
20012
20262
|
};
|
|
20013
20263
|
}
|
|
@@ -20026,7 +20276,7 @@ function buildToolExecuteBaseEnvelope(input2) {
|
|
|
20026
20276
|
summary: input2.summary
|
|
20027
20277
|
};
|
|
20028
20278
|
const envelopeHasCanonicalOutput = isRecord7(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
|
|
20029
|
-
const inspectCommand = `deepline tools execute ${input2.toolId} --input ${
|
|
20279
|
+
const inspectCommand = `deepline tools execute ${input2.toolId} --input ${shellQuote2(JSON.stringify(input2.params))} --json`;
|
|
20030
20280
|
const actions = input2.listConversion ? [
|
|
20031
20281
|
{
|
|
20032
20282
|
label: "next",
|
|
@@ -20260,7 +20510,7 @@ var import_promises6 = require("fs/promises");
|
|
|
20260
20510
|
var import_node_path17 = require("path");
|
|
20261
20511
|
|
|
20262
20512
|
// src/cli/workflow-to-play.ts
|
|
20263
|
-
var
|
|
20513
|
+
var import_node_crypto6 = require("crypto");
|
|
20264
20514
|
var HITL_WAIT_FOR_SIGNAL_TOOL = "deepline_workflow_wait_for_signal";
|
|
20265
20515
|
var HITL_SLACK_TOOL = "slack_message_with_hitl";
|
|
20266
20516
|
var SUB_WORKFLOW_TOOL_PREFIX = "deepline_workflow_";
|
|
@@ -20366,7 +20616,7 @@ function sanitizePlayNameSegment(value) {
|
|
|
20366
20616
|
}
|
|
20367
20617
|
function deriveWorkflowPlayName(workflowName) {
|
|
20368
20618
|
const base = sanitizePlayNameSegment(workflowName) || "workflow";
|
|
20369
|
-
const suffix = (0,
|
|
20619
|
+
const suffix = (0, import_node_crypto6.createHash)("sha256").update(workflowName).digest("hex").slice(0, 8);
|
|
20370
20620
|
const reserved = suffix.length + 1;
|
|
20371
20621
|
const allowedBase = Math.max(1, MAX_PLAY_NAME_LENGTH - reserved);
|
|
20372
20622
|
let name = `${base.slice(0, allowedBase)}_${suffix}`;
|
|
@@ -20745,7 +20995,7 @@ Notes:
|
|
|
20745
20995
|
}
|
|
20746
20996
|
|
|
20747
20997
|
// src/cli/commands/update.ts
|
|
20748
|
-
var
|
|
20998
|
+
var import_node_child_process2 = require("child_process");
|
|
20749
20999
|
var import_node_fs14 = require("fs");
|
|
20750
21000
|
var import_node_path18 = require("path");
|
|
20751
21001
|
function posixShellQuote(value) {
|
|
@@ -20754,14 +21004,14 @@ function posixShellQuote(value) {
|
|
|
20754
21004
|
function windowsCmdQuote(value) {
|
|
20755
21005
|
return `"${value.replace(/"/g, '""')}"`;
|
|
20756
21006
|
}
|
|
20757
|
-
function
|
|
21007
|
+
function shellQuote3(value) {
|
|
20758
21008
|
if (process.platform === "win32") {
|
|
20759
21009
|
return /^[A-Za-z0-9_./:@%+=,-]+$/.test(value) ? value : windowsCmdQuote(value);
|
|
20760
21010
|
}
|
|
20761
21011
|
return posixShellQuote(value);
|
|
20762
21012
|
}
|
|
20763
21013
|
function buildSourceUpdateCommand(sourceRoot) {
|
|
20764
|
-
const quotedRoot =
|
|
21014
|
+
const quotedRoot = shellQuote3(sourceRoot);
|
|
20765
21015
|
const cdCommand = process.platform === "win32" ? `cd /d ${quotedRoot}` : `cd ${quotedRoot}`;
|
|
20766
21016
|
return `${cdCommand} && git fetch origin main --tags && git merge --ff-only origin/main`;
|
|
20767
21017
|
}
|
|
@@ -20792,12 +21042,12 @@ function resolveUpdatePlan() {
|
|
|
20792
21042
|
kind: "npm-global",
|
|
20793
21043
|
command,
|
|
20794
21044
|
args,
|
|
20795
|
-
manualCommand: `${command} ${args.map(
|
|
21045
|
+
manualCommand: `${command} ${args.map(shellQuote3).join(" ")}`
|
|
20796
21046
|
};
|
|
20797
21047
|
}
|
|
20798
21048
|
function runCommand(command, args) {
|
|
20799
21049
|
return new Promise((resolveExitCode) => {
|
|
20800
|
-
const child = (0,
|
|
21050
|
+
const child = (0, import_node_child_process2.spawn)(command, args, {
|
|
20801
21051
|
stdio: "inherit",
|
|
20802
21052
|
shell: process.platform === "win32",
|
|
20803
21053
|
env: process.env
|
|
@@ -20812,6 +21062,12 @@ function runCommand(command, args) {
|
|
|
20812
21062
|
});
|
|
20813
21063
|
});
|
|
20814
21064
|
}
|
|
21065
|
+
async function runNpmGlobalUpdatePlan(plan) {
|
|
21066
|
+
if (plan.kind !== "npm-global") {
|
|
21067
|
+
return 1;
|
|
21068
|
+
}
|
|
21069
|
+
return runCommand(plan.command, plan.args);
|
|
21070
|
+
}
|
|
20815
21071
|
async function handleUpdate(options) {
|
|
20816
21072
|
const plan = resolveUpdatePlan();
|
|
20817
21073
|
const render = {
|
|
@@ -20958,16 +21214,27 @@ function skillsIndexUrl(baseUrl) {
|
|
|
20958
21214
|
return `${normalizeBaseUrl2(baseUrl)}${INSTALL_COMMANDS.skills.index_path}`;
|
|
20959
21215
|
}
|
|
20960
21216
|
function buildSkillsAddArgs(baseUrl, skillName, options = {}) {
|
|
21217
|
+
const skillNames = Array.isArray(skillName) ? skillName : [skillName];
|
|
21218
|
+
const [firstSkillName, ...extraSkillNames] = skillNames;
|
|
20961
21219
|
const values = {
|
|
20962
21220
|
skills_index_url: skillsIndexUrl(baseUrl),
|
|
20963
21221
|
agents: INSTALL_COMMANDS.skills.default_agents.join(" "),
|
|
20964
|
-
skill_name:
|
|
21222
|
+
skill_name: firstSkillName ?? ""
|
|
20965
21223
|
};
|
|
20966
21224
|
const rendered = INSTALL_COMMANDS.skills.npx_add_args_template.flatMap(
|
|
20967
21225
|
(arg, index) => {
|
|
20968
21226
|
const next = index === 0 && options.firstArg ? options.firstArg : arg;
|
|
20969
21227
|
const value = renderTemplate(next, values);
|
|
20970
|
-
|
|
21228
|
+
if (arg === "{agents}") {
|
|
21229
|
+
return INSTALL_COMMANDS.skills.default_agents;
|
|
21230
|
+
}
|
|
21231
|
+
if (arg === "{skill_name}") {
|
|
21232
|
+
return [
|
|
21233
|
+
value,
|
|
21234
|
+
...extraSkillNames.flatMap((name) => ["--skill", name])
|
|
21235
|
+
];
|
|
21236
|
+
}
|
|
21237
|
+
return value;
|
|
20971
21238
|
}
|
|
20972
21239
|
);
|
|
20973
21240
|
return rendered;
|
|
@@ -21038,13 +21305,78 @@ function unknownCommandNameFromMessage(message) {
|
|
|
21038
21305
|
return command ? command : null;
|
|
21039
21306
|
}
|
|
21040
21307
|
|
|
21308
|
+
// src/cli/self-update.ts
|
|
21309
|
+
var import_node_child_process3 = require("child_process");
|
|
21310
|
+
function envTruthy(name) {
|
|
21311
|
+
const value = process.env[name]?.trim().toLowerCase();
|
|
21312
|
+
return value === "1" || value === "true" || value === "yes";
|
|
21313
|
+
}
|
|
21314
|
+
function isCi() {
|
|
21315
|
+
return envTruthy("CI") || envTruthy("GITHUB_ACTIONS");
|
|
21316
|
+
}
|
|
21317
|
+
function shouldSkipSelfUpdate() {
|
|
21318
|
+
return envTruthy("DEEPLINE_SKIP_SELF_UPDATE") || envTruthy("DEEPLINE_NO_AUTO_UPDATE") || envTruthy("DEEPLINE_SKIP_SDK_AUTO_UPDATE") || envTruthy("DEEPLINE_DISABLE_AUTO_UPDATE") || isCi();
|
|
21319
|
+
}
|
|
21320
|
+
function relaunchCurrentCommand() {
|
|
21321
|
+
return new Promise((resolve16) => {
|
|
21322
|
+
const child = (0, import_node_child_process3.spawn)(process.execPath, process.argv.slice(1), {
|
|
21323
|
+
stdio: "inherit",
|
|
21324
|
+
env: {
|
|
21325
|
+
...process.env,
|
|
21326
|
+
DEEPLINE_NO_AUTO_UPDATE: "1"
|
|
21327
|
+
}
|
|
21328
|
+
});
|
|
21329
|
+
child.on("error", (error) => {
|
|
21330
|
+
process.stderr.write(
|
|
21331
|
+
`Deepline SDK/CLI updated, but relaunch failed: ${error.message}
|
|
21332
|
+
`
|
|
21333
|
+
);
|
|
21334
|
+
resolve16(1);
|
|
21335
|
+
});
|
|
21336
|
+
child.on("close", (code) => resolve16(code ?? 1));
|
|
21337
|
+
});
|
|
21338
|
+
}
|
|
21339
|
+
async function maybeAutoUpdateAndRelaunch(response) {
|
|
21340
|
+
const autoUpdate = response?.auto_update;
|
|
21341
|
+
if (!response || !autoUpdate?.should_auto_update || shouldSkipSelfUpdate()) {
|
|
21342
|
+
return false;
|
|
21343
|
+
}
|
|
21344
|
+
const plan = resolveUpdatePlan();
|
|
21345
|
+
if (plan.kind !== "npm-global") {
|
|
21346
|
+
return false;
|
|
21347
|
+
}
|
|
21348
|
+
const label = autoUpdate.required ? "requires an update" : "is more than the supported auto-update lag behind";
|
|
21349
|
+
process.stderr.write(
|
|
21350
|
+
`Deepline SDK/CLI ${label}; running ${plan.manualCommand}
|
|
21351
|
+
`
|
|
21352
|
+
);
|
|
21353
|
+
const updateExitCode = await runNpmGlobalUpdatePlan(plan);
|
|
21354
|
+
if (updateExitCode !== 0) {
|
|
21355
|
+
if (autoUpdate.required) {
|
|
21356
|
+
throw new Error(
|
|
21357
|
+
`Automatic Deepline SDK/CLI update failed with exit code ${updateExitCode}. ${response.message}`
|
|
21358
|
+
);
|
|
21359
|
+
}
|
|
21360
|
+
process.stderr.write(
|
|
21361
|
+
`Deepline SDK/CLI auto-update failed with exit code ${updateExitCode}; continuing with ${response.current ?? "current version"}.
|
|
21362
|
+
`
|
|
21363
|
+
);
|
|
21364
|
+
return false;
|
|
21365
|
+
}
|
|
21366
|
+
process.stderr.write("Deepline SDK/CLI updated; rerunning command.\n");
|
|
21367
|
+
const exitCode = await relaunchCurrentCommand();
|
|
21368
|
+
process.exit(exitCode);
|
|
21369
|
+
return true;
|
|
21370
|
+
}
|
|
21371
|
+
|
|
21041
21372
|
// src/cli/skills-sync.ts
|
|
21042
|
-
var
|
|
21373
|
+
var import_node_child_process4 = require("child_process");
|
|
21043
21374
|
var import_node_fs15 = require("fs");
|
|
21044
21375
|
var import_node_os11 = require("os");
|
|
21045
21376
|
var import_node_path19 = require("path");
|
|
21046
21377
|
var CHECK_TIMEOUT_MS2 = 3e3;
|
|
21047
21378
|
var SDK_SKILL_NAME = "deepline-plays";
|
|
21379
|
+
var SDK_SKILL_NAMES = [SDK_SKILL_NAME, "deepline-plays-quickstart"];
|
|
21048
21380
|
var attemptedSync = false;
|
|
21049
21381
|
function shouldSkipSkillsSync() {
|
|
21050
21382
|
const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
|
|
@@ -21161,19 +21493,19 @@ async function fetchSkillsUpdate(baseUrl, localVersion) {
|
|
|
21161
21493
|
}
|
|
21162
21494
|
}
|
|
21163
21495
|
function buildSkillsInstallArgs(baseUrl) {
|
|
21164
|
-
return buildSkillsAddArgs(baseUrl,
|
|
21496
|
+
return buildSkillsAddArgs(baseUrl, SDK_SKILL_NAMES);
|
|
21165
21497
|
}
|
|
21166
21498
|
function buildBunxSkillsInstallArgs(baseUrl) {
|
|
21167
|
-
return buildSkillsAddArgs(baseUrl,
|
|
21499
|
+
return buildSkillsAddArgs(baseUrl, SDK_SKILL_NAMES, { firstArg: "--bun" });
|
|
21168
21500
|
}
|
|
21169
21501
|
function hasCommand(command) {
|
|
21170
|
-
const result = (0,
|
|
21502
|
+
const result = (0, import_node_child_process4.spawnSync)(command, ["--version"], {
|
|
21171
21503
|
stdio: "ignore",
|
|
21172
21504
|
shell: process.platform === "win32"
|
|
21173
21505
|
});
|
|
21174
21506
|
return result.status === 0;
|
|
21175
21507
|
}
|
|
21176
|
-
function
|
|
21508
|
+
function shellQuote4(arg) {
|
|
21177
21509
|
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
21178
21510
|
}
|
|
21179
21511
|
function resolveSkillsInstallCommands(baseUrl) {
|
|
@@ -21181,7 +21513,7 @@ function resolveSkillsInstallCommands(baseUrl) {
|
|
|
21181
21513
|
const npxInstall = {
|
|
21182
21514
|
command: "npx",
|
|
21183
21515
|
args: npxArgs,
|
|
21184
|
-
manualCommand: `npx ${npxArgs.map(
|
|
21516
|
+
manualCommand: `npx ${npxArgs.map(shellQuote4).join(" ")}`
|
|
21185
21517
|
};
|
|
21186
21518
|
if (hasCommand("bunx")) {
|
|
21187
21519
|
const bunxArgs = buildBunxSkillsInstallArgs(baseUrl);
|
|
@@ -21189,7 +21521,7 @@ function resolveSkillsInstallCommands(baseUrl) {
|
|
|
21189
21521
|
{
|
|
21190
21522
|
command: "bunx",
|
|
21191
21523
|
args: bunxArgs,
|
|
21192
|
-
manualCommand: `bunx ${bunxArgs.map(
|
|
21524
|
+
manualCommand: `bunx ${bunxArgs.map(shellQuote4).join(" ")}`
|
|
21193
21525
|
},
|
|
21194
21526
|
npxInstall
|
|
21195
21527
|
];
|
|
@@ -21198,7 +21530,7 @@ function resolveSkillsInstallCommands(baseUrl) {
|
|
|
21198
21530
|
}
|
|
21199
21531
|
function runOneSkillsInstall(install) {
|
|
21200
21532
|
return new Promise((resolve16) => {
|
|
21201
|
-
const child = (0,
|
|
21533
|
+
const child = (0, import_node_child_process4.spawn)(install.command, install.args, {
|
|
21202
21534
|
stdio: ["ignore", "ignore", "pipe"],
|
|
21203
21535
|
env: process.env
|
|
21204
21536
|
});
|
|
@@ -21266,7 +21598,7 @@ async function syncSdkSkillsIfNeeded(baseUrl) {
|
|
|
21266
21598
|
if (!update?.needsUpdate && !hasStaleInstalledSkill || !update?.remoteVersion) {
|
|
21267
21599
|
return;
|
|
21268
21600
|
}
|
|
21269
|
-
writeSdkSkillsStatusLine("SDK skills changed; syncing
|
|
21601
|
+
writeSdkSkillsStatusLine("SDK skills changed; syncing Deepline SDK skills...");
|
|
21270
21602
|
const installed = await runSkillsInstall(baseUrl);
|
|
21271
21603
|
if (!installed) return;
|
|
21272
21604
|
if (installedSdkSkillHasStalePositionalExecuteExamples()) {
|
|
@@ -21489,7 +21821,9 @@ async function main() {
|
|
|
21489
21821
|
progress?.phase("loading deepline cli");
|
|
21490
21822
|
}
|
|
21491
21823
|
const program = new import_commander3.Command();
|
|
21492
|
-
program.name("deepline").description(
|
|
21824
|
+
program.name("deepline").description(
|
|
21825
|
+
"Deepline CLI \u2014 GTM enrichment tools, plays, and runs from your terminal."
|
|
21826
|
+
).version(SDK_VERSION, "-v, --version", "Show version").exitOverride().showHelpAfterError().showSuggestionAfterError(true).addHelpText(
|
|
21493
21827
|
"after",
|
|
21494
21828
|
`
|
|
21495
21829
|
Common commands:
|
|
@@ -21530,11 +21864,23 @@ Exit codes:
|
|
|
21530
21864
|
progress?.phase("checking sdk compatibility");
|
|
21531
21865
|
}
|
|
21532
21866
|
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
21533
|
-
await traceCliSpan(
|
|
21867
|
+
const compatibility = await traceCliSpan(
|
|
21534
21868
|
"cli.sdk_compatibility",
|
|
21535
|
-
{ baseUrl },
|
|
21536
|
-
() =>
|
|
21869
|
+
{ baseUrl, command: actionCommand.name() },
|
|
21870
|
+
() => checkSdkCompatibility(baseUrl, {
|
|
21871
|
+
command: actionCommand.name()
|
|
21872
|
+
})
|
|
21873
|
+
);
|
|
21874
|
+
if (compatibility.error) {
|
|
21875
|
+
return;
|
|
21876
|
+
}
|
|
21877
|
+
const relaunched = await maybeAutoUpdateAndRelaunch(
|
|
21878
|
+
compatibility.response
|
|
21537
21879
|
);
|
|
21880
|
+
if (relaunched) {
|
|
21881
|
+
return;
|
|
21882
|
+
}
|
|
21883
|
+
enforceSdkCompatibilityResponse(compatibility.response);
|
|
21538
21884
|
if (printStartupPhase) {
|
|
21539
21885
|
progress?.phase("checking sdk skills");
|
|
21540
21886
|
}
|
|
@@ -21559,6 +21905,7 @@ Exit codes:
|
|
|
21559
21905
|
registerDbCommands(program);
|
|
21560
21906
|
registerFeedbackCommands(program);
|
|
21561
21907
|
registerUpdateCommand(program);
|
|
21908
|
+
registerQuickstartCommands(program);
|
|
21562
21909
|
program.command("preflight").description("Run compact health, auth, and Deepline billing checks.").option("--json", "Force JSON output.").addHelpText(
|
|
21563
21910
|
"after",
|
|
21564
21911
|
`
|
|
@@ -21634,6 +21981,29 @@ Examples:
|
|
|
21634
21981
|
process.stdout.write(`deepline ${SDK_VERSION}
|
|
21635
21982
|
`);
|
|
21636
21983
|
});
|
|
21984
|
+
if (process.argv.slice(2).length === 0) {
|
|
21985
|
+
if (!process.stdout.isTTY) {
|
|
21986
|
+
printJson({
|
|
21987
|
+
ok: false,
|
|
21988
|
+
exitCode: 2,
|
|
21989
|
+
code: "MISSING_COMMAND",
|
|
21990
|
+
message: "No command provided.",
|
|
21991
|
+
next: "deepline --help"
|
|
21992
|
+
});
|
|
21993
|
+
console.error("error: missing command (see: deepline --help)");
|
|
21994
|
+
} else {
|
|
21995
|
+
program.outputHelp({ error: true });
|
|
21996
|
+
console.error("\nerror: missing command (see usage above)");
|
|
21997
|
+
}
|
|
21998
|
+
recordCliTrace({
|
|
21999
|
+
phase: "cli.main_total",
|
|
22000
|
+
ms: Date.now() - mainStartedAt,
|
|
22001
|
+
ok: false,
|
|
22002
|
+
error: "missing command"
|
|
22003
|
+
});
|
|
22004
|
+
process.exitCode = 2;
|
|
22005
|
+
return;
|
|
22006
|
+
}
|
|
21637
22007
|
try {
|
|
21638
22008
|
await program.parseAsync(process.argv);
|
|
21639
22009
|
recordCliTrace({
|