deepline 0.1.259 → 0.1.261
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/config.ts +110 -8
- 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/play-runtime/runtime-api.ts +124 -34
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-postgres-admission.ts +130 -21
- package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +21 -0
- package/dist/cli/index.js +2012 -547
- package/dist/cli/index.mjs +2088 -615
- package/dist/index.js +1 -1
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -182,8 +182,8 @@ configureProxyFromEnv();
|
|
|
182
182
|
|
|
183
183
|
// src/cli/index.ts
|
|
184
184
|
var import_promises6 = require("fs/promises");
|
|
185
|
-
var
|
|
186
|
-
var
|
|
185
|
+
var import_node_path22 = require("path");
|
|
186
|
+
var import_node_os17 = require("os");
|
|
187
187
|
var import_commander4 = require("commander");
|
|
188
188
|
|
|
189
189
|
// src/config.ts
|
|
@@ -499,6 +499,21 @@ function resolveApiKeyForBaseUrl(baseUrl, explicitApiKey) {
|
|
|
499
499
|
cliEnv[API_KEY_ENV]
|
|
500
500
|
);
|
|
501
501
|
}
|
|
502
|
+
function resolveProjectApiKeyForBaseUrl(baseUrl, startDir = process.cwd()) {
|
|
503
|
+
const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
|
|
504
|
+
return firstNonEmpty(
|
|
505
|
+
...loadProjectEnvCandidates(startDir).map(({ env }) => {
|
|
506
|
+
const projectBaseUrl = normalizeBaseUrl(env[HOST_URL_ENV] ?? "");
|
|
507
|
+
return projectBaseUrl === normalizedBaseUrl ? env[API_KEY_ENV] : "";
|
|
508
|
+
})
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
function resolveGlobalApiKeyForBaseUrl(baseUrl) {
|
|
512
|
+
return firstNonEmpty(
|
|
513
|
+
process.env[API_KEY_ENV],
|
|
514
|
+
loadCliEnv(normalizeBaseUrl(baseUrl) || baseUrl)[API_KEY_ENV]
|
|
515
|
+
);
|
|
516
|
+
}
|
|
502
517
|
function getResolvedProjectAuthSource(baseUrl, apiKey, startDir = process.cwd()) {
|
|
503
518
|
const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
|
|
504
519
|
const normalizedApiKey = apiKey.trim();
|
|
@@ -542,14 +557,79 @@ function mergeProjectEnvFile(filePath, values) {
|
|
|
542
557
|
`, "utf-8");
|
|
543
558
|
}
|
|
544
559
|
function ensureProjectEnvIsIgnored(dir) {
|
|
560
|
+
ensureProjectPrivatePathsIgnored(dir, [
|
|
561
|
+
PROJECT_DEEPLINE_ENV_FILE,
|
|
562
|
+
".deepline/"
|
|
563
|
+
]);
|
|
564
|
+
}
|
|
565
|
+
function ensureProjectPrivatePathsIgnored(dir, entries) {
|
|
566
|
+
const gitDir = findNearestGitCommonDir(dir);
|
|
567
|
+
if (gitDir) {
|
|
568
|
+
const excludePath = (0, import_node_path.join)(gitDir, "info", "exclude");
|
|
569
|
+
const existing2 = (0, import_node_fs.existsSync)(excludePath) ? (0, import_node_fs.readFileSync)(excludePath, "utf-8") : "";
|
|
570
|
+
const existingEntries2 = new Set(
|
|
571
|
+
existing2.split(/\r?\n/).map((line) => line.trim()).filter(Boolean)
|
|
572
|
+
);
|
|
573
|
+
const missing2 = entries.filter(
|
|
574
|
+
(entry) => !existingEntries2.has(entry) && !existingEntries2.has(`/${entry}`)
|
|
575
|
+
);
|
|
576
|
+
if (missing2.length === 0) return;
|
|
577
|
+
(0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(excludePath), { recursive: true });
|
|
578
|
+
const prefix2 = existing2 && !existing2.endsWith("\n") ? "\n" : "";
|
|
579
|
+
(0, import_node_fs.writeFileSync)(
|
|
580
|
+
excludePath,
|
|
581
|
+
`${existing2}${prefix2}${missing2.join("\n")}
|
|
582
|
+
`,
|
|
583
|
+
"utf-8"
|
|
584
|
+
);
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
545
587
|
const gitignorePath = (0, import_node_path.join)(dir, ".gitignore");
|
|
546
|
-
const entry = PROJECT_DEEPLINE_ENV_FILE;
|
|
547
588
|
const existing = (0, import_node_fs.existsSync)(gitignorePath) ? (0, import_node_fs.readFileSync)(gitignorePath, "utf-8") : "";
|
|
548
|
-
const
|
|
549
|
-
|
|
589
|
+
const existingEntries = new Set(
|
|
590
|
+
existing.split(/\r?\n/).map((line) => line.trim()).filter(Boolean)
|
|
591
|
+
);
|
|
592
|
+
const missing = entries.filter(
|
|
593
|
+
(entry) => !existingEntries.has(entry) && !existingEntries.has(`/${entry}`)
|
|
594
|
+
);
|
|
595
|
+
if (missing.length === 0) return;
|
|
550
596
|
const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
|
|
551
|
-
(0, import_node_fs.writeFileSync)(
|
|
552
|
-
|
|
597
|
+
(0, import_node_fs.writeFileSync)(
|
|
598
|
+
gitignorePath,
|
|
599
|
+
`${existing}${prefix}${missing.join("\n")}
|
|
600
|
+
`,
|
|
601
|
+
"utf-8"
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
function findNearestGitCommonDir(startDir) {
|
|
605
|
+
let current = (0, import_node_path.resolve)(startDir);
|
|
606
|
+
while (true) {
|
|
607
|
+
const candidate = (0, import_node_path.join)(current, ".git");
|
|
608
|
+
if ((0, import_node_fs.existsSync)(candidate)) {
|
|
609
|
+
try {
|
|
610
|
+
const stat2 = (0, import_node_fs.statSync)(candidate);
|
|
611
|
+
if (stat2.isDirectory()) return candidate;
|
|
612
|
+
if (stat2.isFile()) {
|
|
613
|
+
const match = (0, import_node_fs.readFileSync)(candidate, "utf8").match(
|
|
614
|
+
/^gitdir:\s*(.+)$/m
|
|
615
|
+
);
|
|
616
|
+
const rawGitDir = match?.[1]?.trim();
|
|
617
|
+
if (rawGitDir) {
|
|
618
|
+
const gitDir = (0, import_node_path.isAbsolute)(rawGitDir) ? rawGitDir : (0, import_node_path.resolve)((0, import_node_path.dirname)(candidate), rawGitDir);
|
|
619
|
+
const commonDirPath = (0, import_node_path.join)(gitDir, "commondir");
|
|
620
|
+
if (!(0, import_node_fs.existsSync)(commonDirPath)) return gitDir;
|
|
621
|
+
const rawCommonDir = (0, import_node_fs.readFileSync)(commonDirPath, "utf8").trim();
|
|
622
|
+
return rawCommonDir ? (0, import_node_path.isAbsolute)(rawCommonDir) ? rawCommonDir : (0, import_node_path.resolve)(gitDir, rawCommonDir) : gitDir;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
} catch {
|
|
626
|
+
return null;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
const parent = (0, import_node_path.dirname)(current);
|
|
630
|
+
if (parent === current) return null;
|
|
631
|
+
current = parent;
|
|
632
|
+
}
|
|
553
633
|
}
|
|
554
634
|
function saveProjectDeeplineEnvValues(values, startDir = process.cwd()) {
|
|
555
635
|
const target = resolveProjectPinTarget(startDir);
|
|
@@ -636,7 +716,7 @@ var SDK_RELEASE = {
|
|
|
636
716
|
// Deepline-native radars. Older clients must update before discovering,
|
|
637
717
|
// checking, or deploying an unlaunched monitor integration.
|
|
638
718
|
// 0.1.253 makes play-page browser opening opt-in and retires --no-open.
|
|
639
|
-
version: "0.1.
|
|
719
|
+
version: "0.1.261",
|
|
640
720
|
apiContract: "2026-07-native-monitor-launch-hard-cutover",
|
|
641
721
|
supportPolicy: {
|
|
642
722
|
minimumSupported: "0.1.53",
|
|
@@ -1321,7 +1401,7 @@ function decodeSseFrame(frame) {
|
|
|
1321
1401
|
return parsed;
|
|
1322
1402
|
}
|
|
1323
1403
|
function sleep(ms) {
|
|
1324
|
-
return new Promise((
|
|
1404
|
+
return new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
1325
1405
|
}
|
|
1326
1406
|
function withCoworkNetworkHint(message) {
|
|
1327
1407
|
if (!isCoworkLikeSandbox2() || message.includes(COWORK_NETWORK_HINT)) {
|
|
@@ -2293,14 +2373,14 @@ async function* observeRunEvents(options) {
|
|
|
2293
2373
|
try {
|
|
2294
2374
|
for (; ; ) {
|
|
2295
2375
|
if (queue.length === 0) {
|
|
2296
|
-
const waitForItem = new Promise((
|
|
2297
|
-
wake =
|
|
2376
|
+
const waitForItem = new Promise((resolve15) => {
|
|
2377
|
+
wake = resolve15;
|
|
2298
2378
|
});
|
|
2299
2379
|
if (!sawFirstSnapshot) {
|
|
2300
2380
|
const timedOut = await Promise.race([
|
|
2301
2381
|
waitForItem.then(() => false),
|
|
2302
2382
|
new Promise(
|
|
2303
|
-
(
|
|
2383
|
+
(resolve15) => setTimeout(() => resolve15(true), OBSERVE_BOOTSTRAP_TIMEOUT_MS)
|
|
2304
2384
|
)
|
|
2305
2385
|
]);
|
|
2306
2386
|
if (timedOut && queue.length === 0) {
|
|
@@ -2518,7 +2598,7 @@ function parseEnvTestPolicyOverrides() {
|
|
|
2518
2598
|
return normalizeTestPolicyOverrides(parsed, "DEEPLINE_TEST_POLICY_OVERRIDES");
|
|
2519
2599
|
}
|
|
2520
2600
|
function sleep2(ms) {
|
|
2521
|
-
return new Promise((
|
|
2601
|
+
return new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
2522
2602
|
}
|
|
2523
2603
|
function isTransientCompileManifestError(error) {
|
|
2524
2604
|
if (error instanceof DeeplineError && typeof error.statusCode === "number") {
|
|
@@ -5679,30 +5759,86 @@ var EXIT_SERVER = 5;
|
|
|
5679
5759
|
function envFilePath(baseUrl) {
|
|
5680
5760
|
return hostEnvFilePath(baseUrl);
|
|
5681
5761
|
}
|
|
5682
|
-
function
|
|
5762
|
+
function normalizeAuthScope(value) {
|
|
5763
|
+
if (!value || value === "global") return "global";
|
|
5764
|
+
if (value === "folder") return "folder";
|
|
5765
|
+
throw new Error("--auth-scope must be one of: folder, global");
|
|
5766
|
+
}
|
|
5767
|
+
function parseAuthScope(args) {
|
|
5768
|
+
const index = args.indexOf("--auth-scope");
|
|
5769
|
+
return normalizeAuthScope(index >= 0 ? args[index + 1] : void 0);
|
|
5770
|
+
}
|
|
5771
|
+
function pendingClaimPath(baseUrl, scope) {
|
|
5772
|
+
if (scope === "folder") {
|
|
5773
|
+
const target = resolveProjectPinTarget();
|
|
5774
|
+
if (!target.ok) {
|
|
5775
|
+
throw new Error(
|
|
5776
|
+
`Cowork project folder is ambiguous. Candidate folders: ${target.candidates.join(
|
|
5777
|
+
", "
|
|
5778
|
+
)}. Set CLAUDE_PROJECT_DIR or cd into the intended project folder.`
|
|
5779
|
+
);
|
|
5780
|
+
}
|
|
5781
|
+
return (0, import_node_path5.join)(target.dir, ".deepline", "setup", "pending-auth.json");
|
|
5782
|
+
}
|
|
5783
|
+
return `${hostConfigDirPath(baseUrl)}/pending-auth.json`;
|
|
5784
|
+
}
|
|
5785
|
+
function legacyPendingClaimTokenPath(baseUrl) {
|
|
5683
5786
|
return `${hostConfigDirPath(baseUrl)}/pending-claim-token`;
|
|
5684
5787
|
}
|
|
5685
|
-
function
|
|
5686
|
-
const filePath =
|
|
5788
|
+
function savePendingClaim(baseUrl, claim) {
|
|
5789
|
+
const filePath = pendingClaimPath(baseUrl, claim.scope);
|
|
5687
5790
|
const dir = (0, import_node_path5.dirname)(filePath);
|
|
5688
5791
|
if (!(0, import_node_fs5.existsSync)(dir)) {
|
|
5689
5792
|
(0, import_node_fs5.mkdirSync)(dir, { recursive: true });
|
|
5690
5793
|
}
|
|
5691
|
-
(0, import_node_fs5.writeFileSync)(filePath, `${
|
|
5692
|
-
`,
|
|
5794
|
+
(0, import_node_fs5.writeFileSync)(filePath, `${JSON.stringify(claim, null, 2)}
|
|
5795
|
+
`, {
|
|
5796
|
+
encoding: "utf-8",
|
|
5797
|
+
mode: 384
|
|
5798
|
+
});
|
|
5693
5799
|
}
|
|
5694
|
-
function
|
|
5695
|
-
|
|
5696
|
-
if (!(0, import_node_fs5.existsSync)(filePath)) return "";
|
|
5800
|
+
function readPendingAuthClaim(baseUrl, scope) {
|
|
5801
|
+
let filePath;
|
|
5697
5802
|
try {
|
|
5698
|
-
|
|
5803
|
+
filePath = pendingClaimPath(baseUrl, scope);
|
|
5699
5804
|
} catch {
|
|
5700
|
-
return
|
|
5805
|
+
return null;
|
|
5806
|
+
}
|
|
5807
|
+
if (!(0, import_node_fs5.existsSync)(filePath)) {
|
|
5808
|
+
if (scope !== "global") return null;
|
|
5809
|
+
try {
|
|
5810
|
+
const claimToken = (0, import_node_fs5.readFileSync)(
|
|
5811
|
+
legacyPendingClaimTokenPath(baseUrl),
|
|
5812
|
+
"utf-8"
|
|
5813
|
+
).trim();
|
|
5814
|
+
return claimToken ? {
|
|
5815
|
+
claimToken,
|
|
5816
|
+
claimUrl: `${baseUrl}/api/v2/auth/cli/claim/${encodeURIComponent(claimToken)}`,
|
|
5817
|
+
scope
|
|
5818
|
+
} : null;
|
|
5819
|
+
} catch {
|
|
5820
|
+
return null;
|
|
5821
|
+
}
|
|
5822
|
+
}
|
|
5823
|
+
try {
|
|
5824
|
+
const parsed = JSON.parse((0, import_node_fs5.readFileSync)(filePath, "utf-8"));
|
|
5825
|
+
const claimToken = typeof parsed.claimToken === "string" ? parsed.claimToken.trim() : "";
|
|
5826
|
+
if (!claimToken) return null;
|
|
5827
|
+
return {
|
|
5828
|
+
claimToken,
|
|
5829
|
+
claimUrl: typeof parsed.claimUrl === "string" ? parsed.claimUrl.trim() : "",
|
|
5830
|
+
scope
|
|
5831
|
+
};
|
|
5832
|
+
} catch {
|
|
5833
|
+
return null;
|
|
5701
5834
|
}
|
|
5702
5835
|
}
|
|
5703
|
-
function
|
|
5836
|
+
function clearPendingClaim(baseUrl, scope) {
|
|
5704
5837
|
try {
|
|
5705
|
-
(0, import_node_fs5.rmSync)(
|
|
5838
|
+
(0, import_node_fs5.rmSync)(pendingClaimPath(baseUrl, scope), { force: true });
|
|
5839
|
+
if (scope === "global") {
|
|
5840
|
+
(0, import_node_fs5.rmSync)(legacyPendingClaimTokenPath(baseUrl), { force: true });
|
|
5841
|
+
}
|
|
5706
5842
|
} catch {
|
|
5707
5843
|
}
|
|
5708
5844
|
}
|
|
@@ -5727,12 +5863,16 @@ function shouldWaitForRegisterClaim(mode) {
|
|
|
5727
5863
|
if (mode === "no") return false;
|
|
5728
5864
|
return detectAgentRuntime() !== "claude_cowork";
|
|
5729
5865
|
}
|
|
5730
|
-
function saveEnvValues(values, baseUrl) {
|
|
5866
|
+
function saveEnvValues(values, baseUrl, scope) {
|
|
5731
5867
|
const filtered = {
|
|
5732
5868
|
...values[HOST_URL_ENV] ? { [HOST_URL_ENV]: values[HOST_URL_ENV] } : {},
|
|
5733
5869
|
...values[API_KEY_ENV] ? { [API_KEY_ENV]: values[API_KEY_ENV] } : {}
|
|
5734
5870
|
};
|
|
5735
|
-
|
|
5871
|
+
if (scope === "folder") {
|
|
5872
|
+
saveProjectDeeplineEnvValues(filtered);
|
|
5873
|
+
} else {
|
|
5874
|
+
saveHostEnvValues(baseUrl, filtered);
|
|
5875
|
+
}
|
|
5736
5876
|
}
|
|
5737
5877
|
async function httpJson(method, url, apiKey, body) {
|
|
5738
5878
|
const headers = {
|
|
@@ -5795,7 +5935,7 @@ function buildCandidateUrls2(url) {
|
|
|
5795
5935
|
}
|
|
5796
5936
|
}
|
|
5797
5937
|
function sleep4(ms) {
|
|
5798
|
-
return new Promise((
|
|
5938
|
+
return new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
5799
5939
|
}
|
|
5800
5940
|
function printDeeplineLogo() {
|
|
5801
5941
|
if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
|
|
@@ -5856,8 +5996,13 @@ async function handleRegister(args) {
|
|
|
5856
5996
|
let orgName = "";
|
|
5857
5997
|
let agentName = "";
|
|
5858
5998
|
let waitMode;
|
|
5999
|
+
let authScope;
|
|
5859
6000
|
try {
|
|
5860
6001
|
waitMode = parseRegisterWaitMode(args);
|
|
6002
|
+
authScope = parseAuthScope(args);
|
|
6003
|
+
if (authScope === "folder") {
|
|
6004
|
+
pendingClaimPath(baseUrl, authScope);
|
|
6005
|
+
}
|
|
5861
6006
|
} catch (error) {
|
|
5862
6007
|
console.error(error instanceof Error ? error.message : String(error));
|
|
5863
6008
|
return 2;
|
|
@@ -5890,18 +6035,22 @@ async function handleRegister(args) {
|
|
|
5890
6035
|
const claimUrl = String(data.claim_url || "");
|
|
5891
6036
|
const claimToken = String(data.claim_token || "");
|
|
5892
6037
|
if (claimToken) {
|
|
5893
|
-
|
|
6038
|
+
savePendingClaim(baseUrl, { claimToken, claimUrl, scope: authScope });
|
|
5894
6039
|
saveEnvValues(
|
|
5895
6040
|
{
|
|
5896
6041
|
[HOST_URL_ENV]: baseUrl
|
|
5897
6042
|
},
|
|
5898
|
-
baseUrl
|
|
6043
|
+
baseUrl,
|
|
6044
|
+
authScope
|
|
5899
6045
|
);
|
|
5900
6046
|
}
|
|
5901
6047
|
if (claimUrl) {
|
|
5902
|
-
|
|
5903
|
-
console.log(
|
|
5904
|
-
|
|
6048
|
+
const shouldOpen = waitMode !== "no" && detectAgentRuntime() !== "claude_cowork";
|
|
6049
|
+
console.log(
|
|
6050
|
+
shouldOpen ? " Opening approval page in your browser." : " Open this approval page in your browser:"
|
|
6051
|
+
);
|
|
6052
|
+
console.log(` ${claimUrl}`);
|
|
6053
|
+
if (shouldOpen) openInBrowser(claimUrl);
|
|
5905
6054
|
}
|
|
5906
6055
|
if (data.cli_message) {
|
|
5907
6056
|
console.log(String(data.cli_message));
|
|
@@ -5919,7 +6068,7 @@ async function handleRegister(args) {
|
|
|
5919
6068
|
{ claim_token: claimToken, reveal: true }
|
|
5920
6069
|
);
|
|
5921
6070
|
if (s === 401 || s === 403) {
|
|
5922
|
-
|
|
6071
|
+
clearPendingClaim(baseUrl, authScope);
|
|
5923
6072
|
console.log("Status: unauthorized");
|
|
5924
6073
|
return EXIT_AUTH;
|
|
5925
6074
|
}
|
|
@@ -5940,15 +6089,16 @@ async function handleRegister(args) {
|
|
|
5940
6089
|
[HOST_URL_ENV]: baseUrl,
|
|
5941
6090
|
[API_KEY_ENV]: apiKey
|
|
5942
6091
|
},
|
|
5943
|
-
baseUrl
|
|
6092
|
+
baseUrl,
|
|
6093
|
+
authScope
|
|
5944
6094
|
);
|
|
5945
|
-
|
|
6095
|
+
clearPendingClaim(baseUrl, authScope);
|
|
5946
6096
|
await printClaimSuccessBanner(baseUrl, apiKey, statusData);
|
|
5947
6097
|
return EXIT_OK;
|
|
5948
6098
|
}
|
|
5949
6099
|
}
|
|
5950
6100
|
if (state === "expired") {
|
|
5951
|
-
|
|
6101
|
+
clearPendingClaim(baseUrl, authScope);
|
|
5952
6102
|
console.log(
|
|
5953
6103
|
"That approval link expired. Please run: deepline auth register"
|
|
5954
6104
|
);
|
|
@@ -5960,6 +6110,13 @@ async function handleRegister(args) {
|
|
|
5960
6110
|
async function handleWait(args) {
|
|
5961
6111
|
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
5962
6112
|
let timeoutSeconds = 300;
|
|
6113
|
+
let authScope;
|
|
6114
|
+
try {
|
|
6115
|
+
authScope = parseAuthScope(args);
|
|
6116
|
+
} catch (error) {
|
|
6117
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
6118
|
+
return 2;
|
|
6119
|
+
}
|
|
5963
6120
|
for (let i = 0; i < args.length; i++) {
|
|
5964
6121
|
if (args[i] === "--timeout" && args[i + 1]) {
|
|
5965
6122
|
const parsed = Number.parseInt(args[++i], 10);
|
|
@@ -5968,9 +6125,11 @@ async function handleWait(args) {
|
|
|
5968
6125
|
}
|
|
5969
6126
|
}
|
|
5970
6127
|
}
|
|
5971
|
-
const
|
|
5972
|
-
|
|
5973
|
-
|
|
6128
|
+
const pendingClaim = readPendingAuthClaim(baseUrl, authScope);
|
|
6129
|
+
const claimToken = pendingClaim?.claimToken ?? "";
|
|
6130
|
+
if (!pendingClaim) {
|
|
6131
|
+
const scopedApiKey = authScope === "folder" ? resolveProjectApiKeyForBaseUrl(baseUrl) : resolveGlobalApiKeyForBaseUrl(baseUrl);
|
|
6132
|
+
if (scopedApiKey) {
|
|
5974
6133
|
console.log("Already connected.");
|
|
5975
6134
|
return EXIT_OK;
|
|
5976
6135
|
}
|
|
@@ -5986,7 +6145,7 @@ async function handleWait(args) {
|
|
|
5986
6145
|
{ claim_token: claimToken, reveal: true }
|
|
5987
6146
|
);
|
|
5988
6147
|
if (status === 401 || status === 403) {
|
|
5989
|
-
|
|
6148
|
+
clearPendingClaim(baseUrl, authScope);
|
|
5990
6149
|
console.error("Claim is invalid. Run: deepline auth register");
|
|
5991
6150
|
return EXIT_AUTH;
|
|
5992
6151
|
}
|
|
@@ -6007,15 +6166,16 @@ async function handleWait(args) {
|
|
|
6007
6166
|
[HOST_URL_ENV]: baseUrl,
|
|
6008
6167
|
[API_KEY_ENV]: apiKey
|
|
6009
6168
|
},
|
|
6010
|
-
baseUrl
|
|
6169
|
+
baseUrl,
|
|
6170
|
+
authScope
|
|
6011
6171
|
);
|
|
6012
|
-
|
|
6172
|
+
clearPendingClaim(baseUrl, authScope);
|
|
6013
6173
|
await printClaimSuccessBanner(baseUrl, apiKey, data);
|
|
6014
6174
|
return EXIT_OK;
|
|
6015
6175
|
}
|
|
6016
6176
|
}
|
|
6017
6177
|
if (state === "expired") {
|
|
6018
|
-
|
|
6178
|
+
clearPendingClaim(baseUrl, authScope);
|
|
6019
6179
|
console.error("That approval link expired. Run: deepline auth register");
|
|
6020
6180
|
return EXIT_AUTH;
|
|
6021
6181
|
}
|
|
@@ -6030,6 +6190,16 @@ async function handleStatus(args) {
|
|
|
6030
6190
|
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
6031
6191
|
const reveal = args.includes("--reveal");
|
|
6032
6192
|
const jsonOutput = argsWantJson(args);
|
|
6193
|
+
const hasExplicitAuthScope = args.includes("--auth-scope");
|
|
6194
|
+
let authScope = null;
|
|
6195
|
+
if (hasExplicitAuthScope) {
|
|
6196
|
+
try {
|
|
6197
|
+
authScope = parseAuthScope(args);
|
|
6198
|
+
} catch (error) {
|
|
6199
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
6200
|
+
return 2;
|
|
6201
|
+
}
|
|
6202
|
+
}
|
|
6033
6203
|
let hostStatusPayload = null;
|
|
6034
6204
|
const hostLines = [];
|
|
6035
6205
|
try {
|
|
@@ -6056,14 +6226,16 @@ async function handleStatus(args) {
|
|
|
6056
6226
|
};
|
|
6057
6227
|
hostLines.push(`Host: ${baseUrl} (unreachable)`);
|
|
6058
6228
|
}
|
|
6059
|
-
const apiKey = resolveApiKeyForBaseUrl(baseUrl);
|
|
6229
|
+
const apiKey = authScope === "folder" ? resolveProjectApiKeyForBaseUrl(baseUrl) : authScope === "global" ? resolveGlobalApiKeyForBaseUrl(baseUrl) : resolveApiKeyForBaseUrl(baseUrl);
|
|
6060
6230
|
if (!apiKey) {
|
|
6061
|
-
|
|
6231
|
+
const pendingClaim = authScope ? readPendingAuthClaim(baseUrl, authScope) : readPendingAuthClaim(baseUrl, "folder") ?? readPendingAuthClaim(baseUrl, "global");
|
|
6232
|
+
if (pendingClaim) {
|
|
6062
6233
|
printCommandEnvelope(
|
|
6063
6234
|
{
|
|
6064
6235
|
...hostStatusPayload ?? { host: baseUrl },
|
|
6065
6236
|
status: "pending",
|
|
6066
6237
|
connected: false,
|
|
6238
|
+
authorization_url: pendingClaim.claimUrl || null,
|
|
6067
6239
|
next: "deepline auth wait",
|
|
6068
6240
|
render: {
|
|
6069
6241
|
sections: [
|
|
@@ -6145,7 +6317,8 @@ async function handleStatus(args) {
|
|
|
6145
6317
|
console.error(`Auth status error (status ${status}).`);
|
|
6146
6318
|
return EXIT_SERVER;
|
|
6147
6319
|
}
|
|
6148
|
-
|
|
6320
|
+
const resolvedAuthScope = authScope ?? (getResolvedProjectAuthSource(baseUrl, apiKey) ? "folder" : "global");
|
|
6321
|
+
clearPendingClaim(baseUrl, resolvedAuthScope);
|
|
6149
6322
|
const payload = {
|
|
6150
6323
|
...hostStatusPayload ?? { host: baseUrl },
|
|
6151
6324
|
status: data.status || "(unknown)",
|
|
@@ -6170,9 +6343,15 @@ async function handleStatus(args) {
|
|
|
6170
6343
|
[HOST_URL_ENV]: baseUrl,
|
|
6171
6344
|
[API_KEY_ENV]: apiKeyResp
|
|
6172
6345
|
},
|
|
6173
|
-
baseUrl
|
|
6346
|
+
baseUrl,
|
|
6347
|
+
resolvedAuthScope
|
|
6174
6348
|
);
|
|
6175
|
-
|
|
6349
|
+
if (resolvedAuthScope === "folder") {
|
|
6350
|
+
const target = resolveProjectPinTarget();
|
|
6351
|
+
savedApiKeyPath = target.ok ? (0, import_node_path5.join)(target.dir, ".env.deepline") : null;
|
|
6352
|
+
} else {
|
|
6353
|
+
savedApiKeyPath = envFilePath(baseUrl);
|
|
6354
|
+
}
|
|
6176
6355
|
}
|
|
6177
6356
|
}
|
|
6178
6357
|
printCommandEnvelope(
|
|
@@ -6237,12 +6416,19 @@ Examples:
|
|
|
6237
6416
|
deepline auth register
|
|
6238
6417
|
deepline auth register --org-name Acme --agent-name local-cli
|
|
6239
6418
|
deepline auth register --wait no
|
|
6419
|
+
deepline auth register --auth-scope folder --wait no
|
|
6240
6420
|
`
|
|
6241
|
-
).option("--org-name <name>", "Workspace name to prefill").option("--agent-name <name>", "Agent name to register").option("--wait <mode>", "Wait mode: auto, yes, or no", "auto").option("--no-wait", "Alias for --wait no").
|
|
6421
|
+
).option("--org-name <name>", "Workspace name to prefill").option("--agent-name <name>", "Agent name to register").option("--wait <mode>", "Wait mode: auto, yes, or no", "auto").option("--no-wait", "Alias for --wait no").option(
|
|
6422
|
+
"--auth-scope <scope>",
|
|
6423
|
+
"Credential scope: global or folder",
|
|
6424
|
+
"global"
|
|
6425
|
+
).action(async (options) => {
|
|
6242
6426
|
process.exitCode = await handleRegister([
|
|
6243
6427
|
...options.orgName ? ["--org-name", options.orgName] : [],
|
|
6244
6428
|
...options.agentName ? ["--agent-name", options.agentName] : [],
|
|
6245
|
-
...options.noWait || options.wait === false ? ["--wait", "no"] : ["--wait", String(options.wait ?? "auto")]
|
|
6429
|
+
...options.noWait || options.wait === false ? ["--wait", "no"] : ["--wait", String(options.wait ?? "auto")],
|
|
6430
|
+
"--auth-scope",
|
|
6431
|
+
String(options.authScope ?? "global")
|
|
6246
6432
|
]);
|
|
6247
6433
|
});
|
|
6248
6434
|
auth.command("wait").description("Wait for a pending browser approval and save the API key.").addHelpText(
|
|
@@ -6255,10 +6441,17 @@ Notes:
|
|
|
6255
6441
|
Examples:
|
|
6256
6442
|
deepline auth wait
|
|
6257
6443
|
deepline auth wait --timeout 120
|
|
6444
|
+
deepline auth wait --auth-scope folder --timeout 120
|
|
6258
6445
|
`
|
|
6259
|
-
).option("--timeout <seconds>", "Maximum seconds to wait", "300").
|
|
6446
|
+
).option("--timeout <seconds>", "Maximum seconds to wait", "300").option(
|
|
6447
|
+
"--auth-scope <scope>",
|
|
6448
|
+
"Credential scope: global or folder",
|
|
6449
|
+
"global"
|
|
6450
|
+
).action(async (options) => {
|
|
6260
6451
|
process.exitCode = await handleWait([
|
|
6261
|
-
...options.timeout ? ["--timeout", options.timeout] : []
|
|
6452
|
+
...options.timeout ? ["--timeout", options.timeout] : [],
|
|
6453
|
+
"--auth-scope",
|
|
6454
|
+
String(options.authScope ?? "global")
|
|
6262
6455
|
]);
|
|
6263
6456
|
});
|
|
6264
6457
|
auth.command("status").description("Show the current CLI auth and workspace status.").addHelpText(
|
|
@@ -6271,14 +6464,16 @@ Notes:
|
|
|
6271
6464
|
|
|
6272
6465
|
Examples:
|
|
6273
6466
|
deepline auth status
|
|
6467
|
+
deepline auth status --auth-scope folder
|
|
6274
6468
|
deepline auth status --json
|
|
6275
6469
|
`
|
|
6276
6470
|
).option(
|
|
6277
6471
|
"--reveal",
|
|
6278
6472
|
"Persist the revealed API key back to the host auth file"
|
|
6279
|
-
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
6473
|
+
).option("--auth-scope <scope>", "Read only folder or global auth").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
6280
6474
|
process.exitCode = await handleStatus([
|
|
6281
6475
|
...options.reveal ? ["--reveal"] : [],
|
|
6476
|
+
...options.authScope ? ["--auth-scope", String(options.authScope)] : [],
|
|
6282
6477
|
...options.json ? ["--json"] : []
|
|
6283
6478
|
]);
|
|
6284
6479
|
});
|
|
@@ -11302,7 +11497,7 @@ function traceCliSync(phase, fields, run) {
|
|
|
11302
11497
|
}
|
|
11303
11498
|
}
|
|
11304
11499
|
function sleep5(ms) {
|
|
11305
|
-
return new Promise((
|
|
11500
|
+
return new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
11306
11501
|
}
|
|
11307
11502
|
function parseReferencedPlayTarget2(target) {
|
|
11308
11503
|
const trimmed = target.trim();
|
|
@@ -19617,7 +19812,7 @@ function emitEnrichDebug(message) {
|
|
|
19617
19812
|
);
|
|
19618
19813
|
}
|
|
19619
19814
|
function sleep6(ms) {
|
|
19620
|
-
return new Promise((
|
|
19815
|
+
return new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
19621
19816
|
}
|
|
19622
19817
|
function enrichExportBackingRowsWaitMs() {
|
|
19623
19818
|
const raw = process.env.DEEPLINE_ENRICH_EXPORT_BACKING_ROWS_WAIT_MS?.trim();
|
|
@@ -25044,7 +25239,7 @@ Examples:
|
|
|
25044
25239
|
async function fetchOrganizations(http2, apiKey) {
|
|
25045
25240
|
return http2.post("/api/v2/auth/cli/organizations", { api_key: apiKey });
|
|
25046
25241
|
}
|
|
25047
|
-
function
|
|
25242
|
+
function normalizeAuthScope2(value) {
|
|
25048
25243
|
if (!value) return "auto";
|
|
25049
25244
|
if (value === "auto" || value === "folder" || value === "global") {
|
|
25050
25245
|
return value;
|
|
@@ -25247,7 +25442,7 @@ async function handleOrgStatus(options) {
|
|
|
25247
25442
|
);
|
|
25248
25443
|
}
|
|
25249
25444
|
async function handleOrgSwitch(selection, options) {
|
|
25250
|
-
const authScope =
|
|
25445
|
+
const authScope = normalizeAuthScope2(options.authScope);
|
|
25251
25446
|
const config = resolveConfig();
|
|
25252
25447
|
const http2 = new HttpClient(config);
|
|
25253
25448
|
const payload = await fetchOrganizations(http2, config.apiKey);
|
|
@@ -25624,17 +25819,17 @@ function hasClaudeBinary() {
|
|
|
25624
25819
|
}
|
|
25625
25820
|
}
|
|
25626
25821
|
function launchClaude(prompt) {
|
|
25627
|
-
return new Promise((
|
|
25822
|
+
return new Promise((resolve15) => {
|
|
25628
25823
|
const child = (0, import_node_child_process2.spawn)("claude", [prompt], {
|
|
25629
25824
|
stdio: "inherit",
|
|
25630
25825
|
shell: process.platform === "win32"
|
|
25631
25826
|
});
|
|
25632
|
-
child.on("error", () =>
|
|
25633
|
-
child.on("close", (status) =>
|
|
25827
|
+
child.on("error", () => resolve15(EXIT_SERVER3));
|
|
25828
|
+
child.on("close", (status) => resolve15(status ?? EXIT_OK2));
|
|
25634
25829
|
});
|
|
25635
25830
|
}
|
|
25636
25831
|
function readBody(req) {
|
|
25637
|
-
return new Promise((
|
|
25832
|
+
return new Promise((resolve15, reject) => {
|
|
25638
25833
|
let raw = "";
|
|
25639
25834
|
req.setEncoding("utf8");
|
|
25640
25835
|
req.on("data", (chunk) => {
|
|
@@ -25644,7 +25839,7 @@ function readBody(req) {
|
|
|
25644
25839
|
req.destroy();
|
|
25645
25840
|
}
|
|
25646
25841
|
});
|
|
25647
|
-
req.on("end", () =>
|
|
25842
|
+
req.on("end", () => resolve15(raw));
|
|
25648
25843
|
req.on("error", reject);
|
|
25649
25844
|
});
|
|
25650
25845
|
}
|
|
@@ -25699,7 +25894,7 @@ function startCallbackServer(input2) {
|
|
|
25699
25894
|
writeJson(res, 400, { error: "Invalid request body." });
|
|
25700
25895
|
});
|
|
25701
25896
|
});
|
|
25702
|
-
return new Promise((
|
|
25897
|
+
return new Promise((resolve15, reject) => {
|
|
25703
25898
|
server.once("error", reject);
|
|
25704
25899
|
server.listen(0, "127.0.0.1", () => {
|
|
25705
25900
|
const address = server.address();
|
|
@@ -25707,7 +25902,7 @@ function startCallbackServer(input2) {
|
|
|
25707
25902
|
reject(new Error("Failed to bind quickstart callback server."));
|
|
25708
25903
|
return;
|
|
25709
25904
|
}
|
|
25710
|
-
|
|
25905
|
+
resolve15({ server, port: address.port });
|
|
25711
25906
|
});
|
|
25712
25907
|
});
|
|
25713
25908
|
}
|
|
@@ -25733,8 +25928,8 @@ async function handleQuickstart(options) {
|
|
|
25733
25928
|
}
|
|
25734
25929
|
const state = (0, import_node_crypto6.randomBytes)(32).toString("hex");
|
|
25735
25930
|
let resolveSelection;
|
|
25736
|
-
const selectionPromise = new Promise((
|
|
25737
|
-
resolveSelection =
|
|
25931
|
+
const selectionPromise = new Promise((resolve15) => {
|
|
25932
|
+
resolveSelection = resolve15;
|
|
25738
25933
|
});
|
|
25739
25934
|
let callback;
|
|
25740
25935
|
try {
|
|
@@ -25873,7 +26068,7 @@ async function readHiddenLine(prompt, streams = {}) {
|
|
|
25873
26068
|
}
|
|
25874
26069
|
let value = "";
|
|
25875
26070
|
inputStream.resume();
|
|
25876
|
-
return await new Promise((
|
|
26071
|
+
return await new Promise((resolve15, reject) => {
|
|
25877
26072
|
let settled = false;
|
|
25878
26073
|
const cleanup = () => {
|
|
25879
26074
|
inputStream.off("data", onData);
|
|
@@ -25891,7 +26086,7 @@ async function readHiddenLine(prompt, streams = {}) {
|
|
|
25891
26086
|
settled = true;
|
|
25892
26087
|
outputStream.write("\n");
|
|
25893
26088
|
cleanup();
|
|
25894
|
-
|
|
26089
|
+
resolve15(line);
|
|
25895
26090
|
};
|
|
25896
26091
|
const fail = (error) => {
|
|
25897
26092
|
if (settled) return;
|
|
@@ -28694,12 +28889,13 @@ Notes:
|
|
|
28694
28889
|
// src/cli/commands/update.ts
|
|
28695
28890
|
var import_node_child_process4 = require("child_process");
|
|
28696
28891
|
var import_node_fs17 = require("fs");
|
|
28697
|
-
var
|
|
28892
|
+
var import_node_os14 = require("os");
|
|
28698
28893
|
var import_node_path19 = require("path");
|
|
28699
28894
|
|
|
28700
|
-
// src/cli/skills
|
|
28895
|
+
// src/cli/commands/skills.ts
|
|
28701
28896
|
var import_node_child_process3 = require("child_process");
|
|
28702
28897
|
var import_node_fs16 = require("fs");
|
|
28898
|
+
var import_node_os13 = require("os");
|
|
28703
28899
|
var import_node_path18 = require("path");
|
|
28704
28900
|
|
|
28705
28901
|
// ../shared_libs/cli/install-commands.json
|
|
@@ -28716,7 +28912,7 @@ var install_commands_default = {
|
|
|
28716
28912
|
npx_binary: "npx",
|
|
28717
28913
|
npx_add_args_template: [
|
|
28718
28914
|
"--yes",
|
|
28719
|
-
"skills",
|
|
28915
|
+
"skills@latest",
|
|
28720
28916
|
"add",
|
|
28721
28917
|
"{skills_index_url}",
|
|
28722
28918
|
"--agent",
|
|
@@ -28806,311 +29002,380 @@ function sdkNpmGlobalInstallCommand() {
|
|
|
28806
29002
|
return INSTALL_COMMANDS.cli.sdk_npm_global;
|
|
28807
29003
|
}
|
|
28808
29004
|
|
|
28809
|
-
// src/cli/skills
|
|
28810
|
-
var
|
|
28811
|
-
|
|
28812
|
-
|
|
28813
|
-
|
|
28814
|
-
|
|
28815
|
-
|
|
28816
|
-
|
|
28817
|
-
|
|
29005
|
+
// src/cli/commands/skills.ts
|
|
29006
|
+
var RUNTIME_TO_SKILLS_AGENT = {
|
|
29007
|
+
antigravity: "antigravity",
|
|
29008
|
+
claude_code: "claude-code",
|
|
29009
|
+
claude_cowork: "claude-code",
|
|
29010
|
+
cline: "cline",
|
|
29011
|
+
codex: "codex",
|
|
29012
|
+
cursor: "cursor",
|
|
29013
|
+
gemini: "gemini-cli",
|
|
29014
|
+
windsurf: "windsurf"
|
|
29015
|
+
};
|
|
29016
|
+
var AGENT_MARKERS = [
|
|
29017
|
+
{ agent: "codex", paths: [".codex"] },
|
|
29018
|
+
{ agent: "claude-code", paths: [".claude"] },
|
|
29019
|
+
{ agent: "cursor", paths: [".cursor"] },
|
|
29020
|
+
{ agent: "gemini-cli", paths: [".gemini", ".gemini-cli"] },
|
|
29021
|
+
{ agent: "antigravity", paths: [".antigravity"] }
|
|
29022
|
+
];
|
|
29023
|
+
var WORKSPACE_SKILL_ROOTS_BY_AGENT = {
|
|
29024
|
+
antigravity: [".agents"],
|
|
29025
|
+
"claude-code": [".claude"],
|
|
29026
|
+
cline: [".agents"],
|
|
29027
|
+
codex: [".agents"],
|
|
29028
|
+
cursor: [".agents"],
|
|
29029
|
+
"gemini-cli": [".agents"],
|
|
29030
|
+
windsurf: [".windsurf"],
|
|
29031
|
+
"*": [".agents", ".claude", ".windsurf"]
|
|
29032
|
+
};
|
|
29033
|
+
function workspaceSkillRootsForAgents(agents) {
|
|
29034
|
+
return [
|
|
29035
|
+
...new Set(
|
|
29036
|
+
agents.flatMap((agent) => WORKSPACE_SKILL_ROOTS_BY_AGENT[agent] ?? [])
|
|
29037
|
+
)
|
|
29038
|
+
].sort((a, b) => a.localeCompare(b));
|
|
28818
29039
|
}
|
|
28819
|
-
function
|
|
28820
|
-
|
|
28821
|
-
if (
|
|
28822
|
-
|
|
28823
|
-
|
|
28824
|
-
const dir = process.env.DEEPLINE_PLUGIN_SKILLS_DIR?.trim() ?? "";
|
|
28825
|
-
return dir && (0, import_node_fs16.existsSync)(dir) ? dir : "";
|
|
29040
|
+
function normalizeScope(value) {
|
|
29041
|
+
if (value === "global") return "global";
|
|
29042
|
+
if (value === "local") return "local";
|
|
29043
|
+
if (!value) return inferActiveSkillsScope();
|
|
29044
|
+
throw new Error("--scope must be one of: global, local");
|
|
28826
29045
|
}
|
|
28827
|
-
function
|
|
28828
|
-
|
|
28829
|
-
|
|
28830
|
-
|
|
28831
|
-
|
|
28832
|
-
|
|
28833
|
-
|
|
29046
|
+
function inferActiveSkillsScope(entrypoint = process.argv[1] ?? "") {
|
|
29047
|
+
return /[\\/]\.deepline[\\/]runtime[\\/]/.test(entrypoint) ? "local" : "global";
|
|
29048
|
+
}
|
|
29049
|
+
function resolveLocalRoot() {
|
|
29050
|
+
const target = resolveProjectPinTarget();
|
|
29051
|
+
if (!target.ok) {
|
|
29052
|
+
throw new Error(
|
|
29053
|
+
`Cowork project folder is ambiguous. Candidate folders: ${target.candidates.join(
|
|
29054
|
+
", "
|
|
29055
|
+
)}. Set CLAUDE_PROJECT_DIR or cd into the intended project folder.`
|
|
29056
|
+
);
|
|
28834
29057
|
}
|
|
29058
|
+
return target.dir;
|
|
28835
29059
|
}
|
|
28836
|
-
function
|
|
28837
|
-
|
|
29060
|
+
function detectSkillsAgents(input2) {
|
|
29061
|
+
const runtime = input2.runtime ?? detectAgentRuntime();
|
|
29062
|
+
const knownAgent = RUNTIME_TO_SKILLS_AGENT[runtime];
|
|
29063
|
+
if (knownAgent) return [knownAgent];
|
|
29064
|
+
const roots = [
|
|
29065
|
+
...input2.scope === "local" && input2.root ? [input2.root] : [],
|
|
29066
|
+
input2.homeDir ?? (0, import_node_os13.homedir)()
|
|
29067
|
+
];
|
|
29068
|
+
const detected = AGENT_MARKERS.filter(
|
|
29069
|
+
(marker) => roots.some(
|
|
29070
|
+
(root) => marker.paths.some((path) => (0, import_node_fs16.existsSync)((0, import_node_path18.join)(root, path)))
|
|
29071
|
+
)
|
|
29072
|
+
).map((marker) => marker.agent);
|
|
29073
|
+
return detected.length > 0 ? detected : ["*"];
|
|
28838
29074
|
}
|
|
28839
|
-
function
|
|
28840
|
-
|
|
29075
|
+
async function fetchSkillCatalog(baseUrl) {
|
|
29076
|
+
const response = await fetch(skillsIndexUrl(baseUrl));
|
|
29077
|
+
if (!response.ok) {
|
|
29078
|
+
throw new Error(
|
|
29079
|
+
`Skill catalog request failed (status ${response.status}).`
|
|
29080
|
+
);
|
|
29081
|
+
}
|
|
29082
|
+
const index = await response.json();
|
|
29083
|
+
const skillNames = (index.skills ?? []).filter((skill) => skill.install_surface === "v1").map((skill) => skill.name).filter((name) => typeof name === "string" && Boolean(name)).sort((a, b) => a.localeCompare(b));
|
|
29084
|
+
if (skillNames.length === 0) {
|
|
29085
|
+
throw new Error(
|
|
29086
|
+
"The Deepline skill catalog contains no installable skills."
|
|
29087
|
+
);
|
|
29088
|
+
}
|
|
29089
|
+
return {
|
|
29090
|
+
skillNames,
|
|
29091
|
+
version: typeof index.version === "string" && index.version.trim() ? index.version.trim() : "unversioned"
|
|
29092
|
+
};
|
|
28841
29093
|
}
|
|
28842
|
-
function
|
|
28843
|
-
return (0, import_node_path18.join)(sdkCliStateDirPath(baseUrl), "skills-
|
|
29094
|
+
function skillsStatePathForScope(baseUrl, scope, root) {
|
|
29095
|
+
return scope === "local" && root ? (0, import_node_path18.join)(root, ".deepline", "setup", "skills.json") : (0, import_node_path18.join)(sdkCliStateDirPath(baseUrl), "skills-install.json");
|
|
28844
29096
|
}
|
|
28845
|
-
function
|
|
28846
|
-
const
|
|
28847
|
-
|
|
28848
|
-
|
|
28849
|
-
|
|
28850
|
-
|
|
28851
|
-
|
|
28852
|
-
|
|
28853
|
-
|
|
28854
|
-
|
|
29097
|
+
function buildSkillsPlan(input2) {
|
|
29098
|
+
const scopeArgs = input2.scope === "global" ? ["--global"] : [];
|
|
29099
|
+
const allManagedNames = [
|
|
29100
|
+
.../* @__PURE__ */ new Set([...input2.skillNames, ...LEGACY_SKILL_NAMES_TO_REMOVE])
|
|
29101
|
+
].sort((a, b) => a.localeCompare(b));
|
|
29102
|
+
return {
|
|
29103
|
+
scope: input2.scope,
|
|
29104
|
+
root: input2.root,
|
|
29105
|
+
agents: input2.agents,
|
|
29106
|
+
skillNames: input2.skillNames,
|
|
29107
|
+
version: input2.version,
|
|
29108
|
+
remove: {
|
|
29109
|
+
command: "npm",
|
|
29110
|
+
args: [
|
|
29111
|
+
"exec",
|
|
29112
|
+
"--yes",
|
|
29113
|
+
"--package=skills@latest",
|
|
29114
|
+
"--",
|
|
29115
|
+
"skills",
|
|
29116
|
+
"remove",
|
|
29117
|
+
...scopeArgs,
|
|
29118
|
+
"--agent",
|
|
29119
|
+
...input2.agents,
|
|
29120
|
+
"-y",
|
|
29121
|
+
...allManagedNames
|
|
29122
|
+
]
|
|
29123
|
+
},
|
|
29124
|
+
install: {
|
|
29125
|
+
command: "npm",
|
|
29126
|
+
args: [
|
|
29127
|
+
"exec",
|
|
29128
|
+
"--yes",
|
|
29129
|
+
"--package=skills@latest",
|
|
29130
|
+
"--",
|
|
29131
|
+
"skills",
|
|
29132
|
+
"add",
|
|
29133
|
+
skillsIndexUrl(input2.baseUrl),
|
|
29134
|
+
"--agent",
|
|
29135
|
+
...input2.agents,
|
|
29136
|
+
...scopeArgs,
|
|
29137
|
+
"--yes",
|
|
29138
|
+
...input2.skillNames.flatMap((name) => ["--skill", name]),
|
|
29139
|
+
"--full-depth"
|
|
29140
|
+
]
|
|
29141
|
+
},
|
|
29142
|
+
statePath: skillsStatePathForScope(input2.baseUrl, input2.scope, input2.root)
|
|
29143
|
+
};
|
|
28855
29144
|
}
|
|
28856
|
-
function
|
|
28857
|
-
|
|
28858
|
-
|
|
28859
|
-
|
|
28860
|
-
|
|
29145
|
+
function sortedStrings(value) {
|
|
29146
|
+
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
|
|
29147
|
+
return null;
|
|
29148
|
+
}
|
|
29149
|
+
return [...value].sort((a, b) => a.localeCompare(b));
|
|
28861
29150
|
}
|
|
28862
|
-
function
|
|
28863
|
-
|
|
28864
|
-
|
|
28865
|
-
if ((0, import_node_fs16.existsSync)(path) && (0, import_node_fs16.readFileSync)(path, "utf-8").trim() === remoteVersion) {
|
|
28866
|
-
return;
|
|
28867
|
-
}
|
|
28868
|
-
(0, import_node_fs16.mkdirSync)((0, import_node_path18.dirname)(path), { recursive: true });
|
|
28869
|
-
(0, import_node_fs16.writeFileSync)(path, `${remoteVersion}
|
|
28870
|
-
`, "utf-8");
|
|
28871
|
-
} catch {
|
|
29151
|
+
function isSkillsPlanCurrent(plan, state) {
|
|
29152
|
+
if (!state || state.scope !== plan.scope || state.skillsVersion !== plan.version) {
|
|
29153
|
+
return false;
|
|
28872
29154
|
}
|
|
28873
|
-
const
|
|
28874
|
-
|
|
28875
|
-
|
|
28876
|
-
|
|
28877
|
-
);
|
|
29155
|
+
const installedAgents = sortedStrings(state.agents);
|
|
29156
|
+
const installedSkillNames = sortedStrings(state.skillNames);
|
|
29157
|
+
if (!installedAgents || !installedSkillNames) return false;
|
|
29158
|
+
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");
|
|
28878
29159
|
}
|
|
28879
|
-
function
|
|
29160
|
+
function readSkillsInstallState(path) {
|
|
28880
29161
|
try {
|
|
28881
|
-
(0, import_node_fs16.
|
|
29162
|
+
const parsed = JSON.parse((0, import_node_fs16.readFileSync)(path, "utf8"));
|
|
29163
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
28882
29164
|
} catch {
|
|
29165
|
+
return null;
|
|
28883
29166
|
}
|
|
28884
29167
|
}
|
|
28885
|
-
function
|
|
28886
|
-
return
|
|
28887
|
-
(
|
|
28888
|
-
|
|
29168
|
+
function runProcess(command, args, cwd) {
|
|
29169
|
+
return new Promise((resolve15, reject) => {
|
|
29170
|
+
const child = (0, import_node_child_process3.spawn)(command, args, {
|
|
29171
|
+
cwd,
|
|
29172
|
+
env: process.env,
|
|
29173
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
29174
|
+
shell: process.platform === "win32"
|
|
29175
|
+
});
|
|
29176
|
+
let stderr = "";
|
|
29177
|
+
child.stderr.on("data", (chunk) => {
|
|
29178
|
+
stderr += chunk.toString("utf8");
|
|
29179
|
+
process.stderr.write(chunk);
|
|
29180
|
+
});
|
|
29181
|
+
child.once("error", reject);
|
|
29182
|
+
child.once("close", (code) => {
|
|
29183
|
+
if (code && stderr.trim()) {
|
|
29184
|
+
process.stderr.write(`skills@latest exited ${code}.
|
|
29185
|
+
`);
|
|
29186
|
+
}
|
|
29187
|
+
resolve15(code ?? 1);
|
|
29188
|
+
});
|
|
29189
|
+
});
|
|
28889
29190
|
}
|
|
28890
|
-
async function
|
|
28891
|
-
|
|
28892
|
-
|
|
29191
|
+
async function runSkillsCommand(options, dependencies = {}) {
|
|
29192
|
+
let scope;
|
|
29193
|
+
let root;
|
|
28893
29194
|
try {
|
|
28894
|
-
|
|
28895
|
-
|
|
28896
|
-
|
|
28897
|
-
|
|
28898
|
-
|
|
28899
|
-
|
|
28900
|
-
|
|
28901
|
-
|
|
29195
|
+
scope = normalizeScope(options.scope);
|
|
29196
|
+
root = scope === "local" ? resolveLocalRoot() : null;
|
|
29197
|
+
} catch (error) {
|
|
29198
|
+
printCommandEnvelope(
|
|
29199
|
+
{
|
|
29200
|
+
ok: false,
|
|
29201
|
+
status: "failed",
|
|
29202
|
+
code: "INVALID_SKILLS_SCOPE",
|
|
29203
|
+
exitCode: 2,
|
|
29204
|
+
message: error instanceof Error ? error.message : String(error)
|
|
29205
|
+
},
|
|
29206
|
+
{ json: options.json }
|
|
28902
29207
|
);
|
|
28903
|
-
return
|
|
28904
|
-
} catch {
|
|
28905
|
-
return [];
|
|
28906
|
-
} finally {
|
|
28907
|
-
clearTimeout(timeout);
|
|
29208
|
+
return 2;
|
|
28908
29209
|
}
|
|
28909
|
-
|
|
28910
|
-
|
|
28911
|
-
return sortedUniqueSkillNames(v1SkillNames);
|
|
28912
|
-
}
|
|
28913
|
-
async function fetchSkillsUpdate(baseUrl, localVersion) {
|
|
28914
|
-
const controller = new AbortController();
|
|
28915
|
-
const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS2);
|
|
29210
|
+
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
29211
|
+
let catalog;
|
|
28916
29212
|
try {
|
|
28917
|
-
|
|
28918
|
-
|
|
28919
|
-
|
|
28920
|
-
|
|
28921
|
-
|
|
28922
|
-
|
|
28923
|
-
|
|
28924
|
-
|
|
28925
|
-
|
|
28926
|
-
|
|
28927
|
-
|
|
28928
|
-
|
|
28929
|
-
|
|
28930
|
-
|
|
28931
|
-
return {
|
|
28932
|
-
needsUpdate: skills.needs_update === true,
|
|
28933
|
-
remoteVersion: typeof skills.remote?.version === "string" ? skills.remote.version.trim() : ""
|
|
28934
|
-
};
|
|
28935
|
-
} catch {
|
|
28936
|
-
return null;
|
|
28937
|
-
} finally {
|
|
28938
|
-
clearTimeout(timeout);
|
|
29213
|
+
catalog = options.dryRun ? { skillNames: [...DEFAULT_SDK_SKILL_NAMES], version: "latest" } : await (dependencies.fetchCatalog ?? fetchSkillCatalog)(baseUrl);
|
|
29214
|
+
} catch (error) {
|
|
29215
|
+
printCommandEnvelope(
|
|
29216
|
+
{
|
|
29217
|
+
ok: false,
|
|
29218
|
+
status: "failed",
|
|
29219
|
+
code: "SKILLS_CATALOG_UNAVAILABLE",
|
|
29220
|
+
exitCode: 5,
|
|
29221
|
+
message: error instanceof Error ? error.message : String(error),
|
|
29222
|
+
next: "Retry: deepline skills"
|
|
29223
|
+
},
|
|
29224
|
+
{ json: options.json }
|
|
29225
|
+
);
|
|
29226
|
+
return 5;
|
|
28939
29227
|
}
|
|
28940
|
-
}
|
|
28941
|
-
|
|
28942
|
-
|
|
28943
|
-
|
|
28944
|
-
|
|
28945
|
-
|
|
28946
|
-
|
|
28947
|
-
|
|
28948
|
-
}
|
|
28949
|
-
function hasCommand(command) {
|
|
28950
|
-
const result = (0, import_node_child_process3.spawnSync)(command, ["--version"], {
|
|
28951
|
-
stdio: "ignore",
|
|
28952
|
-
shell: process.platform === "win32"
|
|
28953
|
-
});
|
|
28954
|
-
return result.status === 0;
|
|
28955
|
-
}
|
|
28956
|
-
function shellQuote5(arg) {
|
|
28957
|
-
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
28958
|
-
}
|
|
28959
|
-
function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NAMES) {
|
|
28960
|
-
const commands = [];
|
|
28961
|
-
if (hasCommand("bunx")) {
|
|
28962
|
-
const bunxArgs = buildBunxSkillsInstallArgs(baseUrl, skillNames);
|
|
28963
|
-
commands.push({
|
|
28964
|
-
command: "bunx",
|
|
28965
|
-
args: bunxArgs,
|
|
28966
|
-
manualCommand: `bunx ${bunxArgs.map(shellQuote5).join(" ")}`
|
|
28967
|
-
});
|
|
29228
|
+
const agents = options.agent ? [options.agent] : detectSkillsAgents({ scope, root });
|
|
29229
|
+
const plan = buildSkillsPlan({ baseUrl, scope, root, agents, ...catalog });
|
|
29230
|
+
if (options.dryRun) {
|
|
29231
|
+
printCommandEnvelope(
|
|
29232
|
+
{ ok: true, status: "planned", dryRun: true, ...plan },
|
|
29233
|
+
{ json: options.json }
|
|
29234
|
+
);
|
|
29235
|
+
return 0;
|
|
28968
29236
|
}
|
|
28969
|
-
if (
|
|
28970
|
-
|
|
28971
|
-
|
|
28972
|
-
|
|
28973
|
-
|
|
28974
|
-
|
|
28975
|
-
|
|
29237
|
+
if (isSkillsPlanCurrent(plan, readSkillsInstallState(plan.statePath))) {
|
|
29238
|
+
printCommandEnvelope(
|
|
29239
|
+
{
|
|
29240
|
+
ok: true,
|
|
29241
|
+
status: "current",
|
|
29242
|
+
complete: true,
|
|
29243
|
+
changed: false,
|
|
29244
|
+
skipped: true,
|
|
29245
|
+
skipReason: "skills_version_current",
|
|
29246
|
+
scope,
|
|
29247
|
+
agents,
|
|
29248
|
+
skillsVersion: plan.version,
|
|
29249
|
+
skillCount: plan.skillNames.length,
|
|
29250
|
+
statePath: plan.statePath,
|
|
29251
|
+
render: {
|
|
29252
|
+
sections: [
|
|
29253
|
+
{
|
|
29254
|
+
title: "skills",
|
|
29255
|
+
lines: [
|
|
29256
|
+
`Scope: ${scope}`,
|
|
29257
|
+
`Agents: ${agents.join(", ")}`,
|
|
29258
|
+
`Current: ${plan.skillNames.length}`
|
|
29259
|
+
]
|
|
29260
|
+
}
|
|
29261
|
+
]
|
|
29262
|
+
}
|
|
29263
|
+
},
|
|
29264
|
+
{ json: options.json }
|
|
29265
|
+
);
|
|
29266
|
+
return 0;
|
|
28976
29267
|
}
|
|
28977
|
-
|
|
28978
|
-
|
|
28979
|
-
|
|
28980
|
-
|
|
28981
|
-
const
|
|
28982
|
-
|
|
28983
|
-
|
|
28984
|
-
|
|
28985
|
-
|
|
28986
|
-
|
|
28987
|
-
|
|
28988
|
-
});
|
|
28989
|
-
child.on("error", (error) => {
|
|
28990
|
-
resolve14({
|
|
28991
|
-
ok: false,
|
|
28992
|
-
detail: `failed to start ${install.command}: ${error.message}`,
|
|
28993
|
-
manualCommand: install.manualCommand
|
|
28994
|
-
});
|
|
28995
|
-
});
|
|
28996
|
-
child.on("close", (code) => {
|
|
28997
|
-
if (code === 0) {
|
|
28998
|
-
resolve14({ ok: true, detail: "", manualCommand: install.manualCommand });
|
|
28999
|
-
return;
|
|
29000
|
-
}
|
|
29001
|
-
const detail = stderr.trim();
|
|
29002
|
-
resolve14({
|
|
29003
|
-
ok: false,
|
|
29004
|
-
detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
|
|
29005
|
-
manualCommand: install.manualCommand
|
|
29006
|
-
});
|
|
29007
|
-
});
|
|
29008
|
-
});
|
|
29009
|
-
}
|
|
29010
|
-
async function runSkillsInstall(installs) {
|
|
29011
|
-
const failures = [];
|
|
29012
|
-
for (const install of installs) {
|
|
29013
|
-
const result = await runOneSkillsInstall(install);
|
|
29014
|
-
if (result.ok) return true;
|
|
29015
|
-
failures.push(result);
|
|
29268
|
+
if (scope === "local" && root) {
|
|
29269
|
+
const managedNames = [
|
|
29270
|
+
.../* @__PURE__ */ new Set([...plan.skillNames, ...LEGACY_SKILL_NAMES_TO_REMOVE])
|
|
29271
|
+
];
|
|
29272
|
+
const agentRoots = workspaceSkillRootsForAgents(plan.agents);
|
|
29273
|
+
ensureProjectPrivatePathsIgnored(root, [
|
|
29274
|
+
".deepline/",
|
|
29275
|
+
...agentRoots.flatMap(
|
|
29276
|
+
(agentRoot) => managedNames.map((name) => `${agentRoot}/skills/${name}/`)
|
|
29277
|
+
)
|
|
29278
|
+
]);
|
|
29016
29279
|
}
|
|
29017
|
-
const details = failures.map((failure) => failure.detail).filter(Boolean).join("\n");
|
|
29018
|
-
const manualCommand = failures.at(-1)?.manualCommand;
|
|
29019
29280
|
process.stderr.write(
|
|
29020
|
-
`
|
|
29021
|
-
|
|
29022
|
-
` + (manualCommand ? `Run manually: ${manualCommand}
|
|
29023
|
-
` : "")
|
|
29281
|
+
`Replacing Deepline skills for ${agents.join(", ")} (${scope})...
|
|
29282
|
+
`
|
|
29024
29283
|
);
|
|
29025
|
-
|
|
29026
|
-
|
|
29027
|
-
|
|
29028
|
-
|
|
29029
|
-
|
|
29030
|
-
|
|
29031
|
-
|
|
29032
|
-
|
|
29033
|
-
|
|
29034
|
-
"remove",
|
|
29035
|
-
"--global",
|
|
29036
|
-
"-y",
|
|
29037
|
-
...LEGACY_SKILL_NAMES_TO_REMOVE
|
|
29038
|
-
]
|
|
29039
|
-
},
|
|
29040
|
-
{
|
|
29041
|
-
command: "npx",
|
|
29042
|
-
args: [
|
|
29043
|
-
"--yes",
|
|
29044
|
-
"skills",
|
|
29045
|
-
"remove",
|
|
29046
|
-
"--global",
|
|
29047
|
-
"-y",
|
|
29048
|
-
...LEGACY_SKILL_NAMES_TO_REMOVE
|
|
29049
|
-
]
|
|
29284
|
+
try {
|
|
29285
|
+
const execute = dependencies.runProcess ?? runProcess;
|
|
29286
|
+
const removeCode = await execute(
|
|
29287
|
+
plan.remove.command,
|
|
29288
|
+
plan.remove.args,
|
|
29289
|
+
root ?? void 0
|
|
29290
|
+
);
|
|
29291
|
+
if (removeCode !== 0) {
|
|
29292
|
+
throw new Error("Could not remove the existing Deepline skills.");
|
|
29050
29293
|
}
|
|
29051
|
-
|
|
29052
|
-
|
|
29053
|
-
|
|
29054
|
-
|
|
29055
|
-
|
|
29056
|
-
|
|
29057
|
-
|
|
29058
|
-
"--global",
|
|
29059
|
-
"-y",
|
|
29060
|
-
...LEGACY_SKILL_NAMES_TO_REMOVE
|
|
29061
|
-
]
|
|
29294
|
+
const installCode = await execute(
|
|
29295
|
+
plan.install.command,
|
|
29296
|
+
plan.install.args,
|
|
29297
|
+
root ?? void 0
|
|
29298
|
+
);
|
|
29299
|
+
if (installCode !== 0) {
|
|
29300
|
+
throw new Error("Could not install the current Deepline skills.");
|
|
29062
29301
|
}
|
|
29063
|
-
|
|
29064
|
-
|
|
29065
|
-
|
|
29066
|
-
|
|
29067
|
-
|
|
29068
|
-
|
|
29069
|
-
|
|
29070
|
-
|
|
29071
|
-
|
|
29072
|
-
|
|
29073
|
-
|
|
29074
|
-
|
|
29075
|
-
|
|
29076
|
-
|
|
29077
|
-
return;
|
|
29078
|
-
}
|
|
29079
|
-
process.stderr.write(`${line}
|
|
29080
|
-
`);
|
|
29081
|
-
}
|
|
29082
|
-
async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
|
|
29083
|
-
if (attemptedSync || shouldSkipSkillsSync()) return;
|
|
29084
|
-
attemptedSync = true;
|
|
29085
|
-
const usingPluginSkills = Boolean(activePluginSkillsDir());
|
|
29086
|
-
if (usingPluginSkills) {
|
|
29087
|
-
return;
|
|
29088
|
-
}
|
|
29089
|
-
const localVersion = readSdkSkillsLocalVersion(baseUrl);
|
|
29090
|
-
const update = options.update === void 0 ? await fetchSkillsUpdate(baseUrl, localVersion) : options.update ? {
|
|
29091
|
-
needsUpdate: options.update.needs_update,
|
|
29092
|
-
remoteVersion: options.update.remote.version
|
|
29093
|
-
} : null;
|
|
29094
|
-
if (!update?.needsUpdate || !update.remoteVersion) {
|
|
29095
|
-
return;
|
|
29302
|
+
} catch (error) {
|
|
29303
|
+
printCommandEnvelope(
|
|
29304
|
+
{
|
|
29305
|
+
ok: false,
|
|
29306
|
+
status: "failed",
|
|
29307
|
+
code: "SKILLS_INSTALL_FAILED",
|
|
29308
|
+
exitCode: 5,
|
|
29309
|
+
scope,
|
|
29310
|
+
agents,
|
|
29311
|
+
message: error instanceof Error ? error.message : String(error),
|
|
29312
|
+
next: `deepline skills --scope ${scope} --json`
|
|
29313
|
+
},
|
|
29314
|
+
{ json: options.json }
|
|
29315
|
+
);
|
|
29316
|
+
return 5;
|
|
29096
29317
|
}
|
|
29097
|
-
|
|
29098
|
-
|
|
29099
|
-
|
|
29318
|
+
(0, import_node_fs16.mkdirSync)((0, import_node_path18.dirname)(plan.statePath), { recursive: true });
|
|
29319
|
+
(0, import_node_fs16.writeFileSync)(
|
|
29320
|
+
plan.statePath,
|
|
29321
|
+
`${JSON.stringify(
|
|
29322
|
+
{
|
|
29323
|
+
schemaVersion: 1,
|
|
29324
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29325
|
+
cliVersion: SDK_VERSION,
|
|
29326
|
+
scope,
|
|
29327
|
+
agents,
|
|
29328
|
+
skillsVersion: plan.version,
|
|
29329
|
+
skillNames: plan.skillNames
|
|
29330
|
+
},
|
|
29331
|
+
null,
|
|
29332
|
+
2
|
|
29333
|
+
)}
|
|
29334
|
+
`,
|
|
29335
|
+
"utf8"
|
|
29100
29336
|
);
|
|
29101
|
-
|
|
29102
|
-
|
|
29103
|
-
|
|
29104
|
-
|
|
29105
|
-
|
|
29106
|
-
|
|
29107
|
-
|
|
29108
|
-
|
|
29109
|
-
|
|
29110
|
-
|
|
29111
|
-
|
|
29112
|
-
|
|
29113
|
-
|
|
29337
|
+
printCommandEnvelope(
|
|
29338
|
+
{
|
|
29339
|
+
ok: true,
|
|
29340
|
+
status: "complete",
|
|
29341
|
+
scope,
|
|
29342
|
+
agents,
|
|
29343
|
+
skillsVersion: plan.version,
|
|
29344
|
+
skillCount: plan.skillNames.length,
|
|
29345
|
+
statePath: plan.statePath,
|
|
29346
|
+
render: {
|
|
29347
|
+
sections: [
|
|
29348
|
+
{
|
|
29349
|
+
title: "skills",
|
|
29350
|
+
lines: [
|
|
29351
|
+
`Scope: ${scope}`,
|
|
29352
|
+
`Agents: ${agents.join(", ")}`,
|
|
29353
|
+
`Installed: ${plan.skillNames.length}`
|
|
29354
|
+
]
|
|
29355
|
+
}
|
|
29356
|
+
]
|
|
29357
|
+
}
|
|
29358
|
+
},
|
|
29359
|
+
{ json: options.json }
|
|
29360
|
+
);
|
|
29361
|
+
return 0;
|
|
29362
|
+
}
|
|
29363
|
+
function registerSkillsCommand(program) {
|
|
29364
|
+
program.command("skills").description("Replace Deepline agent skills with the current release.").option("--scope <scope>", "Install scope: global or local").option("--agent <agent>", "Override the detected agent target").option("--dry-run", "Print the install plan without changing files").option("--json", "Emit one JSON result envelope").addHelpText(
|
|
29365
|
+
"after",
|
|
29366
|
+
`
|
|
29367
|
+
Notes:
|
|
29368
|
+
This command removes and reinstalls only Deepline-managed skill names using
|
|
29369
|
+
skills@latest. Local scope writes into the resolved persistent project.
|
|
29370
|
+
|
|
29371
|
+
Examples:
|
|
29372
|
+
deepline skills --json
|
|
29373
|
+
deepline skills --scope local --json
|
|
29374
|
+
deepline skills --agent codex --dry-run --json
|
|
29375
|
+
`
|
|
29376
|
+
).action(async (options) => {
|
|
29377
|
+
process.exitCode = await runSkillsCommand(options);
|
|
29378
|
+
});
|
|
29114
29379
|
}
|
|
29115
29380
|
|
|
29116
29381
|
// src/cli/commands/update.ts
|
|
@@ -29142,14 +29407,14 @@ function posixShellQuote(value) {
|
|
|
29142
29407
|
function windowsCmdQuote(value) {
|
|
29143
29408
|
return `"${value.replace(/"/g, '""')}"`;
|
|
29144
29409
|
}
|
|
29145
|
-
function
|
|
29410
|
+
function shellQuote5(value) {
|
|
29146
29411
|
if (process.platform === "win32") {
|
|
29147
29412
|
return /^[A-Za-z0-9_./:@%+=,-]+$/.test(value) ? value : windowsCmdQuote(value);
|
|
29148
29413
|
}
|
|
29149
29414
|
return posixShellQuote(value);
|
|
29150
29415
|
}
|
|
29151
29416
|
function buildSourceUpdateCommand(sourceRoot) {
|
|
29152
|
-
const quotedRoot =
|
|
29417
|
+
const quotedRoot = shellQuote5(sourceRoot);
|
|
29153
29418
|
const cdCommand = process.platform === "win32" ? `cd /d ${quotedRoot}` : `cd ${quotedRoot}`;
|
|
29154
29419
|
return `${cdCommand} && git fetch origin main --tags && git merge --ff-only origin/main`;
|
|
29155
29420
|
}
|
|
@@ -29161,7 +29426,7 @@ function buildSidecarProjectConfigCommand(versionDir, nodeBin) {
|
|
|
29161
29426
|
"fs.mkdirSync(dir,{recursive:true});",
|
|
29162
29427
|
`fs.writeFileSync(path.join(dir,'package.json'),${JSON.stringify(NPM_SDK_SIDECAR_PACKAGE_JSON)});`
|
|
29163
29428
|
].join("");
|
|
29164
|
-
return `${
|
|
29429
|
+
return `${shellQuote5(nodeBin)} -e ${shellQuote5(script)} ${shellQuote5(versionDir)}`;
|
|
29165
29430
|
}
|
|
29166
29431
|
function sidecarStateDir(input2) {
|
|
29167
29432
|
const scope = input2.env.DEEPLINE_CONFIG_SCOPE?.trim();
|
|
@@ -29224,7 +29489,7 @@ function resolvePythonSidecarUpdatePlan(options) {
|
|
|
29224
29489
|
const npmCommand = "npm";
|
|
29225
29490
|
const registryUrl = sidecarRegistryUrl(hostUrl);
|
|
29226
29491
|
const versionDir = (0, import_node_path19.join)(stateDir, "versions", "<version>");
|
|
29227
|
-
const manualCommand = `${buildSidecarProjectConfigCommand(versionDir, nodeBin)} && ${npmCommand} install --prefix ${
|
|
29492
|
+
const manualCommand = `${buildSidecarProjectConfigCommand(versionDir, nodeBin)} && ${npmCommand} install --prefix ${shellQuote5(versionDir)} --registry ${shellQuote5(registryUrl)} ${NPM_SDK_INSTALL_COMMON_FLAGS.map(shellQuote5).join(" ")} ${shellQuote5(packageSpec)}`;
|
|
29228
29493
|
return {
|
|
29229
29494
|
kind: "python-sidecar",
|
|
29230
29495
|
stateDir,
|
|
@@ -29272,7 +29537,7 @@ function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
|
|
|
29272
29537
|
}
|
|
29273
29538
|
function resolveUpdatePlan(options = {}) {
|
|
29274
29539
|
const env = options.env ?? process.env;
|
|
29275
|
-
const homeDir2 = options.homeDir ?? (0,
|
|
29540
|
+
const homeDir2 = options.homeDir ?? (0, import_node_os14.homedir)();
|
|
29276
29541
|
const entrypoint = options.entrypoint ?? (process.argv[1] ? (0, import_node_path19.resolve)(process.argv[1]) : "");
|
|
29277
29542
|
const sourceRoot = entrypoint ? findRepoBackedSdkRoot((0, import_node_path19.dirname)(entrypoint)) : null;
|
|
29278
29543
|
if (sourceRoot) {
|
|
@@ -29308,7 +29573,7 @@ function resolveUpdatePlan(options = {}) {
|
|
|
29308
29573
|
fallbackRegistryUrl: publicNpmFallbackRegistryUrl(
|
|
29309
29574
|
env.DEEPLINE_HOST_URL?.trim() || autoDetectBaseUrl()
|
|
29310
29575
|
),
|
|
29311
|
-
manualCommand: `${command} ${args.map(
|
|
29576
|
+
manualCommand: `${command} ${args.map(shellQuote5).join(" ")}`
|
|
29312
29577
|
};
|
|
29313
29578
|
}
|
|
29314
29579
|
var AUTO_UPDATE_FAILURE_FILE = ".auto-update-failure.json";
|
|
@@ -29318,7 +29583,7 @@ function autoUpdateFailurePath(plan) {
|
|
|
29318
29583
|
return (0, import_node_path19.join)(plan.stateDir, AUTO_UPDATE_FAILURE_FILE);
|
|
29319
29584
|
}
|
|
29320
29585
|
return (0, import_node_path19.join)(
|
|
29321
|
-
(0,
|
|
29586
|
+
(0, import_node_os14.homedir)(),
|
|
29322
29587
|
".local",
|
|
29323
29588
|
"deepline",
|
|
29324
29589
|
"sdk-cli",
|
|
@@ -29513,9 +29778,9 @@ function writeSidecarLauncher(input2) {
|
|
|
29513
29778
|
input2.path,
|
|
29514
29779
|
[
|
|
29515
29780
|
"#!/usr/bin/env sh",
|
|
29516
|
-
`export DEEPLINE_HOST_URL=${
|
|
29517
|
-
`export DEEPLINE_CONFIG_SCOPE=${
|
|
29518
|
-
`exec ${
|
|
29781
|
+
`export DEEPLINE_HOST_URL=${shellQuote5(input2.hostUrl)}`,
|
|
29782
|
+
`export DEEPLINE_CONFIG_SCOPE=${shellQuote5(input2.scope)}`,
|
|
29783
|
+
`exec ${shellQuote5(input2.nodeBin)} ${shellQuote5(input2.entryPath)} "$@"`,
|
|
29519
29784
|
""
|
|
29520
29785
|
].join("\n"),
|
|
29521
29786
|
{ encoding: "utf8", mode: 493 }
|
|
@@ -29645,7 +29910,20 @@ async function runUpdateCommand(options, dependencies = {}) {
|
|
|
29645
29910
|
const detectBaseUrl = dependencies.detectBaseUrl ?? autoDetectBaseUrl;
|
|
29646
29911
|
const resolvePlan = dependencies.resolvePlan ?? resolveUpdatePlan;
|
|
29647
29912
|
const runPlan = dependencies.runPlan ?? runUpdatePlan;
|
|
29648
|
-
const syncSkills = dependencies.syncSkillsIfNeeded ??
|
|
29913
|
+
const syncSkills = dependencies.syncSkillsIfNeeded ?? (async () => {
|
|
29914
|
+
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
29915
|
+
process.stdout.write = (() => true);
|
|
29916
|
+
try {
|
|
29917
|
+
const exitCode = await runSkillsCommand({ json: true });
|
|
29918
|
+
if (exitCode !== 0) {
|
|
29919
|
+
throw new Error(
|
|
29920
|
+
`Deepline skills update failed with exit ${exitCode}.`
|
|
29921
|
+
);
|
|
29922
|
+
}
|
|
29923
|
+
} finally {
|
|
29924
|
+
process.stdout.write = originalWrite;
|
|
29925
|
+
}
|
|
29926
|
+
});
|
|
29649
29927
|
const stderr = dependencies.stderr ?? process.stderr;
|
|
29650
29928
|
const plan = resolvePlan();
|
|
29651
29929
|
const render = {
|
|
@@ -29713,214 +29991,1399 @@ Examples:
|
|
|
29713
29991
|
});
|
|
29714
29992
|
}
|
|
29715
29993
|
|
|
29716
|
-
//
|
|
29717
|
-
var
|
|
29718
|
-
|
|
29719
|
-
|
|
29720
|
-
|
|
29721
|
-
|
|
29722
|
-
|
|
29723
|
-
|
|
29724
|
-
|
|
29725
|
-
|
|
29726
|
-
|
|
29727
|
-
|
|
29728
|
-
|
|
29729
|
-
|
|
29730
|
-
|
|
29731
|
-
|
|
29732
|
-
|
|
29733
|
-
|
|
29734
|
-
|
|
29735
|
-
|
|
29736
|
-
|
|
29737
|
-
|
|
29738
|
-
|
|
29739
|
-
|
|
29740
|
-
|
|
29741
|
-
|
|
29742
|
-
|
|
29743
|
-
|
|
29744
|
-
|
|
29745
|
-
|
|
29746
|
-
|
|
29747
|
-
|
|
29748
|
-
|
|
29749
|
-
|
|
29750
|
-
|
|
29751
|
-
|
|
29752
|
-
|
|
29994
|
+
// src/cli/commands/setup.ts
|
|
29995
|
+
var import_node_child_process5 = require("child_process");
|
|
29996
|
+
var import_node_fs18 = require("fs");
|
|
29997
|
+
var import_node_os15 = require("os");
|
|
29998
|
+
var import_node_path20 = require("path");
|
|
29999
|
+
var SETUP_PHASE_NAMES = [
|
|
30000
|
+
"cli",
|
|
30001
|
+
"cleanup",
|
|
30002
|
+
"skills",
|
|
30003
|
+
"auth",
|
|
30004
|
+
"verify"
|
|
30005
|
+
];
|
|
30006
|
+
function initialSetupPhases() {
|
|
30007
|
+
return {
|
|
30008
|
+
cli: { status: "pending" },
|
|
30009
|
+
cleanup: { status: "pending" },
|
|
30010
|
+
skills: { status: "pending" },
|
|
30011
|
+
auth: { status: "pending" },
|
|
30012
|
+
verify: { status: "pending" }
|
|
30013
|
+
};
|
|
30014
|
+
}
|
|
30015
|
+
function isSetupPhaseStatus(value) {
|
|
30016
|
+
return value === "pending" || value === "in_progress" || value === "complete" || value === "waiting" || value === "failed";
|
|
30017
|
+
}
|
|
30018
|
+
function parseSetupPhases(value) {
|
|
30019
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
30020
|
+
const source = value;
|
|
30021
|
+
const phases = initialSetupPhases();
|
|
30022
|
+
for (const name of SETUP_PHASE_NAMES) {
|
|
30023
|
+
const phase = source[name];
|
|
30024
|
+
if (!phase || typeof phase !== "object" || Array.isArray(phase)) {
|
|
30025
|
+
return null;
|
|
30026
|
+
}
|
|
30027
|
+
const record = phase;
|
|
30028
|
+
if (!isSetupPhaseStatus(record.status)) return null;
|
|
30029
|
+
phases[name] = {
|
|
30030
|
+
status: record.status,
|
|
30031
|
+
...typeof record.outcome === "string" ? { outcome: record.outcome } : {},
|
|
30032
|
+
...typeof record.code === "string" ? { code: record.code } : {}
|
|
30033
|
+
};
|
|
29753
30034
|
}
|
|
29754
|
-
|
|
29755
|
-
|
|
29756
|
-
// src/cli/command-compatibility.ts
|
|
29757
|
-
var COMMAND_COMPATIBILITY = command_compatibility_default;
|
|
29758
|
-
function cliFamilyLabel(family) {
|
|
29759
|
-
return family === "sdk" ? "SDK CLI" : "legacy Python CLI";
|
|
30035
|
+
return phases;
|
|
29760
30036
|
}
|
|
29761
|
-
function
|
|
29762
|
-
const
|
|
29763
|
-
if (
|
|
29764
|
-
|
|
30037
|
+
function phasesFromLegacyStatus(status) {
|
|
30038
|
+
const phases = initialSetupPhases();
|
|
30039
|
+
if (status === "skills_installed" || status === "authorization_pending" || status === "complete") {
|
|
30040
|
+
phases.cli = { status: "complete" };
|
|
30041
|
+
phases.cleanup = { status: "complete" };
|
|
30042
|
+
phases.skills = { status: "complete" };
|
|
29765
30043
|
}
|
|
29766
|
-
|
|
29767
|
-
|
|
29768
|
-
|
|
29769
|
-
|
|
29770
|
-
""
|
|
29771
|
-
|
|
29772
|
-
|
|
29773
|
-
|
|
29774
|
-
|
|
29775
|
-
|
|
29776
|
-
|
|
29777
|
-
|
|
29778
|
-
|
|
29779
|
-
|
|
29780
|
-
|
|
29781
|
-
" To use the legacy Python CLI instead:",
|
|
29782
|
-
` ${legacyPythonInstallCommand(baseUrl)}`,
|
|
29783
|
-
" `deepline update` updates this SDK CLI, but it will not switch CLI families."
|
|
29784
|
-
);
|
|
29785
|
-
if (compatibility.sdk_alternative) {
|
|
29786
|
-
lines.push(` SDK alternative: ${compatibility.sdk_alternative}`);
|
|
29787
|
-
}
|
|
29788
|
-
} else {
|
|
29789
|
-
lines.push(
|
|
29790
|
-
"",
|
|
29791
|
-
" To use SDK commands, install the SDK CLI and refresh Deepline agent skills:",
|
|
29792
|
-
` ${sdkNpmGlobalInstallCommand()}`,
|
|
29793
|
-
` ${skillsInstallCommand(baseUrl, DEFAULT_SDK_SKILL_NAMES)}`,
|
|
29794
|
-
" `deepline update` updates this Python CLI and its skills, but it will not switch CLI families."
|
|
30044
|
+
if (status === "authorization_pending") {
|
|
30045
|
+
phases.auth = { status: "waiting", outcome: "authorization_pending" };
|
|
30046
|
+
} else if (status === "complete") {
|
|
30047
|
+
phases.auth = { status: "complete" };
|
|
30048
|
+
phases.verify = { status: "complete" };
|
|
30049
|
+
}
|
|
30050
|
+
return phases;
|
|
30051
|
+
}
|
|
30052
|
+
function readSetupState(input2) {
|
|
30053
|
+
try {
|
|
30054
|
+
const parsed = JSON.parse(
|
|
30055
|
+
(0, import_node_fs18.readFileSync)(
|
|
30056
|
+
setupStatePath(input2.baseUrl, input2.scope, input2.root),
|
|
30057
|
+
"utf8"
|
|
30058
|
+
)
|
|
29795
30059
|
);
|
|
29796
|
-
if (
|
|
29797
|
-
|
|
30060
|
+
if (parsed.host !== input2.baseUrl || parsed.scope !== input2.scope || parsed.root !== input2.root || typeof parsed.status !== "string") {
|
|
30061
|
+
return null;
|
|
29798
30062
|
}
|
|
30063
|
+
return {
|
|
30064
|
+
status: parsed.status,
|
|
30065
|
+
phases: parseSetupPhases(parsed.phases) ?? phasesFromLegacyStatus(parsed.status)
|
|
30066
|
+
};
|
|
30067
|
+
} catch {
|
|
30068
|
+
return null;
|
|
29799
30069
|
}
|
|
29800
|
-
return lines.join("\n");
|
|
29801
30070
|
}
|
|
29802
|
-
function
|
|
29803
|
-
const
|
|
29804
|
-
|
|
29805
|
-
|
|
30071
|
+
function selectSetupProgress(previousState) {
|
|
30072
|
+
const resumed = Boolean(previousState && previousState.status !== "complete");
|
|
30073
|
+
return {
|
|
30074
|
+
resumed,
|
|
30075
|
+
phases: resumed ? previousState.phases : initialSetupPhases()
|
|
30076
|
+
};
|
|
29806
30077
|
}
|
|
29807
|
-
|
|
29808
|
-
|
|
29809
|
-
|
|
29810
|
-
|
|
29811
|
-
const value = process.env[name]?.trim().toLowerCase();
|
|
29812
|
-
return value === "1" || value === "true" || value === "yes";
|
|
30078
|
+
function normalizeScope2(value) {
|
|
30079
|
+
if (!value || value === "global") return "global";
|
|
30080
|
+
if (value === "local") return "local";
|
|
30081
|
+
throw new Error("--scope must be one of: global, local");
|
|
29813
30082
|
}
|
|
29814
|
-
function
|
|
29815
|
-
|
|
30083
|
+
function resolveScopeRoot(scope) {
|
|
30084
|
+
if (scope === "global") return null;
|
|
30085
|
+
const target = resolveProjectPinTarget();
|
|
30086
|
+
if (!target.ok) {
|
|
30087
|
+
throw new Error(
|
|
30088
|
+
`Cowork project folder is ambiguous. Candidate folders: ${target.candidates.join(
|
|
30089
|
+
", "
|
|
30090
|
+
)}. Set CLAUDE_PROJECT_DIR or cd into the intended project folder.`
|
|
30091
|
+
);
|
|
30092
|
+
}
|
|
30093
|
+
return target.dir;
|
|
29816
30094
|
}
|
|
29817
|
-
function
|
|
29818
|
-
return
|
|
30095
|
+
function authScopeForSetup(scope) {
|
|
30096
|
+
return scope === "local" ? "folder" : "global";
|
|
29819
30097
|
}
|
|
29820
|
-
function
|
|
29821
|
-
|
|
29822
|
-
if (!trimmed) return null;
|
|
29823
|
-
const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec(
|
|
29824
|
-
trimmed
|
|
29825
|
-
);
|
|
29826
|
-
if (!match) return null;
|
|
29827
|
-
return {
|
|
29828
|
-
major: Number(match[1]),
|
|
29829
|
-
minor: Number(match[2]),
|
|
29830
|
-
patch: Number(match[3]),
|
|
29831
|
-
prerelease: match[4] ?? ""
|
|
29832
|
-
};
|
|
30098
|
+
function setupStatePath(baseUrl, scope, root) {
|
|
30099
|
+
return scope === "local" && root ? (0, import_node_path20.join)(root, ".deepline", "setup", "state.json") : (0, import_node_path20.join)(sdkCliStateDirPath(baseUrl), "setup.json");
|
|
29833
30100
|
}
|
|
29834
|
-
function
|
|
29835
|
-
|
|
29836
|
-
const
|
|
29837
|
-
|
|
29838
|
-
|
|
30101
|
+
async function captureStdout2(run) {
|
|
30102
|
+
let stdout = "";
|
|
30103
|
+
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
30104
|
+
process.stdout.write = ((chunk) => {
|
|
30105
|
+
stdout += typeof chunk === "string" ? chunk : String(chunk);
|
|
30106
|
+
return true;
|
|
30107
|
+
});
|
|
30108
|
+
try {
|
|
30109
|
+
return { exitCode: await run(), stdout, error: null };
|
|
30110
|
+
} catch (error) {
|
|
30111
|
+
return { exitCode: 4, stdout, error };
|
|
30112
|
+
} finally {
|
|
30113
|
+
process.stdout.write = originalWrite;
|
|
29839
30114
|
}
|
|
29840
|
-
|
|
29841
|
-
|
|
30115
|
+
}
|
|
30116
|
+
function parseCapturedJson(stdout) {
|
|
30117
|
+
try {
|
|
30118
|
+
return JSON.parse(stdout.trim());
|
|
30119
|
+
} catch {
|
|
30120
|
+
return null;
|
|
29842
30121
|
}
|
|
29843
|
-
if (a.prerelease === b.prerelease) return 0;
|
|
29844
|
-
if (!a.prerelease) return 1;
|
|
29845
|
-
if (!b.prerelease) return -1;
|
|
29846
|
-
return a.prerelease.localeCompare(b.prerelease);
|
|
29847
30122
|
}
|
|
29848
|
-
function
|
|
29849
|
-
|
|
29850
|
-
const current = response?.current?.trim() || SDK_VERSION;
|
|
29851
|
-
if (!target) return false;
|
|
29852
|
-
return compareSemver(target, current) < 0;
|
|
30123
|
+
function asRecord2(value) {
|
|
30124
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
29853
30125
|
}
|
|
29854
|
-
function
|
|
29855
|
-
|
|
29856
|
-
|
|
29857
|
-
|
|
29858
|
-
|
|
29859
|
-
|
|
29860
|
-
|
|
29861
|
-
|
|
29862
|
-
...process.env,
|
|
29863
|
-
DEEPLINE_NO_AUTO_UPDATE: "1"
|
|
29864
|
-
}
|
|
29865
|
-
});
|
|
29866
|
-
child.on("error", (error) => {
|
|
29867
|
-
process.stderr.write(
|
|
29868
|
-
`Deepline SDK/CLI updated, but relaunch failed: ${error.message}
|
|
29869
|
-
`
|
|
29870
|
-
);
|
|
29871
|
-
resolve14(1);
|
|
29872
|
-
});
|
|
29873
|
-
child.on("close", (code) => resolve14(code ?? 1));
|
|
29874
|
-
});
|
|
30126
|
+
function printCapturedAuthorizationUrl(stdout) {
|
|
30127
|
+
const urls = stdout.match(/https:\/\/[^\s]+/g) ?? [];
|
|
30128
|
+
for (const url of new Set(
|
|
30129
|
+
urls.map((value) => value.replace(/[).,]+$/, ""))
|
|
30130
|
+
)) {
|
|
30131
|
+
process.stderr.write(`Authorize Deepline: ${url}
|
|
30132
|
+
`);
|
|
30133
|
+
}
|
|
29875
30134
|
}
|
|
29876
|
-
|
|
29877
|
-
|
|
29878
|
-
|
|
29879
|
-
|
|
30135
|
+
function safeRead(path) {
|
|
30136
|
+
try {
|
|
30137
|
+
return (0, import_node_fs18.readFileSync)(path, "utf8");
|
|
30138
|
+
} catch {
|
|
30139
|
+
return "";
|
|
29880
30140
|
}
|
|
29881
|
-
|
|
29882
|
-
|
|
29883
|
-
|
|
29884
|
-
|
|
29885
|
-
|
|
29886
|
-
`
|
|
29887
|
-
);
|
|
30141
|
+
}
|
|
30142
|
+
function isNpmManagedDeeplinePath(path) {
|
|
30143
|
+
try {
|
|
30144
|
+
return (0, import_node_fs18.realpathSync)(path).includes(`${(0, import_node_path20.join)("node_modules", "deepline")}`);
|
|
30145
|
+
} catch {
|
|
29888
30146
|
return false;
|
|
29889
30147
|
}
|
|
29890
|
-
|
|
29891
|
-
|
|
29892
|
-
|
|
29893
|
-
|
|
30148
|
+
}
|
|
30149
|
+
function removeKnownLegacyPaths(baseUrl) {
|
|
30150
|
+
const home = (0, import_node_os15.homedir)();
|
|
30151
|
+
const hostDir = (0, import_node_path20.join)(home, ".local", "deepline", baseUrlSlug(baseUrl));
|
|
30152
|
+
const installerCommandPath = safeRead(
|
|
30153
|
+
(0, import_node_path20.join)(hostDir, "sdk", ".command-path")
|
|
30154
|
+
).trim();
|
|
30155
|
+
const candidates = [
|
|
30156
|
+
(0, import_node_path20.join)(home, ".local", "bin", "deepline-real"),
|
|
30157
|
+
(0, import_node_path20.join)(hostDir, "bin", "deepline"),
|
|
30158
|
+
(0, import_node_path20.join)(hostDir, "bin", "deepline-real"),
|
|
30159
|
+
(0, import_node_path20.join)(hostDir, "cli", ".install-method"),
|
|
30160
|
+
(0, import_node_path20.join)(hostDir, "cli", ".version"),
|
|
30161
|
+
(0, import_node_path20.join)(hostDir, "sdk", ".install-method"),
|
|
30162
|
+
(0, import_node_path20.join)(hostDir, "sdk", ".command-path"),
|
|
30163
|
+
...installerCommandPath ? [
|
|
30164
|
+
installerCommandPath,
|
|
30165
|
+
(0, import_node_path20.join)((0, import_node_path20.dirname)(installerCommandPath), "deepline-sdk")
|
|
30166
|
+
] : []
|
|
30167
|
+
];
|
|
30168
|
+
const removed = [];
|
|
30169
|
+
for (const path of candidates) {
|
|
30170
|
+
if (!(0, import_node_fs18.existsSync)(path)) continue;
|
|
30171
|
+
if (path === installerCommandPath && isNpmManagedDeeplinePath(path)) {
|
|
30172
|
+
continue;
|
|
30173
|
+
}
|
|
30174
|
+
(0, import_node_fs18.rmSync)(path, { force: true });
|
|
30175
|
+
removed.push(path);
|
|
29894
30176
|
}
|
|
29895
|
-
|
|
29896
|
-
|
|
29897
|
-
|
|
29898
|
-
|
|
30177
|
+
return removed;
|
|
30178
|
+
}
|
|
30179
|
+
function resolvePathCommands(command) {
|
|
30180
|
+
const lookup = (0, import_node_child_process5.spawnSync)(
|
|
30181
|
+
process.platform === "win32" ? "where" : "which",
|
|
30182
|
+
process.platform === "win32" ? [command] : ["-a", command],
|
|
30183
|
+
{ encoding: "utf8", shell: process.platform === "win32" }
|
|
29899
30184
|
);
|
|
29900
|
-
|
|
29901
|
-
|
|
29902
|
-
|
|
30185
|
+
return [
|
|
30186
|
+
...new Set(
|
|
30187
|
+
String(lookup.stdout ?? "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((path) => (0, import_node_path20.resolve)(path))
|
|
30188
|
+
)
|
|
30189
|
+
];
|
|
30190
|
+
}
|
|
30191
|
+
function resolvePathCommand(command) {
|
|
30192
|
+
return resolvePathCommands(command)[0] ?? null;
|
|
30193
|
+
}
|
|
30194
|
+
function resolvePersistentGlobalCommand() {
|
|
30195
|
+
const prefix = (0, import_node_child_process5.spawnSync)("npm", ["prefix", "-g"], { encoding: "utf8" });
|
|
30196
|
+
if (prefix.status !== 0) return null;
|
|
30197
|
+
const root = String(prefix.stdout ?? "").trim();
|
|
30198
|
+
if (!root) return null;
|
|
30199
|
+
const candidates = process.platform === "win32" ? [(0, import_node_path20.join)(root, "deepline.cmd"), (0, import_node_path20.join)(root, "deepline")] : [(0, import_node_path20.join)(root, "bin", "deepline")];
|
|
30200
|
+
return candidates.find((candidate) => (0, import_node_fs18.existsSync)(candidate)) ?? null;
|
|
30201
|
+
}
|
|
30202
|
+
function inspectGlobalCliAvailability(input2) {
|
|
30203
|
+
const persistentPath = input2 && "persistentGlobalCli" in input2 ? input2.persistentGlobalCli ?? null : resolvePersistentGlobalCommand();
|
|
30204
|
+
const pathClis = input2?.pathClis ?? resolvePathCommands("deepline");
|
|
30205
|
+
const path = persistentPath ? pathClis.find(
|
|
30206
|
+
(candidate) => pathsResolveToSameFile(candidate, persistentPath)
|
|
30207
|
+
) ?? null : null;
|
|
30208
|
+
return { ok: Boolean(path), persistentPath, path };
|
|
30209
|
+
}
|
|
30210
|
+
function pathsResolveToSameFile(left, right) {
|
|
30211
|
+
try {
|
|
30212
|
+
return (0, import_node_fs18.realpathSync)(left) === (0, import_node_fs18.realpathSync)(right);
|
|
30213
|
+
} catch {
|
|
30214
|
+
return (0, import_node_path20.resolve)(left) === (0, import_node_path20.resolve)(right);
|
|
29903
30215
|
}
|
|
29904
|
-
|
|
29905
|
-
|
|
29906
|
-
|
|
29907
|
-
|
|
29908
|
-
|
|
30216
|
+
}
|
|
30217
|
+
function isKnownDeeplineCommand(path) {
|
|
30218
|
+
const entrypoint = process.argv[1] ? (0, import_node_path20.resolve)(process.argv[1]) : "";
|
|
30219
|
+
let resolvedPath = path;
|
|
30220
|
+
try {
|
|
30221
|
+
resolvedPath = (0, import_node_fs18.realpathSync)(path);
|
|
30222
|
+
} catch {
|
|
30223
|
+
}
|
|
30224
|
+
if (entrypoint && resolvedPath === entrypoint) return true;
|
|
30225
|
+
if (resolvedPath.includes(`${(0, import_node_path20.join)("node_modules", "deepline")}`)) return true;
|
|
30226
|
+
const content = safeRead(path);
|
|
30227
|
+
return content.includes("node_modules/deepline") || content.includes("node_modules\\deepline") || content.includes("DEEPLINE_CONFIG_SCOPE") || content.includes("deepline-real");
|
|
30228
|
+
}
|
|
30229
|
+
function inspectPathConflict() {
|
|
30230
|
+
const commandPath = resolvePathCommand("deepline");
|
|
30231
|
+
if (!commandPath || isKnownDeeplineCommand(commandPath)) return null;
|
|
30232
|
+
try {
|
|
30233
|
+
if ((0, import_node_fs18.lstatSync)(commandPath).isSymbolicLink()) {
|
|
30234
|
+
const target = (0, import_node_fs18.realpathSync)(commandPath);
|
|
30235
|
+
if (target.includes(`${(0, import_node_path20.join)("node_modules", "deepline")}`)) return null;
|
|
29909
30236
|
}
|
|
29910
|
-
|
|
29911
|
-
`Deepline SDK/CLI auto-update failed with exit code ${updateResult.exitCode}; continuing with ${response.current ?? "current version"}.
|
|
29912
|
-
`
|
|
29913
|
-
);
|
|
29914
|
-
return false;
|
|
30237
|
+
} catch {
|
|
29915
30238
|
}
|
|
29916
|
-
|
|
29917
|
-
const exitCode = await relaunchCurrentCommand(plan);
|
|
29918
|
-
process.exit(exitCode);
|
|
29919
|
-
return true;
|
|
30239
|
+
return commandPath;
|
|
29920
30240
|
}
|
|
29921
|
-
|
|
29922
|
-
|
|
29923
|
-
|
|
30241
|
+
function writeSetupState(input2) {
|
|
30242
|
+
const path = setupStatePath(input2.baseUrl, input2.scope, input2.root);
|
|
30243
|
+
(0, import_node_fs18.mkdirSync)((0, import_node_path20.dirname)(path), { recursive: true });
|
|
30244
|
+
(0, import_node_fs18.writeFileSync)(
|
|
30245
|
+
path,
|
|
30246
|
+
`${JSON.stringify(
|
|
30247
|
+
{
|
|
30248
|
+
schemaVersion: 2,
|
|
30249
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30250
|
+
cliVersion: SDK_VERSION,
|
|
30251
|
+
host: input2.baseUrl,
|
|
30252
|
+
scope: input2.scope,
|
|
30253
|
+
root: input2.root,
|
|
30254
|
+
status: input2.status,
|
|
30255
|
+
phases: input2.phases
|
|
30256
|
+
},
|
|
30257
|
+
null,
|
|
30258
|
+
2
|
|
30259
|
+
)}
|
|
30260
|
+
`,
|
|
30261
|
+
"utf8"
|
|
30262
|
+
);
|
|
30263
|
+
return path;
|
|
30264
|
+
}
|
|
30265
|
+
function persistSetupProgress(input2) {
|
|
30266
|
+
return writeSetupState({
|
|
30267
|
+
...input2,
|
|
30268
|
+
status: input2.status ?? "in_progress"
|
|
30269
|
+
});
|
|
30270
|
+
}
|
|
30271
|
+
function completeSetupPhase(phases, phase, outcome) {
|
|
30272
|
+
phases[phase] = {
|
|
30273
|
+
status: "complete",
|
|
30274
|
+
...outcome ? { outcome } : {}
|
|
30275
|
+
};
|
|
30276
|
+
}
|
|
30277
|
+
function beginSetupPhase(phases, phase) {
|
|
30278
|
+
phases[phase] = { status: "in_progress" };
|
|
30279
|
+
}
|
|
30280
|
+
function failSetupPhase(phases, phase, code) {
|
|
30281
|
+
phases[phase] = { status: "failed", code };
|
|
30282
|
+
}
|
|
30283
|
+
function rollbackCommand(scope, root) {
|
|
30284
|
+
const prefix = scope === "local" && root ? ` --prefix ${JSON.stringify((0, import_node_path20.join)(root, ".deepline", "runtime"))}` : "";
|
|
30285
|
+
return `npm install -g${prefix} --no-audit --no-fund --include=optional --allow-scripts=esbuild deepline@${SDK_VERSION}`;
|
|
30286
|
+
}
|
|
30287
|
+
function setupQuickstartCommand(baseUrl) {
|
|
30288
|
+
return baseUrl === "https://code.deepline.com" ? "deepline quickstart" : `DEEPLINE_HOST_URL=${JSON.stringify(baseUrl)} deepline quickstart`;
|
|
30289
|
+
}
|
|
30290
|
+
function setupResumeCommand(baseUrl, scope) {
|
|
30291
|
+
const hostPrefix = baseUrl === "https://code.deepline.com" ? "" : `DEEPLINE_HOST_URL=${JSON.stringify(baseUrl)} `;
|
|
30292
|
+
return `${hostPrefix}deepline setup --scope ${scope} --json`;
|
|
30293
|
+
}
|
|
30294
|
+
function setupRetry(input2) {
|
|
30295
|
+
return {
|
|
30296
|
+
phase: input2.phase,
|
|
30297
|
+
command: setupResumeCommand(input2.baseUrl, input2.scope),
|
|
30298
|
+
automatic: true
|
|
30299
|
+
};
|
|
30300
|
+
}
|
|
30301
|
+
function reportSetupPhaseFailure(input2) {
|
|
30302
|
+
failSetupPhase(input2.phases, input2.phase, input2.code);
|
|
30303
|
+
const statePath = persistSetupProgress({
|
|
30304
|
+
baseUrl: input2.baseUrl,
|
|
30305
|
+
scope: input2.scope,
|
|
30306
|
+
root: input2.root,
|
|
30307
|
+
phases: input2.phases,
|
|
30308
|
+
status: "failed"
|
|
30309
|
+
});
|
|
30310
|
+
const retry = setupRetry(input2);
|
|
30311
|
+
printCommandEnvelope(
|
|
30312
|
+
{
|
|
30313
|
+
ok: false,
|
|
30314
|
+
status: "failed",
|
|
30315
|
+
code: input2.code,
|
|
30316
|
+
exitCode: input2.exitCode,
|
|
30317
|
+
scope: input2.scope,
|
|
30318
|
+
message: input2.message,
|
|
30319
|
+
phases: input2.phases,
|
|
30320
|
+
failedPhase: input2.phase,
|
|
30321
|
+
retry,
|
|
30322
|
+
statePath,
|
|
30323
|
+
next: retry.command,
|
|
30324
|
+
...input2.extra ?? {}
|
|
30325
|
+
},
|
|
30326
|
+
{ json: input2.json }
|
|
30327
|
+
);
|
|
30328
|
+
return input2.exitCode;
|
|
30329
|
+
}
|
|
30330
|
+
async function readAuthStatus(authScope) {
|
|
30331
|
+
try {
|
|
30332
|
+
const captured = await captureStdout2(
|
|
30333
|
+
() => handleStatus([
|
|
30334
|
+
"--json",
|
|
30335
|
+
...authScope ? ["--auth-scope", authScope] : []
|
|
30336
|
+
])
|
|
30337
|
+
);
|
|
30338
|
+
return {
|
|
30339
|
+
exitCode: captured.exitCode,
|
|
30340
|
+
payload: parseCapturedJson(captured.stdout),
|
|
30341
|
+
error: captured.error
|
|
30342
|
+
};
|
|
30343
|
+
} catch (error) {
|
|
30344
|
+
return { exitCode: 4, payload: null, error };
|
|
30345
|
+
}
|
|
30346
|
+
}
|
|
30347
|
+
function reportSetupAuthStatusFailure(input2) {
|
|
30348
|
+
if (!input2.auth.error) return null;
|
|
30349
|
+
return reportSetupPhaseFailure({
|
|
30350
|
+
baseUrl: input2.baseUrl,
|
|
30351
|
+
scope: input2.scope,
|
|
30352
|
+
root: input2.root,
|
|
30353
|
+
phases: input2.phases,
|
|
30354
|
+
phase: "auth",
|
|
30355
|
+
code: "AUTH_STATUS_FAILED",
|
|
30356
|
+
exitCode: 4,
|
|
30357
|
+
message: "Deepline could not verify authorization with the configured host.",
|
|
30358
|
+
json: input2.json,
|
|
30359
|
+
extra: { authScope: input2.authScope }
|
|
30360
|
+
});
|
|
30361
|
+
}
|
|
30362
|
+
function buildDoctorAssessment(input2) {
|
|
30363
|
+
const skillsStatePath = skillsStatePathForScope(
|
|
30364
|
+
input2.baseUrl,
|
|
30365
|
+
input2.scope,
|
|
30366
|
+
input2.root
|
|
30367
|
+
);
|
|
30368
|
+
const skillsState = parseCapturedJson(safeRead(skillsStatePath));
|
|
30369
|
+
const apiKey = input2.scope === "local" ? resolveProjectApiKeyForBaseUrl(input2.baseUrl) : resolveGlobalApiKeyForBaseUrl(input2.baseUrl);
|
|
30370
|
+
const projectAuth = input2.scope === "local" && apiKey ? getResolvedProjectAuthSource(input2.baseUrl, apiKey) : null;
|
|
30371
|
+
const connected = input2.authStatus.payload?.connected === true;
|
|
30372
|
+
const authScopeOk = input2.scope === "local" ? Boolean(projectAuth) : Boolean(apiKey && !projectAuth);
|
|
30373
|
+
const skillsOk = skillsState?.scope === input2.scope && typeof skillsState.skillsVersion === "string" && Array.isArray(skillsState.agents) && skillsState.agents.length > 0;
|
|
30374
|
+
const runningCliPath = process.argv[1] ? (0, import_node_path20.resolve)(process.argv[1]) : null;
|
|
30375
|
+
const globalCli = input2.scope === "global" ? inspectGlobalCliAvailability() : null;
|
|
30376
|
+
const pathGlobalCli = globalCli?.path ?? null;
|
|
30377
|
+
const cliPath = input2.scope === "global" ? pathGlobalCli : runningCliPath;
|
|
30378
|
+
const cliScopeOk = input2.scope === "global" ? Boolean(pathGlobalCli) : Boolean(
|
|
30379
|
+
input2.root && runningCliPath?.includes((0, import_node_path20.join)(input2.root, ".deepline", "runtime"))
|
|
30380
|
+
);
|
|
30381
|
+
const checks = {
|
|
30382
|
+
cli: {
|
|
30383
|
+
ok: Boolean(cliPath) && cliScopeOk,
|
|
30384
|
+
version: SDK_VERSION,
|
|
30385
|
+
path: cliPath,
|
|
30386
|
+
scope: input2.scope
|
|
30387
|
+
},
|
|
30388
|
+
skills: {
|
|
30389
|
+
ok: skillsOk,
|
|
30390
|
+
statePath: skillsStatePath,
|
|
30391
|
+
version: skillsState?.skillsVersion ?? null,
|
|
30392
|
+
agents: skillsState?.agents ?? []
|
|
30393
|
+
},
|
|
30394
|
+
auth: {
|
|
30395
|
+
ok: connected && authScopeOk,
|
|
30396
|
+
scope: projectAuth ? "local" : apiKey ? "global" : null,
|
|
30397
|
+
status: input2.authStatus.payload?.status ?? "not_connected"
|
|
30398
|
+
},
|
|
30399
|
+
api: {
|
|
30400
|
+
ok: connected && input2.authStatus.exitCode === 0,
|
|
30401
|
+
host: input2.baseUrl,
|
|
30402
|
+
workspace: input2.authStatus.payload?.workspace ?? null,
|
|
30403
|
+
providerSpend: false
|
|
30404
|
+
}
|
|
30405
|
+
};
|
|
30406
|
+
return {
|
|
30407
|
+
ok: Object.values(checks).every((check) => check.ok),
|
|
30408
|
+
checks
|
|
30409
|
+
};
|
|
30410
|
+
}
|
|
30411
|
+
async function runDoctorCommand(options) {
|
|
30412
|
+
let scope;
|
|
30413
|
+
let root;
|
|
30414
|
+
try {
|
|
30415
|
+
scope = normalizeScope2(options.scope);
|
|
30416
|
+
root = resolveScopeRoot(scope);
|
|
30417
|
+
} catch (error) {
|
|
30418
|
+
printCommandEnvelope(
|
|
30419
|
+
{
|
|
30420
|
+
ok: false,
|
|
30421
|
+
status: "failed",
|
|
30422
|
+
code: "INVALID_SETUP_SCOPE",
|
|
30423
|
+
exitCode: 2,
|
|
30424
|
+
message: error instanceof Error ? error.message : String(error)
|
|
30425
|
+
},
|
|
30426
|
+
{ json: options.json }
|
|
30427
|
+
);
|
|
30428
|
+
return 2;
|
|
30429
|
+
}
|
|
30430
|
+
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
30431
|
+
const authScope = authScopeForSetup(scope);
|
|
30432
|
+
const authStatus = await readAuthStatus(authScope);
|
|
30433
|
+
const { ok, checks } = buildDoctorAssessment({
|
|
30434
|
+
baseUrl,
|
|
30435
|
+
scope,
|
|
30436
|
+
root,
|
|
30437
|
+
authStatus
|
|
30438
|
+
});
|
|
30439
|
+
const quickstart = setupQuickstartCommand(baseUrl);
|
|
30440
|
+
printCommandEnvelope(
|
|
30441
|
+
{
|
|
30442
|
+
ok,
|
|
30443
|
+
status: ok ? "complete" : "failed",
|
|
30444
|
+
code: ok ? "DOCTOR_OK" : "DOCTOR_FAILED",
|
|
30445
|
+
exitCode: ok ? 0 : 7,
|
|
30446
|
+
checks,
|
|
30447
|
+
next: ok ? quickstart : "Review failed checks, then rerun: deepline doctor --json",
|
|
30448
|
+
render: {
|
|
30449
|
+
sections: [
|
|
30450
|
+
{
|
|
30451
|
+
title: "doctor",
|
|
30452
|
+
lines: Object.entries(checks).map(
|
|
30453
|
+
([name, check]) => `${check.ok ? "pass" : "fail"} ${name}`
|
|
30454
|
+
)
|
|
30455
|
+
}
|
|
30456
|
+
]
|
|
30457
|
+
}
|
|
30458
|
+
},
|
|
30459
|
+
{ json: options.json }
|
|
30460
|
+
);
|
|
30461
|
+
return ok ? 0 : 7;
|
|
30462
|
+
}
|
|
30463
|
+
function pendingResult(input2) {
|
|
30464
|
+
input2.phases.auth = {
|
|
30465
|
+
status: "waiting",
|
|
30466
|
+
outcome: "authorization_pending"
|
|
30467
|
+
};
|
|
30468
|
+
const statePath = writeSetupState({
|
|
30469
|
+
baseUrl: input2.baseUrl,
|
|
30470
|
+
scope: input2.scope,
|
|
30471
|
+
root: input2.root,
|
|
30472
|
+
status: "authorization_pending",
|
|
30473
|
+
phases: input2.phases
|
|
30474
|
+
});
|
|
30475
|
+
if (input2.authorizationUrl) {
|
|
30476
|
+
process.stderr.write(`Authorize Deepline: ${input2.authorizationUrl}
|
|
30477
|
+
`);
|
|
30478
|
+
}
|
|
30479
|
+
printCommandEnvelope(
|
|
30480
|
+
{
|
|
30481
|
+
ok: true,
|
|
30482
|
+
status: "authorization_pending",
|
|
30483
|
+
complete: false,
|
|
30484
|
+
scope: input2.scope,
|
|
30485
|
+
authorizationUrl: input2.authorizationUrl || null,
|
|
30486
|
+
statePath,
|
|
30487
|
+
phases: input2.phases,
|
|
30488
|
+
currentPhase: "auth",
|
|
30489
|
+
resumed: input2.resumed,
|
|
30490
|
+
retry: setupRetry({
|
|
30491
|
+
baseUrl: input2.baseUrl,
|
|
30492
|
+
scope: input2.scope,
|
|
30493
|
+
phase: "auth"
|
|
30494
|
+
}),
|
|
30495
|
+
next: `Approve the link, then run: ${setupResumeCommand(input2.baseUrl, input2.scope)}`,
|
|
30496
|
+
render: {
|
|
30497
|
+
sections: [
|
|
30498
|
+
{
|
|
30499
|
+
title: "setup",
|
|
30500
|
+
lines: [
|
|
30501
|
+
"Authorization is waiting for browser approval.",
|
|
30502
|
+
...input2.authorizationUrl ? [input2.authorizationUrl] : []
|
|
30503
|
+
]
|
|
30504
|
+
}
|
|
30505
|
+
]
|
|
30506
|
+
}
|
|
30507
|
+
},
|
|
30508
|
+
{ json: input2.json }
|
|
30509
|
+
);
|
|
30510
|
+
return 0;
|
|
30511
|
+
}
|
|
30512
|
+
async function runSetupCommand(options) {
|
|
30513
|
+
let scope;
|
|
30514
|
+
let root;
|
|
30515
|
+
try {
|
|
30516
|
+
scope = normalizeScope2(options.scope);
|
|
30517
|
+
root = resolveScopeRoot(scope);
|
|
30518
|
+
} catch (error) {
|
|
30519
|
+
printCommandEnvelope(
|
|
30520
|
+
{
|
|
30521
|
+
ok: false,
|
|
30522
|
+
status: "failed",
|
|
30523
|
+
code: "INVALID_SETUP_SCOPE",
|
|
30524
|
+
exitCode: 2,
|
|
30525
|
+
message: error instanceof Error ? error.message : String(error),
|
|
30526
|
+
phases: {
|
|
30527
|
+
...initialSetupPhases(),
|
|
30528
|
+
cli: { status: "failed", code: "INVALID_SETUP_SCOPE" }
|
|
30529
|
+
},
|
|
30530
|
+
failedPhase: "cli"
|
|
30531
|
+
},
|
|
30532
|
+
{ json: options.json }
|
|
30533
|
+
);
|
|
30534
|
+
return 2;
|
|
30535
|
+
}
|
|
30536
|
+
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
30537
|
+
const previousState = readSetupState({ baseUrl, scope, root });
|
|
30538
|
+
const { resumed, phases } = selectSetupProgress(previousState);
|
|
30539
|
+
if (phases.cli.status !== "complete") {
|
|
30540
|
+
beginSetupPhase(phases, "cli");
|
|
30541
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30542
|
+
if (scope === "global") {
|
|
30543
|
+
const globalCli = inspectGlobalCliAvailability();
|
|
30544
|
+
if (!globalCli.ok) {
|
|
30545
|
+
const installedButUnreachable = Boolean(globalCli.persistentPath);
|
|
30546
|
+
const code = installedButUnreachable ? "GLOBAL_CLI_NOT_ON_PATH" : "GLOBAL_CLI_NOT_INSTALLED";
|
|
30547
|
+
return reportSetupPhaseFailure({
|
|
30548
|
+
baseUrl,
|
|
30549
|
+
scope,
|
|
30550
|
+
root,
|
|
30551
|
+
phases,
|
|
30552
|
+
phase: "cli",
|
|
30553
|
+
code,
|
|
30554
|
+
exitCode: 7,
|
|
30555
|
+
message: installedButUnreachable ? `The global Deepline executable is not reachable on PATH: ${globalCli.persistentPath}` : "No persistent global Deepline executable was found.",
|
|
30556
|
+
json: options.json,
|
|
30557
|
+
extra: {
|
|
30558
|
+
persistentPath: globalCli.persistentPath,
|
|
30559
|
+
fallback: "https://code.deepline.com/INSTALL.md"
|
|
30560
|
+
}
|
|
30561
|
+
});
|
|
30562
|
+
}
|
|
30563
|
+
}
|
|
30564
|
+
const conflict = inspectPathConflict();
|
|
30565
|
+
if (conflict) {
|
|
30566
|
+
return reportSetupPhaseFailure({
|
|
30567
|
+
baseUrl,
|
|
30568
|
+
scope,
|
|
30569
|
+
root,
|
|
30570
|
+
phases,
|
|
30571
|
+
phase: "cli",
|
|
30572
|
+
code: "PATH_CONFLICT",
|
|
30573
|
+
exitCode: 7,
|
|
30574
|
+
message: `An unknown executable named deepline is first on PATH: ${conflict}`,
|
|
30575
|
+
json: options.json,
|
|
30576
|
+
extra: { path: conflict }
|
|
30577
|
+
});
|
|
30578
|
+
}
|
|
30579
|
+
completeSetupPhase(phases, "cli", "available");
|
|
30580
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30581
|
+
}
|
|
30582
|
+
if (phases.cleanup.status !== "complete") {
|
|
30583
|
+
beginSetupPhase(phases, "cleanup");
|
|
30584
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30585
|
+
try {
|
|
30586
|
+
const removedLegacyPaths = removeKnownLegacyPaths(baseUrl);
|
|
30587
|
+
if (removedLegacyPaths.length > 0) {
|
|
30588
|
+
process.stderr.write(
|
|
30589
|
+
`Removed ${removedLegacyPaths.length} known legacy Deepline path(s).
|
|
30590
|
+
`
|
|
30591
|
+
);
|
|
30592
|
+
}
|
|
30593
|
+
completeSetupPhase(
|
|
30594
|
+
phases,
|
|
30595
|
+
"cleanup",
|
|
30596
|
+
removedLegacyPaths.length > 0 ? "removed_legacy_paths" : "clean"
|
|
30597
|
+
);
|
|
30598
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30599
|
+
} catch (error) {
|
|
30600
|
+
return reportSetupPhaseFailure({
|
|
30601
|
+
baseUrl,
|
|
30602
|
+
scope,
|
|
30603
|
+
root,
|
|
30604
|
+
phases,
|
|
30605
|
+
phase: "cleanup",
|
|
30606
|
+
code: "LEGACY_CLEANUP_FAILED",
|
|
30607
|
+
exitCode: 5,
|
|
30608
|
+
message: error instanceof Error ? error.message : String(error),
|
|
30609
|
+
json: options.json
|
|
30610
|
+
});
|
|
30611
|
+
}
|
|
30612
|
+
}
|
|
30613
|
+
let skillsPayload = null;
|
|
30614
|
+
if (phases.skills.status !== "complete") {
|
|
30615
|
+
beginSetupPhase(phases, "skills");
|
|
30616
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30617
|
+
process.stderr.write(`Installing Deepline skills (${scope})...
|
|
30618
|
+
`);
|
|
30619
|
+
const skills = await captureStdout2(
|
|
30620
|
+
() => runSkillsCommand({ scope, json: true })
|
|
30621
|
+
);
|
|
30622
|
+
skillsPayload = parseCapturedJson(skills.stdout);
|
|
30623
|
+
if (skills.exitCode !== 0) {
|
|
30624
|
+
return reportSetupPhaseFailure({
|
|
30625
|
+
baseUrl,
|
|
30626
|
+
scope,
|
|
30627
|
+
root,
|
|
30628
|
+
phases,
|
|
30629
|
+
phase: "skills",
|
|
30630
|
+
code: "SKILLS_INSTALL_FAILED",
|
|
30631
|
+
exitCode: skills.exitCode,
|
|
30632
|
+
message: typeof skillsPayload?.message === "string" ? skillsPayload.message : "Deepline skills could not be installed.",
|
|
30633
|
+
json: options.json,
|
|
30634
|
+
extra: { detail: skillsPayload }
|
|
30635
|
+
});
|
|
30636
|
+
}
|
|
30637
|
+
completeSetupPhase(
|
|
30638
|
+
phases,
|
|
30639
|
+
"skills",
|
|
30640
|
+
skillsPayload?.status === "current" ? "current" : "installed"
|
|
30641
|
+
);
|
|
30642
|
+
writeSetupState({
|
|
30643
|
+
baseUrl,
|
|
30644
|
+
scope,
|
|
30645
|
+
root,
|
|
30646
|
+
status: "skills_installed",
|
|
30647
|
+
phases
|
|
30648
|
+
});
|
|
30649
|
+
} else {
|
|
30650
|
+
skillsPayload = parseCapturedJson(
|
|
30651
|
+
safeRead(skillsStatePathForScope(baseUrl, scope, root))
|
|
30652
|
+
);
|
|
30653
|
+
}
|
|
30654
|
+
const authScope = authScopeForSetup(scope);
|
|
30655
|
+
beginSetupPhase(phases, "auth");
|
|
30656
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30657
|
+
let auth = await readAuthStatus(authScope);
|
|
30658
|
+
const initialAuthFailure = reportSetupAuthStatusFailure({
|
|
30659
|
+
auth,
|
|
30660
|
+
baseUrl,
|
|
30661
|
+
authScope,
|
|
30662
|
+
scope,
|
|
30663
|
+
root,
|
|
30664
|
+
phases,
|
|
30665
|
+
json: options.json
|
|
30666
|
+
});
|
|
30667
|
+
if (initialAuthFailure !== null) return initialAuthFailure;
|
|
30668
|
+
if (auth.payload?.connected !== true) {
|
|
30669
|
+
const pending = readPendingAuthClaim(baseUrl, authScope);
|
|
30670
|
+
if (pending) {
|
|
30671
|
+
process.stderr.write("Checking pending Deepline authorization...\n");
|
|
30672
|
+
const waited = await captureStdout2(
|
|
30673
|
+
() => handleWait(["--timeout", "1", "--auth-scope", authScope])
|
|
30674
|
+
);
|
|
30675
|
+
printCapturedAuthorizationUrl(waited.stdout);
|
|
30676
|
+
auth = await readAuthStatus(authScope);
|
|
30677
|
+
const resumedAuthFailure = reportSetupAuthStatusFailure({
|
|
30678
|
+
auth,
|
|
30679
|
+
baseUrl,
|
|
30680
|
+
authScope,
|
|
30681
|
+
scope,
|
|
30682
|
+
root,
|
|
30683
|
+
phases,
|
|
30684
|
+
json: options.json
|
|
30685
|
+
});
|
|
30686
|
+
if (resumedAuthFailure !== null) return resumedAuthFailure;
|
|
30687
|
+
if (auth.payload?.connected !== true) {
|
|
30688
|
+
const stillPending = readPendingAuthClaim(baseUrl, authScope);
|
|
30689
|
+
if (stillPending) {
|
|
30690
|
+
return pendingResult({
|
|
30691
|
+
baseUrl,
|
|
30692
|
+
scope,
|
|
30693
|
+
root,
|
|
30694
|
+
phases,
|
|
30695
|
+
authorizationUrl: stillPending.claimUrl,
|
|
30696
|
+
resumed,
|
|
30697
|
+
json: options.json
|
|
30698
|
+
});
|
|
30699
|
+
}
|
|
30700
|
+
}
|
|
30701
|
+
}
|
|
30702
|
+
}
|
|
30703
|
+
if (auth.payload?.connected !== true) {
|
|
30704
|
+
process.stderr.write("Starting Deepline browser authorization...\n");
|
|
30705
|
+
const agentRuntime = detectAgentRuntime();
|
|
30706
|
+
const agentLed = agentRuntime !== "unknown";
|
|
30707
|
+
const waitMode = options.json || agentLed || !process.stdin.isTTY ? "no" : "auto";
|
|
30708
|
+
const registered = await captureStdout2(
|
|
30709
|
+
() => handleRegister(["--wait", waitMode, "--auth-scope", authScope])
|
|
30710
|
+
);
|
|
30711
|
+
printCapturedAuthorizationUrl(registered.stdout);
|
|
30712
|
+
if (registered.exitCode !== 0) {
|
|
30713
|
+
return reportSetupPhaseFailure({
|
|
30714
|
+
baseUrl,
|
|
30715
|
+
scope,
|
|
30716
|
+
root,
|
|
30717
|
+
phases,
|
|
30718
|
+
phase: "auth",
|
|
30719
|
+
code: "AUTH_REGISTER_FAILED",
|
|
30720
|
+
exitCode: registered.exitCode,
|
|
30721
|
+
message: "Deepline browser authorization could not be started.",
|
|
30722
|
+
json: options.json,
|
|
30723
|
+
extra: {
|
|
30724
|
+
detail: parseCapturedJson(registered.stdout),
|
|
30725
|
+
authScope
|
|
30726
|
+
}
|
|
30727
|
+
});
|
|
30728
|
+
}
|
|
30729
|
+
auth = await readAuthStatus(authScope);
|
|
30730
|
+
const registeredAuthFailure = reportSetupAuthStatusFailure({
|
|
30731
|
+
auth,
|
|
30732
|
+
baseUrl,
|
|
30733
|
+
authScope,
|
|
30734
|
+
scope,
|
|
30735
|
+
root,
|
|
30736
|
+
phases,
|
|
30737
|
+
json: options.json
|
|
30738
|
+
});
|
|
30739
|
+
if (registeredAuthFailure !== null) return registeredAuthFailure;
|
|
30740
|
+
if (auth.payload?.connected !== true) {
|
|
30741
|
+
const pending = readPendingAuthClaim(baseUrl, authScope);
|
|
30742
|
+
return pendingResult({
|
|
30743
|
+
baseUrl,
|
|
30744
|
+
scope,
|
|
30745
|
+
root,
|
|
30746
|
+
phases,
|
|
30747
|
+
authorizationUrl: pending?.claimUrl ?? "",
|
|
30748
|
+
resumed,
|
|
30749
|
+
json: options.json
|
|
30750
|
+
});
|
|
30751
|
+
}
|
|
30752
|
+
}
|
|
30753
|
+
completeSetupPhase(phases, "auth", "connected");
|
|
30754
|
+
beginSetupPhase(phases, "verify");
|
|
30755
|
+
persistSetupProgress({ baseUrl, scope, root, phases });
|
|
30756
|
+
const assessment = buildDoctorAssessment({
|
|
30757
|
+
baseUrl,
|
|
30758
|
+
scope,
|
|
30759
|
+
root,
|
|
30760
|
+
authStatus: auth
|
|
30761
|
+
});
|
|
30762
|
+
const quickstart = setupQuickstartCommand(baseUrl);
|
|
30763
|
+
const doctorPayload = {
|
|
30764
|
+
ok: assessment.ok,
|
|
30765
|
+
status: assessment.ok ? "complete" : "failed",
|
|
30766
|
+
code: assessment.ok ? "DOCTOR_OK" : "DOCTOR_FAILED",
|
|
30767
|
+
exitCode: assessment.ok ? 0 : 7,
|
|
30768
|
+
checks: assessment.checks,
|
|
30769
|
+
next: assessment.ok ? quickstart : `deepline doctor --scope ${scope} --json`
|
|
30770
|
+
};
|
|
30771
|
+
if (!assessment.ok) {
|
|
30772
|
+
return reportSetupPhaseFailure({
|
|
30773
|
+
baseUrl,
|
|
30774
|
+
scope,
|
|
30775
|
+
root,
|
|
30776
|
+
phases,
|
|
30777
|
+
phase: "verify",
|
|
30778
|
+
code: "DOCTOR_FAILED",
|
|
30779
|
+
exitCode: 7,
|
|
30780
|
+
message: "Deepline setup verification found one or more failed checks.",
|
|
30781
|
+
json: options.json,
|
|
30782
|
+
extra: {
|
|
30783
|
+
doctor: doctorPayload,
|
|
30784
|
+
diagnostic: {
|
|
30785
|
+
command: `deepline doctor --scope ${scope} --json`
|
|
30786
|
+
}
|
|
30787
|
+
}
|
|
30788
|
+
});
|
|
30789
|
+
}
|
|
30790
|
+
completeSetupPhase(phases, "verify", "verified");
|
|
30791
|
+
const statePath = writeSetupState({
|
|
30792
|
+
baseUrl,
|
|
30793
|
+
scope,
|
|
30794
|
+
root,
|
|
30795
|
+
status: "complete",
|
|
30796
|
+
phases
|
|
30797
|
+
});
|
|
30798
|
+
const doctorChecks = asRecord2(doctorPayload?.checks);
|
|
30799
|
+
const apiCheck = asRecord2(doctorChecks?.api);
|
|
30800
|
+
printCommandEnvelope(
|
|
30801
|
+
{
|
|
30802
|
+
ok: true,
|
|
30803
|
+
status: "complete",
|
|
30804
|
+
complete: true,
|
|
30805
|
+
scope,
|
|
30806
|
+
cliVersion: SDK_VERSION,
|
|
30807
|
+
agents: skillsPayload?.agents ?? [],
|
|
30808
|
+
workspace: apiCheck?.workspace ?? null,
|
|
30809
|
+
rollbackCommand: rollbackCommand(scope, root),
|
|
30810
|
+
statePath,
|
|
30811
|
+
doctor: doctorPayload,
|
|
30812
|
+
phases,
|
|
30813
|
+
currentPhase: null,
|
|
30814
|
+
failedPhase: null,
|
|
30815
|
+
resumed,
|
|
30816
|
+
next: quickstart,
|
|
30817
|
+
render: {
|
|
30818
|
+
sections: [
|
|
30819
|
+
{
|
|
30820
|
+
title: "setup",
|
|
30821
|
+
lines: [
|
|
30822
|
+
"Deepline is installed and connected.",
|
|
30823
|
+
`Next: ${quickstart}`
|
|
30824
|
+
]
|
|
30825
|
+
}
|
|
30826
|
+
]
|
|
30827
|
+
}
|
|
30828
|
+
},
|
|
30829
|
+
{ json: options.json }
|
|
30830
|
+
);
|
|
30831
|
+
return 0;
|
|
30832
|
+
}
|
|
30833
|
+
function registerSetupCommands(program) {
|
|
30834
|
+
program.command("setup").description("Install skills, authenticate, and verify Deepline.").option("--scope <scope>", "Setup scope: global or local", "global").option("--json", "Emit one final JSON result envelope").addHelpText(
|
|
30835
|
+
"after",
|
|
30836
|
+
`
|
|
30837
|
+
Notes:
|
|
30838
|
+
Setup is idempotent. Bare setup resumes the first incomplete or failed phase.
|
|
30839
|
+
It installs skills before auth and does not run quickstart.
|
|
30840
|
+
JSON output includes phase status and an exact retry command.
|
|
30841
|
+
|
|
30842
|
+
Examples:
|
|
30843
|
+
deepline setup --json
|
|
30844
|
+
deepline setup --scope local --json
|
|
30845
|
+
`
|
|
30846
|
+
).action(async (options) => {
|
|
30847
|
+
process.exitCode = await runSetupCommand(options);
|
|
30848
|
+
});
|
|
30849
|
+
program.command("doctor").description("Verify CLI, skills, auth, workspace, and API connectivity.").option(
|
|
30850
|
+
"--scope <scope>",
|
|
30851
|
+
"Expected setup scope: global or local",
|
|
30852
|
+
"global"
|
|
30853
|
+
).option("--json", "Emit one JSON result envelope").addHelpText(
|
|
30854
|
+
"after",
|
|
30855
|
+
`
|
|
30856
|
+
Notes:
|
|
30857
|
+
Doctor is read-only and makes no paid provider calls. It reports repairs but
|
|
30858
|
+
does not apply them automatically.
|
|
30859
|
+
|
|
30860
|
+
Examples:
|
|
30861
|
+
deepline doctor --json
|
|
30862
|
+
deepline doctor --scope local --json
|
|
30863
|
+
`
|
|
30864
|
+
).action(async (options) => {
|
|
30865
|
+
process.exitCode = await runDoctorCommand(options);
|
|
30866
|
+
});
|
|
30867
|
+
}
|
|
30868
|
+
|
|
30869
|
+
// ../shared_libs/cli/command-compatibility.json
|
|
30870
|
+
var command_compatibility_default = {
|
|
30871
|
+
enrich: {
|
|
30872
|
+
family: "python",
|
|
30873
|
+
label: "a legacy Python CLI enrichment command",
|
|
30874
|
+
sdk_alternative: "Use `deepline plays ...` for durable workflows or `deepline tools execute ...` for one tool call."
|
|
30875
|
+
},
|
|
30876
|
+
session: {
|
|
30877
|
+
family: "python",
|
|
30878
|
+
label: "a legacy Python CLI session/playground command",
|
|
30879
|
+
sdk_alternative: "Use `deepline sessions send ...` or `deepline sessions render ...` for transcript workflows."
|
|
30880
|
+
},
|
|
30881
|
+
workflows: {
|
|
30882
|
+
family: "python",
|
|
30883
|
+
label: "a legacy Python CLI workflow command",
|
|
30884
|
+
sdk_alternative: "Use `deepline plays ...` in the SDK CLI."
|
|
30885
|
+
},
|
|
30886
|
+
events: {
|
|
30887
|
+
family: "python",
|
|
30888
|
+
label: "a legacy Python CLI event command"
|
|
30889
|
+
},
|
|
30890
|
+
plays: {
|
|
30891
|
+
family: "sdk",
|
|
30892
|
+
label: "an SDK CLI play command",
|
|
30893
|
+
python_alternative: "Use `deepline workflows ...` only for legacy workflows."
|
|
30894
|
+
},
|
|
30895
|
+
runs: {
|
|
30896
|
+
family: "sdk",
|
|
30897
|
+
label: "an SDK CLI run inspection command"
|
|
30898
|
+
},
|
|
30899
|
+
sessions: {
|
|
30900
|
+
family: "sdk",
|
|
30901
|
+
label: "an SDK CLI session transcript command"
|
|
30902
|
+
},
|
|
30903
|
+
health: {
|
|
30904
|
+
family: "sdk",
|
|
30905
|
+
label: "an SDK CLI health command"
|
|
30906
|
+
}
|
|
30907
|
+
};
|
|
30908
|
+
|
|
30909
|
+
// src/cli/command-compatibility.ts
|
|
30910
|
+
var COMMAND_COMPATIBILITY = command_compatibility_default;
|
|
30911
|
+
function cliFamilyLabel(family) {
|
|
30912
|
+
return family === "sdk" ? "SDK CLI" : "legacy Python CLI";
|
|
30913
|
+
}
|
|
30914
|
+
function commandCompatibilityHint(currentFamily, commandName, baseUrl) {
|
|
30915
|
+
const compatibility = COMMAND_COMPATIBILITY[commandName];
|
|
30916
|
+
if (!compatibility || compatibility.family === currentFamily) {
|
|
30917
|
+
return null;
|
|
30918
|
+
}
|
|
30919
|
+
const expectedFamily = compatibility.family;
|
|
30920
|
+
const currentLabel = cliFamilyLabel(currentFamily);
|
|
30921
|
+
const expectedLabel = cliFamilyLabel(expectedFamily);
|
|
30922
|
+
const lines = [
|
|
30923
|
+
"",
|
|
30924
|
+
"Command compatibility:",
|
|
30925
|
+
` \`deepline ${commandName}\` is ${compatibility.label}.`,
|
|
30926
|
+
` Current binary: ${currentLabel}. Required binary: ${expectedLabel}.`,
|
|
30927
|
+
" If this came from an agent skill, the installed skill likely targets the other Deepline CLI."
|
|
30928
|
+
];
|
|
30929
|
+
if (currentFamily === "sdk") {
|
|
30930
|
+
lines.push(
|
|
30931
|
+
"",
|
|
30932
|
+
" To stay on the SDK CLI, refresh the Deepline agent skills:",
|
|
30933
|
+
` ${skillsInstallCommand(baseUrl, DEFAULT_SDK_SKILL_NAMES)}`,
|
|
30934
|
+
" To use the legacy Python CLI instead:",
|
|
30935
|
+
` ${legacyPythonInstallCommand(baseUrl)}`,
|
|
30936
|
+
" `deepline update` updates this SDK CLI, but it will not switch CLI families."
|
|
30937
|
+
);
|
|
30938
|
+
if (compatibility.sdk_alternative) {
|
|
30939
|
+
lines.push(` SDK alternative: ${compatibility.sdk_alternative}`);
|
|
30940
|
+
}
|
|
30941
|
+
} else {
|
|
30942
|
+
lines.push(
|
|
30943
|
+
"",
|
|
30944
|
+
" To use SDK commands, install the SDK CLI and refresh Deepline agent skills:",
|
|
30945
|
+
` ${sdkNpmGlobalInstallCommand()}`,
|
|
30946
|
+
` ${skillsInstallCommand(baseUrl, DEFAULT_SDK_SKILL_NAMES)}`,
|
|
30947
|
+
" `deepline update` updates this Python CLI and its skills, but it will not switch CLI families."
|
|
30948
|
+
);
|
|
30949
|
+
if (compatibility.python_alternative) {
|
|
30950
|
+
lines.push(` Python alternative: ${compatibility.python_alternative}`);
|
|
30951
|
+
}
|
|
30952
|
+
}
|
|
30953
|
+
return lines.join("\n");
|
|
30954
|
+
}
|
|
30955
|
+
function unknownCommandNameFromMessage(message) {
|
|
30956
|
+
const match = message.match(/unknown command ['"]([^'"]+)['"]/i);
|
|
30957
|
+
const command = match?.[1]?.trim();
|
|
30958
|
+
return command ? command : null;
|
|
30959
|
+
}
|
|
30960
|
+
|
|
30961
|
+
// src/cli/self-update.ts
|
|
30962
|
+
var import_node_child_process6 = require("child_process");
|
|
30963
|
+
function envTruthy(name) {
|
|
30964
|
+
const value = process.env[name]?.trim().toLowerCase();
|
|
30965
|
+
return value === "1" || value === "true" || value === "yes";
|
|
30966
|
+
}
|
|
30967
|
+
function isCi() {
|
|
30968
|
+
return envTruthy("CI") || envTruthy("GITHUB_ACTIONS");
|
|
30969
|
+
}
|
|
30970
|
+
function shouldSkipSelfUpdate() {
|
|
30971
|
+
return envTruthy("DEEPLINE_SKIP_SELF_UPDATE") || envTruthy("DEEPLINE_NO_AUTO_UPDATE") || envTruthy("DEEPLINE_SKIP_SDK_AUTO_UPDATE") || envTruthy("DEEPLINE_DISABLE_AUTO_UPDATE") || isCi();
|
|
30972
|
+
}
|
|
30973
|
+
function parseSemver(version) {
|
|
30974
|
+
const trimmed = version?.trim();
|
|
30975
|
+
if (!trimmed) return null;
|
|
30976
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec(
|
|
30977
|
+
trimmed
|
|
30978
|
+
);
|
|
30979
|
+
if (!match) return null;
|
|
30980
|
+
return {
|
|
30981
|
+
major: Number(match[1]),
|
|
30982
|
+
minor: Number(match[2]),
|
|
30983
|
+
patch: Number(match[3]),
|
|
30984
|
+
prerelease: match[4] ?? ""
|
|
30985
|
+
};
|
|
30986
|
+
}
|
|
30987
|
+
function compareSemver(left, right) {
|
|
30988
|
+
const a = parseSemver(left);
|
|
30989
|
+
const b = parseSemver(right);
|
|
30990
|
+
if (!a || !b) {
|
|
30991
|
+
return left.localeCompare(right);
|
|
30992
|
+
}
|
|
30993
|
+
for (const key of ["major", "minor", "patch"]) {
|
|
30994
|
+
if (a[key] !== b[key]) return a[key] > b[key] ? 1 : -1;
|
|
30995
|
+
}
|
|
30996
|
+
if (a.prerelease === b.prerelease) return 0;
|
|
30997
|
+
if (!a.prerelease) return 1;
|
|
30998
|
+
if (!b.prerelease) return -1;
|
|
30999
|
+
return a.prerelease.localeCompare(b.prerelease);
|
|
31000
|
+
}
|
|
31001
|
+
function isDowngradeAutoUpdateResponse(response) {
|
|
31002
|
+
const target = response?.latest?.trim();
|
|
31003
|
+
const current = response?.current?.trim() || SDK_VERSION;
|
|
31004
|
+
if (!target) return false;
|
|
31005
|
+
return compareSemver(target, current) < 0;
|
|
31006
|
+
}
|
|
31007
|
+
function relaunchCurrentCommand(plan) {
|
|
31008
|
+
return new Promise((resolve15) => {
|
|
31009
|
+
const command = plan.kind === "python-sidecar" ? plan.sidecarPath : process.execPath;
|
|
31010
|
+
const args = plan.kind === "python-sidecar" ? process.argv.slice(2) : process.argv.slice(1);
|
|
31011
|
+
const child = (0, import_node_child_process6.spawn)(command, args, {
|
|
31012
|
+
stdio: "inherit",
|
|
31013
|
+
shell: process.platform === "win32",
|
|
31014
|
+
env: {
|
|
31015
|
+
...process.env,
|
|
31016
|
+
DEEPLINE_NO_AUTO_UPDATE: "1"
|
|
31017
|
+
}
|
|
31018
|
+
});
|
|
31019
|
+
child.on("error", (error) => {
|
|
31020
|
+
process.stderr.write(
|
|
31021
|
+
`Deepline SDK/CLI updated, but relaunch failed: ${error.message}
|
|
31022
|
+
`
|
|
31023
|
+
);
|
|
31024
|
+
resolve15(1);
|
|
31025
|
+
});
|
|
31026
|
+
child.on("close", (code) => resolve15(code ?? 1));
|
|
31027
|
+
});
|
|
31028
|
+
}
|
|
31029
|
+
async function maybeAutoUpdateAndRelaunch(response) {
|
|
31030
|
+
const autoUpdate = response?.auto_update;
|
|
31031
|
+
if (!response || !autoUpdate?.should_auto_update || shouldSkipSelfUpdate()) {
|
|
31032
|
+
return false;
|
|
31033
|
+
}
|
|
31034
|
+
if (isDowngradeAutoUpdateResponse(response)) {
|
|
31035
|
+
const target = response.latest;
|
|
31036
|
+
const current = response.current?.trim() || SDK_VERSION;
|
|
31037
|
+
process.stderr.write(
|
|
31038
|
+
`Deepline SDK/CLI auto-update refused: server advertised older ${target} than current ${current}. Continuing without mutating the CLI.
|
|
31039
|
+
`
|
|
31040
|
+
);
|
|
31041
|
+
return false;
|
|
31042
|
+
}
|
|
31043
|
+
const packageSpec = response.latest ? `deepline@${response.latest}` : void 0;
|
|
31044
|
+
const plan = resolveUpdatePlan({ packageSpec });
|
|
31045
|
+
if (plan.kind === "source") {
|
|
31046
|
+
return false;
|
|
31047
|
+
}
|
|
31048
|
+
const label = autoUpdate.reason === "rollback_forced" ? "has a server rollback pending and needs the latest rollback-aware CLI" : autoUpdate.reason === "deprecated" ? "is deprecated and will update automatically" : autoUpdate.required ? "requires an update" : "is more than the supported auto-update lag behind";
|
|
31049
|
+
process.stderr.write(
|
|
31050
|
+
`Deepline SDK/CLI ${label}; running ${plan.manualCommand}
|
|
31051
|
+
`
|
|
31052
|
+
);
|
|
31053
|
+
const updateResult = await runAutomaticUpdatePlan(plan);
|
|
31054
|
+
if (updateResult.status === "skipped_previous_failure") {
|
|
31055
|
+
return false;
|
|
31056
|
+
}
|
|
31057
|
+
if (updateResult.exitCode !== 0) {
|
|
31058
|
+
if (autoUpdate.required) {
|
|
31059
|
+
throw new Error(
|
|
31060
|
+
`Automatic Deepline SDK/CLI update failed with exit code ${updateResult.exitCode}. ${response.message}`
|
|
31061
|
+
);
|
|
31062
|
+
}
|
|
31063
|
+
process.stderr.write(
|
|
31064
|
+
`Deepline SDK/CLI auto-update failed with exit code ${updateResult.exitCode}; continuing with ${response.current ?? "current version"}.
|
|
31065
|
+
`
|
|
31066
|
+
);
|
|
31067
|
+
return false;
|
|
31068
|
+
}
|
|
31069
|
+
process.stderr.write("Deepline SDK/CLI updated; rerunning command.\n");
|
|
31070
|
+
const exitCode = await relaunchCurrentCommand(plan);
|
|
31071
|
+
process.exit(exitCode);
|
|
31072
|
+
return true;
|
|
31073
|
+
}
|
|
31074
|
+
|
|
31075
|
+
// src/cli/skills-sync.ts
|
|
31076
|
+
var import_node_child_process7 = require("child_process");
|
|
31077
|
+
var import_node_fs19 = require("fs");
|
|
31078
|
+
var import_node_path21 = require("path");
|
|
31079
|
+
var CHECK_TIMEOUT_MS2 = 3e3;
|
|
31080
|
+
var attemptedSync = false;
|
|
31081
|
+
function shouldSkipSkillsSync() {
|
|
31082
|
+
if (detectAgentRuntime() === "claude_cowork") {
|
|
31083
|
+
return true;
|
|
31084
|
+
}
|
|
31085
|
+
const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
|
|
31086
|
+
return value === "1" || value === "true" || value === "yes" || value === "on";
|
|
31087
|
+
}
|
|
31088
|
+
function activePluginSkillsDir() {
|
|
31089
|
+
const pluginMode = process.env.DEEPLINE_PLUGIN_MODE?.trim().toLowerCase();
|
|
31090
|
+
if (pluginMode !== "true" && pluginMode !== "1" && pluginMode !== "yes" && pluginMode !== "on") {
|
|
31091
|
+
return "";
|
|
31092
|
+
}
|
|
31093
|
+
const dir = process.env.DEEPLINE_PLUGIN_SKILLS_DIR?.trim() ?? "";
|
|
31094
|
+
return dir && (0, import_node_fs19.existsSync)(dir) ? dir : "";
|
|
31095
|
+
}
|
|
31096
|
+
function readPluginSkillsVersion() {
|
|
31097
|
+
const dir = activePluginSkillsDir();
|
|
31098
|
+
if (!dir) return "";
|
|
31099
|
+
try {
|
|
31100
|
+
return (0, import_node_fs19.readFileSync)((0, import_node_path21.join)(dir, ".version"), "utf-8").trim();
|
|
31101
|
+
} catch {
|
|
31102
|
+
return "";
|
|
31103
|
+
}
|
|
31104
|
+
}
|
|
31105
|
+
function sdkSkillsVersionPath(baseUrl) {
|
|
31106
|
+
return (0, import_node_path21.join)(sdkCliStateDirPath(baseUrl), "skills-version");
|
|
31107
|
+
}
|
|
31108
|
+
function legacySdkSkillsVersionPath(baseUrl) {
|
|
31109
|
+
return (0, import_node_path21.join)((0, import_node_path21.dirname)(sdkCliStateDirPath(baseUrl)), "sdk-skills", ".version");
|
|
31110
|
+
}
|
|
31111
|
+
function unavailableSkillsNoticePath(baseUrl) {
|
|
31112
|
+
return (0, import_node_path21.join)(sdkCliStateDirPath(baseUrl), "skills-sync-unavailable-version");
|
|
31113
|
+
}
|
|
31114
|
+
function readSdkSkillsLocalVersion(baseUrl) {
|
|
31115
|
+
const pluginVersion = readPluginSkillsVersion();
|
|
31116
|
+
if (pluginVersion) return pluginVersion;
|
|
31117
|
+
const path = (0, import_node_fs19.existsSync)(sdkSkillsVersionPath(baseUrl)) ? sdkSkillsVersionPath(baseUrl) : legacySdkSkillsVersionPath(baseUrl);
|
|
31118
|
+
if (!(0, import_node_fs19.existsSync)(path)) return "";
|
|
31119
|
+
try {
|
|
31120
|
+
return (0, import_node_fs19.readFileSync)(path, "utf-8").trim();
|
|
31121
|
+
} catch {
|
|
31122
|
+
return "";
|
|
31123
|
+
}
|
|
31124
|
+
}
|
|
31125
|
+
function writeLocalSkillsVersion(baseUrl, version) {
|
|
31126
|
+
const path = sdkSkillsVersionPath(baseUrl);
|
|
31127
|
+
(0, import_node_fs19.mkdirSync)((0, import_node_path21.dirname)(path), { recursive: true });
|
|
31128
|
+
(0, import_node_fs19.writeFileSync)(path, `${version}
|
|
31129
|
+
`, "utf-8");
|
|
31130
|
+
}
|
|
31131
|
+
function writeUnavailableSkillsNotice(baseUrl, remoteVersion, skillNames) {
|
|
31132
|
+
const path = unavailableSkillsNoticePath(baseUrl);
|
|
31133
|
+
try {
|
|
31134
|
+
if ((0, import_node_fs19.existsSync)(path) && (0, import_node_fs19.readFileSync)(path, "utf-8").trim() === remoteVersion) {
|
|
31135
|
+
return;
|
|
31136
|
+
}
|
|
31137
|
+
(0, import_node_fs19.mkdirSync)((0, import_node_path21.dirname)(path), { recursive: true });
|
|
31138
|
+
(0, import_node_fs19.writeFileSync)(path, `${remoteVersion}
|
|
31139
|
+
`, "utf-8");
|
|
31140
|
+
} catch {
|
|
31141
|
+
}
|
|
31142
|
+
const manualCommand = `npx ${buildSkillsInstallArgs(baseUrl, skillNames).join(" ")}`;
|
|
31143
|
+
writeSdkSkillsStatusLine(
|
|
31144
|
+
`Deepline agent skills are out of date, but neither \`bunx\` nor \`npx\` is available. Install Node.js/npm or Bun, then run:
|
|
31145
|
+
${manualCommand}`
|
|
31146
|
+
);
|
|
31147
|
+
}
|
|
31148
|
+
function clearUnavailableSkillsNotice(baseUrl) {
|
|
31149
|
+
try {
|
|
31150
|
+
(0, import_node_fs19.unlinkSync)(unavailableSkillsNoticePath(baseUrl));
|
|
31151
|
+
} catch {
|
|
31152
|
+
}
|
|
31153
|
+
}
|
|
31154
|
+
function sortedUniqueSkillNames(names) {
|
|
31155
|
+
return [...new Set(names.map((name) => name.trim()).filter(Boolean))].sort(
|
|
31156
|
+
(a, b) => a.localeCompare(b)
|
|
31157
|
+
);
|
|
31158
|
+
}
|
|
31159
|
+
async function fetchV1SkillNames(baseUrl) {
|
|
31160
|
+
const controller = new AbortController();
|
|
31161
|
+
const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS2);
|
|
31162
|
+
try {
|
|
31163
|
+
const response = await fetch(
|
|
31164
|
+
new URL("/.well-known/skills/index.json", baseUrl),
|
|
31165
|
+
{ signal: controller.signal }
|
|
31166
|
+
);
|
|
31167
|
+
if (!response.ok) return [];
|
|
31168
|
+
const data = await response.json().catch(() => null);
|
|
31169
|
+
const names = (data?.skills ?? []).filter((skill) => skill.install_surface === "v1").map((skill) => skill.name).filter(
|
|
31170
|
+
(name) => typeof name === "string" && name.length > 0
|
|
31171
|
+
);
|
|
31172
|
+
return sortedUniqueSkillNames(names);
|
|
31173
|
+
} catch {
|
|
31174
|
+
return [];
|
|
31175
|
+
} finally {
|
|
31176
|
+
clearTimeout(timeout);
|
|
31177
|
+
}
|
|
31178
|
+
}
|
|
31179
|
+
function buildSdkSkillNames(v1SkillNames) {
|
|
31180
|
+
return sortedUniqueSkillNames(v1SkillNames);
|
|
31181
|
+
}
|
|
31182
|
+
async function fetchSkillsUpdate(baseUrl, localVersion) {
|
|
31183
|
+
const controller = new AbortController();
|
|
31184
|
+
const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS2);
|
|
31185
|
+
try {
|
|
31186
|
+
const response = await fetch(new URL("/api/v2/cli/update-check", baseUrl), {
|
|
31187
|
+
method: "POST",
|
|
31188
|
+
headers: { "Content-Type": "application/json" },
|
|
31189
|
+
body: JSON.stringify({
|
|
31190
|
+
skills: {
|
|
31191
|
+
version: localVersion
|
|
31192
|
+
}
|
|
31193
|
+
}),
|
|
31194
|
+
signal: controller.signal
|
|
31195
|
+
});
|
|
31196
|
+
if (!response.ok) return null;
|
|
31197
|
+
const data = await response.json().catch(() => null);
|
|
31198
|
+
const skills = data?.skills;
|
|
31199
|
+
if (!skills) return null;
|
|
31200
|
+
return {
|
|
31201
|
+
needsUpdate: skills.needs_update === true,
|
|
31202
|
+
remoteVersion: typeof skills.remote?.version === "string" ? skills.remote.version.trim() : ""
|
|
31203
|
+
};
|
|
31204
|
+
} catch {
|
|
31205
|
+
return null;
|
|
31206
|
+
} finally {
|
|
31207
|
+
clearTimeout(timeout);
|
|
31208
|
+
}
|
|
31209
|
+
}
|
|
31210
|
+
function buildSkillsInstallArgs(baseUrl, skillNames = DEFAULT_SDK_SKILL_NAMES) {
|
|
31211
|
+
return buildSkillsAddArgs(baseUrl, sortedUniqueSkillNames(skillNames));
|
|
31212
|
+
}
|
|
31213
|
+
function buildBunxSkillsInstallArgs(baseUrl, skillNames) {
|
|
31214
|
+
return buildSkillsAddArgs(baseUrl, sortedUniqueSkillNames(skillNames), {
|
|
31215
|
+
firstArg: "--bun"
|
|
31216
|
+
});
|
|
31217
|
+
}
|
|
31218
|
+
function hasCommand(command) {
|
|
31219
|
+
const result = (0, import_node_child_process7.spawnSync)(command, ["--version"], {
|
|
31220
|
+
stdio: "ignore",
|
|
31221
|
+
shell: process.platform === "win32"
|
|
31222
|
+
});
|
|
31223
|
+
return result.status === 0;
|
|
31224
|
+
}
|
|
31225
|
+
function shellQuote6(arg) {
|
|
31226
|
+
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
31227
|
+
}
|
|
31228
|
+
function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NAMES) {
|
|
31229
|
+
const commands = [];
|
|
31230
|
+
if (hasCommand("bunx")) {
|
|
31231
|
+
const bunxArgs = buildBunxSkillsInstallArgs(baseUrl, skillNames);
|
|
31232
|
+
commands.push({
|
|
31233
|
+
command: "bunx",
|
|
31234
|
+
args: bunxArgs,
|
|
31235
|
+
manualCommand: `bunx ${bunxArgs.map(shellQuote6).join(" ")}`
|
|
31236
|
+
});
|
|
31237
|
+
}
|
|
31238
|
+
if (hasCommand("npx")) {
|
|
31239
|
+
const npxArgs = buildSkillsInstallArgs(baseUrl, skillNames);
|
|
31240
|
+
commands.push({
|
|
31241
|
+
command: "npx",
|
|
31242
|
+
args: npxArgs,
|
|
31243
|
+
manualCommand: `npx ${npxArgs.map(shellQuote6).join(" ")}`
|
|
31244
|
+
});
|
|
31245
|
+
}
|
|
31246
|
+
return commands;
|
|
31247
|
+
}
|
|
31248
|
+
function runOneSkillsInstall(install) {
|
|
31249
|
+
return new Promise((resolve15) => {
|
|
31250
|
+
const child = (0, import_node_child_process7.spawn)(install.command, install.args, {
|
|
31251
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
31252
|
+
env: process.env
|
|
31253
|
+
});
|
|
31254
|
+
let stderr = "";
|
|
31255
|
+
child.stderr.on("data", (chunk) => {
|
|
31256
|
+
stderr += chunk.toString("utf-8");
|
|
31257
|
+
});
|
|
31258
|
+
child.on("error", (error) => {
|
|
31259
|
+
resolve15({
|
|
31260
|
+
ok: false,
|
|
31261
|
+
detail: `failed to start ${install.command}: ${error.message}`,
|
|
31262
|
+
manualCommand: install.manualCommand
|
|
31263
|
+
});
|
|
31264
|
+
});
|
|
31265
|
+
child.on("close", (code) => {
|
|
31266
|
+
if (code === 0) {
|
|
31267
|
+
resolve15({ ok: true, detail: "", manualCommand: install.manualCommand });
|
|
31268
|
+
return;
|
|
31269
|
+
}
|
|
31270
|
+
const detail = stderr.trim();
|
|
31271
|
+
resolve15({
|
|
31272
|
+
ok: false,
|
|
31273
|
+
detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
|
|
31274
|
+
manualCommand: install.manualCommand
|
|
31275
|
+
});
|
|
31276
|
+
});
|
|
31277
|
+
});
|
|
31278
|
+
}
|
|
31279
|
+
async function runSkillsInstall(installs) {
|
|
31280
|
+
const failures = [];
|
|
31281
|
+
for (const install of installs) {
|
|
31282
|
+
const result = await runOneSkillsInstall(install);
|
|
31283
|
+
if (result.ok) return true;
|
|
31284
|
+
failures.push(result);
|
|
31285
|
+
}
|
|
31286
|
+
const details = failures.map((failure) => failure.detail).filter(Boolean).join("\n");
|
|
31287
|
+
const manualCommand = failures.at(-1)?.manualCommand;
|
|
31288
|
+
process.stderr.write(
|
|
31289
|
+
`SDK skills sync failed${details ? `:
|
|
31290
|
+
${details}` : ""}
|
|
31291
|
+
` + (manualCommand ? `Run manually: ${manualCommand}
|
|
31292
|
+
` : "")
|
|
31293
|
+
);
|
|
31294
|
+
return false;
|
|
31295
|
+
}
|
|
31296
|
+
function runLegacySkillsCleanup() {
|
|
31297
|
+
const candidates = hasCommand("bunx") ? [
|
|
31298
|
+
{
|
|
31299
|
+
command: "bunx",
|
|
31300
|
+
args: [
|
|
31301
|
+
"--bun",
|
|
31302
|
+
"skills",
|
|
31303
|
+
"remove",
|
|
31304
|
+
"--global",
|
|
31305
|
+
"-y",
|
|
31306
|
+
...LEGACY_SKILL_NAMES_TO_REMOVE
|
|
31307
|
+
]
|
|
31308
|
+
},
|
|
31309
|
+
{
|
|
31310
|
+
command: "npx",
|
|
31311
|
+
args: [
|
|
31312
|
+
"--yes",
|
|
31313
|
+
"skills",
|
|
31314
|
+
"remove",
|
|
31315
|
+
"--global",
|
|
31316
|
+
"-y",
|
|
31317
|
+
...LEGACY_SKILL_NAMES_TO_REMOVE
|
|
31318
|
+
]
|
|
31319
|
+
}
|
|
31320
|
+
] : [
|
|
31321
|
+
{
|
|
31322
|
+
command: "npx",
|
|
31323
|
+
args: [
|
|
31324
|
+
"--yes",
|
|
31325
|
+
"skills",
|
|
31326
|
+
"remove",
|
|
31327
|
+
"--global",
|
|
31328
|
+
"-y",
|
|
31329
|
+
...LEGACY_SKILL_NAMES_TO_REMOVE
|
|
31330
|
+
]
|
|
31331
|
+
}
|
|
31332
|
+
];
|
|
31333
|
+
for (const candidate of candidates) {
|
|
31334
|
+
const result = (0, import_node_child_process7.spawnSync)(candidate.command, candidate.args, {
|
|
31335
|
+
stdio: "ignore",
|
|
31336
|
+
env: process.env,
|
|
31337
|
+
shell: process.platform === "win32"
|
|
31338
|
+
});
|
|
31339
|
+
if (result.status === 0) return;
|
|
31340
|
+
}
|
|
31341
|
+
}
|
|
31342
|
+
function writeSdkSkillsStatusLine(line) {
|
|
31343
|
+
const progress = getActiveCliProgress();
|
|
31344
|
+
if (progress) {
|
|
31345
|
+
progress.writeLine(line);
|
|
31346
|
+
return;
|
|
31347
|
+
}
|
|
31348
|
+
process.stderr.write(`${line}
|
|
31349
|
+
`);
|
|
31350
|
+
}
|
|
31351
|
+
async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
|
|
31352
|
+
if (attemptedSync || shouldSkipSkillsSync()) return;
|
|
31353
|
+
attemptedSync = true;
|
|
31354
|
+
const usingPluginSkills = Boolean(activePluginSkillsDir());
|
|
31355
|
+
if (usingPluginSkills) {
|
|
31356
|
+
return;
|
|
31357
|
+
}
|
|
31358
|
+
const localVersion = readSdkSkillsLocalVersion(baseUrl);
|
|
31359
|
+
const update = options.update === void 0 ? await fetchSkillsUpdate(baseUrl, localVersion) : options.update ? {
|
|
31360
|
+
needsUpdate: options.update.needs_update,
|
|
31361
|
+
remoteVersion: options.update.remote.version
|
|
31362
|
+
} : null;
|
|
31363
|
+
if (!update?.needsUpdate || !update.remoteVersion) {
|
|
31364
|
+
return;
|
|
31365
|
+
}
|
|
31366
|
+
const remoteSkillNames = await fetchV1SkillNames(baseUrl);
|
|
31367
|
+
const skillNames = buildSdkSkillNames(
|
|
31368
|
+
remoteSkillNames.length > 0 ? remoteSkillNames : DEFAULT_SDK_SKILL_NAMES
|
|
31369
|
+
);
|
|
31370
|
+
if (skillNames.length === 0) return;
|
|
31371
|
+
const installs = resolveSkillsInstallCommands(baseUrl, skillNames);
|
|
31372
|
+
if (installs.length === 0) {
|
|
31373
|
+
writeUnavailableSkillsNotice(baseUrl, update.remoteVersion, skillNames);
|
|
31374
|
+
return;
|
|
31375
|
+
}
|
|
31376
|
+
writeSdkSkillsStatusLine("Deepline skills changed; syncing agent skills...");
|
|
31377
|
+
const installed = await runSkillsInstall(installs);
|
|
31378
|
+
if (!installed) return;
|
|
31379
|
+
runLegacySkillsCleanup();
|
|
31380
|
+
writeLocalSkillsVersion(baseUrl, update.remoteVersion);
|
|
31381
|
+
clearUnavailableSkillsNotice(baseUrl);
|
|
31382
|
+
writeSdkSkillsStatusLine("Deepline agent skills are up to date.");
|
|
31383
|
+
}
|
|
31384
|
+
|
|
31385
|
+
// src/cli/failure-reporting.ts
|
|
31386
|
+
var import_node_os16 = require("os");
|
|
29924
31387
|
var FAILURE_REPORT_DISABLE_ENV = "DEEPLINE_DISABLE_FAILURE_REPORTING";
|
|
29925
31388
|
var REPORT_FAILURE_TIMEOUT_MS = 1e4;
|
|
29926
31389
|
var MAX_FAILURE_TEXT_CHARS = 4e3;
|
|
@@ -30022,12 +31485,12 @@ function isNetworkFailure(error) {
|
|
|
30022
31485
|
}
|
|
30023
31486
|
function buildEnvironmentContext() {
|
|
30024
31487
|
const context = {
|
|
30025
|
-
os: (0,
|
|
30026
|
-
os_release: (0,
|
|
30027
|
-
platform: `${(0,
|
|
31488
|
+
os: (0, import_node_os16.platform)(),
|
|
31489
|
+
os_release: (0, import_node_os16.release)(),
|
|
31490
|
+
platform: `${(0, import_node_os16.platform)()}-${(0, import_node_os16.release)()}-${process.arch}`,
|
|
30028
31491
|
node_version: process.version,
|
|
30029
31492
|
runtime: "Node.js",
|
|
30030
|
-
hostname: (0,
|
|
31493
|
+
hostname: (0, import_node_os16.hostname)(),
|
|
30031
31494
|
agent_runtime: detectAgentRuntime()
|
|
30032
31495
|
};
|
|
30033
31496
|
for (const key of ["CLAUDE_CODE_REMOTE", "DEEPLINE_PLUGIN_MODE"]) {
|
|
@@ -30220,8 +31683,8 @@ function topLevelCommandKnown(program, commandName) {
|
|
|
30220
31683
|
);
|
|
30221
31684
|
}
|
|
30222
31685
|
async function runPlayRunnerHealthCheck() {
|
|
30223
|
-
const dir = await (0, import_promises6.mkdtemp)((0,
|
|
30224
|
-
const file = (0,
|
|
31686
|
+
const dir = await (0, import_promises6.mkdtemp)((0, import_node_path22.join)((0, import_node_os17.tmpdir)(), "deepline-health-play-"));
|
|
31687
|
+
const file = (0, import_node_path22.join)(dir, "health-check.play.ts");
|
|
30225
31688
|
try {
|
|
30226
31689
|
await (0, import_promises6.writeFile)(
|
|
30227
31690
|
file,
|
|
@@ -30439,7 +31902,7 @@ Exit codes:
|
|
|
30439
31902
|
`
|
|
30440
31903
|
);
|
|
30441
31904
|
program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
30442
|
-
if (actionCommand.name() === "version" || actionCommand.name() === "update" || actionCommand.name() === "switch" || isLegacyNoopInvocation()) {
|
|
31905
|
+
if (actionCommand.name() === "version" || actionCommand.name() === "update" || actionCommand.name() === "switch" || actionCommand.name() === "setup" || actionCommand.name() === "skills" || actionCommand.name() === "doctor" || isLegacyNoopInvocation()) {
|
|
30443
31906
|
return;
|
|
30444
31907
|
}
|
|
30445
31908
|
if (printStartupPhase) {
|
|
@@ -30511,6 +31974,8 @@ Exit codes:
|
|
|
30511
31974
|
registerFeedbackCommands(program);
|
|
30512
31975
|
registerLegacyNoopCommands(program);
|
|
30513
31976
|
registerUpdateCommand(program);
|
|
31977
|
+
registerSkillsCommand(program);
|
|
31978
|
+
registerSetupCommands(program);
|
|
30514
31979
|
registerQuickstartCommands(program);
|
|
30515
31980
|
registerSwitchCommands(program);
|
|
30516
31981
|
program.command("preflight").description("Run compact health, auth, and Deepline billing checks.").option("--json", "Force JSON output.").addHelpText(
|