@dosu/cli 0.67.1 → 0.68.0
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/README.md +1 -1
- package/bin/dosu.js +515 -340
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -961,6 +961,10 @@ function mcpHeaders(apiKey) {
|
|
|
961
961
|
}
|
|
962
962
|
return { "X-Dosu-API-Key": apiKey };
|
|
963
963
|
}
|
|
964
|
+
function npxRemoteEntry(url, apiKey, npx, path) {
|
|
965
|
+
const remote = mcpRemoteServer(url, apiKey);
|
|
966
|
+
return { command: npx, args: remote.args, env: { PATH: path, ...remote.env } };
|
|
967
|
+
}
|
|
964
968
|
function mcpRemoteServer(url, apiKey) {
|
|
965
969
|
const env = {};
|
|
966
970
|
const headerArgs = Object.entries(mcpHeaders(apiKey)).flatMap(([key, value]) => {
|
|
@@ -1081,6 +1085,12 @@ function isJSONKeyConfigured(configPath, topLevelKey) {
|
|
|
1081
1085
|
return false;
|
|
1082
1086
|
return "dosu" in section;
|
|
1083
1087
|
}
|
|
1088
|
+
function readJSONServer(configPath, topLevelKey) {
|
|
1089
|
+
const section = loadJSONConfig(configPath)[topLevelKey];
|
|
1090
|
+
if (typeof section !== "object" || section === null)
|
|
1091
|
+
return;
|
|
1092
|
+
return section.dosu;
|
|
1093
|
+
}
|
|
1084
1094
|
function installJSONServer(configPath, topKey, server) {
|
|
1085
1095
|
const jsonCfg = readJSONConfig(configPath);
|
|
1086
1096
|
let section = jsonCfg[topKey];
|
|
@@ -1118,7 +1128,7 @@ function isNpxInvocation(channel = INSTALL_CHANNEL, env = process.env) {
|
|
|
1118
1128
|
function getVersionString() {
|
|
1119
1129
|
return `v${VERSION}`;
|
|
1120
1130
|
}
|
|
1121
|
-
var VERSION = "0.
|
|
1131
|
+
var VERSION = "0.68.0", INSTALL_CHANNEL = "npm";
|
|
1122
1132
|
|
|
1123
1133
|
// src/debug/logger.ts
|
|
1124
1134
|
import {
|
|
@@ -14323,7 +14333,7 @@ var init_conflicts = __esm(() => {
|
|
|
14323
14333
|
});
|
|
14324
14334
|
|
|
14325
14335
|
// src/telemetry/debug-id.ts
|
|
14326
|
-
var BUNDLE_DEBUG_ID_PLACEHOLDER = "
|
|
14336
|
+
var BUNDLE_DEBUG_ID_PLACEHOLDER = "2a77eea3-ffbe-b0f0-6475-6e2164756e21";
|
|
14327
14337
|
|
|
14328
14338
|
// src/telemetry/telemetry.ts
|
|
14329
14339
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -62482,6 +62492,68 @@ var init_topics = __esm(() => {
|
|
|
62482
62492
|
import_picocolors31 = __toESM(require_picocolors(), 1);
|
|
62483
62493
|
});
|
|
62484
62494
|
|
|
62495
|
+
// src/mcp/shape.ts
|
|
62496
|
+
function shapeEndpoint(cfg) {
|
|
62497
|
+
const url = cfg?.mode === MODE_OSS ? mcpEndpoint(cfg) : mcpURL(ANY);
|
|
62498
|
+
return ANY + url.slice(getBackendURL().length);
|
|
62499
|
+
}
|
|
62500
|
+
function escapeRegExp(text) {
|
|
62501
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
62502
|
+
}
|
|
62503
|
+
function hasShape(expected, actual) {
|
|
62504
|
+
if (typeof expected === "string") {
|
|
62505
|
+
if (typeof actual !== "string")
|
|
62506
|
+
return false;
|
|
62507
|
+
if (!expected.includes(ANY))
|
|
62508
|
+
return expected === actual;
|
|
62509
|
+
const pattern = expected.split(ANY).map(escapeRegExp).join("[\\s\\S]*");
|
|
62510
|
+
return new RegExp(`^${pattern}$`).test(actual);
|
|
62511
|
+
}
|
|
62512
|
+
if (Array.isArray(expected)) {
|
|
62513
|
+
return Array.isArray(actual) && actual.length === expected.length && expected.every((item, i) => hasShape(item, actual[i]));
|
|
62514
|
+
}
|
|
62515
|
+
if (typeof expected === "object" && expected !== null) {
|
|
62516
|
+
if (typeof actual !== "object" || actual === null || Array.isArray(actual))
|
|
62517
|
+
return false;
|
|
62518
|
+
const expectedKeys = Object.keys(expected);
|
|
62519
|
+
const actualRecord = actual;
|
|
62520
|
+
return expectedKeys.length === Object.keys(actualRecord).length && expectedKeys.every((key) => (key in actualRecord) && hasShape(expected[key], actualRecord[key]));
|
|
62521
|
+
}
|
|
62522
|
+
return expected === actual;
|
|
62523
|
+
}
|
|
62524
|
+
function isUserChoiceKey(key) {
|
|
62525
|
+
return USER_CHOICE_KEYS.has(key);
|
|
62526
|
+
}
|
|
62527
|
+
function withoutUserChoices(entry) {
|
|
62528
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry))
|
|
62529
|
+
return entry;
|
|
62530
|
+
return Object.fromEntries(Object.entries(entry).filter(([key]) => !isUserChoiceKey(key)));
|
|
62531
|
+
}
|
|
62532
|
+
function entryHasShape(expected, actual) {
|
|
62533
|
+
return hasShape(withoutUserChoices(expected), withoutUserChoices(actual));
|
|
62534
|
+
}
|
|
62535
|
+
var ANY = "\x00any\x00", USER_CHOICE_KEYS;
|
|
62536
|
+
var init_shape = __esm(() => {
|
|
62537
|
+
init_config();
|
|
62538
|
+
init_config_helpers();
|
|
62539
|
+
USER_CHOICE_KEYS = new Set([
|
|
62540
|
+
"disabled",
|
|
62541
|
+
"enabled",
|
|
62542
|
+
"autoApprove",
|
|
62543
|
+
"disabledTools",
|
|
62544
|
+
"timeout",
|
|
62545
|
+
"trust",
|
|
62546
|
+
"includeTools",
|
|
62547
|
+
"excludeTools",
|
|
62548
|
+
"enabled_tools",
|
|
62549
|
+
"disabled_tools",
|
|
62550
|
+
"default_tools_approval_mode",
|
|
62551
|
+
"required",
|
|
62552
|
+
"startup_timeout_sec",
|
|
62553
|
+
"tool_timeout_sec"
|
|
62554
|
+
]);
|
|
62555
|
+
});
|
|
62556
|
+
|
|
62485
62557
|
// src/mcp/providers/base.ts
|
|
62486
62558
|
function createJSONProvider(opts) {
|
|
62487
62559
|
const buildServer = opts.buildServer ?? defaultBuildServer;
|
|
@@ -62494,6 +62566,7 @@ function createJSONProvider(opts) {
|
|
|
62494
62566
|
isInstalled: () => isInstalled(opts.paths),
|
|
62495
62567
|
globalConfigPath: () => expandHome(opts.globalPath),
|
|
62496
62568
|
isConfigured: () => isJSONKeyConfigured(expandHome(opts.globalPath), opts.topKey),
|
|
62569
|
+
isCurrent: (cfg) => entryHasShape(buildServer({ url: shapeEndpoint(cfg), headers: mcpHeaders(ANY) }), readJSONServer(expandHome(opts.globalPath), opts.topKey)),
|
|
62497
62570
|
install(cfg, global2) {
|
|
62498
62571
|
const endpoint = {
|
|
62499
62572
|
url: mcpEndpoint(cfg),
|
|
@@ -62507,7 +62580,7 @@ function createJSONProvider(opts) {
|
|
|
62507
62580
|
} else {
|
|
62508
62581
|
throw new Error(`${opts.providerName} does not support local installation`);
|
|
62509
62582
|
}
|
|
62510
|
-
installJSONServer(configPath, opts.topKey, buildServer(endpoint
|
|
62583
|
+
installJSONServer(configPath, opts.topKey, buildServer(endpoint));
|
|
62511
62584
|
},
|
|
62512
62585
|
remove(global2) {
|
|
62513
62586
|
let configPath;
|
|
@@ -62530,6 +62603,7 @@ var defaultBuildServer = ({ url, headers }) => ({
|
|
|
62530
62603
|
var init_base = __esm(() => {
|
|
62531
62604
|
init_config_helpers();
|
|
62532
62605
|
init_detect();
|
|
62606
|
+
init_shape();
|
|
62533
62607
|
});
|
|
62534
62608
|
|
|
62535
62609
|
// src/mcp/providers/antigravity.ts
|
|
@@ -62581,17 +62655,13 @@ var ClaudeDesktopProvider = () => ({
|
|
|
62581
62655
|
isInstalled: () => isInstalled([join26(appSupportDir(), "Claude")]),
|
|
62582
62656
|
globalConfigPath: () => configPath(),
|
|
62583
62657
|
isConfigured: () => isJSONKeyConfigured(configPath(), "mcpServers"),
|
|
62658
|
+
isCurrent: (cfg) => entryHasShape(npxRemoteEntry(shapeEndpoint(cfg), ANY, ANY, npxPathEnv(join26(ANY, "npx"))), readJSONServer(configPath(), "mcpServers")),
|
|
62584
62659
|
install(cfg, global2) {
|
|
62585
62660
|
if (!global2)
|
|
62586
62661
|
throw new Error("Claude Desktop does not support local installation");
|
|
62587
62662
|
const url = mcpEndpoint(cfg);
|
|
62588
62663
|
const npx = findNpx();
|
|
62589
|
-
|
|
62590
|
-
installJSONServer(configPath(), "mcpServers", {
|
|
62591
|
-
command: npx,
|
|
62592
|
-
args: remote.args,
|
|
62593
|
-
env: { PATH: npxPathEnv(npx), ...remote.env }
|
|
62594
|
-
});
|
|
62664
|
+
installJSONServer(configPath(), "mcpServers", npxRemoteEntry(url, cfg.active_account?.target?.api_key, npx, npxPathEnv(npx)));
|
|
62595
62665
|
},
|
|
62596
62666
|
remove(global2) {
|
|
62597
62667
|
if (!global2)
|
|
@@ -62602,6 +62672,7 @@ var ClaudeDesktopProvider = () => ({
|
|
|
62602
62672
|
var init_claude_desktop = __esm(() => {
|
|
62603
62673
|
init_config_helpers();
|
|
62604
62674
|
init_detect();
|
|
62675
|
+
init_shape();
|
|
62605
62676
|
});
|
|
62606
62677
|
|
|
62607
62678
|
// src/mcp/providers/cline.ts
|
|
@@ -62655,7 +62726,7 @@ var init_cline_cli = __esm(() => {
|
|
|
62655
62726
|
import { existsSync as existsSync22, readFileSync as readFileSync22 } from "node:fs";
|
|
62656
62727
|
import { dirname as dirname11, join as join29 } from "node:path";
|
|
62657
62728
|
function codexHome3() {
|
|
62658
|
-
return process.env.CODEX_HOME
|
|
62729
|
+
return process.env.CODEX_HOME || expandHome("~/.codex");
|
|
62659
62730
|
}
|
|
62660
62731
|
function getConfigPath2(global2) {
|
|
62661
62732
|
if (global2)
|
|
@@ -62673,25 +62744,134 @@ function writeTOML(path, content) {
|
|
|
62673
62744
|
function tomlString(value) {
|
|
62674
62745
|
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
|
|
62675
62746
|
}
|
|
62747
|
+
function tomlValue(value) {
|
|
62748
|
+
return Array.isArray(value) ? `[${value.map(tomlString).join(", ")}]` : tomlString(value);
|
|
62749
|
+
}
|
|
62750
|
+
function dosuEntry(url, apiKey, npx, path) {
|
|
62751
|
+
return { ...npxRemoteEntry(url, apiKey, npx, path), omit_tools_from: ["deferred"] };
|
|
62752
|
+
}
|
|
62753
|
+
function isUserKey(key) {
|
|
62754
|
+
return isUserChoiceKey(key) || key === "tools" || key.startsWith("tools.");
|
|
62755
|
+
}
|
|
62756
|
+
function isUserTable(name) {
|
|
62757
|
+
return name === `${DOSU_TABLE}.tools` || name.startsWith(`${DOSU_TABLE}.tools.`);
|
|
62758
|
+
}
|
|
62759
|
+
function renderDosuEntry(entry, kept) {
|
|
62760
|
+
const tables = [[DOSU_TABLE, []]];
|
|
62761
|
+
for (const [key, value] of Object.entries(entry)) {
|
|
62762
|
+
if (typeof value === "string" || Array.isArray(value)) {
|
|
62763
|
+
tables[0][1].push(`${key} = ${tomlValue(value)}`);
|
|
62764
|
+
} else {
|
|
62765
|
+
const lines = Object.entries(value).map(([k, v]) => `${k} = ${tomlValue(v)}`);
|
|
62766
|
+
tables.push([`${DOSU_TABLE}.${key}`, lines]);
|
|
62767
|
+
}
|
|
62768
|
+
}
|
|
62769
|
+
tables[0][1].push(...kept.root);
|
|
62770
|
+
return tables.map(([name, lines]) => `
|
|
62771
|
+
[${name}]
|
|
62772
|
+
${lines.join(`
|
|
62773
|
+
`)}
|
|
62774
|
+
`).join("") + kept.tables.map((table) => `
|
|
62775
|
+
${table}
|
|
62776
|
+
`).join("");
|
|
62777
|
+
}
|
|
62778
|
+
function openBrackets(text) {
|
|
62779
|
+
let depth = 0;
|
|
62780
|
+
let quote = null;
|
|
62781
|
+
for (let i = 0;i < text.length; i++) {
|
|
62782
|
+
const c = text[i];
|
|
62783
|
+
if (quote) {
|
|
62784
|
+
if (c === "\\" && quote === '"')
|
|
62785
|
+
i++;
|
|
62786
|
+
else if (c === quote)
|
|
62787
|
+
quote = null;
|
|
62788
|
+
} else if (c === '"' || c === "'")
|
|
62789
|
+
quote = c;
|
|
62790
|
+
else if (c === "#")
|
|
62791
|
+
break;
|
|
62792
|
+
else if (c === "[" || c === "{")
|
|
62793
|
+
depth++;
|
|
62794
|
+
else if (c === "]" || c === "}")
|
|
62795
|
+
depth--;
|
|
62796
|
+
}
|
|
62797
|
+
return depth;
|
|
62798
|
+
}
|
|
62799
|
+
function dosuTables(content) {
|
|
62800
|
+
const tables = [];
|
|
62801
|
+
let table;
|
|
62802
|
+
let open;
|
|
62803
|
+
let depth = 0;
|
|
62804
|
+
for (const line of content.split(`
|
|
62805
|
+
`)) {
|
|
62806
|
+
const name = sectionName(line);
|
|
62807
|
+
if (name !== null) {
|
|
62808
|
+
open = undefined;
|
|
62809
|
+
table = isDosuSection(name) ? { name, header: line.trim(), statements: [] } : undefined;
|
|
62810
|
+
if (table)
|
|
62811
|
+
tables.push(table);
|
|
62812
|
+
continue;
|
|
62813
|
+
}
|
|
62814
|
+
if (open && depth > 0) {
|
|
62815
|
+
open.value += `
|
|
62816
|
+
${line}`;
|
|
62817
|
+
open.text += `
|
|
62818
|
+
${line}`;
|
|
62819
|
+
depth += openBrackets(line);
|
|
62820
|
+
continue;
|
|
62821
|
+
}
|
|
62822
|
+
open = undefined;
|
|
62823
|
+
const text = line.trim();
|
|
62824
|
+
if (!table || !text || text.startsWith("#"))
|
|
62825
|
+
continue;
|
|
62826
|
+
const eq = text.indexOf("=");
|
|
62827
|
+
const key = eq === -1 ? text : text.slice(0, eq).trim();
|
|
62828
|
+
const value = eq === -1 ? "" : text.slice(eq + 1).trim();
|
|
62829
|
+
open = { key, value, text: line };
|
|
62830
|
+
table.statements.push(open);
|
|
62831
|
+
depth = openBrackets(value);
|
|
62832
|
+
}
|
|
62833
|
+
return tables;
|
|
62834
|
+
}
|
|
62835
|
+
function readDosuEntry(content) {
|
|
62836
|
+
let entry;
|
|
62837
|
+
for (const { name, statements } of dosuTables(content)) {
|
|
62838
|
+
entry ??= {};
|
|
62839
|
+
if (isUserTable(name))
|
|
62840
|
+
continue;
|
|
62841
|
+
const isRoot = name === DOSU_TABLE;
|
|
62842
|
+
const table = isRoot ? entry : {};
|
|
62843
|
+
if (!isRoot)
|
|
62844
|
+
entry[name.slice(DOSU_TABLE.length + 1)] = table;
|
|
62845
|
+
for (const { key, value } of statements) {
|
|
62846
|
+
if (isRoot && isUserKey(key))
|
|
62847
|
+
continue;
|
|
62848
|
+
try {
|
|
62849
|
+
table[key] = JSON.parse(value);
|
|
62850
|
+
} catch {
|
|
62851
|
+
table[key] = value;
|
|
62852
|
+
}
|
|
62853
|
+
}
|
|
62854
|
+
}
|
|
62855
|
+
return entry;
|
|
62856
|
+
}
|
|
62857
|
+
function userSettings(content) {
|
|
62858
|
+
const kept = { root: [], tables: [] };
|
|
62859
|
+
for (const { name, header, statements } of dosuTables(content)) {
|
|
62860
|
+
if (name === DOSU_TABLE) {
|
|
62861
|
+
kept.root.push(...statements.filter(({ key }) => isUserKey(key)).map(({ text }) => text));
|
|
62862
|
+
} else if (isUserTable(name)) {
|
|
62863
|
+
kept.tables.push([header, ...statements.map(({ text }) => text)].join(`
|
|
62864
|
+
`));
|
|
62865
|
+
}
|
|
62866
|
+
}
|
|
62867
|
+
return kept;
|
|
62868
|
+
}
|
|
62676
62869
|
function installDosuToTOML(path, cfg) {
|
|
62677
|
-
|
|
62678
|
-
content = removeDosuFromTOML(
|
|
62870
|
+
const existing = readTOML(path);
|
|
62871
|
+
const content = removeDosuFromTOML(existing);
|
|
62679
62872
|
const npx = findNpx();
|
|
62680
|
-
const
|
|
62681
|
-
|
|
62682
|
-
const envEntries = Object.entries(env).map(([key, value]) => `${key} = ${tomlString(value)}`).join(`
|
|
62683
|
-
`);
|
|
62684
|
-
const args = remote.args.map(tomlString).join(", ");
|
|
62685
|
-
const section = `
|
|
62686
|
-
[mcp_servers.dosu]
|
|
62687
|
-
command = ${tomlString(npx)}
|
|
62688
|
-
args = [${args}]
|
|
62689
|
-
` + `
|
|
62690
|
-
[mcp_servers.dosu.env]
|
|
62691
|
-
${envEntries}
|
|
62692
|
-
`;
|
|
62693
|
-
content += section;
|
|
62694
|
-
writeTOML(path, content);
|
|
62873
|
+
const entry = dosuEntry(mcpEndpoint(cfg), cfg.active_account?.target?.api_key, npx, npxPathEnv(npx));
|
|
62874
|
+
writeTOML(path, content + renderDosuEntry(entry, userSettings(existing)));
|
|
62695
62875
|
}
|
|
62696
62876
|
function sectionName(line) {
|
|
62697
62877
|
const header = line.trim();
|
|
@@ -62699,7 +62879,7 @@ function sectionName(line) {
|
|
|
62699
62879
|
return match ? match[1].trim() : null;
|
|
62700
62880
|
}
|
|
62701
62881
|
function isDosuSection(name) {
|
|
62702
|
-
return name ===
|
|
62882
|
+
return name === DOSU_TABLE || name.startsWith(`${DOSU_TABLE}.`);
|
|
62703
62883
|
}
|
|
62704
62884
|
function removeDosuFromTOML(content) {
|
|
62705
62885
|
const result = [];
|
|
@@ -62757,7 +62937,7 @@ function pruneLegacyRemoteEntry(path) {
|
|
|
62757
62937
|
return;
|
|
62758
62938
|
writeTOML(path, removeDosuFromTOML(content));
|
|
62759
62939
|
}
|
|
62760
|
-
var REMOTE_HTTP_KEY, CodexProvider = () => ({
|
|
62940
|
+
var DOSU_TABLE = "mcp_servers.dosu", REMOTE_HTTP_KEY, CodexProvider = () => ({
|
|
62761
62941
|
name: () => "Codex (CLI + Desktop)",
|
|
62762
62942
|
id: () => "codex",
|
|
62763
62943
|
supportsLocal: () => true,
|
|
@@ -62769,6 +62949,7 @@ var REMOTE_HTTP_KEY, CodexProvider = () => ({
|
|
|
62769
62949
|
const content = readTOML(join29(codexHome3(), "config.toml"));
|
|
62770
62950
|
return content.includes("[mcp_servers.dosu]");
|
|
62771
62951
|
},
|
|
62952
|
+
isCurrent: (cfg) => entryHasShape(dosuEntry(shapeEndpoint(cfg), ANY, ANY, npxPathEnv(join29(ANY, "npx"))), readDosuEntry(readTOML(join29(codexHome3(), "config.toml")))),
|
|
62772
62953
|
install(cfg, global2) {
|
|
62773
62954
|
if (cfg.mode !== MODE_OSS && !cfg.active_account?.target?.deployment_id)
|
|
62774
62955
|
throw new Error("deployment ID is required");
|
|
@@ -62793,11 +62974,15 @@ var init_codex = __esm(() => {
|
|
|
62793
62974
|
init_config();
|
|
62794
62975
|
init_config_helpers();
|
|
62795
62976
|
init_detect();
|
|
62977
|
+
init_shape();
|
|
62796
62978
|
REMOTE_HTTP_KEY = /^(url|type|bearer_token_env_var)\s*=/;
|
|
62797
62979
|
});
|
|
62798
62980
|
|
|
62799
62981
|
// src/mcp/providers/copilot.ts
|
|
62800
62982
|
import { join as join30 } from "node:path";
|
|
62983
|
+
function globalServer(url, apiKey) {
|
|
62984
|
+
return { type: "http", url, tools: ["*"], headers: mcpHeaders(apiKey) };
|
|
62985
|
+
}
|
|
62801
62986
|
function globalPath() {
|
|
62802
62987
|
if (process.env.XDG_CONFIG_HOME) {
|
|
62803
62988
|
return join30(process.env.XDG_CONFIG_HOME, "mcp-config.json");
|
|
@@ -62813,16 +62998,11 @@ var CopilotProvider = () => ({
|
|
|
62813
62998
|
isInstalled: () => isInstalled([expandHome("~/.copilot")]),
|
|
62814
62999
|
globalConfigPath: () => globalPath(),
|
|
62815
63000
|
isConfigured: () => isJSONKeyConfigured(globalPath(), "mcpServers"),
|
|
63001
|
+
isCurrent: (cfg) => entryHasShape(globalServer(shapeEndpoint(cfg), ANY), readJSONServer(globalPath(), "mcpServers")),
|
|
62816
63002
|
install(cfg, global2) {
|
|
62817
63003
|
const url = mcpEndpoint(cfg);
|
|
62818
63004
|
if (global2) {
|
|
62819
|
-
|
|
62820
|
-
type: "http",
|
|
62821
|
-
url,
|
|
62822
|
-
tools: ["*"],
|
|
62823
|
-
headers: mcpHeaders(cfg.active_account.target.api_key)
|
|
62824
|
-
};
|
|
62825
|
-
installJSONServer(globalPath(), "mcpServers", server);
|
|
63005
|
+
installJSONServer(globalPath(), "mcpServers", globalServer(url, cfg.active_account?.target?.api_key));
|
|
62826
63006
|
} else {
|
|
62827
63007
|
const configPath = join30(process.cwd(), ".vscode", "mcp.json");
|
|
62828
63008
|
const server = {
|
|
@@ -62845,6 +63025,7 @@ var CopilotProvider = () => ({
|
|
|
62845
63025
|
var init_copilot = __esm(() => {
|
|
62846
63026
|
init_config_helpers();
|
|
62847
63027
|
init_detect();
|
|
63028
|
+
init_shape();
|
|
62848
63029
|
});
|
|
62849
63030
|
|
|
62850
63031
|
// src/mcp/providers/cursor.ts
|
|
@@ -62937,6 +63118,9 @@ var init_manual = __esm(() => {
|
|
|
62937
63118
|
// src/mcp/providers/mcporter.ts
|
|
62938
63119
|
import { existsSync as existsSync23 } from "node:fs";
|
|
62939
63120
|
import { join as join34 } from "node:path";
|
|
63121
|
+
function server(url, apiKey) {
|
|
63122
|
+
return { type: "http", url, headers: mcpHeaders(apiKey) };
|
|
63123
|
+
}
|
|
62940
63124
|
function resolveGlobalConfigPath() {
|
|
62941
63125
|
const jsonPath = expandHome("~/.mcporter/mcporter.json");
|
|
62942
63126
|
if (existsSync23(jsonPath))
|
|
@@ -62955,14 +63139,10 @@ var MCPorterProvider = () => ({
|
|
|
62955
63139
|
isInstalled: () => isInstalled(["~/.mcporter"]),
|
|
62956
63140
|
globalConfigPath: () => resolveGlobalConfigPath(),
|
|
62957
63141
|
isConfigured: () => isJSONKeyConfigured(resolveGlobalConfigPath(), "mcpServers"),
|
|
63142
|
+
isCurrent: (cfg) => entryHasShape(server(shapeEndpoint(cfg), ANY), readJSONServer(resolveGlobalConfigPath(), "mcpServers")),
|
|
62958
63143
|
install(cfg, global2) {
|
|
62959
63144
|
const configPath = global2 ? resolveGlobalConfigPath() : join34(process.cwd(), "config", "mcporter.json");
|
|
62960
|
-
|
|
62961
|
-
type: "http",
|
|
62962
|
-
url: mcpEndpoint(cfg),
|
|
62963
|
-
headers: mcpHeaders(cfg.active_account.target.api_key)
|
|
62964
|
-
};
|
|
62965
|
-
installJSONServer(configPath, "mcpServers", server);
|
|
63145
|
+
installJSONServer(configPath, "mcpServers", server(mcpEndpoint(cfg), cfg.active_account?.target?.api_key));
|
|
62966
63146
|
},
|
|
62967
63147
|
remove(global2) {
|
|
62968
63148
|
const configPath = global2 ? resolveGlobalConfigPath() : join34(process.cwd(), "config", "mcporter.json");
|
|
@@ -62972,6 +63152,7 @@ var MCPorterProvider = () => ({
|
|
|
62972
63152
|
var init_mcporter = __esm(() => {
|
|
62973
63153
|
init_config_helpers();
|
|
62974
63154
|
init_detect();
|
|
63155
|
+
init_shape();
|
|
62975
63156
|
});
|
|
62976
63157
|
|
|
62977
63158
|
// src/mcp/providers/opencode.ts
|
|
@@ -63085,6 +63266,7 @@ var ZedProvider = (legacyPath = legacyDarwinSettingsPath()) => {
|
|
|
63085
63266
|
return provider;
|
|
63086
63267
|
return {
|
|
63087
63268
|
...provider,
|
|
63269
|
+
isCurrent: (cfg) => provider.isCurrent(cfg) && readJSONServer(legacyPath, "context_servers") === undefined,
|
|
63088
63270
|
install(cfg, global2) {
|
|
63089
63271
|
provider.install(cfg, global2);
|
|
63090
63272
|
if (global2)
|
|
@@ -63163,9 +63345,21 @@ function configuredProviders() {
|
|
|
63163
63345
|
}
|
|
63164
63346
|
});
|
|
63165
63347
|
}
|
|
63348
|
+
function staleProviders(cfg) {
|
|
63349
|
+
return configuredProviders().filter((provider) => {
|
|
63350
|
+
try {
|
|
63351
|
+
return !provider.isCurrent(cfg);
|
|
63352
|
+
} catch {
|
|
63353
|
+
return true;
|
|
63354
|
+
}
|
|
63355
|
+
});
|
|
63356
|
+
}
|
|
63166
63357
|
function refreshConfiguredProviders(cfg) {
|
|
63358
|
+
return refreshProviders(cfg, configuredProviders());
|
|
63359
|
+
}
|
|
63360
|
+
function refreshProviders(cfg, providers) {
|
|
63167
63361
|
const result = { updated: [], failed: [] };
|
|
63168
|
-
for (const provider of
|
|
63362
|
+
for (const provider of providers) {
|
|
63169
63363
|
try {
|
|
63170
63364
|
provider.install(cfg, true);
|
|
63171
63365
|
logger.info("mcp", `Refreshed ${provider.name()} MCP entry`);
|
|
@@ -63377,199 +63571,18 @@ var init_auto_update = __esm(() => {
|
|
|
63377
63571
|
VERSION_PATTERN = /^[0-9A-Za-z.+-]{1,64}$/;
|
|
63378
63572
|
});
|
|
63379
63573
|
|
|
63380
|
-
// src/version/
|
|
63574
|
+
// src/version/mcp-refresh-check.ts
|
|
63381
63575
|
import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync24, writeFileSync as writeFileSync16 } from "node:fs";
|
|
63382
63576
|
import { join as join40 } from "node:path";
|
|
63383
|
-
function isValidVersion2(value) {
|
|
63384
|
-
return typeof value === "string" && SEMVER_PATTERN.test(value);
|
|
63385
|
-
}
|
|
63386
|
-
function stripPrerelease(version) {
|
|
63387
|
-
return version.replace(/[-+].*$/, "");
|
|
63388
|
-
}
|
|
63389
|
-
function isNewerVersion(latest, current) {
|
|
63390
|
-
const a = stripPrerelease(latest).split(".").map(Number);
|
|
63391
|
-
const b = stripPrerelease(current).split(".").map(Number);
|
|
63392
|
-
const len = Math.max(a.length, b.length);
|
|
63393
|
-
for (let i = 0;i < len; i++) {
|
|
63394
|
-
const av = a[i] ?? 0;
|
|
63395
|
-
const bv = b[i] ?? 0;
|
|
63396
|
-
if (av > bv)
|
|
63397
|
-
return true;
|
|
63398
|
-
if (av < bv)
|
|
63399
|
-
return false;
|
|
63400
|
-
}
|
|
63401
|
-
return false;
|
|
63402
|
-
}
|
|
63403
63577
|
function getCachePath2() {
|
|
63404
63578
|
return join40(getConfigDir(), CACHE_FILENAME3);
|
|
63405
63579
|
}
|
|
63406
|
-
function
|
|
63580
|
+
function readMcpRefreshCache() {
|
|
63407
63581
|
try {
|
|
63408
63582
|
const path = getCachePath2();
|
|
63409
63583
|
if (!existsSync25(path))
|
|
63410
63584
|
return null;
|
|
63411
63585
|
const data = JSON.parse(readFileSync24(path, "utf-8"));
|
|
63412
|
-
if (typeof data.lastCheck === "number" && isValidVersion2(data.latestVersion)) {
|
|
63413
|
-
return data;
|
|
63414
|
-
}
|
|
63415
|
-
return null;
|
|
63416
|
-
} catch {
|
|
63417
|
-
return null;
|
|
63418
|
-
}
|
|
63419
|
-
}
|
|
63420
|
-
function writeCache(cache) {
|
|
63421
|
-
try {
|
|
63422
|
-
const dir = getConfigDir();
|
|
63423
|
-
if (!existsSync25(dir)) {
|
|
63424
|
-
mkdirSync15(dir, { recursive: true, mode: 448 });
|
|
63425
|
-
}
|
|
63426
|
-
writeFileSync16(getCachePath2(), JSON.stringify(cache), { mode: 384 });
|
|
63427
|
-
} catch {}
|
|
63428
|
-
}
|
|
63429
|
-
async function fetchLatestVersion() {
|
|
63430
|
-
const controller = new AbortController;
|
|
63431
|
-
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS2);
|
|
63432
|
-
try {
|
|
63433
|
-
const resp = await fetch(REGISTRY_URL, { signal: controller.signal });
|
|
63434
|
-
if (!resp.ok)
|
|
63435
|
-
return null;
|
|
63436
|
-
const data = await resp.json();
|
|
63437
|
-
const latest = data.latest;
|
|
63438
|
-
return isValidVersion2(latest) ? latest : null;
|
|
63439
|
-
} catch {
|
|
63440
|
-
return null;
|
|
63441
|
-
} finally {
|
|
63442
|
-
clearTimeout(timeout);
|
|
63443
|
-
}
|
|
63444
|
-
}
|
|
63445
|
-
function buildUpdateHint(channel, npx = false) {
|
|
63446
|
-
if (channel === "npm" && npx) {
|
|
63447
|
-
return 'Use "npx -y @dosu/cli@latest" for the next Dosu command';
|
|
63448
|
-
}
|
|
63449
|
-
return 'Run "dosu upgrade"';
|
|
63450
|
-
}
|
|
63451
|
-
function styleHint(hint) {
|
|
63452
|
-
const match = hint.match(/^(.*)("[^"]+")(.*)$/);
|
|
63453
|
-
if (!match)
|
|
63454
|
-
return import_picocolors32.default.dim(hint);
|
|
63455
|
-
const [, before, command, after] = match;
|
|
63456
|
-
return [before && import_picocolors32.default.dim(before), import_picocolors32.default.cyan(command), after && import_picocolors32.default.dim(after)].filter(Boolean).join("");
|
|
63457
|
-
}
|
|
63458
|
-
function framedNotice(content, width) {
|
|
63459
|
-
const innerWidth = Math.max(...content.map(visibleWidth2)) + BOX_PADDING * 2;
|
|
63460
|
-
const framed = (line) => {
|
|
63461
|
-
const pad = innerWidth - visibleWidth2(line);
|
|
63462
|
-
const left = Math.floor(pad / 2);
|
|
63463
|
-
return `${import_picocolors32.default.yellow("│")}${" ".repeat(left)}${line}${" ".repeat(pad - left)}${import_picocolors32.default.yellow("│")}`;
|
|
63464
|
-
};
|
|
63465
|
-
const box = [
|
|
63466
|
-
import_picocolors32.default.yellow(`╭${"─".repeat(innerWidth)}╮`),
|
|
63467
|
-
framed(""),
|
|
63468
|
-
...content.map(framed),
|
|
63469
|
-
framed(""),
|
|
63470
|
-
import_picocolors32.default.yellow(`╰${"─".repeat(innerWidth)}╯`)
|
|
63471
|
-
];
|
|
63472
|
-
return `
|
|
63473
|
-
${centerBlock(box, width).join(`
|
|
63474
|
-
`)}
|
|
63475
|
-
`;
|
|
63476
|
-
}
|
|
63477
|
-
function versionArrow(current, latest) {
|
|
63478
|
-
return `${import_picocolors32.default.dim(current)} ${import_picocolors32.default.dim("→")} ${import_picocolors32.default.bold(brand(latest))}`;
|
|
63479
|
-
}
|
|
63480
|
-
function buildAutoUpdateNotice(current, latest, interactive, width = process.stderr.columns ?? 80) {
|
|
63481
|
-
if (interactive) {
|
|
63482
|
-
return framedNotice([
|
|
63483
|
-
`Updating Dosu: ${versionArrow(current, latest)}`,
|
|
63484
|
-
import_picocolors32.default.dim("Installing in the background; your next command uses it")
|
|
63485
|
-
], width);
|
|
63486
|
-
}
|
|
63487
|
-
return `
|
|
63488
|
-
[dosu:update] Installing Dosu ${latest} in the background (running ${current}). ` + `The next Dosu command uses it; no action needed.
|
|
63489
|
-
`;
|
|
63490
|
-
}
|
|
63491
|
-
function buildUpdateNotice(current, latest, channel, interactive, npx = false, width = process.stderr.columns ?? 80) {
|
|
63492
|
-
const hint = buildUpdateHint(channel, npx);
|
|
63493
|
-
if (interactive) {
|
|
63494
|
-
return framedNotice([`Update available: ${versionArrow(current, latest)}`, styleHint(hint)], width);
|
|
63495
|
-
}
|
|
63496
|
-
const agentAction = hint[0].toLowerCase() + hint.slice(1);
|
|
63497
|
-
const verifyCommand = npx ? "npx -y @dosu/cli@latest --version" : "dosu --version";
|
|
63498
|
-
return `
|
|
63499
|
-
[dosu:update] Update available: ${current} → ${latest}
|
|
63500
|
-
` + `Tell the user Dosu CLI is outdated. After they approve, ${agentAction}, ` + `then verify with "${verifyCommand}".
|
|
63501
|
-
`;
|
|
63502
|
-
}
|
|
63503
|
-
function getAvailableUpdate() {
|
|
63504
|
-
const cache = readCache();
|
|
63505
|
-
return cache && isNewerVersion(cache.latestVersion, VERSION) ? cache.latestVersion : null;
|
|
63506
|
-
}
|
|
63507
|
-
function handleNewerVersion(latest, notify) {
|
|
63508
|
-
const autoUpdate = startAutoUpdate(latest);
|
|
63509
|
-
if (!notify)
|
|
63510
|
-
return;
|
|
63511
|
-
const interactive = process.stderr.isTTY === true;
|
|
63512
|
-
console.error(autoUpdate === "unavailable" ? buildUpdateNotice(VERSION, latest, INSTALL_CHANNEL, interactive, isNpxInvocation()) : buildAutoUpdateNotice(VERSION, latest, interactive));
|
|
63513
|
-
}
|
|
63514
|
-
async function checkForUpdates(options = {}) {
|
|
63515
|
-
const notify = options.notify ?? true;
|
|
63516
|
-
try {
|
|
63517
|
-
const cache = readCache();
|
|
63518
|
-
const isStale = !cache || Date.now() - cache.lastCheck > CHECK_INTERVAL_MS2;
|
|
63519
|
-
if (!isStale) {
|
|
63520
|
-
if (isNewerVersion(cache.latestVersion, VERSION)) {
|
|
63521
|
-
handleNewerVersion(cache.latestVersion, notify);
|
|
63522
|
-
}
|
|
63523
|
-
return;
|
|
63524
|
-
}
|
|
63525
|
-
const latest = await fetchLatestVersion();
|
|
63526
|
-
const latestKnownVersion = latest ?? cache?.latestVersion ?? VERSION;
|
|
63527
|
-
writeCache({
|
|
63528
|
-
lastCheck: Date.now(),
|
|
63529
|
-
latestVersion: latestKnownVersion
|
|
63530
|
-
});
|
|
63531
|
-
if (latest) {
|
|
63532
|
-
logger.debug("update-check", `Cached latest version: ${latest}`);
|
|
63533
|
-
}
|
|
63534
|
-
if (isNewerVersion(latestKnownVersion, VERSION)) {
|
|
63535
|
-
handleNewerVersion(latestKnownVersion, notify);
|
|
63536
|
-
}
|
|
63537
|
-
} catch (err) {
|
|
63538
|
-
logger.error("update-check", `Update check failed: ${err}`);
|
|
63539
|
-
}
|
|
63540
|
-
}
|
|
63541
|
-
var import_picocolors32, CACHE_FILENAME3 = "update-check.json", CHECK_INTERVAL_MS2, FETCH_TIMEOUT_MS2 = 1000, REGISTRY_URL = "https://registry.npmjs.org/-/package/@dosu/cli/dist-tags", SEMVER_PATTERN, BOX_PADDING = 3;
|
|
63542
|
-
var init_update_check = __esm(() => {
|
|
63543
|
-
init_config();
|
|
63544
|
-
init_logger();
|
|
63545
|
-
init_styles();
|
|
63546
|
-
init_layout();
|
|
63547
|
-
init_auto_update();
|
|
63548
|
-
import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
63549
|
-
CHECK_INTERVAL_MS2 = 6 * 60 * 60 * 1000;
|
|
63550
|
-
SEMVER_PATTERN = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
63551
|
-
});
|
|
63552
|
-
|
|
63553
|
-
// src/version/mcp-refresh-check.ts
|
|
63554
|
-
import { existsSync as existsSync26, mkdirSync as mkdirSync16, readFileSync as readFileSync25, writeFileSync as writeFileSync17 } from "node:fs";
|
|
63555
|
-
import { join as join41 } from "node:path";
|
|
63556
|
-
function needsMcpRefresh(previous, current) {
|
|
63557
|
-
if (previous === null)
|
|
63558
|
-
return true;
|
|
63559
|
-
if (previous === current)
|
|
63560
|
-
return false;
|
|
63561
|
-
const [older, newer] = isNewerVersion(current, previous) ? [previous, current] : [current, previous];
|
|
63562
|
-
return MCP_FORMAT_CHANGES.some((change) => isNewerVersion(change, older) && !isNewerVersion(change, newer));
|
|
63563
|
-
}
|
|
63564
|
-
function getCachePath3() {
|
|
63565
|
-
return join41(getConfigDir(), CACHE_FILENAME4);
|
|
63566
|
-
}
|
|
63567
|
-
function readMcpRefreshCache() {
|
|
63568
|
-
try {
|
|
63569
|
-
const path = getCachePath3();
|
|
63570
|
-
if (!existsSync26(path))
|
|
63571
|
-
return null;
|
|
63572
|
-
const data = JSON.parse(readFileSync25(path, "utf-8"));
|
|
63573
63586
|
if (typeof data?.version === "string")
|
|
63574
63587
|
return { version: data.version };
|
|
63575
63588
|
return null;
|
|
@@ -63580,10 +63593,10 @@ function readMcpRefreshCache() {
|
|
|
63580
63593
|
function writeMcpRefreshCache(cache) {
|
|
63581
63594
|
try {
|
|
63582
63595
|
const dir = getConfigDir();
|
|
63583
|
-
if (!
|
|
63584
|
-
|
|
63596
|
+
if (!existsSync25(dir)) {
|
|
63597
|
+
mkdirSync15(dir, { recursive: true, mode: 448 });
|
|
63585
63598
|
}
|
|
63586
|
-
|
|
63599
|
+
writeFileSync16(getCachePath2(), JSON.stringify(cache), { mode: 384 });
|
|
63587
63600
|
} catch {}
|
|
63588
63601
|
}
|
|
63589
63602
|
function canRefreshMcp(cfg) {
|
|
@@ -63594,26 +63607,21 @@ function canRefreshMcp(cfg) {
|
|
|
63594
63607
|
}
|
|
63595
63608
|
function displayNotice(names) {
|
|
63596
63609
|
console.error(`
|
|
63597
|
-
${
|
|
63598
|
-
` + `${
|
|
63610
|
+
${import_picocolors32.default.green(`✓ Dosu ${VERSION}: refreshed MCP config for ${names.join(", ")}`)}
|
|
63611
|
+
` + `${import_picocolors32.default.dim(` Run ${import_picocolors32.default.cyan('"dosu setup"')} to also update hooks and rules, then restart your AI agents.`)}
|
|
63599
63612
|
`);
|
|
63600
63613
|
}
|
|
63601
63614
|
function checkForMcpRefresh(options = {}) {
|
|
63602
63615
|
const notify = options.notify ?? true;
|
|
63603
63616
|
try {
|
|
63604
|
-
|
|
63605
|
-
if (previous === VERSION)
|
|
63617
|
+
if (readMcpRefreshCache()?.version === VERSION)
|
|
63606
63618
|
return;
|
|
63607
|
-
if (!needsMcpRefresh(previous, VERSION)) {
|
|
63608
|
-
writeMcpRefreshCache({ version: VERSION });
|
|
63609
|
-
return;
|
|
63610
|
-
}
|
|
63611
63619
|
const cfg = loadConfigNonBlocking();
|
|
63612
63620
|
if (!cfg || !canRefreshMcp(cfg)) {
|
|
63613
63621
|
logger.debug("mcp-refresh", "Skipping MCP refresh: no API key or deployment configured");
|
|
63614
63622
|
return;
|
|
63615
63623
|
}
|
|
63616
|
-
const result =
|
|
63624
|
+
const result = refreshProviders(cfg, staleProviders(cfg));
|
|
63617
63625
|
writeMcpRefreshCache({ version: VERSION });
|
|
63618
63626
|
logger.info("mcp-refresh", `Version ${VERSION}: refreshed ${result.updated.length}, failed ${result.failed.length}`);
|
|
63619
63627
|
if (notify && result.updated.length > 0) {
|
|
@@ -63623,24 +63631,19 @@ function checkForMcpRefresh(options = {}) {
|
|
|
63623
63631
|
logger.error("mcp-refresh", `MCP refresh check failed: ${err}`);
|
|
63624
63632
|
}
|
|
63625
63633
|
}
|
|
63626
|
-
var
|
|
63634
|
+
var import_picocolors32, CACHE_FILENAME3 = "mcp-refresh.json";
|
|
63627
63635
|
var init_mcp_refresh_check = __esm(() => {
|
|
63628
63636
|
init_config();
|
|
63629
63637
|
init_logger();
|
|
63630
63638
|
init_refresh();
|
|
63631
|
-
|
|
63632
|
-
import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
63633
|
-
MCP_FORMAT_CHANGES = [
|
|
63634
|
-
"0.53.0",
|
|
63635
|
-
"0.62.0"
|
|
63636
|
-
];
|
|
63639
|
+
import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
63637
63640
|
});
|
|
63638
63641
|
|
|
63639
63642
|
// src/version/skill-update-check.ts
|
|
63640
63643
|
function displayNotice2() {
|
|
63641
63644
|
console.error(`
|
|
63642
|
-
${
|
|
63643
|
-
` + `${
|
|
63645
|
+
${import_picocolors33.default.green(`✓ Dosu ${VERSION}: refreshed the bundled agent skills`)}
|
|
63646
|
+
` + `${import_picocolors33.default.dim(" Restart your AI agents to pick up the new skill content.")}
|
|
63644
63647
|
`);
|
|
63645
63648
|
}
|
|
63646
63649
|
function checkForSkillUpdates(options = {}) {
|
|
@@ -63661,11 +63664,11 @@ function checkForSkillUpdates(options = {}) {
|
|
|
63661
63664
|
logger.error("skill-update-check", `Skill update check failed: ${err}`);
|
|
63662
63665
|
}
|
|
63663
63666
|
}
|
|
63664
|
-
var
|
|
63667
|
+
var import_picocolors33;
|
|
63665
63668
|
var init_skill_update_check = __esm(() => {
|
|
63666
63669
|
init_skill();
|
|
63667
63670
|
init_logger();
|
|
63668
|
-
|
|
63671
|
+
import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
63669
63672
|
});
|
|
63670
63673
|
|
|
63671
63674
|
// src/auth/errors.ts
|
|
@@ -63731,15 +63734,15 @@ function createLogFollower(path, emit) {
|
|
|
63731
63734
|
var init_follow = () => {};
|
|
63732
63735
|
|
|
63733
63736
|
// src/sessions/session-title.ts
|
|
63734
|
-
import { existsSync as
|
|
63737
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync16, readFileSync as readFileSync25, renameSync as renameSync7, statSync as statSync10, writeFileSync as writeFileSync17 } from "node:fs";
|
|
63735
63738
|
import { homedir as homedir11 } from "node:os";
|
|
63736
|
-
import { join as
|
|
63739
|
+
import { join as join41 } from "node:path";
|
|
63737
63740
|
function cachePath2(configDir) {
|
|
63738
|
-
return
|
|
63741
|
+
return join41(configDir, CACHE_FILENAME4);
|
|
63739
63742
|
}
|
|
63740
63743
|
function loadCacheFile2(configDir) {
|
|
63741
63744
|
try {
|
|
63742
|
-
const raw = JSON.parse(
|
|
63745
|
+
const raw = JSON.parse(readFileSync25(cachePath2(configDir), "utf-8"));
|
|
63743
63746
|
if (raw.schema_version !== CACHE_SCHEMA_VERSION2 || typeof raw.entries !== "object")
|
|
63744
63747
|
return {};
|
|
63745
63748
|
return raw.entries;
|
|
@@ -63749,12 +63752,12 @@ function loadCacheFile2(configDir) {
|
|
|
63749
63752
|
}
|
|
63750
63753
|
function saveCacheFile2(configDir, entries) {
|
|
63751
63754
|
try {
|
|
63752
|
-
if (!
|
|
63753
|
-
|
|
63755
|
+
if (!existsSync26(configDir))
|
|
63756
|
+
mkdirSync16(configDir, { recursive: true, mode: 448 });
|
|
63754
63757
|
const path = cachePath2(configDir);
|
|
63755
63758
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
63756
63759
|
const file = { schema_version: CACHE_SCHEMA_VERSION2, entries };
|
|
63757
|
-
|
|
63760
|
+
writeFileSync17(tmp, JSON.stringify(file), { mode: 384 });
|
|
63758
63761
|
renameSync7(tmp, path);
|
|
63759
63762
|
} catch {}
|
|
63760
63763
|
}
|
|
@@ -63787,15 +63790,15 @@ function claudeSummaryFromHead(text) {
|
|
|
63787
63790
|
}
|
|
63788
63791
|
return null;
|
|
63789
63792
|
}
|
|
63790
|
-
function reconstructSession(harness, id, slug, home = homedir11(), exists =
|
|
63793
|
+
function reconstructSession(harness, id, slug, home = homedir11(), exists = existsSync26) {
|
|
63791
63794
|
if (!slug)
|
|
63792
63795
|
return null;
|
|
63793
63796
|
const candidates = [];
|
|
63794
63797
|
if (harness === "claude") {
|
|
63795
|
-
candidates.push(
|
|
63798
|
+
candidates.push(join41(home, ".claude", "projects", slug, `${id}.jsonl`));
|
|
63796
63799
|
} else if (harness === "cursor") {
|
|
63797
|
-
const project =
|
|
63798
|
-
candidates.push(
|
|
63800
|
+
const project = join41(home, ".cursor", "projects", slug);
|
|
63801
|
+
candidates.push(join41(project, "agent-transcripts", id, `${id}.jsonl`), join41(project, "agent-transcripts", `${id}.jsonl`));
|
|
63799
63802
|
} else {
|
|
63800
63803
|
return null;
|
|
63801
63804
|
}
|
|
@@ -63807,7 +63810,7 @@ function reconstructSession(harness, id, slug, home = homedir11(), exists = exis
|
|
|
63807
63810
|
}
|
|
63808
63811
|
function readHead2(path) {
|
|
63809
63812
|
try {
|
|
63810
|
-
return
|
|
63813
|
+
return readFileSync25(path, "utf-8").slice(0, 128 * 1024);
|
|
63811
63814
|
} catch {
|
|
63812
63815
|
return null;
|
|
63813
63816
|
}
|
|
@@ -63858,7 +63861,7 @@ function createSessionTitleResolver(configDir = getConfigDir(), deps = {}) {
|
|
|
63858
63861
|
}
|
|
63859
63862
|
};
|
|
63860
63863
|
}
|
|
63861
|
-
var
|
|
63864
|
+
var CACHE_FILENAME4 = "session-titles.json", CACHE_SCHEMA_VERSION2 = 3, HEAD_LINES2 = 50, SESSION_NAME_MAX = 80;
|
|
63862
63865
|
var init_session_title = __esm(() => {
|
|
63863
63866
|
init_config();
|
|
63864
63867
|
init_read();
|
|
@@ -63887,7 +63890,7 @@ var init_alt_screen = __esm(() => {
|
|
|
63887
63890
|
});
|
|
63888
63891
|
|
|
63889
63892
|
// src/tui/activity-view.ts
|
|
63890
|
-
import { existsSync as
|
|
63893
|
+
import { existsSync as existsSync27, readFileSync as readFileSync26 } from "node:fs";
|
|
63891
63894
|
import { basename as basename6 } from "node:path";
|
|
63892
63895
|
function reduceActivityViewKey(key) {
|
|
63893
63896
|
if (key === "q" || key === ESC7 || key === CTRL_C4)
|
|
@@ -64028,15 +64031,15 @@ function statusLine(status) {
|
|
|
64028
64031
|
if (status.running) {
|
|
64029
64032
|
const since = status.startedAt ? ` · since ${localTime(status.startedAt)}` : "";
|
|
64030
64033
|
const pid = status.pid !== undefined ? ` (pid ${status.pid})` : "";
|
|
64031
|
-
return `\uD83D\uDCDA ${
|
|
64034
|
+
return `\uD83D\uDCDA ${import_picocolors34.default.bold(brand("Studying sessions..."))}${import_picocolors34.default.dim(`${pid}${since}`)}`;
|
|
64032
64035
|
}
|
|
64033
64036
|
if (status.state.paused) {
|
|
64034
|
-
return `${
|
|
64037
|
+
return `${import_picocolors34.default.yellow("○")} ${import_picocolors34.default.bold("Paused")} ${import_picocolors34.default.dim("· studying stays off until you resume")}`;
|
|
64035
64038
|
}
|
|
64036
64039
|
if (status.staleLock) {
|
|
64037
|
-
return `${
|
|
64040
|
+
return `${import_picocolors34.default.yellow("○")} ${import_picocolors34.default.bold("Not running")} ${import_picocolors34.default.dim("· a previous run exited without cleaning up")}`;
|
|
64038
64041
|
}
|
|
64039
|
-
return `${
|
|
64042
|
+
return `${import_picocolors34.default.dim("○")} ${import_picocolors34.default.bold("Idle")} ${import_picocolors34.default.dim("· hooks study new sessions automatically")}`;
|
|
64040
64043
|
}
|
|
64041
64044
|
function progressLine(done, ready, width, notes = 0) {
|
|
64042
64045
|
const total = done + ready;
|
|
@@ -64045,7 +64048,7 @@ function progressLine(done, ready, width, notes = 0) {
|
|
|
64045
64048
|
const cells = Math.max(10, Math.min(30, width - 44));
|
|
64046
64049
|
const ratio = Math.max(0, Math.min(1, done / total));
|
|
64047
64050
|
const filled = Math.min(cells, Math.round(ratio * cells));
|
|
64048
|
-
const bar = brand("█".repeat(filled)) +
|
|
64051
|
+
const bar = brand("█".repeat(filled)) + import_picocolors34.default.dim("░".repeat(cells - filled));
|
|
64049
64052
|
const pct = Math.floor(ratio * 100);
|
|
64050
64053
|
const suffix = notes > 0 ? ` · ${notes} suggested page${notes === 1 ? "" : "s"}` : "";
|
|
64051
64054
|
return `${bar} ${done}/${total} studied · ${pct}%${suffix}`;
|
|
@@ -64084,17 +64087,17 @@ function confirmBox(queuedCount, backlog, width, mode = "start") {
|
|
|
64084
64087
|
const verb = mode === "clear" ? "clear" : mode === "stop" ? "stop" : mode === "resume" ? "resume" : "start";
|
|
64085
64088
|
const maxInner = Math.max(20, Math.min(width, contentWidth()) - 4);
|
|
64086
64089
|
const rows = [
|
|
64087
|
-
|
|
64088
|
-
...wrapLine(scope, maxInner, "").map((line) =>
|
|
64090
|
+
import_picocolors34.default.bold(brand(title)),
|
|
64091
|
+
...wrapLine(scope, maxInner, "").map((line) => import_picocolors34.default.dim(line)),
|
|
64089
64092
|
"",
|
|
64090
|
-
`${
|
|
64093
|
+
`${import_picocolors34.default.bold("enter")} ${verb} · ${import_picocolors34.default.bold("esc")} cancel`
|
|
64091
64094
|
];
|
|
64092
64095
|
const inner = Math.min(maxInner, Math.max(...rows.map(visibleWidth2)));
|
|
64093
64096
|
const pad = (row) => row + " ".repeat(Math.max(0, inner - visibleWidth2(row)));
|
|
64094
64097
|
return [
|
|
64095
|
-
|
|
64096
|
-
...rows.map((row) => `${
|
|
64097
|
-
|
|
64098
|
+
import_picocolors34.default.dim(`╭${"─".repeat(inner + 2)}╮`),
|
|
64099
|
+
...rows.map((row) => `${import_picocolors34.default.dim("│")} ${pad(row)} ${import_picocolors34.default.dim("│")}`),
|
|
64100
|
+
import_picocolors34.default.dim(`╰${"─".repeat(inner + 2)}╯`)
|
|
64098
64101
|
];
|
|
64099
64102
|
}
|
|
64100
64103
|
function buildActivityFrame(status, activity, width, backlog = null, pane = DEFAULT_PANE, queued = [], studiedBeforeRun = 0, open = [], runProgress = null, projectNames = {}, sessionNames = {}, frameLines) {
|
|
@@ -64110,7 +64113,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
64110
64113
|
progress = progressLine(studiedDelta + stepDone, Math.max(0, backlog.ready - stepDone), width, runProgress?.notes ?? 0);
|
|
64111
64114
|
}
|
|
64112
64115
|
const refusal = !status.running && status.state.last_refusal;
|
|
64113
|
-
const refusalLines = refusal ? wrapLine(`! Studying paused: ${refusal.message} (${localTime(refusal.at)})`, width).map((line) =>
|
|
64116
|
+
const refusalLines = refusal ? wrapLine(`! Studying paused: ${refusal.message} (${localTime(refusal.at)})`, width).map((line) => import_picocolors34.default.yellow(line)) : [];
|
|
64114
64117
|
const fullRows = Boolean(pane.fullRows);
|
|
64115
64118
|
const withName = (item, key) => projectNames[key] ? { ...item, project: projectNames[key] } : item;
|
|
64116
64119
|
const latestPass = new Map;
|
|
@@ -64136,8 +64139,8 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
64136
64139
|
breadcrumb(["home", "activity"], width),
|
|
64137
64140
|
"",
|
|
64138
64141
|
statusLine(status),
|
|
64139
|
-
|
|
64140
|
-
...queueDetail.length > 0 ? wrapLine(queueDetail.join(" · "), width).map((line) =>
|
|
64142
|
+
import_picocolors34.default.dim(studied),
|
|
64143
|
+
...queueDetail.length > 0 ? wrapLine(queueDetail.join(" · "), width).map((line) => import_picocolors34.default.dim(line)) : [],
|
|
64141
64144
|
...progress ? [progress] : [],
|
|
64142
64145
|
...refusalLines,
|
|
64143
64146
|
"",
|
|
@@ -64153,7 +64156,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
64153
64156
|
status.running ? "s stop" : status.state.paused ? "s resume" : "s sync now",
|
|
64154
64157
|
...!status.running && status.state.watermark ? ["c clear"] : [],
|
|
64155
64158
|
"esc back"
|
|
64156
|
-
].join(" · "), width, "").map((line) =>
|
|
64159
|
+
].join(" · "), width, "").map((line) => import_picocolors34.default.dim(line))
|
|
64157
64160
|
]
|
|
64158
64161
|
];
|
|
64159
64162
|
const defaultHeight = fullRows ? ACTIVITY_VIEW_FULL_LIST_ROWS : ACTIVITY_VIEW_LIST_LINES;
|
|
@@ -64166,7 +64169,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
64166
64169
|
({ visible, above, below } = windowList(source, pane.scroll, height));
|
|
64167
64170
|
display = visible.flatMap((row) => wrapRow(row, width));
|
|
64168
64171
|
}
|
|
64169
|
-
const listRows = display.length > 0 ? display.map((row) =>
|
|
64172
|
+
const listRows = display.length > 0 ? display.map((row) => import_picocolors34.default.dim(row)) : [import_picocolors34.default.dim(empty)];
|
|
64170
64173
|
const scrollParts = [];
|
|
64171
64174
|
if (above > 0)
|
|
64172
64175
|
scrollParts.push(`↑ ${above} earlier`);
|
|
@@ -64175,7 +64178,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
64175
64178
|
const lines = [
|
|
64176
64179
|
...header,
|
|
64177
64180
|
...listRows,
|
|
64178
|
-
...scrollParts.length > 0 ? [
|
|
64181
|
+
...scrollParts.length > 0 ? [import_picocolors34.default.dim(clip(scrollParts.join(" · "), width))] : [],
|
|
64179
64182
|
...footer
|
|
64180
64183
|
];
|
|
64181
64184
|
return { lines, listHeight: height };
|
|
@@ -64208,7 +64211,7 @@ function createRowNamer() {
|
|
|
64208
64211
|
names.titles[key] = t;
|
|
64209
64212
|
};
|
|
64210
64213
|
for (const s of [...backlog.queued, ...backlog.open]) {
|
|
64211
|
-
if (!
|
|
64214
|
+
if (!existsSync27(s.path))
|
|
64212
64215
|
continue;
|
|
64213
64216
|
const key = `${s.harness}/${s.id}`;
|
|
64214
64217
|
const dir = dirs.resolve(s);
|
|
@@ -64245,7 +64248,7 @@ function createRowNamer() {
|
|
|
64245
64248
|
}
|
|
64246
64249
|
function defaultReadLog2() {
|
|
64247
64250
|
try {
|
|
64248
|
-
return
|
|
64251
|
+
return readFileSync26(logger.getLogPath(), "utf-8");
|
|
64249
64252
|
} catch {
|
|
64250
64253
|
return "";
|
|
64251
64254
|
}
|
|
@@ -64430,7 +64433,7 @@ ${CLEAR_BELOW}`);
|
|
|
64430
64433
|
input.on("data", onData);
|
|
64431
64434
|
});
|
|
64432
64435
|
}
|
|
64433
|
-
var
|
|
64436
|
+
var import_picocolors34, ESC7, HIDE_CURSOR3, SHOW_CURSOR3, CTRL_C4, KEY_UP4, KEY_DOWN4, KEY_RIGHT3, KEY_LEFT3, CURSOR_HOME, CLEAR_BELOW, CLEAR_EOL, ACTIVITY_VIEW_POLL_MS = 500, ACTIVITY_VIEW_LIST_LINES = 10, ACTIVITY_VIEW_FULL_LIST_ROWS = 5, ACTIVITY_VIEW_BUFFER_LINES = 200, ACTIVITY_VIEW_TABS, DEFAULT_PANE, TITLE_READS_PER_DRAW = 25;
|
|
64434
64437
|
var init_activity_view = __esm(() => {
|
|
64435
64438
|
init_follow();
|
|
64436
64439
|
init_logger();
|
|
@@ -64445,7 +64448,7 @@ var init_activity_view = __esm(() => {
|
|
|
64445
64448
|
init_alt_screen();
|
|
64446
64449
|
init_layout();
|
|
64447
64450
|
init_menu();
|
|
64448
|
-
|
|
64451
|
+
import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
64449
64452
|
ESC7 = String.fromCharCode(27);
|
|
64450
64453
|
HIDE_CURSOR3 = `${ESC7}[?25l`;
|
|
64451
64454
|
SHOW_CURSOR3 = `${ESC7}[?25h`;
|
|
@@ -64462,14 +64465,14 @@ var init_activity_view = __esm(() => {
|
|
|
64462
64465
|
});
|
|
64463
64466
|
|
|
64464
64467
|
// src/rules/installer.ts
|
|
64465
|
-
import { existsSync as
|
|
64468
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync27, unlinkSync as unlinkSync5, writeFileSync as writeFileSync18 } from "node:fs";
|
|
64466
64469
|
import { homedir as homedir12 } from "node:os";
|
|
64467
|
-
import { dirname as dirname12, join as
|
|
64470
|
+
import { dirname as dirname12, join as join42 } from "node:path";
|
|
64468
64471
|
function claudeConfigDir4() {
|
|
64469
|
-
return process.env.CLAUDE_CONFIG_DIR ||
|
|
64472
|
+
return process.env.CLAUDE_CONFIG_DIR || join42(homedir12(), ".claude");
|
|
64470
64473
|
}
|
|
64471
64474
|
function codexHome4() {
|
|
64472
|
-
return process.env.CODEX_HOME ||
|
|
64475
|
+
return process.env.CODEX_HOME || join42(homedir12(), ".codex");
|
|
64473
64476
|
}
|
|
64474
64477
|
function isRuleAgent(agent) {
|
|
64475
64478
|
return Object.hasOwn(RULE_TARGETS, agent);
|
|
@@ -64495,17 +64498,17 @@ async function fetchDosuRule(fetchImpl = globalThis.fetch) {
|
|
|
64495
64498
|
return normalizeRule(FALLBACK_DOSU_RULE);
|
|
64496
64499
|
}
|
|
64497
64500
|
function ensureParent(path) {
|
|
64498
|
-
|
|
64501
|
+
mkdirSync17(dirname12(path), { recursive: true });
|
|
64499
64502
|
}
|
|
64500
64503
|
function writeIfChanged(path, content) {
|
|
64501
|
-
if (!
|
|
64504
|
+
if (!existsSync28(path)) {
|
|
64502
64505
|
ensureParent(path);
|
|
64503
|
-
|
|
64506
|
+
writeFileSync18(path, content, "utf-8");
|
|
64504
64507
|
return "created";
|
|
64505
64508
|
}
|
|
64506
|
-
if (
|
|
64509
|
+
if (readFileSync27(path, "utf-8") === content)
|
|
64507
64510
|
return "unchanged";
|
|
64508
|
-
|
|
64511
|
+
writeFileSync18(path, content, "utf-8");
|
|
64509
64512
|
return "updated";
|
|
64510
64513
|
}
|
|
64511
64514
|
function findSection(content) {
|
|
@@ -64531,14 +64534,14 @@ function buildSection(content, lineEnding = `
|
|
|
64531
64534
|
return `${DOSU_RULE_SECTION_START}${lineEnding}${body}${lineEnding}${DOSU_RULE_SECTION_END}`;
|
|
64532
64535
|
}
|
|
64533
64536
|
function upsertSection(path, content) {
|
|
64534
|
-
if (!
|
|
64537
|
+
if (!existsSync28(path)) {
|
|
64535
64538
|
const section = buildSection(content);
|
|
64536
64539
|
ensureParent(path);
|
|
64537
|
-
|
|
64540
|
+
writeFileSync18(path, `${section}
|
|
64538
64541
|
`, "utf-8");
|
|
64539
64542
|
return "created";
|
|
64540
64543
|
}
|
|
64541
|
-
const existing =
|
|
64544
|
+
const existing = readFileSync27(path, "utf-8");
|
|
64542
64545
|
const lineEnding = lineEndingFor(existing);
|
|
64543
64546
|
const section = buildSection(content, lineEnding);
|
|
64544
64547
|
const location = findSection(existing);
|
|
@@ -64551,7 +64554,7 @@ function upsertSection(path, content) {
|
|
|
64551
64554
|
}
|
|
64552
64555
|
if (next === existing)
|
|
64553
64556
|
return "unchanged";
|
|
64554
|
-
|
|
64557
|
+
writeFileSync18(path, next, "utf-8");
|
|
64555
64558
|
return "updated";
|
|
64556
64559
|
}
|
|
64557
64560
|
function installRuleForAgent(agent, content) {
|
|
@@ -64568,13 +64571,13 @@ function removeRuleForAgent(agent) {
|
|
|
64568
64571
|
return null;
|
|
64569
64572
|
const target = RULE_TARGETS[agent];
|
|
64570
64573
|
const path = target.path();
|
|
64571
|
-
if (!
|
|
64574
|
+
if (!existsSync28(path))
|
|
64572
64575
|
return { agent, path, action: "not_found" };
|
|
64573
64576
|
if (target.kind === "file") {
|
|
64574
64577
|
unlinkSync5(path);
|
|
64575
64578
|
return { agent, path, action: "removed" };
|
|
64576
64579
|
}
|
|
64577
|
-
const existing =
|
|
64580
|
+
const existing = readFileSync27(path, "utf-8");
|
|
64578
64581
|
const lineEnding = lineEndingFor(existing);
|
|
64579
64582
|
const location = findSection(existing);
|
|
64580
64583
|
if (!location)
|
|
@@ -64583,7 +64586,7 @@ function removeRuleForAgent(agent) {
|
|
|
64583
64586
|
if (!next) {
|
|
64584
64587
|
unlinkSync5(path);
|
|
64585
64588
|
} else {
|
|
64586
|
-
|
|
64589
|
+
writeFileSync18(path, `${next}${lineEnding}`, "utf-8");
|
|
64587
64590
|
}
|
|
64588
64591
|
return { agent, path, action: "removed" };
|
|
64589
64592
|
}
|
|
@@ -64611,36 +64614,36 @@ var init_installer = __esm(() => {
|
|
|
64611
64614
|
RULE_TARGETS = {
|
|
64612
64615
|
claude: {
|
|
64613
64616
|
kind: "file",
|
|
64614
|
-
path: () =>
|
|
64617
|
+
path: () => join42(claudeConfigDir4(), "rules", "dosu.md")
|
|
64615
64618
|
},
|
|
64616
64619
|
cursor: {
|
|
64617
64620
|
kind: "file",
|
|
64618
|
-
path: () =>
|
|
64621
|
+
path: () => join42(homedir12(), ".cursor", "rules", "dosu.mdc"),
|
|
64619
64622
|
cursorFrontmatter: true
|
|
64620
64623
|
},
|
|
64621
64624
|
codex: {
|
|
64622
64625
|
kind: "section",
|
|
64623
|
-
path: () =>
|
|
64626
|
+
path: () => join42(codexHome4(), "AGENTS.md")
|
|
64624
64627
|
},
|
|
64625
64628
|
opencode: {
|
|
64626
64629
|
kind: "section",
|
|
64627
|
-
path: () =>
|
|
64630
|
+
path: () => join42(homedir12(), ".config", "opencode", "AGENTS.md")
|
|
64628
64631
|
},
|
|
64629
64632
|
gemini: {
|
|
64630
64633
|
kind: "section",
|
|
64631
|
-
path: () =>
|
|
64634
|
+
path: () => join42(homedir12(), ".gemini", "GEMINI.md")
|
|
64632
64635
|
},
|
|
64633
64636
|
antigravity: {
|
|
64634
64637
|
kind: "section",
|
|
64635
|
-
path: () =>
|
|
64638
|
+
path: () => join42(homedir12(), ".gemini", "GEMINI.md")
|
|
64636
64639
|
}
|
|
64637
64640
|
};
|
|
64638
64641
|
});
|
|
64639
64642
|
|
|
64640
64643
|
// src/setup/agents-md-step.ts
|
|
64641
64644
|
import { execSync as execSync2 } from "node:child_process";
|
|
64642
|
-
import { existsSync as
|
|
64643
|
-
import { join as
|
|
64645
|
+
import { existsSync as existsSync29, readFileSync as readFileSync28, writeFileSync as writeFileSync19 } from "node:fs";
|
|
64646
|
+
import { join as join43 } from "node:path";
|
|
64644
64647
|
function inGitWorkTree(cwd = process.cwd()) {
|
|
64645
64648
|
try {
|
|
64646
64649
|
const stdout = execSync2("git rev-parse --is-inside-work-tree", {
|
|
@@ -64654,10 +64657,10 @@ function inGitWorkTree(cwd = process.cwd()) {
|
|
|
64654
64657
|
}
|
|
64655
64658
|
function dosuAgentsSectionState(cwd = process.cwd()) {
|
|
64656
64659
|
try {
|
|
64657
|
-
const path =
|
|
64658
|
-
if (!
|
|
64660
|
+
const path = join43(cwd, "AGENTS.md");
|
|
64661
|
+
if (!existsSync29(path))
|
|
64659
64662
|
return "missing";
|
|
64660
|
-
const content =
|
|
64663
|
+
const content = readFileSync28(path, "utf-8");
|
|
64661
64664
|
const startMatch = content.match(SECTION_START_RE);
|
|
64662
64665
|
if (!startMatch || !content.includes(DOSU_SECTION_END))
|
|
64663
64666
|
return "missing";
|
|
@@ -64692,14 +64695,14 @@ function findSection2(content) {
|
|
|
64692
64695
|
return { start, end };
|
|
64693
64696
|
}
|
|
64694
64697
|
function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RULE) {
|
|
64695
|
-
const path =
|
|
64696
|
-
if (!
|
|
64698
|
+
const path = join43(cwd, "AGENTS.md");
|
|
64699
|
+
if (!existsSync29(path)) {
|
|
64697
64700
|
const section = buildDosuAgentsSection(content);
|
|
64698
|
-
|
|
64701
|
+
writeFileSync19(path, `${section}
|
|
64699
64702
|
`);
|
|
64700
64703
|
return { path, action: "created" };
|
|
64701
64704
|
}
|
|
64702
|
-
const existing =
|
|
64705
|
+
const existing = readFileSync28(path, "utf-8");
|
|
64703
64706
|
const lineEnding = lineEndingFor2(existing);
|
|
64704
64707
|
const section = renderDosuAgentsSection(content, lineEnding);
|
|
64705
64708
|
const location = findSection2(existing);
|
|
@@ -64711,7 +64714,7 @@ function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RU
|
|
|
64711
64714
|
}
|
|
64712
64715
|
if (next === existing)
|
|
64713
64716
|
return { path, action: "unchanged" };
|
|
64714
|
-
|
|
64717
|
+
writeFileSync19(path, next);
|
|
64715
64718
|
return { path, action: "updated" };
|
|
64716
64719
|
}
|
|
64717
64720
|
async function stepUpdateAgentsMd(cwd = process.cwd(), content) {
|
|
@@ -66163,7 +66166,7 @@ async function stepSelectTools(detected) {
|
|
|
66163
66166
|
initialValues: preselected,
|
|
66164
66167
|
statusFor: (id, picked) => {
|
|
66165
66168
|
if (configuredMap.get(id))
|
|
66166
|
-
return picked ? dim("configured") :
|
|
66169
|
+
return picked ? dim("configured") : import_picocolors35.default.yellow("will remove");
|
|
66167
66170
|
return picked ? brand("will configure") : undefined;
|
|
66168
66171
|
},
|
|
66169
66172
|
summary: (picked) => {
|
|
@@ -66338,7 +66341,7 @@ ${dim(wrapLog("Type it in a chat to keep that chat out of Dosu. To keep a whole
|
|
|
66338
66341
|
log2.success("All agents already configured. No changes needed.");
|
|
66339
66342
|
}
|
|
66340
66343
|
}
|
|
66341
|
-
var
|
|
66344
|
+
var import_picocolors35, OAUTH_ANALYTICS_REASONS, SETUP_HANDSHAKE_TIMEOUT_MS = 1800000, LIBRARY_SELECT_CANCELLED;
|
|
66342
66345
|
var init_flow2 = __esm(() => {
|
|
66343
66346
|
init_errors4();
|
|
66344
66347
|
init_client();
|
|
@@ -66361,7 +66364,7 @@ var init_flow2 = __esm(() => {
|
|
|
66361
66364
|
init_analytics2();
|
|
66362
66365
|
init_rules_step();
|
|
66363
66366
|
init_styles();
|
|
66364
|
-
|
|
66367
|
+
import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
66365
66368
|
OAUTH_ANALYTICS_REASONS = new Set([
|
|
66366
66369
|
"access_denied",
|
|
66367
66370
|
"bad_oauth_state",
|
|
@@ -66525,7 +66528,7 @@ Could not update Dosu automatically.`);
|
|
|
66525
66528
|
${plan.manualCommand}`);
|
|
66526
66529
|
return result.status && result.status > 0 ? result.status : 1;
|
|
66527
66530
|
}
|
|
66528
|
-
console.log(
|
|
66531
|
+
console.log(import_picocolors36.default.green(`
|
|
66529
66532
|
✓ Update command completed.`));
|
|
66530
66533
|
console.log('Run "dosu --version" to verify.');
|
|
66531
66534
|
return 0;
|
|
@@ -66567,12 +66570,13 @@ async function completeUpgrade(channel = INSTALL_CHANNEL, options = {}) {
|
|
|
66567
66570
|
finishWithNewBinary(channel, options);
|
|
66568
66571
|
return 0;
|
|
66569
66572
|
}
|
|
66570
|
-
async function finishUpgrade(
|
|
66571
|
-
const
|
|
66572
|
-
|
|
66573
|
+
async function finishUpgrade(_from, options = {}) {
|
|
66574
|
+
const cfg = loadConfigNonBlocking();
|
|
66575
|
+
const stale = staleProviders(cfg);
|
|
66576
|
+
if (stale.length === 0) {
|
|
66573
66577
|
checkForSkillUpdates();
|
|
66574
66578
|
writeMcpRefreshCache({ version: VERSION });
|
|
66575
|
-
console.log(
|
|
66579
|
+
console.log(import_picocolors36.default.green(`✓ Dosu ${VERSION} is ready. Your AI agents need no changes.`));
|
|
66576
66580
|
return 0;
|
|
66577
66581
|
}
|
|
66578
66582
|
if (options.interactive ?? isInteractiveTerminal()) {
|
|
@@ -66584,14 +66588,13 @@ This update changes how agents connect to Dosu. Running setup...
|
|
|
66584
66588
|
return 0;
|
|
66585
66589
|
}
|
|
66586
66590
|
checkForSkillUpdates();
|
|
66587
|
-
const cfg = loadConfigNonBlocking();
|
|
66588
66591
|
if (!cfg || !canRefreshMcp(cfg)) {
|
|
66589
66592
|
console.error(SETUP_FALLBACK);
|
|
66590
66593
|
return 0;
|
|
66591
66594
|
}
|
|
66592
66595
|
console.log(`
|
|
66593
66596
|
Refreshing agent MCP configs with the new version...`);
|
|
66594
|
-
const result =
|
|
66597
|
+
const result = refreshProviders(cfg, stale);
|
|
66595
66598
|
writeMcpRefreshCache({ version: VERSION });
|
|
66596
66599
|
for (const provider of result.updated)
|
|
66597
66600
|
console.log(` ✓ ${provider.name()}`);
|
|
@@ -66637,7 +66640,7 @@ function upgradeCommand() {
|
|
|
66637
66640
|
process.exitCode = status;
|
|
66638
66641
|
});
|
|
66639
66642
|
}
|
|
66640
|
-
var
|
|
66643
|
+
var import_picocolors36, PACKAGE_NAME = "@dosu/cli", LATEST_PACKAGE, BREW_MANUAL_COMMAND = "brew upgrade dosu-ai/dosu/dosu", NPX_COMMAND = "npx -y @dosu/cli@latest", PROBE_TIMEOUT_MS = 5000, RELEASES_URL = "https://github.com/dosu-ai/dosu-cli/releases/latest", PACKAGE_MANAGERS, SETUP_FALLBACK = 'Run "dosu setup" to finish updating your AI agents.';
|
|
66641
66644
|
var init_upgrade = __esm(() => {
|
|
66642
66645
|
init_commander();
|
|
66643
66646
|
init_config();
|
|
@@ -66645,7 +66648,7 @@ var init_upgrade = __esm(() => {
|
|
|
66645
66648
|
init_auto_update();
|
|
66646
66649
|
init_mcp_refresh_check();
|
|
66647
66650
|
init_skill_update_check();
|
|
66648
|
-
|
|
66651
|
+
import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
66649
66652
|
LATEST_PACKAGE = `${PACKAGE_NAME}@latest`;
|
|
66650
66653
|
PACKAGE_MANAGERS = {
|
|
66651
66654
|
npm: {
|
|
@@ -66664,31 +66667,30 @@ var init_upgrade = __esm(() => {
|
|
|
66664
66667
|
installArgs: ["global", "add", LATEST_PACKAGE]
|
|
66665
66668
|
}
|
|
66666
66669
|
};
|
|
66667
|
-
SEMVER = /^\d+\.\d+\.\d+/;
|
|
66668
66670
|
});
|
|
66669
66671
|
|
|
66670
66672
|
// src/version/incognito-backfill-check.ts
|
|
66671
|
-
import { existsSync as
|
|
66672
|
-
import { join as
|
|
66673
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync18, writeFileSync as writeFileSync20 } from "node:fs";
|
|
66674
|
+
import { join as join44 } from "node:path";
|
|
66673
66675
|
function markerPath() {
|
|
66674
|
-
return
|
|
66676
|
+
return join44(getConfigDir(), MARKER_FILENAME);
|
|
66675
66677
|
}
|
|
66676
66678
|
function writeMarker() {
|
|
66677
66679
|
const dir = getConfigDir();
|
|
66678
|
-
if (!
|
|
66679
|
-
|
|
66680
|
-
|
|
66680
|
+
if (!existsSync30(dir))
|
|
66681
|
+
mkdirSync18(dir, { recursive: true, mode: 448 });
|
|
66682
|
+
writeFileSync20(markerPath(), JSON.stringify({ done: true }), { mode: 384 });
|
|
66681
66683
|
}
|
|
66682
66684
|
function displayNotice3(names) {
|
|
66683
66685
|
console.error(`
|
|
66684
|
-
${
|
|
66685
|
-
` + `${
|
|
66686
|
+
${import_picocolors37.default.green(`✓ Dosu: added the /${INCOGNITO_COMMAND_NAME} command to ${names.join(", ")}`)}
|
|
66687
|
+
` + `${import_picocolors37.default.dim(` Type /${INCOGNITO_COMMAND_NAME} in a chat to keep that chat out of Dosu.`)}
|
|
66686
66688
|
`);
|
|
66687
66689
|
}
|
|
66688
66690
|
function checkForIncognitoBackfill(options = {}) {
|
|
66689
66691
|
const notify = options.notify ?? true;
|
|
66690
66692
|
try {
|
|
66691
|
-
if (
|
|
66693
|
+
if (existsSync30(markerPath()))
|
|
66692
66694
|
return;
|
|
66693
66695
|
const added = [];
|
|
66694
66696
|
let failed = false;
|
|
@@ -66715,14 +66717,187 @@ function checkForIncognitoBackfill(options = {}) {
|
|
|
66715
66717
|
logger.error("incognito-backfill", `Incognito backfill failed: ${err}`);
|
|
66716
66718
|
}
|
|
66717
66719
|
}
|
|
66718
|
-
var
|
|
66720
|
+
var import_picocolors37, MARKER_FILENAME = "incognito-backfill.json";
|
|
66719
66721
|
var init_incognito_backfill_check = __esm(() => {
|
|
66720
66722
|
init_config();
|
|
66721
66723
|
init_logger();
|
|
66722
66724
|
init_agents();
|
|
66723
66725
|
init_agents3();
|
|
66724
66726
|
init_incognito();
|
|
66727
|
+
import_picocolors37 = __toESM(require_picocolors(), 1);
|
|
66728
|
+
});
|
|
66729
|
+
|
|
66730
|
+
// src/version/update-check.ts
|
|
66731
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync19, readFileSync as readFileSync29, writeFileSync as writeFileSync21 } from "node:fs";
|
|
66732
|
+
import { join as join45 } from "node:path";
|
|
66733
|
+
function isValidVersion2(value) {
|
|
66734
|
+
return typeof value === "string" && SEMVER_PATTERN.test(value);
|
|
66735
|
+
}
|
|
66736
|
+
function stripPrerelease(version) {
|
|
66737
|
+
return version.replace(/[-+].*$/, "");
|
|
66738
|
+
}
|
|
66739
|
+
function isNewerVersion(latest, current) {
|
|
66740
|
+
const a = stripPrerelease(latest).split(".").map(Number);
|
|
66741
|
+
const b = stripPrerelease(current).split(".").map(Number);
|
|
66742
|
+
const len = Math.max(a.length, b.length);
|
|
66743
|
+
for (let i = 0;i < len; i++) {
|
|
66744
|
+
const av = a[i] ?? 0;
|
|
66745
|
+
const bv = b[i] ?? 0;
|
|
66746
|
+
if (av > bv)
|
|
66747
|
+
return true;
|
|
66748
|
+
if (av < bv)
|
|
66749
|
+
return false;
|
|
66750
|
+
}
|
|
66751
|
+
return false;
|
|
66752
|
+
}
|
|
66753
|
+
function getCachePath3() {
|
|
66754
|
+
return join45(getConfigDir(), CACHE_FILENAME5);
|
|
66755
|
+
}
|
|
66756
|
+
function readCache() {
|
|
66757
|
+
try {
|
|
66758
|
+
const path = getCachePath3();
|
|
66759
|
+
if (!existsSync31(path))
|
|
66760
|
+
return null;
|
|
66761
|
+
const data = JSON.parse(readFileSync29(path, "utf-8"));
|
|
66762
|
+
if (typeof data.lastCheck === "number" && isValidVersion2(data.latestVersion)) {
|
|
66763
|
+
return data;
|
|
66764
|
+
}
|
|
66765
|
+
return null;
|
|
66766
|
+
} catch {
|
|
66767
|
+
return null;
|
|
66768
|
+
}
|
|
66769
|
+
}
|
|
66770
|
+
function writeCache(cache) {
|
|
66771
|
+
try {
|
|
66772
|
+
const dir = getConfigDir();
|
|
66773
|
+
if (!existsSync31(dir)) {
|
|
66774
|
+
mkdirSync19(dir, { recursive: true, mode: 448 });
|
|
66775
|
+
}
|
|
66776
|
+
writeFileSync21(getCachePath3(), JSON.stringify(cache), { mode: 384 });
|
|
66777
|
+
} catch {}
|
|
66778
|
+
}
|
|
66779
|
+
async function fetchLatestVersion() {
|
|
66780
|
+
const controller = new AbortController;
|
|
66781
|
+
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS2);
|
|
66782
|
+
try {
|
|
66783
|
+
const resp = await fetch(REGISTRY_URL, { signal: controller.signal });
|
|
66784
|
+
if (!resp.ok)
|
|
66785
|
+
return null;
|
|
66786
|
+
const data = await resp.json();
|
|
66787
|
+
const latest = data.latest;
|
|
66788
|
+
return isValidVersion2(latest) ? latest : null;
|
|
66789
|
+
} catch {
|
|
66790
|
+
return null;
|
|
66791
|
+
} finally {
|
|
66792
|
+
clearTimeout(timeout);
|
|
66793
|
+
}
|
|
66794
|
+
}
|
|
66795
|
+
function buildUpdateHint(channel, npx = false) {
|
|
66796
|
+
if (channel === "npm" && npx) {
|
|
66797
|
+
return 'Use "npx -y @dosu/cli@latest" for the next Dosu command';
|
|
66798
|
+
}
|
|
66799
|
+
return 'Run "dosu upgrade"';
|
|
66800
|
+
}
|
|
66801
|
+
function styleHint(hint) {
|
|
66802
|
+
const match = hint.match(/^(.*)("[^"]+")(.*)$/);
|
|
66803
|
+
if (!match)
|
|
66804
|
+
return import_picocolors38.default.dim(hint);
|
|
66805
|
+
const [, before, command, after] = match;
|
|
66806
|
+
return [before && import_picocolors38.default.dim(before), import_picocolors38.default.cyan(command), after && import_picocolors38.default.dim(after)].filter(Boolean).join("");
|
|
66807
|
+
}
|
|
66808
|
+
function framedNotice(content, width) {
|
|
66809
|
+
const innerWidth = Math.max(...content.map(visibleWidth2)) + BOX_PADDING * 2;
|
|
66810
|
+
const framed = (line) => {
|
|
66811
|
+
const pad = innerWidth - visibleWidth2(line);
|
|
66812
|
+
const left = Math.floor(pad / 2);
|
|
66813
|
+
return `${import_picocolors38.default.yellow("│")}${" ".repeat(left)}${line}${" ".repeat(pad - left)}${import_picocolors38.default.yellow("│")}`;
|
|
66814
|
+
};
|
|
66815
|
+
const box = [
|
|
66816
|
+
import_picocolors38.default.yellow(`╭${"─".repeat(innerWidth)}╮`),
|
|
66817
|
+
framed(""),
|
|
66818
|
+
...content.map(framed),
|
|
66819
|
+
framed(""),
|
|
66820
|
+
import_picocolors38.default.yellow(`╰${"─".repeat(innerWidth)}╯`)
|
|
66821
|
+
];
|
|
66822
|
+
return `
|
|
66823
|
+
${centerBlock(box, width).join(`
|
|
66824
|
+
`)}
|
|
66825
|
+
`;
|
|
66826
|
+
}
|
|
66827
|
+
function versionArrow(current, latest) {
|
|
66828
|
+
return `${import_picocolors38.default.dim(current)} ${import_picocolors38.default.dim("→")} ${import_picocolors38.default.bold(brand(latest))}`;
|
|
66829
|
+
}
|
|
66830
|
+
function buildAutoUpdateNotice(current, latest, interactive, width = process.stderr.columns ?? 80) {
|
|
66831
|
+
if (interactive) {
|
|
66832
|
+
return framedNotice([
|
|
66833
|
+
`Updating Dosu: ${versionArrow(current, latest)}`,
|
|
66834
|
+
import_picocolors38.default.dim("Installing in the background; your next command uses it")
|
|
66835
|
+
], width);
|
|
66836
|
+
}
|
|
66837
|
+
return `
|
|
66838
|
+
[dosu:update] Installing Dosu ${latest} in the background (running ${current}). ` + `The next Dosu command uses it; no action needed.
|
|
66839
|
+
`;
|
|
66840
|
+
}
|
|
66841
|
+
function buildUpdateNotice(current, latest, channel, interactive, npx = false, width = process.stderr.columns ?? 80) {
|
|
66842
|
+
const hint = buildUpdateHint(channel, npx);
|
|
66843
|
+
if (interactive) {
|
|
66844
|
+
return framedNotice([`Update available: ${versionArrow(current, latest)}`, styleHint(hint)], width);
|
|
66845
|
+
}
|
|
66846
|
+
const agentAction = hint[0].toLowerCase() + hint.slice(1);
|
|
66847
|
+
const verifyCommand = npx ? "npx -y @dosu/cli@latest --version" : "dosu --version";
|
|
66848
|
+
return `
|
|
66849
|
+
[dosu:update] Update available: ${current} → ${latest}
|
|
66850
|
+
` + `Tell the user Dosu CLI is outdated. After they approve, ${agentAction}, ` + `then verify with "${verifyCommand}".
|
|
66851
|
+
`;
|
|
66852
|
+
}
|
|
66853
|
+
function getAvailableUpdate() {
|
|
66854
|
+
const cache = readCache();
|
|
66855
|
+
return cache && isNewerVersion(cache.latestVersion, VERSION) ? cache.latestVersion : null;
|
|
66856
|
+
}
|
|
66857
|
+
function handleNewerVersion(latest, notify) {
|
|
66858
|
+
const autoUpdate = startAutoUpdate(latest);
|
|
66859
|
+
if (!notify)
|
|
66860
|
+
return;
|
|
66861
|
+
const interactive = process.stderr.isTTY === true;
|
|
66862
|
+
console.error(autoUpdate === "unavailable" ? buildUpdateNotice(VERSION, latest, INSTALL_CHANNEL, interactive, isNpxInvocation()) : buildAutoUpdateNotice(VERSION, latest, interactive));
|
|
66863
|
+
}
|
|
66864
|
+
async function checkForUpdates(options = {}) {
|
|
66865
|
+
const notify = options.notify ?? true;
|
|
66866
|
+
try {
|
|
66867
|
+
const cache = readCache();
|
|
66868
|
+
const isStale = !cache || Date.now() - cache.lastCheck > CHECK_INTERVAL_MS2;
|
|
66869
|
+
if (!isStale) {
|
|
66870
|
+
if (isNewerVersion(cache.latestVersion, VERSION)) {
|
|
66871
|
+
handleNewerVersion(cache.latestVersion, notify);
|
|
66872
|
+
}
|
|
66873
|
+
return;
|
|
66874
|
+
}
|
|
66875
|
+
const latest = await fetchLatestVersion();
|
|
66876
|
+
const latestKnownVersion = latest ?? cache?.latestVersion ?? VERSION;
|
|
66877
|
+
writeCache({
|
|
66878
|
+
lastCheck: Date.now(),
|
|
66879
|
+
latestVersion: latestKnownVersion
|
|
66880
|
+
});
|
|
66881
|
+
if (latest) {
|
|
66882
|
+
logger.debug("update-check", `Cached latest version: ${latest}`);
|
|
66883
|
+
}
|
|
66884
|
+
if (isNewerVersion(latestKnownVersion, VERSION)) {
|
|
66885
|
+
handleNewerVersion(latestKnownVersion, notify);
|
|
66886
|
+
}
|
|
66887
|
+
} catch (err) {
|
|
66888
|
+
logger.error("update-check", `Update check failed: ${err}`);
|
|
66889
|
+
}
|
|
66890
|
+
}
|
|
66891
|
+
var import_picocolors38, CACHE_FILENAME5 = "update-check.json", CHECK_INTERVAL_MS2, FETCH_TIMEOUT_MS2 = 1000, REGISTRY_URL = "https://registry.npmjs.org/-/package/@dosu/cli/dist-tags", SEMVER_PATTERN, BOX_PADDING = 3;
|
|
66892
|
+
var init_update_check = __esm(() => {
|
|
66893
|
+
init_config();
|
|
66894
|
+
init_logger();
|
|
66895
|
+
init_styles();
|
|
66896
|
+
init_layout();
|
|
66897
|
+
init_auto_update();
|
|
66725
66898
|
import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
66899
|
+
CHECK_INTERVAL_MS2 = 6 * 60 * 60 * 1000;
|
|
66900
|
+
SEMVER_PATTERN = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
66726
66901
|
});
|
|
66727
66902
|
|
|
66728
66903
|
// src/cli/fatal-error.ts
|
|
@@ -69109,4 +69284,4 @@ main().catch((err) => {
|
|
|
69109
69284
|
process.exit(1);
|
|
69110
69285
|
});
|
|
69111
69286
|
|
|
69112
|
-
//# debugId=
|
|
69287
|
+
//# debugId=2a77eea3-ffbe-b0f0-6475-6e2164756e21
|