deepline 0.1.260 → 0.1.262
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/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/gateway-auth-session.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +2 -8
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +147 -40
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +57 -71
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +8 -0
- package/dist/bundling-sources/shared_libs/plays/tool-category-descriptions.ts +51 -0
- package/dist/cli/index.js +715 -168
- package/dist/cli/index.mjs +726 -179
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -701,7 +701,7 @@ var SDK_RELEASE = {
|
|
|
701
701
|
// Deepline-native radars. Older clients must update before discovering,
|
|
702
702
|
// checking, or deploying an unlaunched monitor integration.
|
|
703
703
|
// 0.1.253 makes play-page browser opening opt-in and retires --no-open.
|
|
704
|
-
version: "0.1.
|
|
704
|
+
version: "0.1.262",
|
|
705
705
|
apiContract: "2026-07-native-monitor-launch-hard-cutover",
|
|
706
706
|
supportPolicy: {
|
|
707
707
|
minimumSupported: "0.1.53",
|
|
@@ -26664,6 +26664,33 @@ function extractSummaryFields(payload) {
|
|
|
26664
26664
|
return {};
|
|
26665
26665
|
}
|
|
26666
26666
|
|
|
26667
|
+
// ../shared_libs/plays/tool-category-descriptions.ts
|
|
26668
|
+
var TOOL_CATEGORY_DESCRIPTIONS = {
|
|
26669
|
+
company_search: "Find companies matching firmographic, ad, or web criteria.",
|
|
26670
|
+
people_search: "Find people matching role, company, or persona criteria.",
|
|
26671
|
+
people_enrich: "Enrich a known person with contact, social, and profile data.",
|
|
26672
|
+
company_enrich: "Enrich a known company with firmographic and account data.",
|
|
26673
|
+
email_finder: "Find work or personal email addresses for a person.",
|
|
26674
|
+
email_verify: "Validate email deliverability and catch-all status.",
|
|
26675
|
+
phone_finder: "Find mobile or direct phone numbers for a person.",
|
|
26676
|
+
phone_verify: "Validate phone-number reachability and line type.",
|
|
26677
|
+
research: "Research accounts, people, news, and signals for context and scoring.",
|
|
26678
|
+
autocomplete: "Resolve names and entities to canonical catalog records.",
|
|
26679
|
+
automation: "Kick off provider-side jobs, exports, and asynchronous workflows.",
|
|
26680
|
+
outbound_tools: "Run outbound sequencing, deliverability, and campaign operations.",
|
|
26681
|
+
admin: "Provider-side status, metadata, and account operations behind other tools.",
|
|
26682
|
+
smb: "Look up small-business listings, local records, and public filings.",
|
|
26683
|
+
identity_resolution: "Match a partial identity to a single resolved person or company.",
|
|
26684
|
+
reverse_lookup: "Resolve an email, phone, or profile back to a person.",
|
|
26685
|
+
enrichment: "General-purpose record enrichment across people and companies.",
|
|
26686
|
+
batch: "Run an enrichment or search operation over many rows at once.",
|
|
26687
|
+
premium: "Higher-cost tools with premium provider coverage.",
|
|
26688
|
+
free: "Free tools that do not spend Deepline credits."
|
|
26689
|
+
};
|
|
26690
|
+
function describeToolCategory(category) {
|
|
26691
|
+
return TOOL_CATEGORY_DESCRIPTIONS[category] ?? null;
|
|
26692
|
+
}
|
|
26693
|
+
|
|
26667
26694
|
// src/cli/commands/model-description.ts
|
|
26668
26695
|
function formatModelDescription(description) {
|
|
26669
26696
|
const lines = [];
|
|
@@ -26830,21 +26857,181 @@ function zeroMatchRender(emptyResult) {
|
|
|
26830
26857
|
]
|
|
26831
26858
|
};
|
|
26832
26859
|
}
|
|
26833
|
-
|
|
26860
|
+
function firstSentence(text) {
|
|
26861
|
+
const clean = (text ?? "").replace(/\s+/g, " ").trim();
|
|
26862
|
+
if (!clean) return "";
|
|
26863
|
+
const match = clean.match(/^.*?[.!?](?=\s|$)/);
|
|
26864
|
+
return (match ? match[0] : clean).trim();
|
|
26865
|
+
}
|
|
26866
|
+
function requiredInputIds(tool) {
|
|
26867
|
+
const inputSchema = recordField2(
|
|
26868
|
+
tool,
|
|
26869
|
+
"inputSchema",
|
|
26870
|
+
"input_schema"
|
|
26871
|
+
);
|
|
26872
|
+
return toolInputFieldsForDisplay(inputSchema).filter((field) => field.required === true).map((field) => String(field.name ?? "")).filter(Boolean);
|
|
26873
|
+
}
|
|
26874
|
+
function shortPricingHint(tool) {
|
|
26875
|
+
const pricing = recordField2(
|
|
26876
|
+
tool,
|
|
26877
|
+
"pricing"
|
|
26878
|
+
);
|
|
26879
|
+
const credits = numberField2(pricing, "creditsPerUnit", "credits_per_unit");
|
|
26880
|
+
const unit = stringField2(pricing, "unit");
|
|
26881
|
+
if (credits !== null) {
|
|
26882
|
+
return `${formatDecimal(credits)} cr/${unit || "unit"}`;
|
|
26883
|
+
}
|
|
26884
|
+
const summary = stringField2(pricing, "summary");
|
|
26885
|
+
if (summary) return summary;
|
|
26886
|
+
const displayText = stringField2(pricing, "displayText", "display_text");
|
|
26887
|
+
return displayText || null;
|
|
26888
|
+
}
|
|
26889
|
+
function aggregateCategorySummaries(tools) {
|
|
26890
|
+
const counts = /* @__PURE__ */ new Map();
|
|
26891
|
+
for (const tool of tools) {
|
|
26892
|
+
for (const category of tool.categories ?? []) {
|
|
26893
|
+
counts.set(category, (counts.get(category) ?? 0) + 1);
|
|
26894
|
+
}
|
|
26895
|
+
}
|
|
26896
|
+
return [...counts.entries()].map(([name, count]) => ({
|
|
26897
|
+
name,
|
|
26898
|
+
count,
|
|
26899
|
+
description: describeToolCategory(name)
|
|
26900
|
+
})).sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
|
|
26901
|
+
}
|
|
26902
|
+
function categoryEnumerationRender(summaries) {
|
|
26903
|
+
const nameWidth = summaries.reduce(
|
|
26904
|
+
(max, item) => Math.max(max, item.name.length),
|
|
26905
|
+
0
|
|
26906
|
+
);
|
|
26907
|
+
const countWidth = summaries.reduce(
|
|
26908
|
+
(max, item) => Math.max(max, String(item.count).length),
|
|
26909
|
+
0
|
|
26910
|
+
);
|
|
26911
|
+
return {
|
|
26912
|
+
sections: [
|
|
26913
|
+
{
|
|
26914
|
+
title: `${summaries.length} tool categories:`,
|
|
26915
|
+
lines: summaries.map((item) => {
|
|
26916
|
+
const name = item.name.padEnd(nameWidth);
|
|
26917
|
+
const count = String(item.count).padStart(countWidth);
|
|
26918
|
+
const definition = item.description ? ` - ${item.description}` : "";
|
|
26919
|
+
return `${name} ${count}${definition}`;
|
|
26920
|
+
})
|
|
26921
|
+
},
|
|
26922
|
+
{
|
|
26923
|
+
title: "next",
|
|
26924
|
+
lines: ["Pass a category: deepline tools list email_finder"]
|
|
26925
|
+
}
|
|
26926
|
+
]
|
|
26927
|
+
};
|
|
26928
|
+
}
|
|
26929
|
+
async function listToolCategories(emitJson, compact) {
|
|
26930
|
+
const client2 = new DeeplineClient();
|
|
26931
|
+
const rawTools = await client2.listTools({ compact });
|
|
26932
|
+
const items = rawTools.map(toListedTool);
|
|
26933
|
+
const summaries = aggregateCategorySummaries(rawTools);
|
|
26934
|
+
const outputItems = compact ? items.map(compactTool) : items;
|
|
26935
|
+
printCommandEnvelope(
|
|
26936
|
+
{
|
|
26937
|
+
tools: outputItems,
|
|
26938
|
+
count: outputItems.length,
|
|
26939
|
+
categories: summaries,
|
|
26940
|
+
filters: {
|
|
26941
|
+
categories: []
|
|
26942
|
+
},
|
|
26943
|
+
commandTemplates: TOOL_COMMAND_TEMPLATES,
|
|
26944
|
+
render: categoryEnumerationRender(summaries)
|
|
26945
|
+
},
|
|
26946
|
+
{ json: emitJson }
|
|
26947
|
+
);
|
|
26948
|
+
return 0;
|
|
26949
|
+
}
|
|
26950
|
+
function unknownCategoryError(category, summaries, emitJson) {
|
|
26951
|
+
const known = summaries.map((item) => item.name);
|
|
26952
|
+
const message = `Unknown tool category "${category}". Run \`deepline tools list\` to browse categories.`;
|
|
26953
|
+
if (emitJson) {
|
|
26954
|
+
printJson({
|
|
26955
|
+
ok: false,
|
|
26956
|
+
exitCode: 4,
|
|
26957
|
+
code: "TOOL_CATEGORY_NOT_FOUND",
|
|
26958
|
+
message,
|
|
26959
|
+
category,
|
|
26960
|
+
categories: summaries,
|
|
26961
|
+
next: "deepline tools list"
|
|
26962
|
+
});
|
|
26963
|
+
return 4;
|
|
26964
|
+
}
|
|
26965
|
+
const render = categoryEnumerationRender(summaries);
|
|
26966
|
+
console.error(message);
|
|
26967
|
+
console.error("");
|
|
26968
|
+
console.error(renderCommandEnvelopeText({ render }).trimEnd());
|
|
26969
|
+
console.error("");
|
|
26970
|
+
console.error(`Valid categories: ${known.join(", ")}`);
|
|
26971
|
+
return 4;
|
|
26972
|
+
}
|
|
26973
|
+
async function listToolsInCategory(category, emitJson) {
|
|
26974
|
+
const client2 = new DeeplineClient();
|
|
26975
|
+
const rawTools = await client2.listTools({
|
|
26976
|
+
categories: category,
|
|
26977
|
+
compact: false
|
|
26978
|
+
});
|
|
26979
|
+
const allTools = await client2.listTools({ compact: true });
|
|
26980
|
+
const summaries = aggregateCategorySummaries(allTools);
|
|
26981
|
+
if (!summaries.some((item) => item.name === category)) {
|
|
26982
|
+
return unknownCategoryError(category, summaries, emitJson);
|
|
26983
|
+
}
|
|
26984
|
+
const rows = rawTools.filter((tool) => tool.categories?.includes(category)).map((tool) => ({
|
|
26985
|
+
id: tool.toolId,
|
|
26986
|
+
provider: tool.provider,
|
|
26987
|
+
required: requiredInputIds(tool),
|
|
26988
|
+
pricing: shortPricingHint(tool),
|
|
26989
|
+
description: firstSentence(tool.description)
|
|
26990
|
+
})).sort((a, b) => a.id.localeCompare(b.id));
|
|
26991
|
+
const idWidth = rows.reduce((max, row) => Math.max(max, row.id.length), 0);
|
|
26992
|
+
const render = {
|
|
26993
|
+
sections: [
|
|
26994
|
+
{
|
|
26995
|
+
title: `${rows.length} tools in ${category}:`,
|
|
26996
|
+
lines: rows.map((row) => {
|
|
26997
|
+
const id = row.id.padEnd(idWidth);
|
|
26998
|
+
const required = row.required.length ? `(${row.required.join(", ")})` : "(no required inputs)";
|
|
26999
|
+
const pricing = row.pricing ? ` [${row.pricing}]` : "";
|
|
27000
|
+
const description = row.description ? ` - ${row.description}` : "";
|
|
27001
|
+
return `${id} ${required}${pricing}${description}`;
|
|
27002
|
+
})
|
|
27003
|
+
},
|
|
27004
|
+
{
|
|
27005
|
+
title: "next",
|
|
27006
|
+
lines: [
|
|
27007
|
+
"Run `deepline tools describe <toolId>` for the full contract."
|
|
27008
|
+
]
|
|
27009
|
+
}
|
|
27010
|
+
]
|
|
27011
|
+
};
|
|
27012
|
+
printCommandEnvelope(
|
|
27013
|
+
{
|
|
27014
|
+
category,
|
|
27015
|
+
total: rows.length,
|
|
27016
|
+
tools: rows,
|
|
27017
|
+
commandTemplates: TOOL_COMMAND_TEMPLATES,
|
|
27018
|
+
render
|
|
27019
|
+
},
|
|
27020
|
+
{ json: emitJson }
|
|
27021
|
+
);
|
|
27022
|
+
return 0;
|
|
27023
|
+
}
|
|
27024
|
+
async function listToolsForCategoryFilter(requestedCategories, emitJson, compact) {
|
|
26834
27025
|
const client2 = new DeeplineClient();
|
|
26835
|
-
const categoryArgIndex = args.findIndex((arg) => arg === "--categories");
|
|
26836
|
-
const categoryFilter = categoryArgIndex >= 0 ? args[categoryArgIndex + 1] : "";
|
|
26837
|
-
const compact = !args.includes("--full");
|
|
26838
|
-
const requestedCategories = categoryFilter ? categoryFilter.split(",").map((item) => item.trim()).filter(Boolean) : [];
|
|
26839
27026
|
const items = (await client2.listTools({
|
|
26840
|
-
|
|
27027
|
+
categories: requestedCategories.join(","),
|
|
26841
27028
|
compact
|
|
26842
27029
|
})).map(toListedTool).filter(
|
|
26843
|
-
(item) => requestedCategories.
|
|
27030
|
+
(item) => requestedCategories.some(
|
|
26844
27031
|
(category) => item.categories.includes(category)
|
|
26845
27032
|
)
|
|
26846
27033
|
);
|
|
26847
|
-
const emptyResult = items.length === 0
|
|
27034
|
+
const emptyResult = items.length === 0 ? zeroMatchToolGuidance({ categories: requestedCategories }) : null;
|
|
26848
27035
|
const render = {
|
|
26849
27036
|
sections: emptyResult ? zeroMatchRender(emptyResult).sections : [
|
|
26850
27037
|
{
|
|
@@ -26875,10 +27062,41 @@ async function listTools(args) {
|
|
|
26875
27062
|
commandTemplates: TOOL_COMMAND_TEMPLATES,
|
|
26876
27063
|
render
|
|
26877
27064
|
},
|
|
26878
|
-
{ json:
|
|
27065
|
+
{ json: emitJson }
|
|
26879
27066
|
);
|
|
26880
27067
|
return 0;
|
|
26881
27068
|
}
|
|
27069
|
+
async function listTools(category, options = {}) {
|
|
27070
|
+
const positional = category?.trim() ?? "";
|
|
27071
|
+
const flagCategories = (options.categories ?? "").split(",").map((item) => item.trim()).filter(Boolean);
|
|
27072
|
+
const compact = options.compact !== false;
|
|
27073
|
+
const emitJson = options.json === true || shouldEmitJson();
|
|
27074
|
+
if (positional && flagCategories.length > 0) {
|
|
27075
|
+
const flagIsSameSingle = flagCategories.length === 1 && flagCategories[0] === positional;
|
|
27076
|
+
if (!flagIsSameSingle) {
|
|
27077
|
+
const message = `Category "${positional}" and --categories ${flagCategories.join(",")} disagree. Pass one: deepline tools list ${positional}`;
|
|
27078
|
+
if (emitJson) {
|
|
27079
|
+
printJson({
|
|
27080
|
+
ok: false,
|
|
27081
|
+
exitCode: 2,
|
|
27082
|
+
code: "TOOL_LIST_CATEGORY_CONFLICT",
|
|
27083
|
+
message,
|
|
27084
|
+
next: `deepline tools list ${positional}`
|
|
27085
|
+
});
|
|
27086
|
+
} else {
|
|
27087
|
+
console.error(message);
|
|
27088
|
+
}
|
|
27089
|
+
return 2;
|
|
27090
|
+
}
|
|
27091
|
+
}
|
|
27092
|
+
if (positional) {
|
|
27093
|
+
return listToolsInCategory(positional, emitJson);
|
|
27094
|
+
}
|
|
27095
|
+
if (flagCategories.length > 0) {
|
|
27096
|
+
return listToolsForCategoryFilter(flagCategories, emitJson, compact);
|
|
27097
|
+
}
|
|
27098
|
+
return listToolCategories(emitJson, compact);
|
|
27099
|
+
}
|
|
26882
27100
|
async function searchTools(queryInput, options = {}) {
|
|
26883
27101
|
const query = queryInput?.trim() ?? "";
|
|
26884
27102
|
const hasStructuredSearch = Boolean(
|
|
@@ -27077,27 +27295,37 @@ Output:
|
|
|
27077
27295
|
Use execute to run a tool.
|
|
27078
27296
|
`
|
|
27079
27297
|
);
|
|
27080
|
-
tools.command("list").description("
|
|
27298
|
+
tools.command("list [category]").description("Browse tool categories, or list every tool in a category.").addHelpText(
|
|
27081
27299
|
"after",
|
|
27082
27300
|
`
|
|
27083
27301
|
Notes:
|
|
27084
|
-
|
|
27085
|
-
|
|
27302
|
+
Bare \`tools list\` prints the category enumeration: one line per category with
|
|
27303
|
+
its tool count and definition. Pass a category to list every tool in it, one
|
|
27304
|
+
succinct row each (required inputs, Deepline pricing hint, first sentence).
|
|
27305
|
+
The listing is exhaustive and never truncated. Use search for ranked discovery
|
|
27306
|
+
by intent, aliases, descriptions, and schema fields.
|
|
27307
|
+
|
|
27308
|
+
--categories is a back-compat inventory filter. Passing it alone returns the
|
|
27309
|
+
legacy flat inventory envelope (one row per tool). The positional category is
|
|
27310
|
+
the newer exhaustive per-category view. If both are given they must name the
|
|
27311
|
+
same category (the positional view wins); otherwise it is a usage error.
|
|
27086
27312
|
|
|
27087
27313
|
Examples:
|
|
27088
27314
|
deepline tools list
|
|
27315
|
+
deepline tools list email_finder
|
|
27316
|
+
deepline tools list email_finder --json
|
|
27089
27317
|
deepline tools list --categories email_finder --json
|
|
27090
27318
|
deepline tools search email --json
|
|
27091
27319
|
`
|
|
27092
27320
|
).option(
|
|
27093
27321
|
"--categories <categories>",
|
|
27094
|
-
"Comma-separated categories
|
|
27095
|
-
).option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
27096
|
-
process.exitCode = await listTools(
|
|
27097
|
-
|
|
27098
|
-
|
|
27099
|
-
|
|
27100
|
-
|
|
27322
|
+
"Comma-separated categories filter (back-compat alias for the positional)"
|
|
27323
|
+
).option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (category, options) => {
|
|
27324
|
+
process.exitCode = await listTools(category, {
|
|
27325
|
+
categories: typeof options.categories === "string" ? options.categories : void 0,
|
|
27326
|
+
compact: options.compact !== false,
|
|
27327
|
+
json: Boolean(options.json)
|
|
27328
|
+
});
|
|
27101
27329
|
});
|
|
27102
27330
|
const addToolSearchCommand = (command) => command.description(
|
|
27103
27331
|
"Search available tools by intent query or structured filters."
|
|
@@ -28940,7 +29168,7 @@ import {
|
|
|
28940
29168
|
existsSync as existsSync12,
|
|
28941
29169
|
mkdirSync as mkdirSync10,
|
|
28942
29170
|
realpathSync as realpathSync3,
|
|
28943
|
-
readFileSync as
|
|
29171
|
+
readFileSync as readFileSync13,
|
|
28944
29172
|
renameSync,
|
|
28945
29173
|
rmSync as rmSync4,
|
|
28946
29174
|
unlinkSync,
|
|
@@ -28951,7 +29179,7 @@ import { dirname as dirname13, isAbsolute as isAbsolute3, join as join15, relati
|
|
|
28951
29179
|
|
|
28952
29180
|
// src/cli/commands/skills.ts
|
|
28953
29181
|
import { spawn as spawn3 } from "child_process";
|
|
28954
|
-
import { existsSync as existsSync11, mkdirSync as mkdirSync9, writeFileSync as writeFileSync14 } from "fs";
|
|
29182
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync14 } from "fs";
|
|
28955
29183
|
import { homedir as homedir11 } from "os";
|
|
28956
29184
|
import { dirname as dirname12, join as join14 } from "path";
|
|
28957
29185
|
|
|
@@ -29163,10 +29391,13 @@ function buildSkillsPlan(input2) {
|
|
|
29163
29391
|
skillNames: input2.skillNames,
|
|
29164
29392
|
version: input2.version,
|
|
29165
29393
|
remove: {
|
|
29166
|
-
command: "
|
|
29394
|
+
command: "npm",
|
|
29167
29395
|
args: [
|
|
29396
|
+
"exec",
|
|
29168
29397
|
"--yes",
|
|
29169
|
-
"skills@latest",
|
|
29398
|
+
"--package=skills@latest",
|
|
29399
|
+
"--",
|
|
29400
|
+
"skills",
|
|
29170
29401
|
"remove",
|
|
29171
29402
|
...scopeArgs,
|
|
29172
29403
|
"--agent",
|
|
@@ -29176,10 +29407,13 @@ function buildSkillsPlan(input2) {
|
|
|
29176
29407
|
]
|
|
29177
29408
|
},
|
|
29178
29409
|
install: {
|
|
29179
|
-
command: "
|
|
29410
|
+
command: "npm",
|
|
29180
29411
|
args: [
|
|
29412
|
+
"exec",
|
|
29181
29413
|
"--yes",
|
|
29182
|
-
"skills@latest",
|
|
29414
|
+
"--package=skills@latest",
|
|
29415
|
+
"--",
|
|
29416
|
+
"skills",
|
|
29183
29417
|
"add",
|
|
29184
29418
|
skillsIndexUrl(input2.baseUrl),
|
|
29185
29419
|
"--agent",
|
|
@@ -29193,6 +29427,29 @@ function buildSkillsPlan(input2) {
|
|
|
29193
29427
|
statePath: skillsStatePathForScope(input2.baseUrl, input2.scope, input2.root)
|
|
29194
29428
|
};
|
|
29195
29429
|
}
|
|
29430
|
+
function sortedStrings(value) {
|
|
29431
|
+
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
|
|
29432
|
+
return null;
|
|
29433
|
+
}
|
|
29434
|
+
return [...value].sort((a, b) => a.localeCompare(b));
|
|
29435
|
+
}
|
|
29436
|
+
function isSkillsPlanCurrent(plan, state) {
|
|
29437
|
+
if (!state || state.scope !== plan.scope || state.skillsVersion !== plan.version) {
|
|
29438
|
+
return false;
|
|
29439
|
+
}
|
|
29440
|
+
const installedAgents = sortedStrings(state.agents);
|
|
29441
|
+
const installedSkillNames = sortedStrings(state.skillNames);
|
|
29442
|
+
if (!installedAgents || !installedSkillNames) return false;
|
|
29443
|
+
return installedAgents.join("\0") === [...plan.agents].sort((a, b) => a.localeCompare(b)).join("\0") && installedSkillNames.join("\0") === [...plan.skillNames].sort((a, b) => a.localeCompare(b)).join("\0");
|
|
29444
|
+
}
|
|
29445
|
+
function readSkillsInstallState(path) {
|
|
29446
|
+
try {
|
|
29447
|
+
const parsed = JSON.parse(readFileSync12(path, "utf8"));
|
|
29448
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
29449
|
+
} catch {
|
|
29450
|
+
return null;
|
|
29451
|
+
}
|
|
29452
|
+
}
|
|
29196
29453
|
function runProcess(command, args, cwd) {
|
|
29197
29454
|
return new Promise((resolve15, reject) => {
|
|
29198
29455
|
const child = spawn3(command, args, {
|
|
@@ -29216,7 +29473,7 @@ function runProcess(command, args, cwd) {
|
|
|
29216
29473
|
});
|
|
29217
29474
|
});
|
|
29218
29475
|
}
|
|
29219
|
-
async function runSkillsCommand(options) {
|
|
29476
|
+
async function runSkillsCommand(options, dependencies = {}) {
|
|
29220
29477
|
let scope;
|
|
29221
29478
|
let root;
|
|
29222
29479
|
try {
|
|
@@ -29238,7 +29495,7 @@ async function runSkillsCommand(options) {
|
|
|
29238
29495
|
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
29239
29496
|
let catalog;
|
|
29240
29497
|
try {
|
|
29241
|
-
catalog = options.dryRun ? { skillNames: [...DEFAULT_SDK_SKILL_NAMES], version: "latest" } : await fetchSkillCatalog(baseUrl);
|
|
29498
|
+
catalog = options.dryRun ? { skillNames: [...DEFAULT_SDK_SKILL_NAMES], version: "latest" } : await (dependencies.fetchCatalog ?? fetchSkillCatalog)(baseUrl);
|
|
29242
29499
|
} catch (error) {
|
|
29243
29500
|
printCommandEnvelope(
|
|
29244
29501
|
{
|
|
@@ -29262,6 +29519,37 @@ async function runSkillsCommand(options) {
|
|
|
29262
29519
|
);
|
|
29263
29520
|
return 0;
|
|
29264
29521
|
}
|
|
29522
|
+
if (isSkillsPlanCurrent(plan, readSkillsInstallState(plan.statePath))) {
|
|
29523
|
+
printCommandEnvelope(
|
|
29524
|
+
{
|
|
29525
|
+
ok: true,
|
|
29526
|
+
status: "current",
|
|
29527
|
+
complete: true,
|
|
29528
|
+
changed: false,
|
|
29529
|
+
skipped: true,
|
|
29530
|
+
skipReason: "skills_version_current",
|
|
29531
|
+
scope,
|
|
29532
|
+
agents,
|
|
29533
|
+
skillsVersion: plan.version,
|
|
29534
|
+
skillCount: plan.skillNames.length,
|
|
29535
|
+
statePath: plan.statePath,
|
|
29536
|
+
render: {
|
|
29537
|
+
sections: [
|
|
29538
|
+
{
|
|
29539
|
+
title: "skills",
|
|
29540
|
+
lines: [
|
|
29541
|
+
`Scope: ${scope}`,
|
|
29542
|
+
`Agents: ${agents.join(", ")}`,
|
|
29543
|
+
`Current: ${plan.skillNames.length}`
|
|
29544
|
+
]
|
|
29545
|
+
}
|
|
29546
|
+
]
|
|
29547
|
+
}
|
|
29548
|
+
},
|
|
29549
|
+
{ json: options.json }
|
|
29550
|
+
);
|
|
29551
|
+
return 0;
|
|
29552
|
+
}
|
|
29265
29553
|
if (scope === "local" && root) {
|
|
29266
29554
|
const managedNames = [
|
|
29267
29555
|
.../* @__PURE__ */ new Set([...plan.skillNames, ...LEGACY_SKILL_NAMES_TO_REMOVE])
|
|
@@ -29279,7 +29567,8 @@ async function runSkillsCommand(options) {
|
|
|
29279
29567
|
`
|
|
29280
29568
|
);
|
|
29281
29569
|
try {
|
|
29282
|
-
const
|
|
29570
|
+
const execute = dependencies.runProcess ?? runProcess;
|
|
29571
|
+
const removeCode = await execute(
|
|
29283
29572
|
plan.remove.command,
|
|
29284
29573
|
plan.remove.args,
|
|
29285
29574
|
root ?? void 0
|
|
@@ -29287,7 +29576,7 @@ async function runSkillsCommand(options) {
|
|
|
29287
29576
|
if (removeCode !== 0) {
|
|
29288
29577
|
throw new Error("Could not remove the existing Deepline skills.");
|
|
29289
29578
|
}
|
|
29290
|
-
const installCode = await
|
|
29579
|
+
const installCode = await execute(
|
|
29291
29580
|
plan.install.command,
|
|
29292
29581
|
plan.install.args,
|
|
29293
29582
|
root ?? void 0
|
|
@@ -29456,7 +29745,7 @@ function publicNpmFallbackRegistryUrl(hostUrl) {
|
|
|
29456
29745
|
}
|
|
29457
29746
|
function readOptionalText(path) {
|
|
29458
29747
|
try {
|
|
29459
|
-
return
|
|
29748
|
+
return readFileSync13(path, "utf8").trim();
|
|
29460
29749
|
} catch {
|
|
29461
29750
|
return "";
|
|
29462
29751
|
}
|
|
@@ -29596,7 +29885,7 @@ function readAutoUpdateFailure(plan) {
|
|
|
29596
29885
|
if (!path) return null;
|
|
29597
29886
|
try {
|
|
29598
29887
|
const parsed = JSON.parse(
|
|
29599
|
-
|
|
29888
|
+
readFileSync13(path, "utf8")
|
|
29600
29889
|
);
|
|
29601
29890
|
if ((parsed.kind === "npm-global" || parsed.kind === "python-sidecar") && typeof parsed.packageSpec === "string" && typeof parsed.failedAt === "string" && typeof parsed.exitCode === "number" && typeof parsed.manualCommand === "string") {
|
|
29602
29891
|
return parsed;
|
|
@@ -29680,7 +29969,7 @@ function installedPackageVersion(versionDir) {
|
|
|
29680
29969
|
"package.json"
|
|
29681
29970
|
);
|
|
29682
29971
|
try {
|
|
29683
|
-
const parsed = JSON.parse(
|
|
29972
|
+
const parsed = JSON.parse(readFileSync13(packageJsonPath, "utf8"));
|
|
29684
29973
|
return typeof parsed.version === "string" ? safeVersionSegment(parsed.version) : "";
|
|
29685
29974
|
} catch {
|
|
29686
29975
|
return "";
|
|
@@ -29993,13 +30282,92 @@ import {
|
|
|
29993
30282
|
existsSync as existsSync13,
|
|
29994
30283
|
lstatSync,
|
|
29995
30284
|
mkdirSync as mkdirSync11,
|
|
29996
|
-
readFileSync as
|
|
30285
|
+
readFileSync as readFileSync14,
|
|
29997
30286
|
realpathSync as realpathSync4,
|
|
29998
30287
|
rmSync as rmSync5,
|
|
29999
30288
|
writeFileSync as writeFileSync16
|
|
30000
30289
|
} from "fs";
|
|
30001
30290
|
import { homedir as homedir13 } from "os";
|
|
30002
30291
|
import { dirname as dirname14, join as join16, resolve as resolve14 } from "path";
|
|
30292
|
+
var SETUP_PHASE_NAMES = [
|
|
30293
|
+
"cli",
|
|
30294
|
+
"cleanup",
|
|
30295
|
+
"skills",
|
|
30296
|
+
"auth",
|
|
30297
|
+
"verify"
|
|
30298
|
+
];
|
|
30299
|
+
function initialSetupPhases() {
|
|
30300
|
+
return {
|
|
30301
|
+
cli: { status: "pending" },
|
|
30302
|
+
cleanup: { status: "pending" },
|
|
30303
|
+
skills: { status: "pending" },
|
|
30304
|
+
auth: { status: "pending" },
|
|
30305
|
+
verify: { status: "pending" }
|
|
30306
|
+
};
|
|
30307
|
+
}
|
|
30308
|
+
function isSetupPhaseStatus(value) {
|
|
30309
|
+
return value === "pending" || value === "in_progress" || value === "complete" || value === "waiting" || value === "failed";
|
|
30310
|
+
}
|
|
30311
|
+
function parseSetupPhases(value) {
|
|
30312
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
30313
|
+
const source = value;
|
|
30314
|
+
const phases = initialSetupPhases();
|
|
30315
|
+
for (const name of SETUP_PHASE_NAMES) {
|
|
30316
|
+
const phase = source[name];
|
|
30317
|
+
if (!phase || typeof phase !== "object" || Array.isArray(phase)) {
|
|
30318
|
+
return null;
|
|
30319
|
+
}
|
|
30320
|
+
const record = phase;
|
|
30321
|
+
if (!isSetupPhaseStatus(record.status)) return null;
|
|
30322
|
+
phases[name] = {
|
|
30323
|
+
status: record.status,
|
|
30324
|
+
...typeof record.outcome === "string" ? { outcome: record.outcome } : {},
|
|
30325
|
+
...typeof record.code === "string" ? { code: record.code } : {}
|
|
30326
|
+
};
|
|
30327
|
+
}
|
|
30328
|
+
return phases;
|
|
30329
|
+
}
|
|
30330
|
+
function phasesFromLegacyStatus(status) {
|
|
30331
|
+
const phases = initialSetupPhases();
|
|
30332
|
+
if (status === "skills_installed" || status === "authorization_pending" || status === "complete") {
|
|
30333
|
+
phases.cli = { status: "complete" };
|
|
30334
|
+
phases.cleanup = { status: "complete" };
|
|
30335
|
+
phases.skills = { status: "complete" };
|
|
30336
|
+
}
|
|
30337
|
+
if (status === "authorization_pending") {
|
|
30338
|
+
phases.auth = { status: "waiting", outcome: "authorization_pending" };
|
|
30339
|
+
} else if (status === "complete") {
|
|
30340
|
+
phases.auth = { status: "complete" };
|
|
30341
|
+
phases.verify = { status: "complete" };
|
|
30342
|
+
}
|
|
30343
|
+
return phases;
|
|
30344
|
+
}
|
|
30345
|
+
function readSetupState(input2) {
|
|
30346
|
+
try {
|
|
30347
|
+
const parsed = JSON.parse(
|
|
30348
|
+
readFileSync14(
|
|
30349
|
+
setupStatePath(input2.baseUrl, input2.scope, input2.root),
|
|
30350
|
+
"utf8"
|
|
30351
|
+
)
|
|
30352
|
+
);
|
|
30353
|
+
if (parsed.host !== input2.baseUrl || parsed.scope !== input2.scope || parsed.root !== input2.root || typeof parsed.status !== "string") {
|
|
30354
|
+
return null;
|
|
30355
|
+
}
|
|
30356
|
+
return {
|
|
30357
|
+
status: parsed.status,
|
|
30358
|
+
phases: parseSetupPhases(parsed.phases) ?? phasesFromLegacyStatus(parsed.status)
|
|
30359
|
+
};
|
|
30360
|
+
} catch {
|
|
30361
|
+
return null;
|
|
30362
|
+
}
|
|
30363
|
+
}
|
|
30364
|
+
function selectSetupProgress(previousState) {
|
|
30365
|
+
const resumed = Boolean(previousState && previousState.status !== "complete");
|
|
30366
|
+
return {
|
|
30367
|
+
resumed,
|
|
30368
|
+
phases: resumed ? previousState.phases : initialSetupPhases()
|
|
30369
|
+
};
|
|
30370
|
+
}
|
|
30003
30371
|
function normalizeScope2(value) {
|
|
30004
30372
|
if (!value || value === "global") return "global";
|
|
30005
30373
|
if (value === "local") return "local";
|
|
@@ -30059,7 +30427,7 @@ function printCapturedAuthorizationUrl(stdout) {
|
|
|
30059
30427
|
}
|
|
30060
30428
|
function safeRead(path) {
|
|
30061
30429
|
try {
|
|
30062
|
-
return
|
|
30430
|
+
return readFileSync14(path, "utf8");
|
|
30063
30431
|
} catch {
|
|
30064
30432
|
return "";
|
|
30065
30433
|
}
|
|
@@ -30170,13 +30538,14 @@ function writeSetupState(input2) {
|
|
|
30170
30538
|
path,
|
|
30171
30539
|
`${JSON.stringify(
|
|
30172
30540
|
{
|
|
30173
|
-
schemaVersion:
|
|
30541
|
+
schemaVersion: 2,
|
|
30174
30542
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30175
30543
|
cliVersion: SDK_VERSION,
|
|
30176
30544
|
host: input2.baseUrl,
|
|
30177
30545
|
scope: input2.scope,
|
|
30178
30546
|
root: input2.root,
|
|
30179
|
-
status: input2.status
|
|
30547
|
+
status: input2.status,
|
|
30548
|
+
phases: input2.phases
|
|
30180
30549
|
},
|
|
30181
30550
|
null,
|
|
30182
30551
|
2
|
|
@@ -30186,6 +30555,24 @@ function writeSetupState(input2) {
|
|
|
30186
30555
|
);
|
|
30187
30556
|
return path;
|
|
30188
30557
|
}
|
|
30558
|
+
function persistSetupProgress(input2) {
|
|
30559
|
+
return writeSetupState({
|
|
30560
|
+
...input2,
|
|
30561
|
+
status: input2.status ?? "in_progress"
|
|
30562
|
+
});
|
|
30563
|
+
}
|
|
30564
|
+
function completeSetupPhase(phases, phase, outcome) {
|
|
30565
|
+
phases[phase] = {
|
|
30566
|
+
status: "complete",
|
|
30567
|
+
...outcome ? { outcome } : {}
|
|
30568
|
+
};
|
|
30569
|
+
}
|
|
30570
|
+
function beginSetupPhase(phases, phase) {
|
|
30571
|
+
phases[phase] = { status: "in_progress" };
|
|
30572
|
+
}
|
|
30573
|
+
function failSetupPhase(phases, phase, code) {
|
|
30574
|
+
phases[phase] = { status: "failed", code };
|
|
30575
|
+
}
|
|
30189
30576
|
function rollbackCommand(scope, root) {
|
|
30190
30577
|
const prefix = scope === "local" && root ? ` --prefix ${JSON.stringify(join16(root, ".deepline", "runtime"))}` : "";
|
|
30191
30578
|
return `npm install -g${prefix} --no-audit --no-fund --include=optional --allow-scripts=esbuild deepline@${SDK_VERSION}`;
|
|
@@ -30197,6 +30584,42 @@ function setupResumeCommand(baseUrl, scope) {
|
|
|
30197
30584
|
const hostPrefix = baseUrl === "https://code.deepline.com" ? "" : `DEEPLINE_HOST_URL=${JSON.stringify(baseUrl)} `;
|
|
30198
30585
|
return `${hostPrefix}deepline setup --scope ${scope} --json`;
|
|
30199
30586
|
}
|
|
30587
|
+
function setupRetry(input2) {
|
|
30588
|
+
return {
|
|
30589
|
+
phase: input2.phase,
|
|
30590
|
+
command: setupResumeCommand(input2.baseUrl, input2.scope),
|
|
30591
|
+
automatic: true
|
|
30592
|
+
};
|
|
30593
|
+
}
|
|
30594
|
+
function reportSetupPhaseFailure(input2) {
|
|
30595
|
+
failSetupPhase(input2.phases, input2.phase, input2.code);
|
|
30596
|
+
const statePath = persistSetupProgress({
|
|
30597
|
+
baseUrl: input2.baseUrl,
|
|
30598
|
+
scope: input2.scope,
|
|
30599
|
+
root: input2.root,
|
|
30600
|
+
phases: input2.phases,
|
|
30601
|
+
status: "failed"
|
|
30602
|
+
});
|
|
30603
|
+
const retry = setupRetry(input2);
|
|
30604
|
+
printCommandEnvelope(
|
|
30605
|
+
{
|
|
30606
|
+
ok: false,
|
|
30607
|
+
status: "failed",
|
|
30608
|
+
code: input2.code,
|
|
30609
|
+
exitCode: input2.exitCode,
|
|
30610
|
+
scope: input2.scope,
|
|
30611
|
+
message: input2.message,
|
|
30612
|
+
phases: input2.phases,
|
|
30613
|
+
failedPhase: input2.phase,
|
|
30614
|
+
retry,
|
|
30615
|
+
statePath,
|
|
30616
|
+
next: retry.command,
|
|
30617
|
+
...input2.extra ?? {}
|
|
30618
|
+
},
|
|
30619
|
+
{ json: input2.json }
|
|
30620
|
+
);
|
|
30621
|
+
return input2.exitCode;
|
|
30622
|
+
}
|
|
30200
30623
|
async function readAuthStatus(authScope) {
|
|
30201
30624
|
try {
|
|
30202
30625
|
const captured = await captureStdout2(
|
|
@@ -30216,63 +30639,44 @@ async function readAuthStatus(authScope) {
|
|
|
30216
30639
|
}
|
|
30217
30640
|
function reportSetupAuthStatusFailure(input2) {
|
|
30218
30641
|
if (!input2.auth.error) return null;
|
|
30219
|
-
|
|
30220
|
-
|
|
30221
|
-
|
|
30222
|
-
|
|
30223
|
-
|
|
30224
|
-
|
|
30225
|
-
|
|
30226
|
-
|
|
30227
|
-
|
|
30228
|
-
|
|
30229
|
-
}
|
|
30230
|
-
|
|
30231
|
-
);
|
|
30232
|
-
return 4;
|
|
30642
|
+
return reportSetupPhaseFailure({
|
|
30643
|
+
baseUrl: input2.baseUrl,
|
|
30644
|
+
scope: input2.scope,
|
|
30645
|
+
root: input2.root,
|
|
30646
|
+
phases: input2.phases,
|
|
30647
|
+
phase: "auth",
|
|
30648
|
+
code: "AUTH_STATUS_FAILED",
|
|
30649
|
+
exitCode: 4,
|
|
30650
|
+
message: "Deepline could not verify authorization with the configured host.",
|
|
30651
|
+
json: input2.json,
|
|
30652
|
+
extra: { authScope: input2.authScope }
|
|
30653
|
+
});
|
|
30233
30654
|
}
|
|
30234
|
-
|
|
30235
|
-
|
|
30236
|
-
|
|
30237
|
-
|
|
30238
|
-
|
|
30239
|
-
|
|
30240
|
-
} catch (error) {
|
|
30241
|
-
printCommandEnvelope(
|
|
30242
|
-
{
|
|
30243
|
-
ok: false,
|
|
30244
|
-
status: "failed",
|
|
30245
|
-
code: "INVALID_SETUP_SCOPE",
|
|
30246
|
-
exitCode: 2,
|
|
30247
|
-
message: error instanceof Error ? error.message : String(error)
|
|
30248
|
-
},
|
|
30249
|
-
{ json: options.json }
|
|
30250
|
-
);
|
|
30251
|
-
return 2;
|
|
30252
|
-
}
|
|
30253
|
-
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
30254
|
-
const skillsStatePath = skillsStatePathForScope(baseUrl, scope, root);
|
|
30655
|
+
function buildDoctorAssessment(input2) {
|
|
30656
|
+
const skillsStatePath = skillsStatePathForScope(
|
|
30657
|
+
input2.baseUrl,
|
|
30658
|
+
input2.scope,
|
|
30659
|
+
input2.root
|
|
30660
|
+
);
|
|
30255
30661
|
const skillsState = parseCapturedJson(safeRead(skillsStatePath));
|
|
30256
|
-
const
|
|
30257
|
-
const
|
|
30258
|
-
const
|
|
30259
|
-
const
|
|
30260
|
-
const
|
|
30261
|
-
const authScopeOk = scope === "local" ? Boolean(projectAuth) : Boolean(apiKey && !projectAuth);
|
|
30262
|
-
const skillsOk = skillsState?.scope === scope && Array.isArray(skillsState.agents) && skillsState.agents.length > 0;
|
|
30662
|
+
const apiKey = input2.scope === "local" ? resolveProjectApiKeyForBaseUrl(input2.baseUrl) : resolveGlobalApiKeyForBaseUrl(input2.baseUrl);
|
|
30663
|
+
const projectAuth = input2.scope === "local" && apiKey ? getResolvedProjectAuthSource(input2.baseUrl, apiKey) : null;
|
|
30664
|
+
const connected = input2.authStatus.payload?.connected === true;
|
|
30665
|
+
const authScopeOk = input2.scope === "local" ? Boolean(projectAuth) : Boolean(apiKey && !projectAuth);
|
|
30666
|
+
const skillsOk = skillsState?.scope === input2.scope && typeof skillsState.skillsVersion === "string" && Array.isArray(skillsState.agents) && skillsState.agents.length > 0;
|
|
30263
30667
|
const runningCliPath = process.argv[1] ? resolve14(process.argv[1]) : null;
|
|
30264
|
-
const globalCli = scope === "global" ? inspectGlobalCliAvailability() : null;
|
|
30668
|
+
const globalCli = input2.scope === "global" ? inspectGlobalCliAvailability() : null;
|
|
30265
30669
|
const pathGlobalCli = globalCli?.path ?? null;
|
|
30266
|
-
const cliPath = scope === "global" ? pathGlobalCli : runningCliPath;
|
|
30267
|
-
const cliScopeOk = scope === "global" ? Boolean(pathGlobalCli) : Boolean(
|
|
30268
|
-
root && runningCliPath?.includes(join16(root, ".deepline", "runtime"))
|
|
30670
|
+
const cliPath = input2.scope === "global" ? pathGlobalCli : runningCliPath;
|
|
30671
|
+
const cliScopeOk = input2.scope === "global" ? Boolean(pathGlobalCli) : Boolean(
|
|
30672
|
+
input2.root && runningCliPath?.includes(join16(input2.root, ".deepline", "runtime"))
|
|
30269
30673
|
);
|
|
30270
30674
|
const checks = {
|
|
30271
30675
|
cli: {
|
|
30272
30676
|
ok: Boolean(cliPath) && cliScopeOk,
|
|
30273
30677
|
version: SDK_VERSION,
|
|
30274
30678
|
path: cliPath,
|
|
30275
|
-
scope
|
|
30679
|
+
scope: input2.scope
|
|
30276
30680
|
},
|
|
30277
30681
|
skills: {
|
|
30278
30682
|
ok: skillsOk,
|
|
@@ -30283,16 +30687,48 @@ async function runDoctorCommand(options) {
|
|
|
30283
30687
|
auth: {
|
|
30284
30688
|
ok: connected && authScopeOk,
|
|
30285
30689
|
scope: projectAuth ? "local" : apiKey ? "global" : null,
|
|
30286
|
-
status: authStatus.payload?.status ?? "not_connected"
|
|
30690
|
+
status: input2.authStatus.payload?.status ?? "not_connected"
|
|
30287
30691
|
},
|
|
30288
30692
|
api: {
|
|
30289
|
-
ok: connected && authStatus.exitCode === 0,
|
|
30290
|
-
host: baseUrl,
|
|
30291
|
-
workspace: authStatus.payload?.workspace ?? null,
|
|
30693
|
+
ok: connected && input2.authStatus.exitCode === 0,
|
|
30694
|
+
host: input2.baseUrl,
|
|
30695
|
+
workspace: input2.authStatus.payload?.workspace ?? null,
|
|
30292
30696
|
providerSpend: false
|
|
30293
30697
|
}
|
|
30294
30698
|
};
|
|
30295
|
-
|
|
30699
|
+
return {
|
|
30700
|
+
ok: Object.values(checks).every((check) => check.ok),
|
|
30701
|
+
checks
|
|
30702
|
+
};
|
|
30703
|
+
}
|
|
30704
|
+
async function runDoctorCommand(options) {
|
|
30705
|
+
let scope;
|
|
30706
|
+
let root;
|
|
30707
|
+
try {
|
|
30708
|
+
scope = normalizeScope2(options.scope);
|
|
30709
|
+
root = resolveScopeRoot(scope);
|
|
30710
|
+
} catch (error) {
|
|
30711
|
+
printCommandEnvelope(
|
|
30712
|
+
{
|
|
30713
|
+
ok: false,
|
|
30714
|
+
status: "failed",
|
|
30715
|
+
code: "INVALID_SETUP_SCOPE",
|
|
30716
|
+
exitCode: 2,
|
|
30717
|
+
message: error instanceof Error ? error.message : String(error)
|
|
30718
|
+
},
|
|
30719
|
+
{ json: options.json }
|
|
30720
|
+
);
|
|
30721
|
+
return 2;
|
|
30722
|
+
}
|
|
30723
|
+
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
30724
|
+
const authScope = authScopeForSetup(scope);
|
|
30725
|
+
const authStatus = await readAuthStatus(authScope);
|
|
30726
|
+
const { ok, checks } = buildDoctorAssessment({
|
|
30727
|
+
baseUrl,
|
|
30728
|
+
scope,
|
|
30729
|
+
root,
|
|
30730
|
+
authStatus
|
|
30731
|
+
});
|
|
30296
30732
|
const quickstart = setupQuickstartCommand(baseUrl);
|
|
30297
30733
|
printCommandEnvelope(
|
|
30298
30734
|
{
|
|
@@ -30318,11 +30754,16 @@ async function runDoctorCommand(options) {
|
|
|
30318
30754
|
return ok ? 0 : 7;
|
|
30319
30755
|
}
|
|
30320
30756
|
function pendingResult(input2) {
|
|
30757
|
+
input2.phases.auth = {
|
|
30758
|
+
status: "waiting",
|
|
30759
|
+
outcome: "authorization_pending"
|
|
30760
|
+
};
|
|
30321
30761
|
const statePath = writeSetupState({
|
|
30322
30762
|
baseUrl: input2.baseUrl,
|
|
30323
30763
|
scope: input2.scope,
|
|
30324
30764
|
root: input2.root,
|
|
30325
|
-
status: "authorization_pending"
|
|
30765
|
+
status: "authorization_pending",
|
|
30766
|
+
phases: input2.phases
|
|
30326
30767
|
});
|
|
30327
30768
|
if (input2.authorizationUrl) {
|
|
30328
30769
|
process.stderr.write(`Authorize Deepline: ${input2.authorizationUrl}
|
|
@@ -30336,6 +30777,14 @@ function pendingResult(input2) {
|
|
|
30336
30777
|
scope: input2.scope,
|
|
30337
30778
|
authorizationUrl: input2.authorizationUrl || null,
|
|
30338
30779
|
statePath,
|
|
30780
|
+
phases: input2.phases,
|
|
30781
|
+
currentPhase: "auth",
|
|
30782
|
+
resumed: input2.resumed,
|
|
30783
|
+
retry: setupRetry({
|
|
30784
|
+
baseUrl: input2.baseUrl,
|
|
30785
|
+
scope: input2.scope,
|
|
30786
|
+
phase: "auth"
|
|
30787
|
+
}),
|
|
30339
30788
|
next: `Approve the link, then run: ${setupResumeCommand(input2.baseUrl, input2.scope)}`,
|
|
30340
30789
|
render: {
|
|
30341
30790
|
sections: [
|
|
@@ -30366,84 +30815,146 @@ async function runSetupCommand(options) {
|
|
|
30366
30815
|
status: "failed",
|
|
30367
30816
|
code: "INVALID_SETUP_SCOPE",
|
|
30368
30817
|
exitCode: 2,
|
|
30369
|
-
message: error instanceof Error ? error.message : String(error)
|
|
30818
|
+
message: error instanceof Error ? error.message : String(error),
|
|
30819
|
+
phases: {
|
|
30820
|
+
...initialSetupPhases(),
|
|
30821
|
+
cli: { status: "failed", code: "INVALID_SETUP_SCOPE" }
|
|
30822
|
+
},
|
|
30823
|
+
failedPhase: "cli"
|
|
30370
30824
|
},
|
|
30371
30825
|
{ json: options.json }
|
|
30372
30826
|
);
|
|
30373
30827
|
return 2;
|
|
30374
30828
|
}
|
|
30375
30829
|
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
30376
|
-
|
|
30377
|
-
|
|
30378
|
-
|
|
30379
|
-
|
|
30380
|
-
|
|
30381
|
-
|
|
30382
|
-
|
|
30383
|
-
|
|
30384
|
-
|
|
30385
|
-
|
|
30830
|
+
const previousState = readSetupState({ baseUrl, scope, root });
|
|
30831
|
+
const { resumed, phases } = selectSetupProgress(previousState);
|
|
30832
|
+
if (phases.cli.status !== "complete") {
|
|
30833
|
+
beginSetupPhase(phases, "cli");
|
|
30834
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30835
|
+
if (scope === "global") {
|
|
30836
|
+
const globalCli = inspectGlobalCliAvailability();
|
|
30837
|
+
if (!globalCli.ok) {
|
|
30838
|
+
const installedButUnreachable = Boolean(globalCli.persistentPath);
|
|
30839
|
+
const code = installedButUnreachable ? "GLOBAL_CLI_NOT_ON_PATH" : "GLOBAL_CLI_NOT_INSTALLED";
|
|
30840
|
+
return reportSetupPhaseFailure({
|
|
30841
|
+
baseUrl,
|
|
30386
30842
|
scope,
|
|
30387
|
-
|
|
30843
|
+
root,
|
|
30844
|
+
phases,
|
|
30845
|
+
phase: "cli",
|
|
30846
|
+
code,
|
|
30847
|
+
exitCode: 7,
|
|
30388
30848
|
message: installedButUnreachable ? `The global Deepline executable is not reachable on PATH: ${globalCli.persistentPath}` : "No persistent global Deepline executable was found.",
|
|
30389
|
-
|
|
30390
|
-
|
|
30391
|
-
|
|
30392
|
-
|
|
30393
|
-
|
|
30849
|
+
json: options.json,
|
|
30850
|
+
extra: {
|
|
30851
|
+
persistentPath: globalCli.persistentPath,
|
|
30852
|
+
fallback: "https://code.deepline.com/INSTALL.md"
|
|
30853
|
+
}
|
|
30854
|
+
});
|
|
30855
|
+
}
|
|
30394
30856
|
}
|
|
30395
|
-
|
|
30396
|
-
|
|
30397
|
-
|
|
30398
|
-
|
|
30399
|
-
|
|
30400
|
-
|
|
30401
|
-
|
|
30857
|
+
const conflict = inspectPathConflict();
|
|
30858
|
+
if (conflict) {
|
|
30859
|
+
return reportSetupPhaseFailure({
|
|
30860
|
+
baseUrl,
|
|
30861
|
+
scope,
|
|
30862
|
+
root,
|
|
30863
|
+
phases,
|
|
30864
|
+
phase: "cli",
|
|
30402
30865
|
code: "PATH_CONFLICT",
|
|
30403
30866
|
exitCode: 7,
|
|
30404
|
-
path: conflict,
|
|
30405
30867
|
message: `An unknown executable named deepline is first on PATH: ${conflict}`,
|
|
30406
|
-
|
|
30407
|
-
|
|
30408
|
-
|
|
30409
|
-
|
|
30410
|
-
|
|
30868
|
+
json: options.json,
|
|
30869
|
+
extra: { path: conflict }
|
|
30870
|
+
});
|
|
30871
|
+
}
|
|
30872
|
+
completeSetupPhase(phases, "cli", "available");
|
|
30873
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30411
30874
|
}
|
|
30412
|
-
|
|
30413
|
-
|
|
30414
|
-
|
|
30415
|
-
|
|
30875
|
+
if (phases.cleanup.status !== "complete") {
|
|
30876
|
+
beginSetupPhase(phases, "cleanup");
|
|
30877
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30878
|
+
try {
|
|
30879
|
+
const removedLegacyPaths = removeKnownLegacyPaths(baseUrl);
|
|
30880
|
+
if (removedLegacyPaths.length > 0) {
|
|
30881
|
+
process.stderr.write(
|
|
30882
|
+
`Removed ${removedLegacyPaths.length} known legacy Deepline path(s).
|
|
30416
30883
|
`
|
|
30417
|
-
|
|
30884
|
+
);
|
|
30885
|
+
}
|
|
30886
|
+
completeSetupPhase(
|
|
30887
|
+
phases,
|
|
30888
|
+
"cleanup",
|
|
30889
|
+
removedLegacyPaths.length > 0 ? "removed_legacy_paths" : "clean"
|
|
30890
|
+
);
|
|
30891
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30892
|
+
} catch (error) {
|
|
30893
|
+
return reportSetupPhaseFailure({
|
|
30894
|
+
baseUrl,
|
|
30895
|
+
scope,
|
|
30896
|
+
root,
|
|
30897
|
+
phases,
|
|
30898
|
+
phase: "cleanup",
|
|
30899
|
+
code: "LEGACY_CLEANUP_FAILED",
|
|
30900
|
+
exitCode: 5,
|
|
30901
|
+
message: error instanceof Error ? error.message : String(error),
|
|
30902
|
+
json: options.json
|
|
30903
|
+
});
|
|
30904
|
+
}
|
|
30418
30905
|
}
|
|
30419
|
-
|
|
30906
|
+
let skillsPayload = null;
|
|
30907
|
+
if (phases.skills.status !== "complete") {
|
|
30908
|
+
beginSetupPhase(phases, "skills");
|
|
30909
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30910
|
+
process.stderr.write(`Installing Deepline skills (${scope})...
|
|
30420
30911
|
`);
|
|
30421
|
-
|
|
30422
|
-
|
|
30423
|
-
|
|
30424
|
-
|
|
30425
|
-
|
|
30426
|
-
|
|
30427
|
-
|
|
30428
|
-
|
|
30429
|
-
|
|
30912
|
+
const skills = await captureStdout2(
|
|
30913
|
+
() => runSkillsCommand({ scope, json: true })
|
|
30914
|
+
);
|
|
30915
|
+
skillsPayload = parseCapturedJson(skills.stdout);
|
|
30916
|
+
if (skills.exitCode !== 0) {
|
|
30917
|
+
return reportSetupPhaseFailure({
|
|
30918
|
+
baseUrl,
|
|
30919
|
+
scope,
|
|
30920
|
+
root,
|
|
30921
|
+
phases,
|
|
30922
|
+
phase: "skills",
|
|
30430
30923
|
code: "SKILLS_INSTALL_FAILED",
|
|
30431
30924
|
exitCode: skills.exitCode,
|
|
30432
|
-
|
|
30433
|
-
|
|
30434
|
-
|
|
30435
|
-
}
|
|
30436
|
-
|
|
30925
|
+
message: typeof skillsPayload?.message === "string" ? skillsPayload.message : "Deepline skills could not be installed.",
|
|
30926
|
+
json: options.json,
|
|
30927
|
+
extra: { detail: skillsPayload }
|
|
30928
|
+
});
|
|
30929
|
+
}
|
|
30930
|
+
completeSetupPhase(
|
|
30931
|
+
phases,
|
|
30932
|
+
"skills",
|
|
30933
|
+
skillsPayload?.status === "current" ? "current" : "installed"
|
|
30934
|
+
);
|
|
30935
|
+
writeSetupState({
|
|
30936
|
+
baseUrl,
|
|
30937
|
+
scope,
|
|
30938
|
+
root,
|
|
30939
|
+
status: "skills_installed",
|
|
30940
|
+
phases
|
|
30941
|
+
});
|
|
30942
|
+
} else {
|
|
30943
|
+
skillsPayload = parseCapturedJson(
|
|
30944
|
+
safeRead(skillsStatePathForScope(baseUrl, scope, root))
|
|
30437
30945
|
);
|
|
30438
|
-
return skills.exitCode;
|
|
30439
30946
|
}
|
|
30440
|
-
writeSetupState({ baseUrl, scope, root, status: "skills_installed" });
|
|
30441
30947
|
const authScope = authScopeForSetup(scope);
|
|
30948
|
+
beginSetupPhase(phases, "auth");
|
|
30949
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30442
30950
|
let auth = await readAuthStatus(authScope);
|
|
30443
30951
|
const initialAuthFailure = reportSetupAuthStatusFailure({
|
|
30444
30952
|
auth,
|
|
30953
|
+
baseUrl,
|
|
30445
30954
|
authScope,
|
|
30446
30955
|
scope,
|
|
30956
|
+
root,
|
|
30957
|
+
phases,
|
|
30447
30958
|
json: options.json
|
|
30448
30959
|
});
|
|
30449
30960
|
if (initialAuthFailure !== null) return initialAuthFailure;
|
|
@@ -30458,8 +30969,11 @@ async function runSetupCommand(options) {
|
|
|
30458
30969
|
auth = await readAuthStatus(authScope);
|
|
30459
30970
|
const resumedAuthFailure = reportSetupAuthStatusFailure({
|
|
30460
30971
|
auth,
|
|
30972
|
+
baseUrl,
|
|
30461
30973
|
authScope,
|
|
30462
30974
|
scope,
|
|
30975
|
+
root,
|
|
30976
|
+
phases,
|
|
30463
30977
|
json: options.json
|
|
30464
30978
|
});
|
|
30465
30979
|
if (resumedAuthFailure !== null) return resumedAuthFailure;
|
|
@@ -30470,7 +30984,9 @@ async function runSetupCommand(options) {
|
|
|
30470
30984
|
baseUrl,
|
|
30471
30985
|
scope,
|
|
30472
30986
|
root,
|
|
30987
|
+
phases,
|
|
30473
30988
|
authorizationUrl: stillPending.claimUrl,
|
|
30989
|
+
resumed,
|
|
30474
30990
|
json: options.json
|
|
30475
30991
|
});
|
|
30476
30992
|
}
|
|
@@ -30487,24 +31003,30 @@ async function runSetupCommand(options) {
|
|
|
30487
31003
|
);
|
|
30488
31004
|
printCapturedAuthorizationUrl(registered.stdout);
|
|
30489
31005
|
if (registered.exitCode !== 0) {
|
|
30490
|
-
|
|
30491
|
-
|
|
30492
|
-
|
|
30493
|
-
|
|
30494
|
-
|
|
30495
|
-
|
|
30496
|
-
|
|
30497
|
-
|
|
30498
|
-
|
|
30499
|
-
|
|
30500
|
-
|
|
30501
|
-
|
|
31006
|
+
return reportSetupPhaseFailure({
|
|
31007
|
+
baseUrl,
|
|
31008
|
+
scope,
|
|
31009
|
+
root,
|
|
31010
|
+
phases,
|
|
31011
|
+
phase: "auth",
|
|
31012
|
+
code: "AUTH_REGISTER_FAILED",
|
|
31013
|
+
exitCode: registered.exitCode,
|
|
31014
|
+
message: "Deepline browser authorization could not be started.",
|
|
31015
|
+
json: options.json,
|
|
31016
|
+
extra: {
|
|
31017
|
+
detail: parseCapturedJson(registered.stdout),
|
|
31018
|
+
authScope
|
|
31019
|
+
}
|
|
31020
|
+
});
|
|
30502
31021
|
}
|
|
30503
31022
|
auth = await readAuthStatus(authScope);
|
|
30504
31023
|
const registeredAuthFailure = reportSetupAuthStatusFailure({
|
|
30505
31024
|
auth,
|
|
31025
|
+
baseUrl,
|
|
30506
31026
|
authScope,
|
|
30507
31027
|
scope,
|
|
31028
|
+
root,
|
|
31029
|
+
phases,
|
|
30508
31030
|
json: options.json
|
|
30509
31031
|
});
|
|
30510
31032
|
if (registeredAuthFailure !== null) return registeredAuthFailure;
|
|
@@ -30514,40 +31036,60 @@ async function runSetupCommand(options) {
|
|
|
30514
31036
|
baseUrl,
|
|
30515
31037
|
scope,
|
|
30516
31038
|
root,
|
|
31039
|
+
phases,
|
|
30517
31040
|
authorizationUrl: pending?.claimUrl ?? "",
|
|
31041
|
+
resumed,
|
|
30518
31042
|
json: options.json
|
|
30519
31043
|
});
|
|
30520
31044
|
}
|
|
30521
31045
|
}
|
|
30522
|
-
|
|
30523
|
-
|
|
30524
|
-
|
|
30525
|
-
|
|
30526
|
-
|
|
30527
|
-
|
|
30528
|
-
|
|
30529
|
-
|
|
30530
|
-
|
|
30531
|
-
|
|
30532
|
-
|
|
30533
|
-
|
|
30534
|
-
|
|
31046
|
+
completeSetupPhase(phases, "auth", "connected");
|
|
31047
|
+
beginSetupPhase(phases, "verify");
|
|
31048
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
31049
|
+
const assessment = buildDoctorAssessment({
|
|
31050
|
+
baseUrl,
|
|
31051
|
+
scope,
|
|
31052
|
+
root,
|
|
31053
|
+
authStatus: auth
|
|
31054
|
+
});
|
|
31055
|
+
const quickstart = setupQuickstartCommand(baseUrl);
|
|
31056
|
+
const doctorPayload = {
|
|
31057
|
+
ok: assessment.ok,
|
|
31058
|
+
status: assessment.ok ? "complete" : "failed",
|
|
31059
|
+
code: assessment.ok ? "DOCTOR_OK" : "DOCTOR_FAILED",
|
|
31060
|
+
exitCode: assessment.ok ? 0 : 7,
|
|
31061
|
+
checks: assessment.checks,
|
|
31062
|
+
next: assessment.ok ? quickstart : `deepline doctor --scope ${scope} --json`
|
|
31063
|
+
};
|
|
31064
|
+
if (!assessment.ok) {
|
|
31065
|
+
return reportSetupPhaseFailure({
|
|
31066
|
+
baseUrl,
|
|
31067
|
+
scope,
|
|
31068
|
+
root,
|
|
31069
|
+
phases,
|
|
31070
|
+
phase: "verify",
|
|
31071
|
+
code: "DOCTOR_FAILED",
|
|
31072
|
+
exitCode: 7,
|
|
31073
|
+
message: "Deepline setup verification found one or more failed checks.",
|
|
31074
|
+
json: options.json,
|
|
31075
|
+
extra: {
|
|
30535
31076
|
doctor: doctorPayload,
|
|
30536
|
-
|
|
30537
|
-
|
|
30538
|
-
|
|
30539
|
-
|
|
30540
|
-
|
|
31077
|
+
diagnostic: {
|
|
31078
|
+
command: `deepline doctor --scope ${scope} --json`
|
|
31079
|
+
}
|
|
31080
|
+
}
|
|
31081
|
+
});
|
|
30541
31082
|
}
|
|
31083
|
+
completeSetupPhase(phases, "verify", "verified");
|
|
30542
31084
|
const statePath = writeSetupState({
|
|
30543
31085
|
baseUrl,
|
|
30544
31086
|
scope,
|
|
30545
31087
|
root,
|
|
30546
|
-
status: "complete"
|
|
31088
|
+
status: "complete",
|
|
31089
|
+
phases
|
|
30547
31090
|
});
|
|
30548
31091
|
const doctorChecks = asRecord2(doctorPayload?.checks);
|
|
30549
31092
|
const apiCheck = asRecord2(doctorChecks?.api);
|
|
30550
|
-
const quickstart = setupQuickstartCommand(baseUrl);
|
|
30551
31093
|
printCommandEnvelope(
|
|
30552
31094
|
{
|
|
30553
31095
|
ok: true,
|
|
@@ -30560,6 +31102,10 @@ async function runSetupCommand(options) {
|
|
|
30560
31102
|
rollbackCommand: rollbackCommand(scope, root),
|
|
30561
31103
|
statePath,
|
|
30562
31104
|
doctor: doctorPayload,
|
|
31105
|
+
phases,
|
|
31106
|
+
currentPhase: null,
|
|
31107
|
+
failedPhase: null,
|
|
31108
|
+
resumed,
|
|
30563
31109
|
next: quickstart,
|
|
30564
31110
|
render: {
|
|
30565
31111
|
sections: [
|
|
@@ -30582,8 +31128,9 @@ function registerSetupCommands(program) {
|
|
|
30582
31128
|
"after",
|
|
30583
31129
|
`
|
|
30584
31130
|
Notes:
|
|
30585
|
-
Setup is idempotent. Bare setup resumes
|
|
31131
|
+
Setup is idempotent. Bare setup resumes the first incomplete or failed phase.
|
|
30586
31132
|
It installs skills before auth and does not run quickstart.
|
|
31133
|
+
JSON output includes phase status and an exact retry command.
|
|
30587
31134
|
|
|
30588
31135
|
Examples:
|
|
30589
31136
|
deepline setup --json
|
|
@@ -30823,7 +31370,7 @@ import { spawn as spawn6, spawnSync as spawnSync3 } from "child_process";
|
|
|
30823
31370
|
import {
|
|
30824
31371
|
existsSync as existsSync14,
|
|
30825
31372
|
mkdirSync as mkdirSync12,
|
|
30826
|
-
readFileSync as
|
|
31373
|
+
readFileSync as readFileSync15,
|
|
30827
31374
|
unlinkSync as unlinkSync2,
|
|
30828
31375
|
writeFileSync as writeFileSync17
|
|
30829
31376
|
} from "fs";
|
|
@@ -30849,7 +31396,7 @@ function readPluginSkillsVersion() {
|
|
|
30849
31396
|
const dir = activePluginSkillsDir();
|
|
30850
31397
|
if (!dir) return "";
|
|
30851
31398
|
try {
|
|
30852
|
-
return
|
|
31399
|
+
return readFileSync15(join17(dir, ".version"), "utf-8").trim();
|
|
30853
31400
|
} catch {
|
|
30854
31401
|
return "";
|
|
30855
31402
|
}
|
|
@@ -30869,7 +31416,7 @@ function readSdkSkillsLocalVersion(baseUrl) {
|
|
|
30869
31416
|
const path = existsSync14(sdkSkillsVersionPath(baseUrl)) ? sdkSkillsVersionPath(baseUrl) : legacySdkSkillsVersionPath(baseUrl);
|
|
30870
31417
|
if (!existsSync14(path)) return "";
|
|
30871
31418
|
try {
|
|
30872
|
-
return
|
|
31419
|
+
return readFileSync15(path, "utf-8").trim();
|
|
30873
31420
|
} catch {
|
|
30874
31421
|
return "";
|
|
30875
31422
|
}
|
|
@@ -30883,7 +31430,7 @@ function writeLocalSkillsVersion(baseUrl, version) {
|
|
|
30883
31430
|
function writeUnavailableSkillsNotice(baseUrl, remoteVersion, skillNames) {
|
|
30884
31431
|
const path = unavailableSkillsNoticePath(baseUrl);
|
|
30885
31432
|
try {
|
|
30886
|
-
if (existsSync14(path) &&
|
|
31433
|
+
if (existsSync14(path) && readFileSync15(path, "utf-8").trim() === remoteVersion) {
|
|
30887
31434
|
return;
|
|
30888
31435
|
}
|
|
30889
31436
|
mkdirSync12(dirname15(path), { recursive: true });
|