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.js
CHANGED
|
@@ -716,7 +716,7 @@ var SDK_RELEASE = {
|
|
|
716
716
|
// Deepline-native radars. Older clients must update before discovering,
|
|
717
717
|
// checking, or deploying an unlaunched monitor integration.
|
|
718
718
|
// 0.1.253 makes play-page browser opening opt-in and retires --no-open.
|
|
719
|
-
version: "0.1.
|
|
719
|
+
version: "0.1.262",
|
|
720
720
|
apiContract: "2026-07-native-monitor-launch-hard-cutover",
|
|
721
721
|
supportPolicy: {
|
|
722
722
|
minimumSupported: "0.1.53",
|
|
@@ -26616,6 +26616,33 @@ function extractSummaryFields(payload) {
|
|
|
26616
26616
|
return {};
|
|
26617
26617
|
}
|
|
26618
26618
|
|
|
26619
|
+
// ../shared_libs/plays/tool-category-descriptions.ts
|
|
26620
|
+
var TOOL_CATEGORY_DESCRIPTIONS = {
|
|
26621
|
+
company_search: "Find companies matching firmographic, ad, or web criteria.",
|
|
26622
|
+
people_search: "Find people matching role, company, or persona criteria.",
|
|
26623
|
+
people_enrich: "Enrich a known person with contact, social, and profile data.",
|
|
26624
|
+
company_enrich: "Enrich a known company with firmographic and account data.",
|
|
26625
|
+
email_finder: "Find work or personal email addresses for a person.",
|
|
26626
|
+
email_verify: "Validate email deliverability and catch-all status.",
|
|
26627
|
+
phone_finder: "Find mobile or direct phone numbers for a person.",
|
|
26628
|
+
phone_verify: "Validate phone-number reachability and line type.",
|
|
26629
|
+
research: "Research accounts, people, news, and signals for context and scoring.",
|
|
26630
|
+
autocomplete: "Resolve names and entities to canonical catalog records.",
|
|
26631
|
+
automation: "Kick off provider-side jobs, exports, and asynchronous workflows.",
|
|
26632
|
+
outbound_tools: "Run outbound sequencing, deliverability, and campaign operations.",
|
|
26633
|
+
admin: "Provider-side status, metadata, and account operations behind other tools.",
|
|
26634
|
+
smb: "Look up small-business listings, local records, and public filings.",
|
|
26635
|
+
identity_resolution: "Match a partial identity to a single resolved person or company.",
|
|
26636
|
+
reverse_lookup: "Resolve an email, phone, or profile back to a person.",
|
|
26637
|
+
enrichment: "General-purpose record enrichment across people and companies.",
|
|
26638
|
+
batch: "Run an enrichment or search operation over many rows at once.",
|
|
26639
|
+
premium: "Higher-cost tools with premium provider coverage.",
|
|
26640
|
+
free: "Free tools that do not spend Deepline credits."
|
|
26641
|
+
};
|
|
26642
|
+
function describeToolCategory(category) {
|
|
26643
|
+
return TOOL_CATEGORY_DESCRIPTIONS[category] ?? null;
|
|
26644
|
+
}
|
|
26645
|
+
|
|
26619
26646
|
// src/cli/commands/model-description.ts
|
|
26620
26647
|
function formatModelDescription(description) {
|
|
26621
26648
|
const lines = [];
|
|
@@ -26782,21 +26809,181 @@ function zeroMatchRender(emptyResult) {
|
|
|
26782
26809
|
]
|
|
26783
26810
|
};
|
|
26784
26811
|
}
|
|
26785
|
-
|
|
26812
|
+
function firstSentence(text) {
|
|
26813
|
+
const clean = (text ?? "").replace(/\s+/g, " ").trim();
|
|
26814
|
+
if (!clean) return "";
|
|
26815
|
+
const match = clean.match(/^.*?[.!?](?=\s|$)/);
|
|
26816
|
+
return (match ? match[0] : clean).trim();
|
|
26817
|
+
}
|
|
26818
|
+
function requiredInputIds(tool) {
|
|
26819
|
+
const inputSchema = recordField2(
|
|
26820
|
+
tool,
|
|
26821
|
+
"inputSchema",
|
|
26822
|
+
"input_schema"
|
|
26823
|
+
);
|
|
26824
|
+
return toolInputFieldsForDisplay(inputSchema).filter((field) => field.required === true).map((field) => String(field.name ?? "")).filter(Boolean);
|
|
26825
|
+
}
|
|
26826
|
+
function shortPricingHint(tool) {
|
|
26827
|
+
const pricing = recordField2(
|
|
26828
|
+
tool,
|
|
26829
|
+
"pricing"
|
|
26830
|
+
);
|
|
26831
|
+
const credits = numberField2(pricing, "creditsPerUnit", "credits_per_unit");
|
|
26832
|
+
const unit = stringField2(pricing, "unit");
|
|
26833
|
+
if (credits !== null) {
|
|
26834
|
+
return `${formatDecimal(credits)} cr/${unit || "unit"}`;
|
|
26835
|
+
}
|
|
26836
|
+
const summary = stringField2(pricing, "summary");
|
|
26837
|
+
if (summary) return summary;
|
|
26838
|
+
const displayText = stringField2(pricing, "displayText", "display_text");
|
|
26839
|
+
return displayText || null;
|
|
26840
|
+
}
|
|
26841
|
+
function aggregateCategorySummaries(tools) {
|
|
26842
|
+
const counts = /* @__PURE__ */ new Map();
|
|
26843
|
+
for (const tool of tools) {
|
|
26844
|
+
for (const category of tool.categories ?? []) {
|
|
26845
|
+
counts.set(category, (counts.get(category) ?? 0) + 1);
|
|
26846
|
+
}
|
|
26847
|
+
}
|
|
26848
|
+
return [...counts.entries()].map(([name, count]) => ({
|
|
26849
|
+
name,
|
|
26850
|
+
count,
|
|
26851
|
+
description: describeToolCategory(name)
|
|
26852
|
+
})).sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
|
|
26853
|
+
}
|
|
26854
|
+
function categoryEnumerationRender(summaries) {
|
|
26855
|
+
const nameWidth = summaries.reduce(
|
|
26856
|
+
(max, item) => Math.max(max, item.name.length),
|
|
26857
|
+
0
|
|
26858
|
+
);
|
|
26859
|
+
const countWidth = summaries.reduce(
|
|
26860
|
+
(max, item) => Math.max(max, String(item.count).length),
|
|
26861
|
+
0
|
|
26862
|
+
);
|
|
26863
|
+
return {
|
|
26864
|
+
sections: [
|
|
26865
|
+
{
|
|
26866
|
+
title: `${summaries.length} tool categories:`,
|
|
26867
|
+
lines: summaries.map((item) => {
|
|
26868
|
+
const name = item.name.padEnd(nameWidth);
|
|
26869
|
+
const count = String(item.count).padStart(countWidth);
|
|
26870
|
+
const definition = item.description ? ` - ${item.description}` : "";
|
|
26871
|
+
return `${name} ${count}${definition}`;
|
|
26872
|
+
})
|
|
26873
|
+
},
|
|
26874
|
+
{
|
|
26875
|
+
title: "next",
|
|
26876
|
+
lines: ["Pass a category: deepline tools list email_finder"]
|
|
26877
|
+
}
|
|
26878
|
+
]
|
|
26879
|
+
};
|
|
26880
|
+
}
|
|
26881
|
+
async function listToolCategories(emitJson, compact) {
|
|
26882
|
+
const client2 = new DeeplineClient();
|
|
26883
|
+
const rawTools = await client2.listTools({ compact });
|
|
26884
|
+
const items = rawTools.map(toListedTool);
|
|
26885
|
+
const summaries = aggregateCategorySummaries(rawTools);
|
|
26886
|
+
const outputItems = compact ? items.map(compactTool) : items;
|
|
26887
|
+
printCommandEnvelope(
|
|
26888
|
+
{
|
|
26889
|
+
tools: outputItems,
|
|
26890
|
+
count: outputItems.length,
|
|
26891
|
+
categories: summaries,
|
|
26892
|
+
filters: {
|
|
26893
|
+
categories: []
|
|
26894
|
+
},
|
|
26895
|
+
commandTemplates: TOOL_COMMAND_TEMPLATES,
|
|
26896
|
+
render: categoryEnumerationRender(summaries)
|
|
26897
|
+
},
|
|
26898
|
+
{ json: emitJson }
|
|
26899
|
+
);
|
|
26900
|
+
return 0;
|
|
26901
|
+
}
|
|
26902
|
+
function unknownCategoryError(category, summaries, emitJson) {
|
|
26903
|
+
const known = summaries.map((item) => item.name);
|
|
26904
|
+
const message = `Unknown tool category "${category}". Run \`deepline tools list\` to browse categories.`;
|
|
26905
|
+
if (emitJson) {
|
|
26906
|
+
printJson({
|
|
26907
|
+
ok: false,
|
|
26908
|
+
exitCode: 4,
|
|
26909
|
+
code: "TOOL_CATEGORY_NOT_FOUND",
|
|
26910
|
+
message,
|
|
26911
|
+
category,
|
|
26912
|
+
categories: summaries,
|
|
26913
|
+
next: "deepline tools list"
|
|
26914
|
+
});
|
|
26915
|
+
return 4;
|
|
26916
|
+
}
|
|
26917
|
+
const render = categoryEnumerationRender(summaries);
|
|
26918
|
+
console.error(message);
|
|
26919
|
+
console.error("");
|
|
26920
|
+
console.error(renderCommandEnvelopeText({ render }).trimEnd());
|
|
26921
|
+
console.error("");
|
|
26922
|
+
console.error(`Valid categories: ${known.join(", ")}`);
|
|
26923
|
+
return 4;
|
|
26924
|
+
}
|
|
26925
|
+
async function listToolsInCategory(category, emitJson) {
|
|
26926
|
+
const client2 = new DeeplineClient();
|
|
26927
|
+
const rawTools = await client2.listTools({
|
|
26928
|
+
categories: category,
|
|
26929
|
+
compact: false
|
|
26930
|
+
});
|
|
26931
|
+
const allTools = await client2.listTools({ compact: true });
|
|
26932
|
+
const summaries = aggregateCategorySummaries(allTools);
|
|
26933
|
+
if (!summaries.some((item) => item.name === category)) {
|
|
26934
|
+
return unknownCategoryError(category, summaries, emitJson);
|
|
26935
|
+
}
|
|
26936
|
+
const rows = rawTools.filter((tool) => tool.categories?.includes(category)).map((tool) => ({
|
|
26937
|
+
id: tool.toolId,
|
|
26938
|
+
provider: tool.provider,
|
|
26939
|
+
required: requiredInputIds(tool),
|
|
26940
|
+
pricing: shortPricingHint(tool),
|
|
26941
|
+
description: firstSentence(tool.description)
|
|
26942
|
+
})).sort((a, b) => a.id.localeCompare(b.id));
|
|
26943
|
+
const idWidth = rows.reduce((max, row) => Math.max(max, row.id.length), 0);
|
|
26944
|
+
const render = {
|
|
26945
|
+
sections: [
|
|
26946
|
+
{
|
|
26947
|
+
title: `${rows.length} tools in ${category}:`,
|
|
26948
|
+
lines: rows.map((row) => {
|
|
26949
|
+
const id = row.id.padEnd(idWidth);
|
|
26950
|
+
const required = row.required.length ? `(${row.required.join(", ")})` : "(no required inputs)";
|
|
26951
|
+
const pricing = row.pricing ? ` [${row.pricing}]` : "";
|
|
26952
|
+
const description = row.description ? ` - ${row.description}` : "";
|
|
26953
|
+
return `${id} ${required}${pricing}${description}`;
|
|
26954
|
+
})
|
|
26955
|
+
},
|
|
26956
|
+
{
|
|
26957
|
+
title: "next",
|
|
26958
|
+
lines: [
|
|
26959
|
+
"Run `deepline tools describe <toolId>` for the full contract."
|
|
26960
|
+
]
|
|
26961
|
+
}
|
|
26962
|
+
]
|
|
26963
|
+
};
|
|
26964
|
+
printCommandEnvelope(
|
|
26965
|
+
{
|
|
26966
|
+
category,
|
|
26967
|
+
total: rows.length,
|
|
26968
|
+
tools: rows,
|
|
26969
|
+
commandTemplates: TOOL_COMMAND_TEMPLATES,
|
|
26970
|
+
render
|
|
26971
|
+
},
|
|
26972
|
+
{ json: emitJson }
|
|
26973
|
+
);
|
|
26974
|
+
return 0;
|
|
26975
|
+
}
|
|
26976
|
+
async function listToolsForCategoryFilter(requestedCategories, emitJson, compact) {
|
|
26786
26977
|
const client2 = new DeeplineClient();
|
|
26787
|
-
const categoryArgIndex = args.findIndex((arg) => arg === "--categories");
|
|
26788
|
-
const categoryFilter = categoryArgIndex >= 0 ? args[categoryArgIndex + 1] : "";
|
|
26789
|
-
const compact = !args.includes("--full");
|
|
26790
|
-
const requestedCategories = categoryFilter ? categoryFilter.split(",").map((item) => item.trim()).filter(Boolean) : [];
|
|
26791
26978
|
const items = (await client2.listTools({
|
|
26792
|
-
|
|
26979
|
+
categories: requestedCategories.join(","),
|
|
26793
26980
|
compact
|
|
26794
26981
|
})).map(toListedTool).filter(
|
|
26795
|
-
(item) => requestedCategories.
|
|
26982
|
+
(item) => requestedCategories.some(
|
|
26796
26983
|
(category) => item.categories.includes(category)
|
|
26797
26984
|
)
|
|
26798
26985
|
);
|
|
26799
|
-
const emptyResult = items.length === 0
|
|
26986
|
+
const emptyResult = items.length === 0 ? zeroMatchToolGuidance({ categories: requestedCategories }) : null;
|
|
26800
26987
|
const render = {
|
|
26801
26988
|
sections: emptyResult ? zeroMatchRender(emptyResult).sections : [
|
|
26802
26989
|
{
|
|
@@ -26827,10 +27014,41 @@ async function listTools(args) {
|
|
|
26827
27014
|
commandTemplates: TOOL_COMMAND_TEMPLATES,
|
|
26828
27015
|
render
|
|
26829
27016
|
},
|
|
26830
|
-
{ json:
|
|
27017
|
+
{ json: emitJson }
|
|
26831
27018
|
);
|
|
26832
27019
|
return 0;
|
|
26833
27020
|
}
|
|
27021
|
+
async function listTools(category, options = {}) {
|
|
27022
|
+
const positional = category?.trim() ?? "";
|
|
27023
|
+
const flagCategories = (options.categories ?? "").split(",").map((item) => item.trim()).filter(Boolean);
|
|
27024
|
+
const compact = options.compact !== false;
|
|
27025
|
+
const emitJson = options.json === true || shouldEmitJson();
|
|
27026
|
+
if (positional && flagCategories.length > 0) {
|
|
27027
|
+
const flagIsSameSingle = flagCategories.length === 1 && flagCategories[0] === positional;
|
|
27028
|
+
if (!flagIsSameSingle) {
|
|
27029
|
+
const message = `Category "${positional}" and --categories ${flagCategories.join(",")} disagree. Pass one: deepline tools list ${positional}`;
|
|
27030
|
+
if (emitJson) {
|
|
27031
|
+
printJson({
|
|
27032
|
+
ok: false,
|
|
27033
|
+
exitCode: 2,
|
|
27034
|
+
code: "TOOL_LIST_CATEGORY_CONFLICT",
|
|
27035
|
+
message,
|
|
27036
|
+
next: `deepline tools list ${positional}`
|
|
27037
|
+
});
|
|
27038
|
+
} else {
|
|
27039
|
+
console.error(message);
|
|
27040
|
+
}
|
|
27041
|
+
return 2;
|
|
27042
|
+
}
|
|
27043
|
+
}
|
|
27044
|
+
if (positional) {
|
|
27045
|
+
return listToolsInCategory(positional, emitJson);
|
|
27046
|
+
}
|
|
27047
|
+
if (flagCategories.length > 0) {
|
|
27048
|
+
return listToolsForCategoryFilter(flagCategories, emitJson, compact);
|
|
27049
|
+
}
|
|
27050
|
+
return listToolCategories(emitJson, compact);
|
|
27051
|
+
}
|
|
26834
27052
|
async function searchTools(queryInput, options = {}) {
|
|
26835
27053
|
const query = queryInput?.trim() ?? "";
|
|
26836
27054
|
const hasStructuredSearch = Boolean(
|
|
@@ -27029,27 +27247,37 @@ Output:
|
|
|
27029
27247
|
Use execute to run a tool.
|
|
27030
27248
|
`
|
|
27031
27249
|
);
|
|
27032
|
-
tools.command("list").description("
|
|
27250
|
+
tools.command("list [category]").description("Browse tool categories, or list every tool in a category.").addHelpText(
|
|
27033
27251
|
"after",
|
|
27034
27252
|
`
|
|
27035
27253
|
Notes:
|
|
27036
|
-
|
|
27037
|
-
|
|
27254
|
+
Bare \`tools list\` prints the category enumeration: one line per category with
|
|
27255
|
+
its tool count and definition. Pass a category to list every tool in it, one
|
|
27256
|
+
succinct row each (required inputs, Deepline pricing hint, first sentence).
|
|
27257
|
+
The listing is exhaustive and never truncated. Use search for ranked discovery
|
|
27258
|
+
by intent, aliases, descriptions, and schema fields.
|
|
27259
|
+
|
|
27260
|
+
--categories is a back-compat inventory filter. Passing it alone returns the
|
|
27261
|
+
legacy flat inventory envelope (one row per tool). The positional category is
|
|
27262
|
+
the newer exhaustive per-category view. If both are given they must name the
|
|
27263
|
+
same category (the positional view wins); otherwise it is a usage error.
|
|
27038
27264
|
|
|
27039
27265
|
Examples:
|
|
27040
27266
|
deepline tools list
|
|
27267
|
+
deepline tools list email_finder
|
|
27268
|
+
deepline tools list email_finder --json
|
|
27041
27269
|
deepline tools list --categories email_finder --json
|
|
27042
27270
|
deepline tools search email --json
|
|
27043
27271
|
`
|
|
27044
27272
|
).option(
|
|
27045
27273
|
"--categories <categories>",
|
|
27046
|
-
"Comma-separated categories
|
|
27047
|
-
).option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
27048
|
-
process.exitCode = await listTools(
|
|
27049
|
-
|
|
27050
|
-
|
|
27051
|
-
|
|
27052
|
-
|
|
27274
|
+
"Comma-separated categories filter (back-compat alias for the positional)"
|
|
27275
|
+
).option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (category, options) => {
|
|
27276
|
+
process.exitCode = await listTools(category, {
|
|
27277
|
+
categories: typeof options.categories === "string" ? options.categories : void 0,
|
|
27278
|
+
compact: options.compact !== false,
|
|
27279
|
+
json: Boolean(options.json)
|
|
27280
|
+
});
|
|
27053
27281
|
});
|
|
27054
27282
|
const addToolSearchCommand = (command) => command.description(
|
|
27055
27283
|
"Search available tools by intent query or structured filters."
|
|
@@ -29106,10 +29334,13 @@ function buildSkillsPlan(input2) {
|
|
|
29106
29334
|
skillNames: input2.skillNames,
|
|
29107
29335
|
version: input2.version,
|
|
29108
29336
|
remove: {
|
|
29109
|
-
command: "
|
|
29337
|
+
command: "npm",
|
|
29110
29338
|
args: [
|
|
29339
|
+
"exec",
|
|
29111
29340
|
"--yes",
|
|
29112
|
-
"skills@latest",
|
|
29341
|
+
"--package=skills@latest",
|
|
29342
|
+
"--",
|
|
29343
|
+
"skills",
|
|
29113
29344
|
"remove",
|
|
29114
29345
|
...scopeArgs,
|
|
29115
29346
|
"--agent",
|
|
@@ -29119,10 +29350,13 @@ function buildSkillsPlan(input2) {
|
|
|
29119
29350
|
]
|
|
29120
29351
|
},
|
|
29121
29352
|
install: {
|
|
29122
|
-
command: "
|
|
29353
|
+
command: "npm",
|
|
29123
29354
|
args: [
|
|
29355
|
+
"exec",
|
|
29124
29356
|
"--yes",
|
|
29125
|
-
"skills@latest",
|
|
29357
|
+
"--package=skills@latest",
|
|
29358
|
+
"--",
|
|
29359
|
+
"skills",
|
|
29126
29360
|
"add",
|
|
29127
29361
|
skillsIndexUrl(input2.baseUrl),
|
|
29128
29362
|
"--agent",
|
|
@@ -29136,6 +29370,29 @@ function buildSkillsPlan(input2) {
|
|
|
29136
29370
|
statePath: skillsStatePathForScope(input2.baseUrl, input2.scope, input2.root)
|
|
29137
29371
|
};
|
|
29138
29372
|
}
|
|
29373
|
+
function sortedStrings(value) {
|
|
29374
|
+
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
|
|
29375
|
+
return null;
|
|
29376
|
+
}
|
|
29377
|
+
return [...value].sort((a, b) => a.localeCompare(b));
|
|
29378
|
+
}
|
|
29379
|
+
function isSkillsPlanCurrent(plan, state) {
|
|
29380
|
+
if (!state || state.scope !== plan.scope || state.skillsVersion !== plan.version) {
|
|
29381
|
+
return false;
|
|
29382
|
+
}
|
|
29383
|
+
const installedAgents = sortedStrings(state.agents);
|
|
29384
|
+
const installedSkillNames = sortedStrings(state.skillNames);
|
|
29385
|
+
if (!installedAgents || !installedSkillNames) return false;
|
|
29386
|
+
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");
|
|
29387
|
+
}
|
|
29388
|
+
function readSkillsInstallState(path) {
|
|
29389
|
+
try {
|
|
29390
|
+
const parsed = JSON.parse((0, import_node_fs16.readFileSync)(path, "utf8"));
|
|
29391
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
29392
|
+
} catch {
|
|
29393
|
+
return null;
|
|
29394
|
+
}
|
|
29395
|
+
}
|
|
29139
29396
|
function runProcess(command, args, cwd) {
|
|
29140
29397
|
return new Promise((resolve15, reject) => {
|
|
29141
29398
|
const child = (0, import_node_child_process3.spawn)(command, args, {
|
|
@@ -29159,7 +29416,7 @@ function runProcess(command, args, cwd) {
|
|
|
29159
29416
|
});
|
|
29160
29417
|
});
|
|
29161
29418
|
}
|
|
29162
|
-
async function runSkillsCommand(options) {
|
|
29419
|
+
async function runSkillsCommand(options, dependencies = {}) {
|
|
29163
29420
|
let scope;
|
|
29164
29421
|
let root;
|
|
29165
29422
|
try {
|
|
@@ -29181,7 +29438,7 @@ async function runSkillsCommand(options) {
|
|
|
29181
29438
|
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
29182
29439
|
let catalog;
|
|
29183
29440
|
try {
|
|
29184
|
-
catalog = options.dryRun ? { skillNames: [...DEFAULT_SDK_SKILL_NAMES], version: "latest" } : await fetchSkillCatalog(baseUrl);
|
|
29441
|
+
catalog = options.dryRun ? { skillNames: [...DEFAULT_SDK_SKILL_NAMES], version: "latest" } : await (dependencies.fetchCatalog ?? fetchSkillCatalog)(baseUrl);
|
|
29185
29442
|
} catch (error) {
|
|
29186
29443
|
printCommandEnvelope(
|
|
29187
29444
|
{
|
|
@@ -29205,6 +29462,37 @@ async function runSkillsCommand(options) {
|
|
|
29205
29462
|
);
|
|
29206
29463
|
return 0;
|
|
29207
29464
|
}
|
|
29465
|
+
if (isSkillsPlanCurrent(plan, readSkillsInstallState(plan.statePath))) {
|
|
29466
|
+
printCommandEnvelope(
|
|
29467
|
+
{
|
|
29468
|
+
ok: true,
|
|
29469
|
+
status: "current",
|
|
29470
|
+
complete: true,
|
|
29471
|
+
changed: false,
|
|
29472
|
+
skipped: true,
|
|
29473
|
+
skipReason: "skills_version_current",
|
|
29474
|
+
scope,
|
|
29475
|
+
agents,
|
|
29476
|
+
skillsVersion: plan.version,
|
|
29477
|
+
skillCount: plan.skillNames.length,
|
|
29478
|
+
statePath: plan.statePath,
|
|
29479
|
+
render: {
|
|
29480
|
+
sections: [
|
|
29481
|
+
{
|
|
29482
|
+
title: "skills",
|
|
29483
|
+
lines: [
|
|
29484
|
+
`Scope: ${scope}`,
|
|
29485
|
+
`Agents: ${agents.join(", ")}`,
|
|
29486
|
+
`Current: ${plan.skillNames.length}`
|
|
29487
|
+
]
|
|
29488
|
+
}
|
|
29489
|
+
]
|
|
29490
|
+
}
|
|
29491
|
+
},
|
|
29492
|
+
{ json: options.json }
|
|
29493
|
+
);
|
|
29494
|
+
return 0;
|
|
29495
|
+
}
|
|
29208
29496
|
if (scope === "local" && root) {
|
|
29209
29497
|
const managedNames = [
|
|
29210
29498
|
.../* @__PURE__ */ new Set([...plan.skillNames, ...LEGACY_SKILL_NAMES_TO_REMOVE])
|
|
@@ -29222,7 +29510,8 @@ async function runSkillsCommand(options) {
|
|
|
29222
29510
|
`
|
|
29223
29511
|
);
|
|
29224
29512
|
try {
|
|
29225
|
-
const
|
|
29513
|
+
const execute = dependencies.runProcess ?? runProcess;
|
|
29514
|
+
const removeCode = await execute(
|
|
29226
29515
|
plan.remove.command,
|
|
29227
29516
|
plan.remove.args,
|
|
29228
29517
|
root ?? void 0
|
|
@@ -29230,7 +29519,7 @@ async function runSkillsCommand(options) {
|
|
|
29230
29519
|
if (removeCode !== 0) {
|
|
29231
29520
|
throw new Error("Could not remove the existing Deepline skills.");
|
|
29232
29521
|
}
|
|
29233
|
-
const installCode = await
|
|
29522
|
+
const installCode = await execute(
|
|
29234
29523
|
plan.install.command,
|
|
29235
29524
|
plan.install.args,
|
|
29236
29525
|
root ?? void 0
|
|
@@ -29935,6 +30224,85 @@ var import_node_child_process5 = require("child_process");
|
|
|
29935
30224
|
var import_node_fs18 = require("fs");
|
|
29936
30225
|
var import_node_os15 = require("os");
|
|
29937
30226
|
var import_node_path20 = require("path");
|
|
30227
|
+
var SETUP_PHASE_NAMES = [
|
|
30228
|
+
"cli",
|
|
30229
|
+
"cleanup",
|
|
30230
|
+
"skills",
|
|
30231
|
+
"auth",
|
|
30232
|
+
"verify"
|
|
30233
|
+
];
|
|
30234
|
+
function initialSetupPhases() {
|
|
30235
|
+
return {
|
|
30236
|
+
cli: { status: "pending" },
|
|
30237
|
+
cleanup: { status: "pending" },
|
|
30238
|
+
skills: { status: "pending" },
|
|
30239
|
+
auth: { status: "pending" },
|
|
30240
|
+
verify: { status: "pending" }
|
|
30241
|
+
};
|
|
30242
|
+
}
|
|
30243
|
+
function isSetupPhaseStatus(value) {
|
|
30244
|
+
return value === "pending" || value === "in_progress" || value === "complete" || value === "waiting" || value === "failed";
|
|
30245
|
+
}
|
|
30246
|
+
function parseSetupPhases(value) {
|
|
30247
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
30248
|
+
const source = value;
|
|
30249
|
+
const phases = initialSetupPhases();
|
|
30250
|
+
for (const name of SETUP_PHASE_NAMES) {
|
|
30251
|
+
const phase = source[name];
|
|
30252
|
+
if (!phase || typeof phase !== "object" || Array.isArray(phase)) {
|
|
30253
|
+
return null;
|
|
30254
|
+
}
|
|
30255
|
+
const record = phase;
|
|
30256
|
+
if (!isSetupPhaseStatus(record.status)) return null;
|
|
30257
|
+
phases[name] = {
|
|
30258
|
+
status: record.status,
|
|
30259
|
+
...typeof record.outcome === "string" ? { outcome: record.outcome } : {},
|
|
30260
|
+
...typeof record.code === "string" ? { code: record.code } : {}
|
|
30261
|
+
};
|
|
30262
|
+
}
|
|
30263
|
+
return phases;
|
|
30264
|
+
}
|
|
30265
|
+
function phasesFromLegacyStatus(status) {
|
|
30266
|
+
const phases = initialSetupPhases();
|
|
30267
|
+
if (status === "skills_installed" || status === "authorization_pending" || status === "complete") {
|
|
30268
|
+
phases.cli = { status: "complete" };
|
|
30269
|
+
phases.cleanup = { status: "complete" };
|
|
30270
|
+
phases.skills = { status: "complete" };
|
|
30271
|
+
}
|
|
30272
|
+
if (status === "authorization_pending") {
|
|
30273
|
+
phases.auth = { status: "waiting", outcome: "authorization_pending" };
|
|
30274
|
+
} else if (status === "complete") {
|
|
30275
|
+
phases.auth = { status: "complete" };
|
|
30276
|
+
phases.verify = { status: "complete" };
|
|
30277
|
+
}
|
|
30278
|
+
return phases;
|
|
30279
|
+
}
|
|
30280
|
+
function readSetupState(input2) {
|
|
30281
|
+
try {
|
|
30282
|
+
const parsed = JSON.parse(
|
|
30283
|
+
(0, import_node_fs18.readFileSync)(
|
|
30284
|
+
setupStatePath(input2.baseUrl, input2.scope, input2.root),
|
|
30285
|
+
"utf8"
|
|
30286
|
+
)
|
|
30287
|
+
);
|
|
30288
|
+
if (parsed.host !== input2.baseUrl || parsed.scope !== input2.scope || parsed.root !== input2.root || typeof parsed.status !== "string") {
|
|
30289
|
+
return null;
|
|
30290
|
+
}
|
|
30291
|
+
return {
|
|
30292
|
+
status: parsed.status,
|
|
30293
|
+
phases: parseSetupPhases(parsed.phases) ?? phasesFromLegacyStatus(parsed.status)
|
|
30294
|
+
};
|
|
30295
|
+
} catch {
|
|
30296
|
+
return null;
|
|
30297
|
+
}
|
|
30298
|
+
}
|
|
30299
|
+
function selectSetupProgress(previousState) {
|
|
30300
|
+
const resumed = Boolean(previousState && previousState.status !== "complete");
|
|
30301
|
+
return {
|
|
30302
|
+
resumed,
|
|
30303
|
+
phases: resumed ? previousState.phases : initialSetupPhases()
|
|
30304
|
+
};
|
|
30305
|
+
}
|
|
29938
30306
|
function normalizeScope2(value) {
|
|
29939
30307
|
if (!value || value === "global") return "global";
|
|
29940
30308
|
if (value === "local") return "local";
|
|
@@ -30105,13 +30473,14 @@ function writeSetupState(input2) {
|
|
|
30105
30473
|
path,
|
|
30106
30474
|
`${JSON.stringify(
|
|
30107
30475
|
{
|
|
30108
|
-
schemaVersion:
|
|
30476
|
+
schemaVersion: 2,
|
|
30109
30477
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30110
30478
|
cliVersion: SDK_VERSION,
|
|
30111
30479
|
host: input2.baseUrl,
|
|
30112
30480
|
scope: input2.scope,
|
|
30113
30481
|
root: input2.root,
|
|
30114
|
-
status: input2.status
|
|
30482
|
+
status: input2.status,
|
|
30483
|
+
phases: input2.phases
|
|
30115
30484
|
},
|
|
30116
30485
|
null,
|
|
30117
30486
|
2
|
|
@@ -30121,6 +30490,24 @@ function writeSetupState(input2) {
|
|
|
30121
30490
|
);
|
|
30122
30491
|
return path;
|
|
30123
30492
|
}
|
|
30493
|
+
function persistSetupProgress(input2) {
|
|
30494
|
+
return writeSetupState({
|
|
30495
|
+
...input2,
|
|
30496
|
+
status: input2.status ?? "in_progress"
|
|
30497
|
+
});
|
|
30498
|
+
}
|
|
30499
|
+
function completeSetupPhase(phases, phase, outcome) {
|
|
30500
|
+
phases[phase] = {
|
|
30501
|
+
status: "complete",
|
|
30502
|
+
...outcome ? { outcome } : {}
|
|
30503
|
+
};
|
|
30504
|
+
}
|
|
30505
|
+
function beginSetupPhase(phases, phase) {
|
|
30506
|
+
phases[phase] = { status: "in_progress" };
|
|
30507
|
+
}
|
|
30508
|
+
function failSetupPhase(phases, phase, code) {
|
|
30509
|
+
phases[phase] = { status: "failed", code };
|
|
30510
|
+
}
|
|
30124
30511
|
function rollbackCommand(scope, root) {
|
|
30125
30512
|
const prefix = scope === "local" && root ? ` --prefix ${JSON.stringify((0, import_node_path20.join)(root, ".deepline", "runtime"))}` : "";
|
|
30126
30513
|
return `npm install -g${prefix} --no-audit --no-fund --include=optional --allow-scripts=esbuild deepline@${SDK_VERSION}`;
|
|
@@ -30132,6 +30519,42 @@ function setupResumeCommand(baseUrl, scope) {
|
|
|
30132
30519
|
const hostPrefix = baseUrl === "https://code.deepline.com" ? "" : `DEEPLINE_HOST_URL=${JSON.stringify(baseUrl)} `;
|
|
30133
30520
|
return `${hostPrefix}deepline setup --scope ${scope} --json`;
|
|
30134
30521
|
}
|
|
30522
|
+
function setupRetry(input2) {
|
|
30523
|
+
return {
|
|
30524
|
+
phase: input2.phase,
|
|
30525
|
+
command: setupResumeCommand(input2.baseUrl, input2.scope),
|
|
30526
|
+
automatic: true
|
|
30527
|
+
};
|
|
30528
|
+
}
|
|
30529
|
+
function reportSetupPhaseFailure(input2) {
|
|
30530
|
+
failSetupPhase(input2.phases, input2.phase, input2.code);
|
|
30531
|
+
const statePath = persistSetupProgress({
|
|
30532
|
+
baseUrl: input2.baseUrl,
|
|
30533
|
+
scope: input2.scope,
|
|
30534
|
+
root: input2.root,
|
|
30535
|
+
phases: input2.phases,
|
|
30536
|
+
status: "failed"
|
|
30537
|
+
});
|
|
30538
|
+
const retry = setupRetry(input2);
|
|
30539
|
+
printCommandEnvelope(
|
|
30540
|
+
{
|
|
30541
|
+
ok: false,
|
|
30542
|
+
status: "failed",
|
|
30543
|
+
code: input2.code,
|
|
30544
|
+
exitCode: input2.exitCode,
|
|
30545
|
+
scope: input2.scope,
|
|
30546
|
+
message: input2.message,
|
|
30547
|
+
phases: input2.phases,
|
|
30548
|
+
failedPhase: input2.phase,
|
|
30549
|
+
retry,
|
|
30550
|
+
statePath,
|
|
30551
|
+
next: retry.command,
|
|
30552
|
+
...input2.extra ?? {}
|
|
30553
|
+
},
|
|
30554
|
+
{ json: input2.json }
|
|
30555
|
+
);
|
|
30556
|
+
return input2.exitCode;
|
|
30557
|
+
}
|
|
30135
30558
|
async function readAuthStatus(authScope) {
|
|
30136
30559
|
try {
|
|
30137
30560
|
const captured = await captureStdout2(
|
|
@@ -30151,63 +30574,44 @@ async function readAuthStatus(authScope) {
|
|
|
30151
30574
|
}
|
|
30152
30575
|
function reportSetupAuthStatusFailure(input2) {
|
|
30153
30576
|
if (!input2.auth.error) return null;
|
|
30154
|
-
|
|
30155
|
-
|
|
30156
|
-
|
|
30157
|
-
|
|
30158
|
-
|
|
30159
|
-
|
|
30160
|
-
|
|
30161
|
-
|
|
30162
|
-
|
|
30163
|
-
|
|
30164
|
-
}
|
|
30165
|
-
|
|
30166
|
-
);
|
|
30167
|
-
return 4;
|
|
30577
|
+
return reportSetupPhaseFailure({
|
|
30578
|
+
baseUrl: input2.baseUrl,
|
|
30579
|
+
scope: input2.scope,
|
|
30580
|
+
root: input2.root,
|
|
30581
|
+
phases: input2.phases,
|
|
30582
|
+
phase: "auth",
|
|
30583
|
+
code: "AUTH_STATUS_FAILED",
|
|
30584
|
+
exitCode: 4,
|
|
30585
|
+
message: "Deepline could not verify authorization with the configured host.",
|
|
30586
|
+
json: input2.json,
|
|
30587
|
+
extra: { authScope: input2.authScope }
|
|
30588
|
+
});
|
|
30168
30589
|
}
|
|
30169
|
-
|
|
30170
|
-
|
|
30171
|
-
|
|
30172
|
-
|
|
30173
|
-
|
|
30174
|
-
|
|
30175
|
-
} catch (error) {
|
|
30176
|
-
printCommandEnvelope(
|
|
30177
|
-
{
|
|
30178
|
-
ok: false,
|
|
30179
|
-
status: "failed",
|
|
30180
|
-
code: "INVALID_SETUP_SCOPE",
|
|
30181
|
-
exitCode: 2,
|
|
30182
|
-
message: error instanceof Error ? error.message : String(error)
|
|
30183
|
-
},
|
|
30184
|
-
{ json: options.json }
|
|
30185
|
-
);
|
|
30186
|
-
return 2;
|
|
30187
|
-
}
|
|
30188
|
-
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
30189
|
-
const skillsStatePath = skillsStatePathForScope(baseUrl, scope, root);
|
|
30590
|
+
function buildDoctorAssessment(input2) {
|
|
30591
|
+
const skillsStatePath = skillsStatePathForScope(
|
|
30592
|
+
input2.baseUrl,
|
|
30593
|
+
input2.scope,
|
|
30594
|
+
input2.root
|
|
30595
|
+
);
|
|
30190
30596
|
const skillsState = parseCapturedJson(safeRead(skillsStatePath));
|
|
30191
|
-
const
|
|
30192
|
-
const
|
|
30193
|
-
const
|
|
30194
|
-
const
|
|
30195
|
-
const
|
|
30196
|
-
const authScopeOk = scope === "local" ? Boolean(projectAuth) : Boolean(apiKey && !projectAuth);
|
|
30197
|
-
const skillsOk = skillsState?.scope === scope && Array.isArray(skillsState.agents) && skillsState.agents.length > 0;
|
|
30597
|
+
const apiKey = input2.scope === "local" ? resolveProjectApiKeyForBaseUrl(input2.baseUrl) : resolveGlobalApiKeyForBaseUrl(input2.baseUrl);
|
|
30598
|
+
const projectAuth = input2.scope === "local" && apiKey ? getResolvedProjectAuthSource(input2.baseUrl, apiKey) : null;
|
|
30599
|
+
const connected = input2.authStatus.payload?.connected === true;
|
|
30600
|
+
const authScopeOk = input2.scope === "local" ? Boolean(projectAuth) : Boolean(apiKey && !projectAuth);
|
|
30601
|
+
const skillsOk = skillsState?.scope === input2.scope && typeof skillsState.skillsVersion === "string" && Array.isArray(skillsState.agents) && skillsState.agents.length > 0;
|
|
30198
30602
|
const runningCliPath = process.argv[1] ? (0, import_node_path20.resolve)(process.argv[1]) : null;
|
|
30199
|
-
const globalCli = scope === "global" ? inspectGlobalCliAvailability() : null;
|
|
30603
|
+
const globalCli = input2.scope === "global" ? inspectGlobalCliAvailability() : null;
|
|
30200
30604
|
const pathGlobalCli = globalCli?.path ?? null;
|
|
30201
|
-
const cliPath = scope === "global" ? pathGlobalCli : runningCliPath;
|
|
30202
|
-
const cliScopeOk = scope === "global" ? Boolean(pathGlobalCli) : Boolean(
|
|
30203
|
-
root && runningCliPath?.includes((0, import_node_path20.join)(root, ".deepline", "runtime"))
|
|
30605
|
+
const cliPath = input2.scope === "global" ? pathGlobalCli : runningCliPath;
|
|
30606
|
+
const cliScopeOk = input2.scope === "global" ? Boolean(pathGlobalCli) : Boolean(
|
|
30607
|
+
input2.root && runningCliPath?.includes((0, import_node_path20.join)(input2.root, ".deepline", "runtime"))
|
|
30204
30608
|
);
|
|
30205
30609
|
const checks = {
|
|
30206
30610
|
cli: {
|
|
30207
30611
|
ok: Boolean(cliPath) && cliScopeOk,
|
|
30208
30612
|
version: SDK_VERSION,
|
|
30209
30613
|
path: cliPath,
|
|
30210
|
-
scope
|
|
30614
|
+
scope: input2.scope
|
|
30211
30615
|
},
|
|
30212
30616
|
skills: {
|
|
30213
30617
|
ok: skillsOk,
|
|
@@ -30218,16 +30622,48 @@ async function runDoctorCommand(options) {
|
|
|
30218
30622
|
auth: {
|
|
30219
30623
|
ok: connected && authScopeOk,
|
|
30220
30624
|
scope: projectAuth ? "local" : apiKey ? "global" : null,
|
|
30221
|
-
status: authStatus.payload?.status ?? "not_connected"
|
|
30625
|
+
status: input2.authStatus.payload?.status ?? "not_connected"
|
|
30222
30626
|
},
|
|
30223
30627
|
api: {
|
|
30224
|
-
ok: connected && authStatus.exitCode === 0,
|
|
30225
|
-
host: baseUrl,
|
|
30226
|
-
workspace: authStatus.payload?.workspace ?? null,
|
|
30628
|
+
ok: connected && input2.authStatus.exitCode === 0,
|
|
30629
|
+
host: input2.baseUrl,
|
|
30630
|
+
workspace: input2.authStatus.payload?.workspace ?? null,
|
|
30227
30631
|
providerSpend: false
|
|
30228
30632
|
}
|
|
30229
30633
|
};
|
|
30230
|
-
|
|
30634
|
+
return {
|
|
30635
|
+
ok: Object.values(checks).every((check) => check.ok),
|
|
30636
|
+
checks
|
|
30637
|
+
};
|
|
30638
|
+
}
|
|
30639
|
+
async function runDoctorCommand(options) {
|
|
30640
|
+
let scope;
|
|
30641
|
+
let root;
|
|
30642
|
+
try {
|
|
30643
|
+
scope = normalizeScope2(options.scope);
|
|
30644
|
+
root = resolveScopeRoot(scope);
|
|
30645
|
+
} catch (error) {
|
|
30646
|
+
printCommandEnvelope(
|
|
30647
|
+
{
|
|
30648
|
+
ok: false,
|
|
30649
|
+
status: "failed",
|
|
30650
|
+
code: "INVALID_SETUP_SCOPE",
|
|
30651
|
+
exitCode: 2,
|
|
30652
|
+
message: error instanceof Error ? error.message : String(error)
|
|
30653
|
+
},
|
|
30654
|
+
{ json: options.json }
|
|
30655
|
+
);
|
|
30656
|
+
return 2;
|
|
30657
|
+
}
|
|
30658
|
+
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
30659
|
+
const authScope = authScopeForSetup(scope);
|
|
30660
|
+
const authStatus = await readAuthStatus(authScope);
|
|
30661
|
+
const { ok, checks } = buildDoctorAssessment({
|
|
30662
|
+
baseUrl,
|
|
30663
|
+
scope,
|
|
30664
|
+
root,
|
|
30665
|
+
authStatus
|
|
30666
|
+
});
|
|
30231
30667
|
const quickstart = setupQuickstartCommand(baseUrl);
|
|
30232
30668
|
printCommandEnvelope(
|
|
30233
30669
|
{
|
|
@@ -30253,11 +30689,16 @@ async function runDoctorCommand(options) {
|
|
|
30253
30689
|
return ok ? 0 : 7;
|
|
30254
30690
|
}
|
|
30255
30691
|
function pendingResult(input2) {
|
|
30692
|
+
input2.phases.auth = {
|
|
30693
|
+
status: "waiting",
|
|
30694
|
+
outcome: "authorization_pending"
|
|
30695
|
+
};
|
|
30256
30696
|
const statePath = writeSetupState({
|
|
30257
30697
|
baseUrl: input2.baseUrl,
|
|
30258
30698
|
scope: input2.scope,
|
|
30259
30699
|
root: input2.root,
|
|
30260
|
-
status: "authorization_pending"
|
|
30700
|
+
status: "authorization_pending",
|
|
30701
|
+
phases: input2.phases
|
|
30261
30702
|
});
|
|
30262
30703
|
if (input2.authorizationUrl) {
|
|
30263
30704
|
process.stderr.write(`Authorize Deepline: ${input2.authorizationUrl}
|
|
@@ -30271,6 +30712,14 @@ function pendingResult(input2) {
|
|
|
30271
30712
|
scope: input2.scope,
|
|
30272
30713
|
authorizationUrl: input2.authorizationUrl || null,
|
|
30273
30714
|
statePath,
|
|
30715
|
+
phases: input2.phases,
|
|
30716
|
+
currentPhase: "auth",
|
|
30717
|
+
resumed: input2.resumed,
|
|
30718
|
+
retry: setupRetry({
|
|
30719
|
+
baseUrl: input2.baseUrl,
|
|
30720
|
+
scope: input2.scope,
|
|
30721
|
+
phase: "auth"
|
|
30722
|
+
}),
|
|
30274
30723
|
next: `Approve the link, then run: ${setupResumeCommand(input2.baseUrl, input2.scope)}`,
|
|
30275
30724
|
render: {
|
|
30276
30725
|
sections: [
|
|
@@ -30301,84 +30750,146 @@ async function runSetupCommand(options) {
|
|
|
30301
30750
|
status: "failed",
|
|
30302
30751
|
code: "INVALID_SETUP_SCOPE",
|
|
30303
30752
|
exitCode: 2,
|
|
30304
|
-
message: error instanceof Error ? error.message : String(error)
|
|
30753
|
+
message: error instanceof Error ? error.message : String(error),
|
|
30754
|
+
phases: {
|
|
30755
|
+
...initialSetupPhases(),
|
|
30756
|
+
cli: { status: "failed", code: "INVALID_SETUP_SCOPE" }
|
|
30757
|
+
},
|
|
30758
|
+
failedPhase: "cli"
|
|
30305
30759
|
},
|
|
30306
30760
|
{ json: options.json }
|
|
30307
30761
|
);
|
|
30308
30762
|
return 2;
|
|
30309
30763
|
}
|
|
30310
30764
|
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
30311
|
-
|
|
30312
|
-
|
|
30313
|
-
|
|
30314
|
-
|
|
30315
|
-
|
|
30316
|
-
|
|
30317
|
-
|
|
30318
|
-
|
|
30319
|
-
|
|
30320
|
-
|
|
30765
|
+
const previousState = readSetupState({ baseUrl, scope, root });
|
|
30766
|
+
const { resumed, phases } = selectSetupProgress(previousState);
|
|
30767
|
+
if (phases.cli.status !== "complete") {
|
|
30768
|
+
beginSetupPhase(phases, "cli");
|
|
30769
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30770
|
+
if (scope === "global") {
|
|
30771
|
+
const globalCli = inspectGlobalCliAvailability();
|
|
30772
|
+
if (!globalCli.ok) {
|
|
30773
|
+
const installedButUnreachable = Boolean(globalCli.persistentPath);
|
|
30774
|
+
const code = installedButUnreachable ? "GLOBAL_CLI_NOT_ON_PATH" : "GLOBAL_CLI_NOT_INSTALLED";
|
|
30775
|
+
return reportSetupPhaseFailure({
|
|
30776
|
+
baseUrl,
|
|
30321
30777
|
scope,
|
|
30322
|
-
|
|
30778
|
+
root,
|
|
30779
|
+
phases,
|
|
30780
|
+
phase: "cli",
|
|
30781
|
+
code,
|
|
30782
|
+
exitCode: 7,
|
|
30323
30783
|
message: installedButUnreachable ? `The global Deepline executable is not reachable on PATH: ${globalCli.persistentPath}` : "No persistent global Deepline executable was found.",
|
|
30324
|
-
|
|
30325
|
-
|
|
30326
|
-
|
|
30327
|
-
|
|
30328
|
-
|
|
30784
|
+
json: options.json,
|
|
30785
|
+
extra: {
|
|
30786
|
+
persistentPath: globalCli.persistentPath,
|
|
30787
|
+
fallback: "https://code.deepline.com/INSTALL.md"
|
|
30788
|
+
}
|
|
30789
|
+
});
|
|
30790
|
+
}
|
|
30329
30791
|
}
|
|
30330
|
-
|
|
30331
|
-
|
|
30332
|
-
|
|
30333
|
-
|
|
30334
|
-
|
|
30335
|
-
|
|
30336
|
-
|
|
30792
|
+
const conflict = inspectPathConflict();
|
|
30793
|
+
if (conflict) {
|
|
30794
|
+
return reportSetupPhaseFailure({
|
|
30795
|
+
baseUrl,
|
|
30796
|
+
scope,
|
|
30797
|
+
root,
|
|
30798
|
+
phases,
|
|
30799
|
+
phase: "cli",
|
|
30337
30800
|
code: "PATH_CONFLICT",
|
|
30338
30801
|
exitCode: 7,
|
|
30339
|
-
path: conflict,
|
|
30340
30802
|
message: `An unknown executable named deepline is first on PATH: ${conflict}`,
|
|
30341
|
-
|
|
30342
|
-
|
|
30343
|
-
|
|
30344
|
-
|
|
30345
|
-
|
|
30803
|
+
json: options.json,
|
|
30804
|
+
extra: { path: conflict }
|
|
30805
|
+
});
|
|
30806
|
+
}
|
|
30807
|
+
completeSetupPhase(phases, "cli", "available");
|
|
30808
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30346
30809
|
}
|
|
30347
|
-
|
|
30348
|
-
|
|
30349
|
-
|
|
30350
|
-
|
|
30810
|
+
if (phases.cleanup.status !== "complete") {
|
|
30811
|
+
beginSetupPhase(phases, "cleanup");
|
|
30812
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30813
|
+
try {
|
|
30814
|
+
const removedLegacyPaths = removeKnownLegacyPaths(baseUrl);
|
|
30815
|
+
if (removedLegacyPaths.length > 0) {
|
|
30816
|
+
process.stderr.write(
|
|
30817
|
+
`Removed ${removedLegacyPaths.length} known legacy Deepline path(s).
|
|
30351
30818
|
`
|
|
30352
|
-
|
|
30819
|
+
);
|
|
30820
|
+
}
|
|
30821
|
+
completeSetupPhase(
|
|
30822
|
+
phases,
|
|
30823
|
+
"cleanup",
|
|
30824
|
+
removedLegacyPaths.length > 0 ? "removed_legacy_paths" : "clean"
|
|
30825
|
+
);
|
|
30826
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30827
|
+
} catch (error) {
|
|
30828
|
+
return reportSetupPhaseFailure({
|
|
30829
|
+
baseUrl,
|
|
30830
|
+
scope,
|
|
30831
|
+
root,
|
|
30832
|
+
phases,
|
|
30833
|
+
phase: "cleanup",
|
|
30834
|
+
code: "LEGACY_CLEANUP_FAILED",
|
|
30835
|
+
exitCode: 5,
|
|
30836
|
+
message: error instanceof Error ? error.message : String(error),
|
|
30837
|
+
json: options.json
|
|
30838
|
+
});
|
|
30839
|
+
}
|
|
30353
30840
|
}
|
|
30354
|
-
|
|
30841
|
+
let skillsPayload = null;
|
|
30842
|
+
if (phases.skills.status !== "complete") {
|
|
30843
|
+
beginSetupPhase(phases, "skills");
|
|
30844
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30845
|
+
process.stderr.write(`Installing Deepline skills (${scope})...
|
|
30355
30846
|
`);
|
|
30356
|
-
|
|
30357
|
-
|
|
30358
|
-
|
|
30359
|
-
|
|
30360
|
-
|
|
30361
|
-
|
|
30362
|
-
|
|
30363
|
-
|
|
30364
|
-
|
|
30847
|
+
const skills = await captureStdout2(
|
|
30848
|
+
() => runSkillsCommand({ scope, json: true })
|
|
30849
|
+
);
|
|
30850
|
+
skillsPayload = parseCapturedJson(skills.stdout);
|
|
30851
|
+
if (skills.exitCode !== 0) {
|
|
30852
|
+
return reportSetupPhaseFailure({
|
|
30853
|
+
baseUrl,
|
|
30854
|
+
scope,
|
|
30855
|
+
root,
|
|
30856
|
+
phases,
|
|
30857
|
+
phase: "skills",
|
|
30365
30858
|
code: "SKILLS_INSTALL_FAILED",
|
|
30366
30859
|
exitCode: skills.exitCode,
|
|
30367
|
-
|
|
30368
|
-
|
|
30369
|
-
|
|
30370
|
-
}
|
|
30371
|
-
|
|
30860
|
+
message: typeof skillsPayload?.message === "string" ? skillsPayload.message : "Deepline skills could not be installed.",
|
|
30861
|
+
json: options.json,
|
|
30862
|
+
extra: { detail: skillsPayload }
|
|
30863
|
+
});
|
|
30864
|
+
}
|
|
30865
|
+
completeSetupPhase(
|
|
30866
|
+
phases,
|
|
30867
|
+
"skills",
|
|
30868
|
+
skillsPayload?.status === "current" ? "current" : "installed"
|
|
30869
|
+
);
|
|
30870
|
+
writeSetupState({
|
|
30871
|
+
baseUrl,
|
|
30872
|
+
scope,
|
|
30873
|
+
root,
|
|
30874
|
+
status: "skills_installed",
|
|
30875
|
+
phases
|
|
30876
|
+
});
|
|
30877
|
+
} else {
|
|
30878
|
+
skillsPayload = parseCapturedJson(
|
|
30879
|
+
safeRead(skillsStatePathForScope(baseUrl, scope, root))
|
|
30372
30880
|
);
|
|
30373
|
-
return skills.exitCode;
|
|
30374
30881
|
}
|
|
30375
|
-
writeSetupState({ baseUrl, scope, root, status: "skills_installed" });
|
|
30376
30882
|
const authScope = authScopeForSetup(scope);
|
|
30883
|
+
beginSetupPhase(phases, "auth");
|
|
30884
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30377
30885
|
let auth = await readAuthStatus(authScope);
|
|
30378
30886
|
const initialAuthFailure = reportSetupAuthStatusFailure({
|
|
30379
30887
|
auth,
|
|
30888
|
+
baseUrl,
|
|
30380
30889
|
authScope,
|
|
30381
30890
|
scope,
|
|
30891
|
+
root,
|
|
30892
|
+
phases,
|
|
30382
30893
|
json: options.json
|
|
30383
30894
|
});
|
|
30384
30895
|
if (initialAuthFailure !== null) return initialAuthFailure;
|
|
@@ -30393,8 +30904,11 @@ async function runSetupCommand(options) {
|
|
|
30393
30904
|
auth = await readAuthStatus(authScope);
|
|
30394
30905
|
const resumedAuthFailure = reportSetupAuthStatusFailure({
|
|
30395
30906
|
auth,
|
|
30907
|
+
baseUrl,
|
|
30396
30908
|
authScope,
|
|
30397
30909
|
scope,
|
|
30910
|
+
root,
|
|
30911
|
+
phases,
|
|
30398
30912
|
json: options.json
|
|
30399
30913
|
});
|
|
30400
30914
|
if (resumedAuthFailure !== null) return resumedAuthFailure;
|
|
@@ -30405,7 +30919,9 @@ async function runSetupCommand(options) {
|
|
|
30405
30919
|
baseUrl,
|
|
30406
30920
|
scope,
|
|
30407
30921
|
root,
|
|
30922
|
+
phases,
|
|
30408
30923
|
authorizationUrl: stillPending.claimUrl,
|
|
30924
|
+
resumed,
|
|
30409
30925
|
json: options.json
|
|
30410
30926
|
});
|
|
30411
30927
|
}
|
|
@@ -30422,24 +30938,30 @@ async function runSetupCommand(options) {
|
|
|
30422
30938
|
);
|
|
30423
30939
|
printCapturedAuthorizationUrl(registered.stdout);
|
|
30424
30940
|
if (registered.exitCode !== 0) {
|
|
30425
|
-
|
|
30426
|
-
|
|
30427
|
-
|
|
30428
|
-
|
|
30429
|
-
|
|
30430
|
-
|
|
30431
|
-
|
|
30432
|
-
|
|
30433
|
-
|
|
30434
|
-
|
|
30435
|
-
|
|
30436
|
-
|
|
30941
|
+
return reportSetupPhaseFailure({
|
|
30942
|
+
baseUrl,
|
|
30943
|
+
scope,
|
|
30944
|
+
root,
|
|
30945
|
+
phases,
|
|
30946
|
+
phase: "auth",
|
|
30947
|
+
code: "AUTH_REGISTER_FAILED",
|
|
30948
|
+
exitCode: registered.exitCode,
|
|
30949
|
+
message: "Deepline browser authorization could not be started.",
|
|
30950
|
+
json: options.json,
|
|
30951
|
+
extra: {
|
|
30952
|
+
detail: parseCapturedJson(registered.stdout),
|
|
30953
|
+
authScope
|
|
30954
|
+
}
|
|
30955
|
+
});
|
|
30437
30956
|
}
|
|
30438
30957
|
auth = await readAuthStatus(authScope);
|
|
30439
30958
|
const registeredAuthFailure = reportSetupAuthStatusFailure({
|
|
30440
30959
|
auth,
|
|
30960
|
+
baseUrl,
|
|
30441
30961
|
authScope,
|
|
30442
30962
|
scope,
|
|
30963
|
+
root,
|
|
30964
|
+
phases,
|
|
30443
30965
|
json: options.json
|
|
30444
30966
|
});
|
|
30445
30967
|
if (registeredAuthFailure !== null) return registeredAuthFailure;
|
|
@@ -30449,40 +30971,60 @@ async function runSetupCommand(options) {
|
|
|
30449
30971
|
baseUrl,
|
|
30450
30972
|
scope,
|
|
30451
30973
|
root,
|
|
30974
|
+
phases,
|
|
30452
30975
|
authorizationUrl: pending?.claimUrl ?? "",
|
|
30976
|
+
resumed,
|
|
30453
30977
|
json: options.json
|
|
30454
30978
|
});
|
|
30455
30979
|
}
|
|
30456
30980
|
}
|
|
30457
|
-
|
|
30458
|
-
|
|
30459
|
-
|
|
30460
|
-
|
|
30461
|
-
|
|
30462
|
-
|
|
30463
|
-
|
|
30464
|
-
|
|
30465
|
-
|
|
30466
|
-
|
|
30467
|
-
|
|
30468
|
-
|
|
30469
|
-
|
|
30981
|
+
completeSetupPhase(phases, "auth", "connected");
|
|
30982
|
+
beginSetupPhase(phases, "verify");
|
|
30983
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30984
|
+
const assessment = buildDoctorAssessment({
|
|
30985
|
+
baseUrl,
|
|
30986
|
+
scope,
|
|
30987
|
+
root,
|
|
30988
|
+
authStatus: auth
|
|
30989
|
+
});
|
|
30990
|
+
const quickstart = setupQuickstartCommand(baseUrl);
|
|
30991
|
+
const doctorPayload = {
|
|
30992
|
+
ok: assessment.ok,
|
|
30993
|
+
status: assessment.ok ? "complete" : "failed",
|
|
30994
|
+
code: assessment.ok ? "DOCTOR_OK" : "DOCTOR_FAILED",
|
|
30995
|
+
exitCode: assessment.ok ? 0 : 7,
|
|
30996
|
+
checks: assessment.checks,
|
|
30997
|
+
next: assessment.ok ? quickstart : `deepline doctor --scope ${scope} --json`
|
|
30998
|
+
};
|
|
30999
|
+
if (!assessment.ok) {
|
|
31000
|
+
return reportSetupPhaseFailure({
|
|
31001
|
+
baseUrl,
|
|
31002
|
+
scope,
|
|
31003
|
+
root,
|
|
31004
|
+
phases,
|
|
31005
|
+
phase: "verify",
|
|
31006
|
+
code: "DOCTOR_FAILED",
|
|
31007
|
+
exitCode: 7,
|
|
31008
|
+
message: "Deepline setup verification found one or more failed checks.",
|
|
31009
|
+
json: options.json,
|
|
31010
|
+
extra: {
|
|
30470
31011
|
doctor: doctorPayload,
|
|
30471
|
-
|
|
30472
|
-
|
|
30473
|
-
|
|
30474
|
-
|
|
30475
|
-
|
|
31012
|
+
diagnostic: {
|
|
31013
|
+
command: `deepline doctor --scope ${scope} --json`
|
|
31014
|
+
}
|
|
31015
|
+
}
|
|
31016
|
+
});
|
|
30476
31017
|
}
|
|
31018
|
+
completeSetupPhase(phases, "verify", "verified");
|
|
30477
31019
|
const statePath = writeSetupState({
|
|
30478
31020
|
baseUrl,
|
|
30479
31021
|
scope,
|
|
30480
31022
|
root,
|
|
30481
|
-
status: "complete"
|
|
31023
|
+
status: "complete",
|
|
31024
|
+
phases
|
|
30482
31025
|
});
|
|
30483
31026
|
const doctorChecks = asRecord2(doctorPayload?.checks);
|
|
30484
31027
|
const apiCheck = asRecord2(doctorChecks?.api);
|
|
30485
|
-
const quickstart = setupQuickstartCommand(baseUrl);
|
|
30486
31028
|
printCommandEnvelope(
|
|
30487
31029
|
{
|
|
30488
31030
|
ok: true,
|
|
@@ -30495,6 +31037,10 @@ async function runSetupCommand(options) {
|
|
|
30495
31037
|
rollbackCommand: rollbackCommand(scope, root),
|
|
30496
31038
|
statePath,
|
|
30497
31039
|
doctor: doctorPayload,
|
|
31040
|
+
phases,
|
|
31041
|
+
currentPhase: null,
|
|
31042
|
+
failedPhase: null,
|
|
31043
|
+
resumed,
|
|
30498
31044
|
next: quickstart,
|
|
30499
31045
|
render: {
|
|
30500
31046
|
sections: [
|
|
@@ -30517,8 +31063,9 @@ function registerSetupCommands(program) {
|
|
|
30517
31063
|
"after",
|
|
30518
31064
|
`
|
|
30519
31065
|
Notes:
|
|
30520
|
-
Setup is idempotent. Bare setup resumes
|
|
31066
|
+
Setup is idempotent. Bare setup resumes the first incomplete or failed phase.
|
|
30521
31067
|
It installs skills before auth and does not run quickstart.
|
|
31068
|
+
JSON output includes phase status and an exact retry command.
|
|
30522
31069
|
|
|
30523
31070
|
Examples:
|
|
30524
31071
|
deepline setup --json
|