deepline 0.1.105 → 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 +417 -36
- package/dist/cli/index.mjs +413 -32
- package/dist/index.js +14 -3
- package/dist/index.mjs +14 -3
- package/dist/repo/sdk/src/release.ts +48 -7
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -218,12 +218,23 @@ var SDK_RELEASE = {
|
|
|
218
218
|
// 0.1.104 ships postgres_fast suspension/billing parity and runtime worker hardening.
|
|
219
219
|
// 0.1.105 ships the billing catalog surface: billing plans, subscribe,
|
|
220
220
|
// subscription status/cancel, invoices, and the client.billing namespace.
|
|
221
|
-
|
|
221
|
+
// 0.1.106 ships play cell provenance metadata and v2 preview retry hardening.
|
|
222
|
+
// 0.1.107 ships the v2 quickstart command, the deepline-plays-quickstart
|
|
223
|
+
// skill on the sdk sync surface, and the people-search-to-email prebuilt.
|
|
224
|
+
version: "0.1.107",
|
|
222
225
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
223
226
|
supportPolicy: {
|
|
224
|
-
latest: "0.1.
|
|
227
|
+
latest: "0.1.107",
|
|
225
228
|
minimumSupported: "0.1.53",
|
|
226
|
-
deprecatedBelow: "0.1.53"
|
|
229
|
+
deprecatedBelow: "0.1.53",
|
|
230
|
+
commandMinimumSupported: [
|
|
231
|
+
{
|
|
232
|
+
command: "enrich",
|
|
233
|
+
minimumSupported: "0.1.106",
|
|
234
|
+
reason: "Older SDK CLI enrich generated stale play source for the current dataset API."
|
|
235
|
+
}
|
|
236
|
+
],
|
|
237
|
+
autoUpdatePatchLag: 2
|
|
227
238
|
}
|
|
228
239
|
};
|
|
229
240
|
|
|
@@ -3145,7 +3156,7 @@ function shouldSkipCompatibilityCheck() {
|
|
|
3145
3156
|
const value = process.env.DEEPLINE_SKIP_SDK_COMPAT_CHECK?.trim().toLowerCase();
|
|
3146
3157
|
return value === "1" || value === "true" || value === "yes";
|
|
3147
3158
|
}
|
|
3148
|
-
async function checkSdkCompatibility(baseUrl) {
|
|
3159
|
+
async function checkSdkCompatibility(baseUrl, options = {}) {
|
|
3149
3160
|
if (shouldSkipCompatibilityCheck()) {
|
|
3150
3161
|
return { response: null, error: null };
|
|
3151
3162
|
}
|
|
@@ -3154,6 +3165,9 @@ async function checkSdkCompatibility(baseUrl) {
|
|
|
3154
3165
|
try {
|
|
3155
3166
|
const url = new URL("/api/v2/sdk/compat", baseUrl);
|
|
3156
3167
|
url.searchParams.set("version", SDK_VERSION);
|
|
3168
|
+
if (options.command?.trim()) {
|
|
3169
|
+
url.searchParams.set("command", options.command.trim());
|
|
3170
|
+
}
|
|
3157
3171
|
const response = await fetch(url, {
|
|
3158
3172
|
method: "GET",
|
|
3159
3173
|
headers: {
|
|
@@ -3174,9 +3188,8 @@ async function checkSdkCompatibility(baseUrl) {
|
|
|
3174
3188
|
clearTimeout(timeout);
|
|
3175
3189
|
}
|
|
3176
3190
|
}
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
if (error || !response) {
|
|
3191
|
+
function enforceSdkCompatibilityResponse(response) {
|
|
3192
|
+
if (!response) {
|
|
3180
3193
|
return;
|
|
3181
3194
|
}
|
|
3182
3195
|
if (response.update_required) {
|
|
@@ -12288,8 +12301,13 @@ function exportableSheetRow(row) {
|
|
|
12288
12301
|
function mergeExportColumns(preferredColumns, rows) {
|
|
12289
12302
|
const columns = [];
|
|
12290
12303
|
const seen = /* @__PURE__ */ new Set();
|
|
12304
|
+
const hasActualColumn = (column) => rows.some((row) => Object.prototype.hasOwnProperty.call(row, column));
|
|
12305
|
+
const hasCanonicalReplacement = (column) => {
|
|
12306
|
+
const canonical = sqlSafeExportColumnName(column);
|
|
12307
|
+
return canonical !== column && hasActualColumn(canonical);
|
|
12308
|
+
};
|
|
12291
12309
|
for (const column of preferredColumns) {
|
|
12292
|
-
if (!column || seen.has(column)) {
|
|
12310
|
+
if (!column || seen.has(column) || hasCanonicalReplacement(column)) {
|
|
12293
12311
|
continue;
|
|
12294
12312
|
}
|
|
12295
12313
|
seen.add(column);
|
|
@@ -12297,7 +12315,7 @@ function mergeExportColumns(preferredColumns, rows) {
|
|
|
12297
12315
|
}
|
|
12298
12316
|
for (const row of rows) {
|
|
12299
12317
|
for (const column of Object.keys(row)) {
|
|
12300
|
-
if (seen.has(column)) {
|
|
12318
|
+
if (seen.has(column) || hasCanonicalReplacement(column)) {
|
|
12301
12319
|
continue;
|
|
12302
12320
|
}
|
|
12303
12321
|
seen.add(column);
|
|
@@ -12306,6 +12324,11 @@ function mergeExportColumns(preferredColumns, rows) {
|
|
|
12306
12324
|
}
|
|
12307
12325
|
return columns;
|
|
12308
12326
|
}
|
|
12327
|
+
function sqlSafeExportColumnName(id) {
|
|
12328
|
+
const normalized = id.trim().replace(/\.+/g, "__").replace(/[^A-Za-z0-9_]+/g, "_").replace(/^_+|_+$/g, "").toLowerCase();
|
|
12329
|
+
const safe = normalized || "column";
|
|
12330
|
+
return /^[A-Za-z_]/.test(safe) ? safe : `c_${safe}`;
|
|
12331
|
+
}
|
|
12309
12332
|
async function fetchBackingDatasetRows(input2) {
|
|
12310
12333
|
const playName = extractRunPlayName(input2.status);
|
|
12311
12334
|
const tableNamespace = input2.rowsInfo.tableNamespace?.trim();
|
|
@@ -17957,6 +17980,244 @@ Examples:
|
|
|
17957
17980
|
).option("--org-id <id>", "Switch using an explicit organization id").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgSwitch);
|
|
17958
17981
|
}
|
|
17959
17982
|
|
|
17983
|
+
// src/cli/commands/quickstart.ts
|
|
17984
|
+
import { spawn, spawnSync } from "child_process";
|
|
17985
|
+
import { randomBytes } from "crypto";
|
|
17986
|
+
import { createServer } from "http";
|
|
17987
|
+
var EXIT_OK2 = 0;
|
|
17988
|
+
var EXIT_AUTH2 = 1;
|
|
17989
|
+
var EXIT_SERVER3 = 2;
|
|
17990
|
+
var MAX_PROMPT_LENGTH = 8e3;
|
|
17991
|
+
var MAX_BODY_BYTES = 64 * 1024;
|
|
17992
|
+
function shellQuote(arg) {
|
|
17993
|
+
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
17994
|
+
}
|
|
17995
|
+
function hasClaudeBinary() {
|
|
17996
|
+
try {
|
|
17997
|
+
const result = spawnSync("claude", ["--version"], {
|
|
17998
|
+
stdio: "ignore",
|
|
17999
|
+
shell: process.platform === "win32"
|
|
18000
|
+
});
|
|
18001
|
+
return result.status === 0;
|
|
18002
|
+
} catch {
|
|
18003
|
+
return false;
|
|
18004
|
+
}
|
|
18005
|
+
}
|
|
18006
|
+
function launchClaude(prompt) {
|
|
18007
|
+
return new Promise((resolve16) => {
|
|
18008
|
+
const child = spawn("claude", [prompt], {
|
|
18009
|
+
stdio: "inherit",
|
|
18010
|
+
shell: process.platform === "win32"
|
|
18011
|
+
});
|
|
18012
|
+
child.on("error", () => resolve16(EXIT_SERVER3));
|
|
18013
|
+
child.on("close", (status) => resolve16(status ?? EXIT_OK2));
|
|
18014
|
+
});
|
|
18015
|
+
}
|
|
18016
|
+
function readBody(req) {
|
|
18017
|
+
return new Promise((resolve16, reject) => {
|
|
18018
|
+
let raw = "";
|
|
18019
|
+
req.setEncoding("utf8");
|
|
18020
|
+
req.on("data", (chunk) => {
|
|
18021
|
+
raw += chunk;
|
|
18022
|
+
if (raw.length > MAX_BODY_BYTES) {
|
|
18023
|
+
reject(new Error("Request body too large."));
|
|
18024
|
+
req.destroy();
|
|
18025
|
+
}
|
|
18026
|
+
});
|
|
18027
|
+
req.on("end", () => resolve16(raw));
|
|
18028
|
+
req.on("error", reject);
|
|
18029
|
+
});
|
|
18030
|
+
}
|
|
18031
|
+
function writeJson(res, status, payload) {
|
|
18032
|
+
res.writeHead(status, { "content-type": "application/json" });
|
|
18033
|
+
res.end(JSON.stringify(payload));
|
|
18034
|
+
}
|
|
18035
|
+
function startCallbackServer(input2) {
|
|
18036
|
+
const server = createServer((req, res) => {
|
|
18037
|
+
res.setHeader("Access-Control-Allow-Origin", req.headers.origin ?? "*");
|
|
18038
|
+
res.setHeader("Vary", "Origin");
|
|
18039
|
+
res.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
|
|
18040
|
+
res.setHeader("Access-Control-Allow-Headers", "content-type");
|
|
18041
|
+
res.setHeader("Access-Control-Allow-Private-Network", "true");
|
|
18042
|
+
res.setHeader("Access-Control-Max-Age", "600");
|
|
18043
|
+
if (req.method === "OPTIONS") {
|
|
18044
|
+
res.writeHead(204);
|
|
18045
|
+
res.end();
|
|
18046
|
+
return;
|
|
18047
|
+
}
|
|
18048
|
+
if (req.method !== "POST" || req.url !== "/submit") {
|
|
18049
|
+
writeJson(res, 404, { error: "Not found." });
|
|
18050
|
+
return;
|
|
18051
|
+
}
|
|
18052
|
+
void readBody(req).then((raw) => {
|
|
18053
|
+
let body = null;
|
|
18054
|
+
try {
|
|
18055
|
+
body = JSON.parse(raw);
|
|
18056
|
+
} catch {
|
|
18057
|
+
body = null;
|
|
18058
|
+
}
|
|
18059
|
+
const state = typeof body?.state === "string" ? body.state : "";
|
|
18060
|
+
const prompt = typeof body?.prompt === "string" ? body.prompt.trim() : "";
|
|
18061
|
+
const workflowId = typeof body?.workflow_id === "string" && body.workflow_id.trim() ? body.workflow_id.trim() : null;
|
|
18062
|
+
if (!state || state !== input2.state) {
|
|
18063
|
+
writeJson(res, 403, { error: "Invalid quickstart state token." });
|
|
18064
|
+
return;
|
|
18065
|
+
}
|
|
18066
|
+
if (!prompt) {
|
|
18067
|
+
writeJson(res, 400, { error: "prompt is required." });
|
|
18068
|
+
return;
|
|
18069
|
+
}
|
|
18070
|
+
if (prompt.length > MAX_PROMPT_LENGTH) {
|
|
18071
|
+
writeJson(res, 400, {
|
|
18072
|
+
error: `prompt exceeds ${MAX_PROMPT_LENGTH} characters.`
|
|
18073
|
+
});
|
|
18074
|
+
return;
|
|
18075
|
+
}
|
|
18076
|
+
writeJson(res, 200, { ok: true });
|
|
18077
|
+
setImmediate(() => input2.onSelection({ prompt, workflowId }));
|
|
18078
|
+
}).catch(() => {
|
|
18079
|
+
writeJson(res, 400, { error: "Invalid request body." });
|
|
18080
|
+
});
|
|
18081
|
+
});
|
|
18082
|
+
return new Promise((resolve16, reject) => {
|
|
18083
|
+
server.once("error", reject);
|
|
18084
|
+
server.listen(0, "127.0.0.1", () => {
|
|
18085
|
+
const address = server.address();
|
|
18086
|
+
if (!address || typeof address === "string") {
|
|
18087
|
+
reject(new Error("Failed to bind quickstart callback server."));
|
|
18088
|
+
return;
|
|
18089
|
+
}
|
|
18090
|
+
resolve16({ server, port: address.port });
|
|
18091
|
+
});
|
|
18092
|
+
});
|
|
18093
|
+
}
|
|
18094
|
+
async function handleQuickstart(options) {
|
|
18095
|
+
const jsonOutput = shouldEmitJson(options.json === true);
|
|
18096
|
+
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
18097
|
+
const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
18098
|
+
let apiKey = resolveApiKeyForBaseUrl(baseUrl);
|
|
18099
|
+
if (!apiKey) {
|
|
18100
|
+
if (interactive) {
|
|
18101
|
+
console.error("Not connected yet \u2014 registering this device first.");
|
|
18102
|
+
const registerExit = await handleRegister([]);
|
|
18103
|
+
if (registerExit !== EXIT_OK2) return registerExit;
|
|
18104
|
+
apiKey = resolveApiKeyForBaseUrl(baseUrl);
|
|
18105
|
+
}
|
|
18106
|
+
if (!apiKey) {
|
|
18107
|
+
console.error("Not connected. Run: deepline auth register");
|
|
18108
|
+
return EXIT_AUTH2;
|
|
18109
|
+
}
|
|
18110
|
+
}
|
|
18111
|
+
const state = randomBytes(32).toString("hex");
|
|
18112
|
+
let resolveSelection;
|
|
18113
|
+
const selectionPromise = new Promise((resolve16) => {
|
|
18114
|
+
resolveSelection = resolve16;
|
|
18115
|
+
});
|
|
18116
|
+
let callback;
|
|
18117
|
+
try {
|
|
18118
|
+
callback = await startCallbackServer({
|
|
18119
|
+
state,
|
|
18120
|
+
onSelection: (selection) => resolveSelection(selection)
|
|
18121
|
+
});
|
|
18122
|
+
} catch (error) {
|
|
18123
|
+
console.error(
|
|
18124
|
+
`Could not start the local quickstart listener: ${error instanceof Error ? error.message : String(error)}`
|
|
18125
|
+
);
|
|
18126
|
+
return EXIT_SERVER3;
|
|
18127
|
+
}
|
|
18128
|
+
const quickstartUrl = `${baseUrl}/cli/quickstart?cb=${callback.port}&state=${state}`;
|
|
18129
|
+
console.error(" Opening the recipe picker in your browser.");
|
|
18130
|
+
console.error(` If it didn't open, cmd+click: ${quickstartUrl}`);
|
|
18131
|
+
if (options.open !== false) {
|
|
18132
|
+
openInBrowser(quickstartUrl);
|
|
18133
|
+
}
|
|
18134
|
+
const timeoutSeconds = Number.parseInt(options.timeout ?? "300", 10);
|
|
18135
|
+
const timeoutMs = (Number.isFinite(timeoutSeconds) && timeoutSeconds > 0 ? timeoutSeconds : 300) * 1e3;
|
|
18136
|
+
const timeoutHandle = setTimeout(
|
|
18137
|
+
() => resolveSelection("timeout"),
|
|
18138
|
+
timeoutMs
|
|
18139
|
+
);
|
|
18140
|
+
const progress = createCliProgress(!jsonOutput);
|
|
18141
|
+
progress.phase("waiting for your pick in the browser (Ctrl+C to skip)");
|
|
18142
|
+
const onSigint = () => resolveSelection("sigint");
|
|
18143
|
+
process.once("SIGINT", onSigint);
|
|
18144
|
+
const outcome = await selectionPromise;
|
|
18145
|
+
clearTimeout(timeoutHandle);
|
|
18146
|
+
process.removeListener("SIGINT", onSigint);
|
|
18147
|
+
callback.server.close();
|
|
18148
|
+
if (outcome === "sigint") {
|
|
18149
|
+
progress.fail();
|
|
18150
|
+
console.error("\nSkipped \u2014 run `deepline quickstart` anytime.");
|
|
18151
|
+
return EXIT_OK2;
|
|
18152
|
+
}
|
|
18153
|
+
if (outcome === "timeout") {
|
|
18154
|
+
progress.fail();
|
|
18155
|
+
console.error(
|
|
18156
|
+
"Timed out waiting for a selection. Run: deepline quickstart"
|
|
18157
|
+
);
|
|
18158
|
+
return EXIT_AUTH2;
|
|
18159
|
+
}
|
|
18160
|
+
progress.complete();
|
|
18161
|
+
const { prompt, workflowId } = outcome;
|
|
18162
|
+
const claudeCommand = `claude ${shellQuote(prompt)}`;
|
|
18163
|
+
const claudeAvailable = hasClaudeBinary();
|
|
18164
|
+
const willLaunch = options.launch !== false && !jsonOutput && interactive && claudeAvailable;
|
|
18165
|
+
printCommandEnvelope(
|
|
18166
|
+
{
|
|
18167
|
+
status: "submitted",
|
|
18168
|
+
workflowId,
|
|
18169
|
+
prompt,
|
|
18170
|
+
claudeCommand,
|
|
18171
|
+
url: quickstartUrl,
|
|
18172
|
+
launched: willLaunch,
|
|
18173
|
+
render: {
|
|
18174
|
+
sections: [
|
|
18175
|
+
{
|
|
18176
|
+
title: "quickstart",
|
|
18177
|
+
lines: [
|
|
18178
|
+
...workflowId ? [`Recipe: ${workflowId}`] : [],
|
|
18179
|
+
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."
|
|
18180
|
+
]
|
|
18181
|
+
}
|
|
18182
|
+
],
|
|
18183
|
+
actions: [{ label: "Run", command: claudeCommand }]
|
|
18184
|
+
}
|
|
18185
|
+
},
|
|
18186
|
+
{ json: jsonOutput }
|
|
18187
|
+
);
|
|
18188
|
+
if (willLaunch) {
|
|
18189
|
+
return launchClaude(prompt);
|
|
18190
|
+
}
|
|
18191
|
+
return EXIT_OK2;
|
|
18192
|
+
}
|
|
18193
|
+
function registerQuickstartCommands(program) {
|
|
18194
|
+
program.command("quickstart").description(
|
|
18195
|
+
"Pick a starter recipe in the browser and launch it with Claude Code."
|
|
18196
|
+
).addHelpText(
|
|
18197
|
+
"after",
|
|
18198
|
+
`
|
|
18199
|
+
Notes:
|
|
18200
|
+
Opens the hosted recipe picker in your browser. The picker sends your
|
|
18201
|
+
selection back to a temporary listener on 127.0.0.1, so the browser must run
|
|
18202
|
+
on the same machine as the CLI. Once a recipe arrives, the CLI prints the
|
|
18203
|
+
matching claude command and, when Claude Code is installed and the shell is
|
|
18204
|
+
interactive, launches it directly. Press Ctrl+C while waiting to skip.
|
|
18205
|
+
|
|
18206
|
+
Examples:
|
|
18207
|
+
deepline quickstart
|
|
18208
|
+
deepline quickstart --no-open
|
|
18209
|
+
deepline quickstart --no-launch --json
|
|
18210
|
+
deepline quickstart --timeout 120
|
|
18211
|
+
`
|
|
18212
|
+
).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(
|
|
18213
|
+
"--timeout <seconds>",
|
|
18214
|
+
"Maximum seconds to wait for a selection",
|
|
18215
|
+
"300"
|
|
18216
|
+
).action(async (options) => {
|
|
18217
|
+
process.exitCode = await handleQuickstart(options);
|
|
18218
|
+
});
|
|
18219
|
+
}
|
|
18220
|
+
|
|
17960
18221
|
// src/cli/commands/secrets.ts
|
|
17961
18222
|
import { stdin as input, stdout as output } from "process";
|
|
17962
18223
|
var hiddenInputBuffer = "";
|
|
@@ -19974,7 +20235,7 @@ function parseExecuteOptions(args) {
|
|
|
19974
20235
|
function safeFileStem(value) {
|
|
19975
20236
|
return value.trim().replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "tool";
|
|
19976
20237
|
}
|
|
19977
|
-
function
|
|
20238
|
+
function shellQuote2(value) {
|
|
19978
20239
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
19979
20240
|
}
|
|
19980
20241
|
function powerShellQuote(value) {
|
|
@@ -20026,7 +20287,7 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
|
|
|
20026
20287
|
path: scriptPath,
|
|
20027
20288
|
sourceCode: script,
|
|
20028
20289
|
projectDir,
|
|
20029
|
-
macCopyCommand: `mkdir -p ${
|
|
20290
|
+
macCopyCommand: `mkdir -p ${shellQuote2(projectDir)} && cp ${shellQuote2(scriptPath)} ${shellQuote2(`${projectDir}/${fileName}`)}`,
|
|
20030
20291
|
windowsCopyCommand: `New-Item -ItemType Directory -Force -Path ${powerShellQuote(projectDir.replace(/\//g, "\\"))} | Out-Null; Copy-Item -LiteralPath ${powerShellQuote(scriptPath)} -Destination ${powerShellQuote(`${projectDir.replace(/\//g, "\\")}\\${fileName}`)}`
|
|
20031
20292
|
};
|
|
20032
20293
|
}
|
|
@@ -20045,7 +20306,7 @@ function buildToolExecuteBaseEnvelope(input2) {
|
|
|
20045
20306
|
summary: input2.summary
|
|
20046
20307
|
};
|
|
20047
20308
|
const envelopeHasCanonicalOutput = isRecord7(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
|
|
20048
|
-
const inspectCommand = `deepline tools execute ${input2.toolId} --input ${
|
|
20309
|
+
const inspectCommand = `deepline tools execute ${input2.toolId} --input ${shellQuote2(JSON.stringify(input2.params))} --json`;
|
|
20049
20310
|
const actions = input2.listConversion ? [
|
|
20050
20311
|
{
|
|
20051
20312
|
label: "next",
|
|
@@ -20764,7 +21025,7 @@ Notes:
|
|
|
20764
21025
|
}
|
|
20765
21026
|
|
|
20766
21027
|
// src/cli/commands/update.ts
|
|
20767
|
-
import { spawn } from "child_process";
|
|
21028
|
+
import { spawn as spawn2 } from "child_process";
|
|
20768
21029
|
import { existsSync as existsSync10 } from "fs";
|
|
20769
21030
|
import { dirname as dirname11, join as join13, resolve as resolve15 } from "path";
|
|
20770
21031
|
function posixShellQuote(value) {
|
|
@@ -20773,14 +21034,14 @@ function posixShellQuote(value) {
|
|
|
20773
21034
|
function windowsCmdQuote(value) {
|
|
20774
21035
|
return `"${value.replace(/"/g, '""')}"`;
|
|
20775
21036
|
}
|
|
20776
|
-
function
|
|
21037
|
+
function shellQuote3(value) {
|
|
20777
21038
|
if (process.platform === "win32") {
|
|
20778
21039
|
return /^[A-Za-z0-9_./:@%+=,-]+$/.test(value) ? value : windowsCmdQuote(value);
|
|
20779
21040
|
}
|
|
20780
21041
|
return posixShellQuote(value);
|
|
20781
21042
|
}
|
|
20782
21043
|
function buildSourceUpdateCommand(sourceRoot) {
|
|
20783
|
-
const quotedRoot =
|
|
21044
|
+
const quotedRoot = shellQuote3(sourceRoot);
|
|
20784
21045
|
const cdCommand = process.platform === "win32" ? `cd /d ${quotedRoot}` : `cd ${quotedRoot}`;
|
|
20785
21046
|
return `${cdCommand} && git fetch origin main --tags && git merge --ff-only origin/main`;
|
|
20786
21047
|
}
|
|
@@ -20811,12 +21072,12 @@ function resolveUpdatePlan() {
|
|
|
20811
21072
|
kind: "npm-global",
|
|
20812
21073
|
command,
|
|
20813
21074
|
args,
|
|
20814
|
-
manualCommand: `${command} ${args.map(
|
|
21075
|
+
manualCommand: `${command} ${args.map(shellQuote3).join(" ")}`
|
|
20815
21076
|
};
|
|
20816
21077
|
}
|
|
20817
21078
|
function runCommand(command, args) {
|
|
20818
21079
|
return new Promise((resolveExitCode) => {
|
|
20819
|
-
const child =
|
|
21080
|
+
const child = spawn2(command, args, {
|
|
20820
21081
|
stdio: "inherit",
|
|
20821
21082
|
shell: process.platform === "win32",
|
|
20822
21083
|
env: process.env
|
|
@@ -20831,6 +21092,12 @@ function runCommand(command, args) {
|
|
|
20831
21092
|
});
|
|
20832
21093
|
});
|
|
20833
21094
|
}
|
|
21095
|
+
async function runNpmGlobalUpdatePlan(plan) {
|
|
21096
|
+
if (plan.kind !== "npm-global") {
|
|
21097
|
+
return 1;
|
|
21098
|
+
}
|
|
21099
|
+
return runCommand(plan.command, plan.args);
|
|
21100
|
+
}
|
|
20834
21101
|
async function handleUpdate(options) {
|
|
20835
21102
|
const plan = resolveUpdatePlan();
|
|
20836
21103
|
const render = {
|
|
@@ -20977,16 +21244,27 @@ function skillsIndexUrl(baseUrl) {
|
|
|
20977
21244
|
return `${normalizeBaseUrl2(baseUrl)}${INSTALL_COMMANDS.skills.index_path}`;
|
|
20978
21245
|
}
|
|
20979
21246
|
function buildSkillsAddArgs(baseUrl, skillName, options = {}) {
|
|
21247
|
+
const skillNames = Array.isArray(skillName) ? skillName : [skillName];
|
|
21248
|
+
const [firstSkillName, ...extraSkillNames] = skillNames;
|
|
20980
21249
|
const values = {
|
|
20981
21250
|
skills_index_url: skillsIndexUrl(baseUrl),
|
|
20982
21251
|
agents: INSTALL_COMMANDS.skills.default_agents.join(" "),
|
|
20983
|
-
skill_name:
|
|
21252
|
+
skill_name: firstSkillName ?? ""
|
|
20984
21253
|
};
|
|
20985
21254
|
const rendered = INSTALL_COMMANDS.skills.npx_add_args_template.flatMap(
|
|
20986
21255
|
(arg, index) => {
|
|
20987
21256
|
const next = index === 0 && options.firstArg ? options.firstArg : arg;
|
|
20988
21257
|
const value = renderTemplate(next, values);
|
|
20989
|
-
|
|
21258
|
+
if (arg === "{agents}") {
|
|
21259
|
+
return INSTALL_COMMANDS.skills.default_agents;
|
|
21260
|
+
}
|
|
21261
|
+
if (arg === "{skill_name}") {
|
|
21262
|
+
return [
|
|
21263
|
+
value,
|
|
21264
|
+
...extraSkillNames.flatMap((name) => ["--skill", name])
|
|
21265
|
+
];
|
|
21266
|
+
}
|
|
21267
|
+
return value;
|
|
20990
21268
|
}
|
|
20991
21269
|
);
|
|
20992
21270
|
return rendered;
|
|
@@ -21057,8 +21335,72 @@ function unknownCommandNameFromMessage(message) {
|
|
|
21057
21335
|
return command ? command : null;
|
|
21058
21336
|
}
|
|
21059
21337
|
|
|
21338
|
+
// src/cli/self-update.ts
|
|
21339
|
+
import { spawn as spawn3 } from "child_process";
|
|
21340
|
+
function envTruthy(name) {
|
|
21341
|
+
const value = process.env[name]?.trim().toLowerCase();
|
|
21342
|
+
return value === "1" || value === "true" || value === "yes";
|
|
21343
|
+
}
|
|
21344
|
+
function isCi() {
|
|
21345
|
+
return envTruthy("CI") || envTruthy("GITHUB_ACTIONS");
|
|
21346
|
+
}
|
|
21347
|
+
function shouldSkipSelfUpdate() {
|
|
21348
|
+
return envTruthy("DEEPLINE_SKIP_SELF_UPDATE") || envTruthy("DEEPLINE_NO_AUTO_UPDATE") || envTruthy("DEEPLINE_SKIP_SDK_AUTO_UPDATE") || envTruthy("DEEPLINE_DISABLE_AUTO_UPDATE") || isCi();
|
|
21349
|
+
}
|
|
21350
|
+
function relaunchCurrentCommand() {
|
|
21351
|
+
return new Promise((resolve16) => {
|
|
21352
|
+
const child = spawn3(process.execPath, process.argv.slice(1), {
|
|
21353
|
+
stdio: "inherit",
|
|
21354
|
+
env: {
|
|
21355
|
+
...process.env,
|
|
21356
|
+
DEEPLINE_NO_AUTO_UPDATE: "1"
|
|
21357
|
+
}
|
|
21358
|
+
});
|
|
21359
|
+
child.on("error", (error) => {
|
|
21360
|
+
process.stderr.write(
|
|
21361
|
+
`Deepline SDK/CLI updated, but relaunch failed: ${error.message}
|
|
21362
|
+
`
|
|
21363
|
+
);
|
|
21364
|
+
resolve16(1);
|
|
21365
|
+
});
|
|
21366
|
+
child.on("close", (code) => resolve16(code ?? 1));
|
|
21367
|
+
});
|
|
21368
|
+
}
|
|
21369
|
+
async function maybeAutoUpdateAndRelaunch(response) {
|
|
21370
|
+
const autoUpdate = response?.auto_update;
|
|
21371
|
+
if (!response || !autoUpdate?.should_auto_update || shouldSkipSelfUpdate()) {
|
|
21372
|
+
return false;
|
|
21373
|
+
}
|
|
21374
|
+
const plan = resolveUpdatePlan();
|
|
21375
|
+
if (plan.kind !== "npm-global") {
|
|
21376
|
+
return false;
|
|
21377
|
+
}
|
|
21378
|
+
const label = autoUpdate.required ? "requires an update" : "is more than the supported auto-update lag behind";
|
|
21379
|
+
process.stderr.write(
|
|
21380
|
+
`Deepline SDK/CLI ${label}; running ${plan.manualCommand}
|
|
21381
|
+
`
|
|
21382
|
+
);
|
|
21383
|
+
const updateExitCode = await runNpmGlobalUpdatePlan(plan);
|
|
21384
|
+
if (updateExitCode !== 0) {
|
|
21385
|
+
if (autoUpdate.required) {
|
|
21386
|
+
throw new Error(
|
|
21387
|
+
`Automatic Deepline SDK/CLI update failed with exit code ${updateExitCode}. ${response.message}`
|
|
21388
|
+
);
|
|
21389
|
+
}
|
|
21390
|
+
process.stderr.write(
|
|
21391
|
+
`Deepline SDK/CLI auto-update failed with exit code ${updateExitCode}; continuing with ${response.current ?? "current version"}.
|
|
21392
|
+
`
|
|
21393
|
+
);
|
|
21394
|
+
return false;
|
|
21395
|
+
}
|
|
21396
|
+
process.stderr.write("Deepline SDK/CLI updated; rerunning command.\n");
|
|
21397
|
+
const exitCode = await relaunchCurrentCommand();
|
|
21398
|
+
process.exit(exitCode);
|
|
21399
|
+
return true;
|
|
21400
|
+
}
|
|
21401
|
+
|
|
21060
21402
|
// src/cli/skills-sync.ts
|
|
21061
|
-
import { spawn as
|
|
21403
|
+
import { spawn as spawn4, spawnSync as spawnSync2 } from "child_process";
|
|
21062
21404
|
import {
|
|
21063
21405
|
existsSync as existsSync11,
|
|
21064
21406
|
mkdirSync as mkdirSync6,
|
|
@@ -21071,6 +21413,7 @@ import { homedir as homedir7 } from "os";
|
|
|
21071
21413
|
import { dirname as dirname12, join as join14 } from "path";
|
|
21072
21414
|
var CHECK_TIMEOUT_MS2 = 3e3;
|
|
21073
21415
|
var SDK_SKILL_NAME = "deepline-plays";
|
|
21416
|
+
var SDK_SKILL_NAMES = [SDK_SKILL_NAME, "deepline-plays-quickstart"];
|
|
21074
21417
|
var attemptedSync = false;
|
|
21075
21418
|
function shouldSkipSkillsSync() {
|
|
21076
21419
|
const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
|
|
@@ -21187,19 +21530,19 @@ async function fetchSkillsUpdate(baseUrl, localVersion) {
|
|
|
21187
21530
|
}
|
|
21188
21531
|
}
|
|
21189
21532
|
function buildSkillsInstallArgs(baseUrl) {
|
|
21190
|
-
return buildSkillsAddArgs(baseUrl,
|
|
21533
|
+
return buildSkillsAddArgs(baseUrl, SDK_SKILL_NAMES);
|
|
21191
21534
|
}
|
|
21192
21535
|
function buildBunxSkillsInstallArgs(baseUrl) {
|
|
21193
|
-
return buildSkillsAddArgs(baseUrl,
|
|
21536
|
+
return buildSkillsAddArgs(baseUrl, SDK_SKILL_NAMES, { firstArg: "--bun" });
|
|
21194
21537
|
}
|
|
21195
21538
|
function hasCommand(command) {
|
|
21196
|
-
const result =
|
|
21539
|
+
const result = spawnSync2(command, ["--version"], {
|
|
21197
21540
|
stdio: "ignore",
|
|
21198
21541
|
shell: process.platform === "win32"
|
|
21199
21542
|
});
|
|
21200
21543
|
return result.status === 0;
|
|
21201
21544
|
}
|
|
21202
|
-
function
|
|
21545
|
+
function shellQuote4(arg) {
|
|
21203
21546
|
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
21204
21547
|
}
|
|
21205
21548
|
function resolveSkillsInstallCommands(baseUrl) {
|
|
@@ -21207,7 +21550,7 @@ function resolveSkillsInstallCommands(baseUrl) {
|
|
|
21207
21550
|
const npxInstall = {
|
|
21208
21551
|
command: "npx",
|
|
21209
21552
|
args: npxArgs,
|
|
21210
|
-
manualCommand: `npx ${npxArgs.map(
|
|
21553
|
+
manualCommand: `npx ${npxArgs.map(shellQuote4).join(" ")}`
|
|
21211
21554
|
};
|
|
21212
21555
|
if (hasCommand("bunx")) {
|
|
21213
21556
|
const bunxArgs = buildBunxSkillsInstallArgs(baseUrl);
|
|
@@ -21215,7 +21558,7 @@ function resolveSkillsInstallCommands(baseUrl) {
|
|
|
21215
21558
|
{
|
|
21216
21559
|
command: "bunx",
|
|
21217
21560
|
args: bunxArgs,
|
|
21218
|
-
manualCommand: `bunx ${bunxArgs.map(
|
|
21561
|
+
manualCommand: `bunx ${bunxArgs.map(shellQuote4).join(" ")}`
|
|
21219
21562
|
},
|
|
21220
21563
|
npxInstall
|
|
21221
21564
|
];
|
|
@@ -21224,7 +21567,7 @@ function resolveSkillsInstallCommands(baseUrl) {
|
|
|
21224
21567
|
}
|
|
21225
21568
|
function runOneSkillsInstall(install) {
|
|
21226
21569
|
return new Promise((resolve16) => {
|
|
21227
|
-
const child =
|
|
21570
|
+
const child = spawn4(install.command, install.args, {
|
|
21228
21571
|
stdio: ["ignore", "ignore", "pipe"],
|
|
21229
21572
|
env: process.env
|
|
21230
21573
|
});
|
|
@@ -21292,7 +21635,7 @@ async function syncSdkSkillsIfNeeded(baseUrl) {
|
|
|
21292
21635
|
if (!update?.needsUpdate && !hasStaleInstalledSkill || !update?.remoteVersion) {
|
|
21293
21636
|
return;
|
|
21294
21637
|
}
|
|
21295
|
-
writeSdkSkillsStatusLine("SDK skills changed; syncing
|
|
21638
|
+
writeSdkSkillsStatusLine("SDK skills changed; syncing Deepline SDK skills...");
|
|
21296
21639
|
const installed = await runSkillsInstall(baseUrl);
|
|
21297
21640
|
if (!installed) return;
|
|
21298
21641
|
if (installedSdkSkillHasStalePositionalExecuteExamples()) {
|
|
@@ -21515,7 +21858,9 @@ async function main() {
|
|
|
21515
21858
|
progress?.phase("loading deepline cli");
|
|
21516
21859
|
}
|
|
21517
21860
|
const program = new Command3();
|
|
21518
|
-
program.name("deepline").description(
|
|
21861
|
+
program.name("deepline").description(
|
|
21862
|
+
"Deepline CLI \u2014 GTM enrichment tools, plays, and runs from your terminal."
|
|
21863
|
+
).version(SDK_VERSION, "-v, --version", "Show version").exitOverride().showHelpAfterError().showSuggestionAfterError(true).addHelpText(
|
|
21519
21864
|
"after",
|
|
21520
21865
|
`
|
|
21521
21866
|
Common commands:
|
|
@@ -21556,11 +21901,23 @@ Exit codes:
|
|
|
21556
21901
|
progress?.phase("checking sdk compatibility");
|
|
21557
21902
|
}
|
|
21558
21903
|
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
21559
|
-
await traceCliSpan(
|
|
21904
|
+
const compatibility = await traceCliSpan(
|
|
21560
21905
|
"cli.sdk_compatibility",
|
|
21561
|
-
{ baseUrl },
|
|
21562
|
-
() =>
|
|
21906
|
+
{ baseUrl, command: actionCommand.name() },
|
|
21907
|
+
() => checkSdkCompatibility(baseUrl, {
|
|
21908
|
+
command: actionCommand.name()
|
|
21909
|
+
})
|
|
21910
|
+
);
|
|
21911
|
+
if (compatibility.error) {
|
|
21912
|
+
return;
|
|
21913
|
+
}
|
|
21914
|
+
const relaunched = await maybeAutoUpdateAndRelaunch(
|
|
21915
|
+
compatibility.response
|
|
21563
21916
|
);
|
|
21917
|
+
if (relaunched) {
|
|
21918
|
+
return;
|
|
21919
|
+
}
|
|
21920
|
+
enforceSdkCompatibilityResponse(compatibility.response);
|
|
21564
21921
|
if (printStartupPhase) {
|
|
21565
21922
|
progress?.phase("checking sdk skills");
|
|
21566
21923
|
}
|
|
@@ -21585,6 +21942,7 @@ Exit codes:
|
|
|
21585
21942
|
registerDbCommands(program);
|
|
21586
21943
|
registerFeedbackCommands(program);
|
|
21587
21944
|
registerUpdateCommand(program);
|
|
21945
|
+
registerQuickstartCommands(program);
|
|
21588
21946
|
program.command("preflight").description("Run compact health, auth, and Deepline billing checks.").option("--json", "Force JSON output.").addHelpText(
|
|
21589
21947
|
"after",
|
|
21590
21948
|
`
|
|
@@ -21660,6 +22018,29 @@ Examples:
|
|
|
21660
22018
|
process.stdout.write(`deepline ${SDK_VERSION}
|
|
21661
22019
|
`);
|
|
21662
22020
|
});
|
|
22021
|
+
if (process.argv.slice(2).length === 0) {
|
|
22022
|
+
if (!process.stdout.isTTY) {
|
|
22023
|
+
printJson({
|
|
22024
|
+
ok: false,
|
|
22025
|
+
exitCode: 2,
|
|
22026
|
+
code: "MISSING_COMMAND",
|
|
22027
|
+
message: "No command provided.",
|
|
22028
|
+
next: "deepline --help"
|
|
22029
|
+
});
|
|
22030
|
+
console.error("error: missing command (see: deepline --help)");
|
|
22031
|
+
} else {
|
|
22032
|
+
program.outputHelp({ error: true });
|
|
22033
|
+
console.error("\nerror: missing command (see usage above)");
|
|
22034
|
+
}
|
|
22035
|
+
recordCliTrace({
|
|
22036
|
+
phase: "cli.main_total",
|
|
22037
|
+
ms: Date.now() - mainStartedAt,
|
|
22038
|
+
ok: false,
|
|
22039
|
+
error: "missing command"
|
|
22040
|
+
});
|
|
22041
|
+
process.exitCode = 2;
|
|
22042
|
+
return;
|
|
22043
|
+
}
|
|
21663
22044
|
try {
|
|
21664
22045
|
await program.parseAsync(process.argv);
|
|
21665
22046
|
recordCliTrace({
|
package/dist/index.js
CHANGED
|
@@ -269,12 +269,23 @@ var SDK_RELEASE = {
|
|
|
269
269
|
// 0.1.104 ships postgres_fast suspension/billing parity and runtime worker hardening.
|
|
270
270
|
// 0.1.105 ships the billing catalog surface: billing plans, subscribe,
|
|
271
271
|
// subscription status/cancel, invoices, and the client.billing namespace.
|
|
272
|
-
|
|
272
|
+
// 0.1.106 ships play cell provenance metadata and v2 preview retry hardening.
|
|
273
|
+
// 0.1.107 ships the v2 quickstart command, the deepline-plays-quickstart
|
|
274
|
+
// skill on the sdk sync surface, and the people-search-to-email prebuilt.
|
|
275
|
+
version: "0.1.107",
|
|
273
276
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
274
277
|
supportPolicy: {
|
|
275
|
-
latest: "0.1.
|
|
278
|
+
latest: "0.1.107",
|
|
276
279
|
minimumSupported: "0.1.53",
|
|
277
|
-
deprecatedBelow: "0.1.53"
|
|
280
|
+
deprecatedBelow: "0.1.53",
|
|
281
|
+
commandMinimumSupported: [
|
|
282
|
+
{
|
|
283
|
+
command: "enrich",
|
|
284
|
+
minimumSupported: "0.1.106",
|
|
285
|
+
reason: "Older SDK CLI enrich generated stale play source for the current dataset API."
|
|
286
|
+
}
|
|
287
|
+
],
|
|
288
|
+
autoUpdatePatchLag: 2
|
|
278
289
|
}
|
|
279
290
|
};
|
|
280
291
|
|