@dosu/cli 0.67.1 → 0.67.2
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 +445 -337
- 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.67.
|
|
1131
|
+
var VERSION = "0.67.2", 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 = "fa693edb-14f4-abcb-6475-6e2164756e21";
|
|
14327
14337
|
|
|
14328
14338
|
// src/telemetry/telemetry.ts
|
|
14329
14339
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -62482,6 +62492,65 @@ 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 withoutUserChoices(entry) {
|
|
62525
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry))
|
|
62526
|
+
return entry;
|
|
62527
|
+
return Object.fromEntries(Object.entries(entry).filter(([key]) => !USER_CHOICE_KEYS.has(key)));
|
|
62528
|
+
}
|
|
62529
|
+
function entryHasShape(expected, actual) {
|
|
62530
|
+
return hasShape(withoutUserChoices(expected), withoutUserChoices(actual));
|
|
62531
|
+
}
|
|
62532
|
+
var ANY = "\x00any\x00", USER_CHOICE_KEYS;
|
|
62533
|
+
var init_shape = __esm(() => {
|
|
62534
|
+
init_config();
|
|
62535
|
+
init_config_helpers();
|
|
62536
|
+
USER_CHOICE_KEYS = new Set([
|
|
62537
|
+
"disabled",
|
|
62538
|
+
"enabled",
|
|
62539
|
+
"autoApprove",
|
|
62540
|
+
"disabledTools",
|
|
62541
|
+
"timeout",
|
|
62542
|
+
"trust",
|
|
62543
|
+
"includeTools",
|
|
62544
|
+
"excludeTools",
|
|
62545
|
+
"enabled_tools",
|
|
62546
|
+
"disabled_tools",
|
|
62547
|
+
"default_tools_approval_mode",
|
|
62548
|
+
"required",
|
|
62549
|
+
"startup_timeout_sec",
|
|
62550
|
+
"tool_timeout_sec"
|
|
62551
|
+
]);
|
|
62552
|
+
});
|
|
62553
|
+
|
|
62485
62554
|
// src/mcp/providers/base.ts
|
|
62486
62555
|
function createJSONProvider(opts) {
|
|
62487
62556
|
const buildServer = opts.buildServer ?? defaultBuildServer;
|
|
@@ -62494,6 +62563,7 @@ function createJSONProvider(opts) {
|
|
|
62494
62563
|
isInstalled: () => isInstalled(opts.paths),
|
|
62495
62564
|
globalConfigPath: () => expandHome(opts.globalPath),
|
|
62496
62565
|
isConfigured: () => isJSONKeyConfigured(expandHome(opts.globalPath), opts.topKey),
|
|
62566
|
+
isCurrent: (cfg) => entryHasShape(buildServer({ url: shapeEndpoint(cfg), headers: mcpHeaders(ANY) }), readJSONServer(expandHome(opts.globalPath), opts.topKey)),
|
|
62497
62567
|
install(cfg, global2) {
|
|
62498
62568
|
const endpoint = {
|
|
62499
62569
|
url: mcpEndpoint(cfg),
|
|
@@ -62507,7 +62577,7 @@ function createJSONProvider(opts) {
|
|
|
62507
62577
|
} else {
|
|
62508
62578
|
throw new Error(`${opts.providerName} does not support local installation`);
|
|
62509
62579
|
}
|
|
62510
|
-
installJSONServer(configPath, opts.topKey, buildServer(endpoint
|
|
62580
|
+
installJSONServer(configPath, opts.topKey, buildServer(endpoint));
|
|
62511
62581
|
},
|
|
62512
62582
|
remove(global2) {
|
|
62513
62583
|
let configPath;
|
|
@@ -62530,6 +62600,7 @@ var defaultBuildServer = ({ url, headers }) => ({
|
|
|
62530
62600
|
var init_base = __esm(() => {
|
|
62531
62601
|
init_config_helpers();
|
|
62532
62602
|
init_detect();
|
|
62603
|
+
init_shape();
|
|
62533
62604
|
});
|
|
62534
62605
|
|
|
62535
62606
|
// src/mcp/providers/antigravity.ts
|
|
@@ -62581,17 +62652,13 @@ var ClaudeDesktopProvider = () => ({
|
|
|
62581
62652
|
isInstalled: () => isInstalled([join26(appSupportDir(), "Claude")]),
|
|
62582
62653
|
globalConfigPath: () => configPath(),
|
|
62583
62654
|
isConfigured: () => isJSONKeyConfigured(configPath(), "mcpServers"),
|
|
62655
|
+
isCurrent: (cfg) => entryHasShape(npxRemoteEntry(shapeEndpoint(cfg), ANY, ANY, npxPathEnv(join26(ANY, "npx"))), readJSONServer(configPath(), "mcpServers")),
|
|
62584
62656
|
install(cfg, global2) {
|
|
62585
62657
|
if (!global2)
|
|
62586
62658
|
throw new Error("Claude Desktop does not support local installation");
|
|
62587
62659
|
const url = mcpEndpoint(cfg);
|
|
62588
62660
|
const npx = findNpx();
|
|
62589
|
-
|
|
62590
|
-
installJSONServer(configPath(), "mcpServers", {
|
|
62591
|
-
command: npx,
|
|
62592
|
-
args: remote.args,
|
|
62593
|
-
env: { PATH: npxPathEnv(npx), ...remote.env }
|
|
62594
|
-
});
|
|
62661
|
+
installJSONServer(configPath(), "mcpServers", npxRemoteEntry(url, cfg.active_account?.target?.api_key, npx, npxPathEnv(npx)));
|
|
62595
62662
|
},
|
|
62596
62663
|
remove(global2) {
|
|
62597
62664
|
if (!global2)
|
|
@@ -62602,6 +62669,7 @@ var ClaudeDesktopProvider = () => ({
|
|
|
62602
62669
|
var init_claude_desktop = __esm(() => {
|
|
62603
62670
|
init_config_helpers();
|
|
62604
62671
|
init_detect();
|
|
62672
|
+
init_shape();
|
|
62605
62673
|
});
|
|
62606
62674
|
|
|
62607
62675
|
// src/mcp/providers/cline.ts
|
|
@@ -62673,25 +62741,70 @@ function writeTOML(path, content) {
|
|
|
62673
62741
|
function tomlString(value) {
|
|
62674
62742
|
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
|
|
62675
62743
|
}
|
|
62744
|
+
function tomlValue(value) {
|
|
62745
|
+
return Array.isArray(value) ? `[${value.map(tomlString).join(", ")}]` : tomlString(value);
|
|
62746
|
+
}
|
|
62747
|
+
function dosuEntry(url, apiKey, npx, path) {
|
|
62748
|
+
return npxRemoteEntry(url, apiKey, npx, path);
|
|
62749
|
+
}
|
|
62750
|
+
function renderDosuEntry(entry) {
|
|
62751
|
+
const tables = [["mcp_servers.dosu", {}]];
|
|
62752
|
+
for (const [key, value] of Object.entries(entry)) {
|
|
62753
|
+
if (typeof value === "string" || Array.isArray(value))
|
|
62754
|
+
tables[0][1][key] = value;
|
|
62755
|
+
else
|
|
62756
|
+
tables.push([`mcp_servers.dosu.${key}`, value]);
|
|
62757
|
+
}
|
|
62758
|
+
return tables.map(([name, keys]) => {
|
|
62759
|
+
const lines = Object.entries(keys).map(([key, value]) => `${key} = ${tomlValue(value)}`);
|
|
62760
|
+
return `
|
|
62761
|
+
[${name}]
|
|
62762
|
+
${lines.join(`
|
|
62763
|
+
`)}
|
|
62764
|
+
`;
|
|
62765
|
+
}).join("");
|
|
62766
|
+
}
|
|
62767
|
+
function isToolApproval(name) {
|
|
62768
|
+
return name.startsWith("mcp_servers.dosu.tools.");
|
|
62769
|
+
}
|
|
62770
|
+
function readDosuEntry(content) {
|
|
62771
|
+
let entry;
|
|
62772
|
+
let table;
|
|
62773
|
+
for (const line of content.split(`
|
|
62774
|
+
`)) {
|
|
62775
|
+
const name = sectionName(line);
|
|
62776
|
+
if (name !== null) {
|
|
62777
|
+
table = undefined;
|
|
62778
|
+
if (!isDosuSection(name) || isToolApproval(name))
|
|
62779
|
+
continue;
|
|
62780
|
+
entry ??= {};
|
|
62781
|
+
if (name === "mcp_servers.dosu") {
|
|
62782
|
+
table = entry;
|
|
62783
|
+
} else {
|
|
62784
|
+
table = {};
|
|
62785
|
+
entry[name.slice("mcp_servers.dosu.".length)] = table;
|
|
62786
|
+
}
|
|
62787
|
+
continue;
|
|
62788
|
+
}
|
|
62789
|
+
const text = line.trim();
|
|
62790
|
+
if (!table || !text || text.startsWith("#"))
|
|
62791
|
+
continue;
|
|
62792
|
+
const eq = text.indexOf("=");
|
|
62793
|
+
const key = eq === -1 ? text : text.slice(0, eq).trim();
|
|
62794
|
+
const raw = eq === -1 ? "" : text.slice(eq + 1).trim();
|
|
62795
|
+
try {
|
|
62796
|
+
table[key] = JSON.parse(raw);
|
|
62797
|
+
} catch {
|
|
62798
|
+
table[key] = raw;
|
|
62799
|
+
}
|
|
62800
|
+
}
|
|
62801
|
+
return entry;
|
|
62802
|
+
}
|
|
62676
62803
|
function installDosuToTOML(path, cfg) {
|
|
62677
|
-
|
|
62678
|
-
content = removeDosuFromTOML(content);
|
|
62804
|
+
const content = removeDosuFromTOML(readTOML(path));
|
|
62679
62805
|
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);
|
|
62806
|
+
const entry = dosuEntry(mcpEndpoint(cfg), cfg.active_account?.target?.api_key, npx, npxPathEnv(npx));
|
|
62807
|
+
writeTOML(path, content + renderDosuEntry(entry));
|
|
62695
62808
|
}
|
|
62696
62809
|
function sectionName(line) {
|
|
62697
62810
|
const header = line.trim();
|
|
@@ -62769,6 +62882,7 @@ var REMOTE_HTTP_KEY, CodexProvider = () => ({
|
|
|
62769
62882
|
const content = readTOML(join29(codexHome3(), "config.toml"));
|
|
62770
62883
|
return content.includes("[mcp_servers.dosu]");
|
|
62771
62884
|
},
|
|
62885
|
+
isCurrent: (cfg) => entryHasShape(dosuEntry(shapeEndpoint(cfg), ANY, ANY, npxPathEnv(join29(ANY, "npx"))), readDosuEntry(readTOML(join29(codexHome3(), "config.toml")))),
|
|
62772
62886
|
install(cfg, global2) {
|
|
62773
62887
|
if (cfg.mode !== MODE_OSS && !cfg.active_account?.target?.deployment_id)
|
|
62774
62888
|
throw new Error("deployment ID is required");
|
|
@@ -62793,11 +62907,15 @@ var init_codex = __esm(() => {
|
|
|
62793
62907
|
init_config();
|
|
62794
62908
|
init_config_helpers();
|
|
62795
62909
|
init_detect();
|
|
62910
|
+
init_shape();
|
|
62796
62911
|
REMOTE_HTTP_KEY = /^(url|type|bearer_token_env_var)\s*=/;
|
|
62797
62912
|
});
|
|
62798
62913
|
|
|
62799
62914
|
// src/mcp/providers/copilot.ts
|
|
62800
62915
|
import { join as join30 } from "node:path";
|
|
62916
|
+
function globalServer(url, apiKey) {
|
|
62917
|
+
return { type: "http", url, tools: ["*"], headers: mcpHeaders(apiKey) };
|
|
62918
|
+
}
|
|
62801
62919
|
function globalPath() {
|
|
62802
62920
|
if (process.env.XDG_CONFIG_HOME) {
|
|
62803
62921
|
return join30(process.env.XDG_CONFIG_HOME, "mcp-config.json");
|
|
@@ -62813,16 +62931,11 @@ var CopilotProvider = () => ({
|
|
|
62813
62931
|
isInstalled: () => isInstalled([expandHome("~/.copilot")]),
|
|
62814
62932
|
globalConfigPath: () => globalPath(),
|
|
62815
62933
|
isConfigured: () => isJSONKeyConfigured(globalPath(), "mcpServers"),
|
|
62934
|
+
isCurrent: (cfg) => entryHasShape(globalServer(shapeEndpoint(cfg), ANY), readJSONServer(globalPath(), "mcpServers")),
|
|
62816
62935
|
install(cfg, global2) {
|
|
62817
62936
|
const url = mcpEndpoint(cfg);
|
|
62818
62937
|
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);
|
|
62938
|
+
installJSONServer(globalPath(), "mcpServers", globalServer(url, cfg.active_account?.target?.api_key));
|
|
62826
62939
|
} else {
|
|
62827
62940
|
const configPath = join30(process.cwd(), ".vscode", "mcp.json");
|
|
62828
62941
|
const server = {
|
|
@@ -62845,6 +62958,7 @@ var CopilotProvider = () => ({
|
|
|
62845
62958
|
var init_copilot = __esm(() => {
|
|
62846
62959
|
init_config_helpers();
|
|
62847
62960
|
init_detect();
|
|
62961
|
+
init_shape();
|
|
62848
62962
|
});
|
|
62849
62963
|
|
|
62850
62964
|
// src/mcp/providers/cursor.ts
|
|
@@ -62937,6 +63051,9 @@ var init_manual = __esm(() => {
|
|
|
62937
63051
|
// src/mcp/providers/mcporter.ts
|
|
62938
63052
|
import { existsSync as existsSync23 } from "node:fs";
|
|
62939
63053
|
import { join as join34 } from "node:path";
|
|
63054
|
+
function server(url, apiKey) {
|
|
63055
|
+
return { type: "http", url, headers: mcpHeaders(apiKey) };
|
|
63056
|
+
}
|
|
62940
63057
|
function resolveGlobalConfigPath() {
|
|
62941
63058
|
const jsonPath = expandHome("~/.mcporter/mcporter.json");
|
|
62942
63059
|
if (existsSync23(jsonPath))
|
|
@@ -62955,14 +63072,10 @@ var MCPorterProvider = () => ({
|
|
|
62955
63072
|
isInstalled: () => isInstalled(["~/.mcporter"]),
|
|
62956
63073
|
globalConfigPath: () => resolveGlobalConfigPath(),
|
|
62957
63074
|
isConfigured: () => isJSONKeyConfigured(resolveGlobalConfigPath(), "mcpServers"),
|
|
63075
|
+
isCurrent: (cfg) => entryHasShape(server(shapeEndpoint(cfg), ANY), readJSONServer(resolveGlobalConfigPath(), "mcpServers")),
|
|
62958
63076
|
install(cfg, global2) {
|
|
62959
63077
|
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);
|
|
63078
|
+
installJSONServer(configPath, "mcpServers", server(mcpEndpoint(cfg), cfg.active_account?.target?.api_key));
|
|
62966
63079
|
},
|
|
62967
63080
|
remove(global2) {
|
|
62968
63081
|
const configPath = global2 ? resolveGlobalConfigPath() : join34(process.cwd(), "config", "mcporter.json");
|
|
@@ -62972,6 +63085,7 @@ var MCPorterProvider = () => ({
|
|
|
62972
63085
|
var init_mcporter = __esm(() => {
|
|
62973
63086
|
init_config_helpers();
|
|
62974
63087
|
init_detect();
|
|
63088
|
+
init_shape();
|
|
62975
63089
|
});
|
|
62976
63090
|
|
|
62977
63091
|
// src/mcp/providers/opencode.ts
|
|
@@ -63085,6 +63199,7 @@ var ZedProvider = (legacyPath = legacyDarwinSettingsPath()) => {
|
|
|
63085
63199
|
return provider;
|
|
63086
63200
|
return {
|
|
63087
63201
|
...provider,
|
|
63202
|
+
isCurrent: (cfg) => provider.isCurrent(cfg) && readJSONServer(legacyPath, "context_servers") === undefined,
|
|
63088
63203
|
install(cfg, global2) {
|
|
63089
63204
|
provider.install(cfg, global2);
|
|
63090
63205
|
if (global2)
|
|
@@ -63163,9 +63278,21 @@ function configuredProviders() {
|
|
|
63163
63278
|
}
|
|
63164
63279
|
});
|
|
63165
63280
|
}
|
|
63281
|
+
function staleProviders(cfg) {
|
|
63282
|
+
return configuredProviders().filter((provider) => {
|
|
63283
|
+
try {
|
|
63284
|
+
return !provider.isCurrent(cfg);
|
|
63285
|
+
} catch {
|
|
63286
|
+
return true;
|
|
63287
|
+
}
|
|
63288
|
+
});
|
|
63289
|
+
}
|
|
63166
63290
|
function refreshConfiguredProviders(cfg) {
|
|
63291
|
+
return refreshProviders(cfg, configuredProviders());
|
|
63292
|
+
}
|
|
63293
|
+
function refreshProviders(cfg, providers) {
|
|
63167
63294
|
const result = { updated: [], failed: [] };
|
|
63168
|
-
for (const provider of
|
|
63295
|
+
for (const provider of providers) {
|
|
63169
63296
|
try {
|
|
63170
63297
|
provider.install(cfg, true);
|
|
63171
63298
|
logger.info("mcp", `Refreshed ${provider.name()} MCP entry`);
|
|
@@ -63377,199 +63504,18 @@ var init_auto_update = __esm(() => {
|
|
|
63377
63504
|
VERSION_PATTERN = /^[0-9A-Za-z.+-]{1,64}$/;
|
|
63378
63505
|
});
|
|
63379
63506
|
|
|
63380
|
-
// src/version/
|
|
63507
|
+
// src/version/mcp-refresh-check.ts
|
|
63381
63508
|
import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync24, writeFileSync as writeFileSync16 } from "node:fs";
|
|
63382
63509
|
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
63510
|
function getCachePath2() {
|
|
63404
63511
|
return join40(getConfigDir(), CACHE_FILENAME3);
|
|
63405
63512
|
}
|
|
63406
|
-
function
|
|
63513
|
+
function readMcpRefreshCache() {
|
|
63407
63514
|
try {
|
|
63408
63515
|
const path = getCachePath2();
|
|
63409
63516
|
if (!existsSync25(path))
|
|
63410
63517
|
return null;
|
|
63411
63518
|
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
63519
|
if (typeof data?.version === "string")
|
|
63574
63520
|
return { version: data.version };
|
|
63575
63521
|
return null;
|
|
@@ -63580,10 +63526,10 @@ function readMcpRefreshCache() {
|
|
|
63580
63526
|
function writeMcpRefreshCache(cache) {
|
|
63581
63527
|
try {
|
|
63582
63528
|
const dir = getConfigDir();
|
|
63583
|
-
if (!
|
|
63584
|
-
|
|
63529
|
+
if (!existsSync25(dir)) {
|
|
63530
|
+
mkdirSync15(dir, { recursive: true, mode: 448 });
|
|
63585
63531
|
}
|
|
63586
|
-
|
|
63532
|
+
writeFileSync16(getCachePath2(), JSON.stringify(cache), { mode: 384 });
|
|
63587
63533
|
} catch {}
|
|
63588
63534
|
}
|
|
63589
63535
|
function canRefreshMcp(cfg) {
|
|
@@ -63594,26 +63540,21 @@ function canRefreshMcp(cfg) {
|
|
|
63594
63540
|
}
|
|
63595
63541
|
function displayNotice(names) {
|
|
63596
63542
|
console.error(`
|
|
63597
|
-
${
|
|
63598
|
-
` + `${
|
|
63543
|
+
${import_picocolors32.default.green(`✓ Dosu ${VERSION}: refreshed MCP config for ${names.join(", ")}`)}
|
|
63544
|
+
` + `${import_picocolors32.default.dim(` Run ${import_picocolors32.default.cyan('"dosu setup"')} to also update hooks and rules, then restart your AI agents.`)}
|
|
63599
63545
|
`);
|
|
63600
63546
|
}
|
|
63601
63547
|
function checkForMcpRefresh(options = {}) {
|
|
63602
63548
|
const notify = options.notify ?? true;
|
|
63603
63549
|
try {
|
|
63604
|
-
|
|
63605
|
-
if (previous === VERSION)
|
|
63606
|
-
return;
|
|
63607
|
-
if (!needsMcpRefresh(previous, VERSION)) {
|
|
63608
|
-
writeMcpRefreshCache({ version: VERSION });
|
|
63550
|
+
if (readMcpRefreshCache()?.version === VERSION)
|
|
63609
63551
|
return;
|
|
63610
|
-
}
|
|
63611
63552
|
const cfg = loadConfigNonBlocking();
|
|
63612
63553
|
if (!cfg || !canRefreshMcp(cfg)) {
|
|
63613
63554
|
logger.debug("mcp-refresh", "Skipping MCP refresh: no API key or deployment configured");
|
|
63614
63555
|
return;
|
|
63615
63556
|
}
|
|
63616
|
-
const result =
|
|
63557
|
+
const result = refreshProviders(cfg, staleProviders(cfg));
|
|
63617
63558
|
writeMcpRefreshCache({ version: VERSION });
|
|
63618
63559
|
logger.info("mcp-refresh", `Version ${VERSION}: refreshed ${result.updated.length}, failed ${result.failed.length}`);
|
|
63619
63560
|
if (notify && result.updated.length > 0) {
|
|
@@ -63623,24 +63564,19 @@ function checkForMcpRefresh(options = {}) {
|
|
|
63623
63564
|
logger.error("mcp-refresh", `MCP refresh check failed: ${err}`);
|
|
63624
63565
|
}
|
|
63625
63566
|
}
|
|
63626
|
-
var
|
|
63567
|
+
var import_picocolors32, CACHE_FILENAME3 = "mcp-refresh.json";
|
|
63627
63568
|
var init_mcp_refresh_check = __esm(() => {
|
|
63628
63569
|
init_config();
|
|
63629
63570
|
init_logger();
|
|
63630
63571
|
init_refresh();
|
|
63631
|
-
|
|
63632
|
-
import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
63633
|
-
MCP_FORMAT_CHANGES = [
|
|
63634
|
-
"0.53.0",
|
|
63635
|
-
"0.62.0"
|
|
63636
|
-
];
|
|
63572
|
+
import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
63637
63573
|
});
|
|
63638
63574
|
|
|
63639
63575
|
// src/version/skill-update-check.ts
|
|
63640
63576
|
function displayNotice2() {
|
|
63641
63577
|
console.error(`
|
|
63642
|
-
${
|
|
63643
|
-
` + `${
|
|
63578
|
+
${import_picocolors33.default.green(`✓ Dosu ${VERSION}: refreshed the bundled agent skills`)}
|
|
63579
|
+
` + `${import_picocolors33.default.dim(" Restart your AI agents to pick up the new skill content.")}
|
|
63644
63580
|
`);
|
|
63645
63581
|
}
|
|
63646
63582
|
function checkForSkillUpdates(options = {}) {
|
|
@@ -63661,11 +63597,11 @@ function checkForSkillUpdates(options = {}) {
|
|
|
63661
63597
|
logger.error("skill-update-check", `Skill update check failed: ${err}`);
|
|
63662
63598
|
}
|
|
63663
63599
|
}
|
|
63664
|
-
var
|
|
63600
|
+
var import_picocolors33;
|
|
63665
63601
|
var init_skill_update_check = __esm(() => {
|
|
63666
63602
|
init_skill();
|
|
63667
63603
|
init_logger();
|
|
63668
|
-
|
|
63604
|
+
import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
63669
63605
|
});
|
|
63670
63606
|
|
|
63671
63607
|
// src/auth/errors.ts
|
|
@@ -63731,15 +63667,15 @@ function createLogFollower(path, emit) {
|
|
|
63731
63667
|
var init_follow = () => {};
|
|
63732
63668
|
|
|
63733
63669
|
// src/sessions/session-title.ts
|
|
63734
|
-
import { existsSync as
|
|
63670
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync16, readFileSync as readFileSync25, renameSync as renameSync7, statSync as statSync10, writeFileSync as writeFileSync17 } from "node:fs";
|
|
63735
63671
|
import { homedir as homedir11 } from "node:os";
|
|
63736
|
-
import { join as
|
|
63672
|
+
import { join as join41 } from "node:path";
|
|
63737
63673
|
function cachePath2(configDir) {
|
|
63738
|
-
return
|
|
63674
|
+
return join41(configDir, CACHE_FILENAME4);
|
|
63739
63675
|
}
|
|
63740
63676
|
function loadCacheFile2(configDir) {
|
|
63741
63677
|
try {
|
|
63742
|
-
const raw = JSON.parse(
|
|
63678
|
+
const raw = JSON.parse(readFileSync25(cachePath2(configDir), "utf-8"));
|
|
63743
63679
|
if (raw.schema_version !== CACHE_SCHEMA_VERSION2 || typeof raw.entries !== "object")
|
|
63744
63680
|
return {};
|
|
63745
63681
|
return raw.entries;
|
|
@@ -63749,12 +63685,12 @@ function loadCacheFile2(configDir) {
|
|
|
63749
63685
|
}
|
|
63750
63686
|
function saveCacheFile2(configDir, entries) {
|
|
63751
63687
|
try {
|
|
63752
|
-
if (!
|
|
63753
|
-
|
|
63688
|
+
if (!existsSync26(configDir))
|
|
63689
|
+
mkdirSync16(configDir, { recursive: true, mode: 448 });
|
|
63754
63690
|
const path = cachePath2(configDir);
|
|
63755
63691
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
63756
63692
|
const file = { schema_version: CACHE_SCHEMA_VERSION2, entries };
|
|
63757
|
-
|
|
63693
|
+
writeFileSync17(tmp, JSON.stringify(file), { mode: 384 });
|
|
63758
63694
|
renameSync7(tmp, path);
|
|
63759
63695
|
} catch {}
|
|
63760
63696
|
}
|
|
@@ -63787,15 +63723,15 @@ function claudeSummaryFromHead(text) {
|
|
|
63787
63723
|
}
|
|
63788
63724
|
return null;
|
|
63789
63725
|
}
|
|
63790
|
-
function reconstructSession(harness, id, slug, home = homedir11(), exists =
|
|
63726
|
+
function reconstructSession(harness, id, slug, home = homedir11(), exists = existsSync26) {
|
|
63791
63727
|
if (!slug)
|
|
63792
63728
|
return null;
|
|
63793
63729
|
const candidates = [];
|
|
63794
63730
|
if (harness === "claude") {
|
|
63795
|
-
candidates.push(
|
|
63731
|
+
candidates.push(join41(home, ".claude", "projects", slug, `${id}.jsonl`));
|
|
63796
63732
|
} else if (harness === "cursor") {
|
|
63797
|
-
const project =
|
|
63798
|
-
candidates.push(
|
|
63733
|
+
const project = join41(home, ".cursor", "projects", slug);
|
|
63734
|
+
candidates.push(join41(project, "agent-transcripts", id, `${id}.jsonl`), join41(project, "agent-transcripts", `${id}.jsonl`));
|
|
63799
63735
|
} else {
|
|
63800
63736
|
return null;
|
|
63801
63737
|
}
|
|
@@ -63807,7 +63743,7 @@ function reconstructSession(harness, id, slug, home = homedir11(), exists = exis
|
|
|
63807
63743
|
}
|
|
63808
63744
|
function readHead2(path) {
|
|
63809
63745
|
try {
|
|
63810
|
-
return
|
|
63746
|
+
return readFileSync25(path, "utf-8").slice(0, 128 * 1024);
|
|
63811
63747
|
} catch {
|
|
63812
63748
|
return null;
|
|
63813
63749
|
}
|
|
@@ -63858,7 +63794,7 @@ function createSessionTitleResolver(configDir = getConfigDir(), deps = {}) {
|
|
|
63858
63794
|
}
|
|
63859
63795
|
};
|
|
63860
63796
|
}
|
|
63861
|
-
var
|
|
63797
|
+
var CACHE_FILENAME4 = "session-titles.json", CACHE_SCHEMA_VERSION2 = 3, HEAD_LINES2 = 50, SESSION_NAME_MAX = 80;
|
|
63862
63798
|
var init_session_title = __esm(() => {
|
|
63863
63799
|
init_config();
|
|
63864
63800
|
init_read();
|
|
@@ -63887,7 +63823,7 @@ var init_alt_screen = __esm(() => {
|
|
|
63887
63823
|
});
|
|
63888
63824
|
|
|
63889
63825
|
// src/tui/activity-view.ts
|
|
63890
|
-
import { existsSync as
|
|
63826
|
+
import { existsSync as existsSync27, readFileSync as readFileSync26 } from "node:fs";
|
|
63891
63827
|
import { basename as basename6 } from "node:path";
|
|
63892
63828
|
function reduceActivityViewKey(key) {
|
|
63893
63829
|
if (key === "q" || key === ESC7 || key === CTRL_C4)
|
|
@@ -64028,15 +63964,15 @@ function statusLine(status) {
|
|
|
64028
63964
|
if (status.running) {
|
|
64029
63965
|
const since = status.startedAt ? ` · since ${localTime(status.startedAt)}` : "";
|
|
64030
63966
|
const pid = status.pid !== undefined ? ` (pid ${status.pid})` : "";
|
|
64031
|
-
return `\uD83D\uDCDA ${
|
|
63967
|
+
return `\uD83D\uDCDA ${import_picocolors34.default.bold(brand("Studying sessions..."))}${import_picocolors34.default.dim(`${pid}${since}`)}`;
|
|
64032
63968
|
}
|
|
64033
63969
|
if (status.state.paused) {
|
|
64034
|
-
return `${
|
|
63970
|
+
return `${import_picocolors34.default.yellow("○")} ${import_picocolors34.default.bold("Paused")} ${import_picocolors34.default.dim("· studying stays off until you resume")}`;
|
|
64035
63971
|
}
|
|
64036
63972
|
if (status.staleLock) {
|
|
64037
|
-
return `${
|
|
63973
|
+
return `${import_picocolors34.default.yellow("○")} ${import_picocolors34.default.bold("Not running")} ${import_picocolors34.default.dim("· a previous run exited without cleaning up")}`;
|
|
64038
63974
|
}
|
|
64039
|
-
return `${
|
|
63975
|
+
return `${import_picocolors34.default.dim("○")} ${import_picocolors34.default.bold("Idle")} ${import_picocolors34.default.dim("· hooks study new sessions automatically")}`;
|
|
64040
63976
|
}
|
|
64041
63977
|
function progressLine(done, ready, width, notes = 0) {
|
|
64042
63978
|
const total = done + ready;
|
|
@@ -64045,7 +63981,7 @@ function progressLine(done, ready, width, notes = 0) {
|
|
|
64045
63981
|
const cells = Math.max(10, Math.min(30, width - 44));
|
|
64046
63982
|
const ratio = Math.max(0, Math.min(1, done / total));
|
|
64047
63983
|
const filled = Math.min(cells, Math.round(ratio * cells));
|
|
64048
|
-
const bar = brand("█".repeat(filled)) +
|
|
63984
|
+
const bar = brand("█".repeat(filled)) + import_picocolors34.default.dim("░".repeat(cells - filled));
|
|
64049
63985
|
const pct = Math.floor(ratio * 100);
|
|
64050
63986
|
const suffix = notes > 0 ? ` · ${notes} suggested page${notes === 1 ? "" : "s"}` : "";
|
|
64051
63987
|
return `${bar} ${done}/${total} studied · ${pct}%${suffix}`;
|
|
@@ -64084,17 +64020,17 @@ function confirmBox(queuedCount, backlog, width, mode = "start") {
|
|
|
64084
64020
|
const verb = mode === "clear" ? "clear" : mode === "stop" ? "stop" : mode === "resume" ? "resume" : "start";
|
|
64085
64021
|
const maxInner = Math.max(20, Math.min(width, contentWidth()) - 4);
|
|
64086
64022
|
const rows = [
|
|
64087
|
-
|
|
64088
|
-
...wrapLine(scope, maxInner, "").map((line) =>
|
|
64023
|
+
import_picocolors34.default.bold(brand(title)),
|
|
64024
|
+
...wrapLine(scope, maxInner, "").map((line) => import_picocolors34.default.dim(line)),
|
|
64089
64025
|
"",
|
|
64090
|
-
`${
|
|
64026
|
+
`${import_picocolors34.default.bold("enter")} ${verb} · ${import_picocolors34.default.bold("esc")} cancel`
|
|
64091
64027
|
];
|
|
64092
64028
|
const inner = Math.min(maxInner, Math.max(...rows.map(visibleWidth2)));
|
|
64093
64029
|
const pad = (row) => row + " ".repeat(Math.max(0, inner - visibleWidth2(row)));
|
|
64094
64030
|
return [
|
|
64095
|
-
|
|
64096
|
-
...rows.map((row) => `${
|
|
64097
|
-
|
|
64031
|
+
import_picocolors34.default.dim(`╭${"─".repeat(inner + 2)}╮`),
|
|
64032
|
+
...rows.map((row) => `${import_picocolors34.default.dim("│")} ${pad(row)} ${import_picocolors34.default.dim("│")}`),
|
|
64033
|
+
import_picocolors34.default.dim(`╰${"─".repeat(inner + 2)}╯`)
|
|
64098
64034
|
];
|
|
64099
64035
|
}
|
|
64100
64036
|
function buildActivityFrame(status, activity, width, backlog = null, pane = DEFAULT_PANE, queued = [], studiedBeforeRun = 0, open = [], runProgress = null, projectNames = {}, sessionNames = {}, frameLines) {
|
|
@@ -64110,7 +64046,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
64110
64046
|
progress = progressLine(studiedDelta + stepDone, Math.max(0, backlog.ready - stepDone), width, runProgress?.notes ?? 0);
|
|
64111
64047
|
}
|
|
64112
64048
|
const refusal = !status.running && status.state.last_refusal;
|
|
64113
|
-
const refusalLines = refusal ? wrapLine(`! Studying paused: ${refusal.message} (${localTime(refusal.at)})`, width).map((line) =>
|
|
64049
|
+
const refusalLines = refusal ? wrapLine(`! Studying paused: ${refusal.message} (${localTime(refusal.at)})`, width).map((line) => import_picocolors34.default.yellow(line)) : [];
|
|
64114
64050
|
const fullRows = Boolean(pane.fullRows);
|
|
64115
64051
|
const withName = (item, key) => projectNames[key] ? { ...item, project: projectNames[key] } : item;
|
|
64116
64052
|
const latestPass = new Map;
|
|
@@ -64136,8 +64072,8 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
64136
64072
|
breadcrumb(["home", "activity"], width),
|
|
64137
64073
|
"",
|
|
64138
64074
|
statusLine(status),
|
|
64139
|
-
|
|
64140
|
-
...queueDetail.length > 0 ? wrapLine(queueDetail.join(" · "), width).map((line) =>
|
|
64075
|
+
import_picocolors34.default.dim(studied),
|
|
64076
|
+
...queueDetail.length > 0 ? wrapLine(queueDetail.join(" · "), width).map((line) => import_picocolors34.default.dim(line)) : [],
|
|
64141
64077
|
...progress ? [progress] : [],
|
|
64142
64078
|
...refusalLines,
|
|
64143
64079
|
"",
|
|
@@ -64153,7 +64089,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
64153
64089
|
status.running ? "s stop" : status.state.paused ? "s resume" : "s sync now",
|
|
64154
64090
|
...!status.running && status.state.watermark ? ["c clear"] : [],
|
|
64155
64091
|
"esc back"
|
|
64156
|
-
].join(" · "), width, "").map((line) =>
|
|
64092
|
+
].join(" · "), width, "").map((line) => import_picocolors34.default.dim(line))
|
|
64157
64093
|
]
|
|
64158
64094
|
];
|
|
64159
64095
|
const defaultHeight = fullRows ? ACTIVITY_VIEW_FULL_LIST_ROWS : ACTIVITY_VIEW_LIST_LINES;
|
|
@@ -64166,7 +64102,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
64166
64102
|
({ visible, above, below } = windowList(source, pane.scroll, height));
|
|
64167
64103
|
display = visible.flatMap((row) => wrapRow(row, width));
|
|
64168
64104
|
}
|
|
64169
|
-
const listRows = display.length > 0 ? display.map((row) =>
|
|
64105
|
+
const listRows = display.length > 0 ? display.map((row) => import_picocolors34.default.dim(row)) : [import_picocolors34.default.dim(empty)];
|
|
64170
64106
|
const scrollParts = [];
|
|
64171
64107
|
if (above > 0)
|
|
64172
64108
|
scrollParts.push(`↑ ${above} earlier`);
|
|
@@ -64175,7 +64111,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
64175
64111
|
const lines = [
|
|
64176
64112
|
...header,
|
|
64177
64113
|
...listRows,
|
|
64178
|
-
...scrollParts.length > 0 ? [
|
|
64114
|
+
...scrollParts.length > 0 ? [import_picocolors34.default.dim(clip(scrollParts.join(" · "), width))] : [],
|
|
64179
64115
|
...footer
|
|
64180
64116
|
];
|
|
64181
64117
|
return { lines, listHeight: height };
|
|
@@ -64208,7 +64144,7 @@ function createRowNamer() {
|
|
|
64208
64144
|
names.titles[key] = t;
|
|
64209
64145
|
};
|
|
64210
64146
|
for (const s of [...backlog.queued, ...backlog.open]) {
|
|
64211
|
-
if (!
|
|
64147
|
+
if (!existsSync27(s.path))
|
|
64212
64148
|
continue;
|
|
64213
64149
|
const key = `${s.harness}/${s.id}`;
|
|
64214
64150
|
const dir = dirs.resolve(s);
|
|
@@ -64245,7 +64181,7 @@ function createRowNamer() {
|
|
|
64245
64181
|
}
|
|
64246
64182
|
function defaultReadLog2() {
|
|
64247
64183
|
try {
|
|
64248
|
-
return
|
|
64184
|
+
return readFileSync26(logger.getLogPath(), "utf-8");
|
|
64249
64185
|
} catch {
|
|
64250
64186
|
return "";
|
|
64251
64187
|
}
|
|
@@ -64430,7 +64366,7 @@ ${CLEAR_BELOW}`);
|
|
|
64430
64366
|
input.on("data", onData);
|
|
64431
64367
|
});
|
|
64432
64368
|
}
|
|
64433
|
-
var
|
|
64369
|
+
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
64370
|
var init_activity_view = __esm(() => {
|
|
64435
64371
|
init_follow();
|
|
64436
64372
|
init_logger();
|
|
@@ -64445,7 +64381,7 @@ var init_activity_view = __esm(() => {
|
|
|
64445
64381
|
init_alt_screen();
|
|
64446
64382
|
init_layout();
|
|
64447
64383
|
init_menu();
|
|
64448
|
-
|
|
64384
|
+
import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
64449
64385
|
ESC7 = String.fromCharCode(27);
|
|
64450
64386
|
HIDE_CURSOR3 = `${ESC7}[?25l`;
|
|
64451
64387
|
SHOW_CURSOR3 = `${ESC7}[?25h`;
|
|
@@ -64462,14 +64398,14 @@ var init_activity_view = __esm(() => {
|
|
|
64462
64398
|
});
|
|
64463
64399
|
|
|
64464
64400
|
// src/rules/installer.ts
|
|
64465
|
-
import { existsSync as
|
|
64401
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync27, unlinkSync as unlinkSync5, writeFileSync as writeFileSync18 } from "node:fs";
|
|
64466
64402
|
import { homedir as homedir12 } from "node:os";
|
|
64467
|
-
import { dirname as dirname12, join as
|
|
64403
|
+
import { dirname as dirname12, join as join42 } from "node:path";
|
|
64468
64404
|
function claudeConfigDir4() {
|
|
64469
|
-
return process.env.CLAUDE_CONFIG_DIR ||
|
|
64405
|
+
return process.env.CLAUDE_CONFIG_DIR || join42(homedir12(), ".claude");
|
|
64470
64406
|
}
|
|
64471
64407
|
function codexHome4() {
|
|
64472
|
-
return process.env.CODEX_HOME ||
|
|
64408
|
+
return process.env.CODEX_HOME || join42(homedir12(), ".codex");
|
|
64473
64409
|
}
|
|
64474
64410
|
function isRuleAgent(agent) {
|
|
64475
64411
|
return Object.hasOwn(RULE_TARGETS, agent);
|
|
@@ -64495,17 +64431,17 @@ async function fetchDosuRule(fetchImpl = globalThis.fetch) {
|
|
|
64495
64431
|
return normalizeRule(FALLBACK_DOSU_RULE);
|
|
64496
64432
|
}
|
|
64497
64433
|
function ensureParent(path) {
|
|
64498
|
-
|
|
64434
|
+
mkdirSync17(dirname12(path), { recursive: true });
|
|
64499
64435
|
}
|
|
64500
64436
|
function writeIfChanged(path, content) {
|
|
64501
|
-
if (!
|
|
64437
|
+
if (!existsSync28(path)) {
|
|
64502
64438
|
ensureParent(path);
|
|
64503
|
-
|
|
64439
|
+
writeFileSync18(path, content, "utf-8");
|
|
64504
64440
|
return "created";
|
|
64505
64441
|
}
|
|
64506
|
-
if (
|
|
64442
|
+
if (readFileSync27(path, "utf-8") === content)
|
|
64507
64443
|
return "unchanged";
|
|
64508
|
-
|
|
64444
|
+
writeFileSync18(path, content, "utf-8");
|
|
64509
64445
|
return "updated";
|
|
64510
64446
|
}
|
|
64511
64447
|
function findSection(content) {
|
|
@@ -64531,14 +64467,14 @@ function buildSection(content, lineEnding = `
|
|
|
64531
64467
|
return `${DOSU_RULE_SECTION_START}${lineEnding}${body}${lineEnding}${DOSU_RULE_SECTION_END}`;
|
|
64532
64468
|
}
|
|
64533
64469
|
function upsertSection(path, content) {
|
|
64534
|
-
if (!
|
|
64470
|
+
if (!existsSync28(path)) {
|
|
64535
64471
|
const section = buildSection(content);
|
|
64536
64472
|
ensureParent(path);
|
|
64537
|
-
|
|
64473
|
+
writeFileSync18(path, `${section}
|
|
64538
64474
|
`, "utf-8");
|
|
64539
64475
|
return "created";
|
|
64540
64476
|
}
|
|
64541
|
-
const existing =
|
|
64477
|
+
const existing = readFileSync27(path, "utf-8");
|
|
64542
64478
|
const lineEnding = lineEndingFor(existing);
|
|
64543
64479
|
const section = buildSection(content, lineEnding);
|
|
64544
64480
|
const location = findSection(existing);
|
|
@@ -64551,7 +64487,7 @@ function upsertSection(path, content) {
|
|
|
64551
64487
|
}
|
|
64552
64488
|
if (next === existing)
|
|
64553
64489
|
return "unchanged";
|
|
64554
|
-
|
|
64490
|
+
writeFileSync18(path, next, "utf-8");
|
|
64555
64491
|
return "updated";
|
|
64556
64492
|
}
|
|
64557
64493
|
function installRuleForAgent(agent, content) {
|
|
@@ -64568,13 +64504,13 @@ function removeRuleForAgent(agent) {
|
|
|
64568
64504
|
return null;
|
|
64569
64505
|
const target = RULE_TARGETS[agent];
|
|
64570
64506
|
const path = target.path();
|
|
64571
|
-
if (!
|
|
64507
|
+
if (!existsSync28(path))
|
|
64572
64508
|
return { agent, path, action: "not_found" };
|
|
64573
64509
|
if (target.kind === "file") {
|
|
64574
64510
|
unlinkSync5(path);
|
|
64575
64511
|
return { agent, path, action: "removed" };
|
|
64576
64512
|
}
|
|
64577
|
-
const existing =
|
|
64513
|
+
const existing = readFileSync27(path, "utf-8");
|
|
64578
64514
|
const lineEnding = lineEndingFor(existing);
|
|
64579
64515
|
const location = findSection(existing);
|
|
64580
64516
|
if (!location)
|
|
@@ -64583,7 +64519,7 @@ function removeRuleForAgent(agent) {
|
|
|
64583
64519
|
if (!next) {
|
|
64584
64520
|
unlinkSync5(path);
|
|
64585
64521
|
} else {
|
|
64586
|
-
|
|
64522
|
+
writeFileSync18(path, `${next}${lineEnding}`, "utf-8");
|
|
64587
64523
|
}
|
|
64588
64524
|
return { agent, path, action: "removed" };
|
|
64589
64525
|
}
|
|
@@ -64611,36 +64547,36 @@ var init_installer = __esm(() => {
|
|
|
64611
64547
|
RULE_TARGETS = {
|
|
64612
64548
|
claude: {
|
|
64613
64549
|
kind: "file",
|
|
64614
|
-
path: () =>
|
|
64550
|
+
path: () => join42(claudeConfigDir4(), "rules", "dosu.md")
|
|
64615
64551
|
},
|
|
64616
64552
|
cursor: {
|
|
64617
64553
|
kind: "file",
|
|
64618
|
-
path: () =>
|
|
64554
|
+
path: () => join42(homedir12(), ".cursor", "rules", "dosu.mdc"),
|
|
64619
64555
|
cursorFrontmatter: true
|
|
64620
64556
|
},
|
|
64621
64557
|
codex: {
|
|
64622
64558
|
kind: "section",
|
|
64623
|
-
path: () =>
|
|
64559
|
+
path: () => join42(codexHome4(), "AGENTS.md")
|
|
64624
64560
|
},
|
|
64625
64561
|
opencode: {
|
|
64626
64562
|
kind: "section",
|
|
64627
|
-
path: () =>
|
|
64563
|
+
path: () => join42(homedir12(), ".config", "opencode", "AGENTS.md")
|
|
64628
64564
|
},
|
|
64629
64565
|
gemini: {
|
|
64630
64566
|
kind: "section",
|
|
64631
|
-
path: () =>
|
|
64567
|
+
path: () => join42(homedir12(), ".gemini", "GEMINI.md")
|
|
64632
64568
|
},
|
|
64633
64569
|
antigravity: {
|
|
64634
64570
|
kind: "section",
|
|
64635
|
-
path: () =>
|
|
64571
|
+
path: () => join42(homedir12(), ".gemini", "GEMINI.md")
|
|
64636
64572
|
}
|
|
64637
64573
|
};
|
|
64638
64574
|
});
|
|
64639
64575
|
|
|
64640
64576
|
// src/setup/agents-md-step.ts
|
|
64641
64577
|
import { execSync as execSync2 } from "node:child_process";
|
|
64642
|
-
import { existsSync as
|
|
64643
|
-
import { join as
|
|
64578
|
+
import { existsSync as existsSync29, readFileSync as readFileSync28, writeFileSync as writeFileSync19 } from "node:fs";
|
|
64579
|
+
import { join as join43 } from "node:path";
|
|
64644
64580
|
function inGitWorkTree(cwd = process.cwd()) {
|
|
64645
64581
|
try {
|
|
64646
64582
|
const stdout = execSync2("git rev-parse --is-inside-work-tree", {
|
|
@@ -64654,10 +64590,10 @@ function inGitWorkTree(cwd = process.cwd()) {
|
|
|
64654
64590
|
}
|
|
64655
64591
|
function dosuAgentsSectionState(cwd = process.cwd()) {
|
|
64656
64592
|
try {
|
|
64657
|
-
const path =
|
|
64658
|
-
if (!
|
|
64593
|
+
const path = join43(cwd, "AGENTS.md");
|
|
64594
|
+
if (!existsSync29(path))
|
|
64659
64595
|
return "missing";
|
|
64660
|
-
const content =
|
|
64596
|
+
const content = readFileSync28(path, "utf-8");
|
|
64661
64597
|
const startMatch = content.match(SECTION_START_RE);
|
|
64662
64598
|
if (!startMatch || !content.includes(DOSU_SECTION_END))
|
|
64663
64599
|
return "missing";
|
|
@@ -64692,14 +64628,14 @@ function findSection2(content) {
|
|
|
64692
64628
|
return { start, end };
|
|
64693
64629
|
}
|
|
64694
64630
|
function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RULE) {
|
|
64695
|
-
const path =
|
|
64696
|
-
if (!
|
|
64631
|
+
const path = join43(cwd, "AGENTS.md");
|
|
64632
|
+
if (!existsSync29(path)) {
|
|
64697
64633
|
const section = buildDosuAgentsSection(content);
|
|
64698
|
-
|
|
64634
|
+
writeFileSync19(path, `${section}
|
|
64699
64635
|
`);
|
|
64700
64636
|
return { path, action: "created" };
|
|
64701
64637
|
}
|
|
64702
|
-
const existing =
|
|
64638
|
+
const existing = readFileSync28(path, "utf-8");
|
|
64703
64639
|
const lineEnding = lineEndingFor2(existing);
|
|
64704
64640
|
const section = renderDosuAgentsSection(content, lineEnding);
|
|
64705
64641
|
const location = findSection2(existing);
|
|
@@ -64711,7 +64647,7 @@ function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RU
|
|
|
64711
64647
|
}
|
|
64712
64648
|
if (next === existing)
|
|
64713
64649
|
return { path, action: "unchanged" };
|
|
64714
|
-
|
|
64650
|
+
writeFileSync19(path, next);
|
|
64715
64651
|
return { path, action: "updated" };
|
|
64716
64652
|
}
|
|
64717
64653
|
async function stepUpdateAgentsMd(cwd = process.cwd(), content) {
|
|
@@ -66163,7 +66099,7 @@ async function stepSelectTools(detected) {
|
|
|
66163
66099
|
initialValues: preselected,
|
|
66164
66100
|
statusFor: (id, picked) => {
|
|
66165
66101
|
if (configuredMap.get(id))
|
|
66166
|
-
return picked ? dim("configured") :
|
|
66102
|
+
return picked ? dim("configured") : import_picocolors35.default.yellow("will remove");
|
|
66167
66103
|
return picked ? brand("will configure") : undefined;
|
|
66168
66104
|
},
|
|
66169
66105
|
summary: (picked) => {
|
|
@@ -66338,7 +66274,7 @@ ${dim(wrapLog("Type it in a chat to keep that chat out of Dosu. To keep a whole
|
|
|
66338
66274
|
log2.success("All agents already configured. No changes needed.");
|
|
66339
66275
|
}
|
|
66340
66276
|
}
|
|
66341
|
-
var
|
|
66277
|
+
var import_picocolors35, OAUTH_ANALYTICS_REASONS, SETUP_HANDSHAKE_TIMEOUT_MS = 1800000, LIBRARY_SELECT_CANCELLED;
|
|
66342
66278
|
var init_flow2 = __esm(() => {
|
|
66343
66279
|
init_errors4();
|
|
66344
66280
|
init_client();
|
|
@@ -66361,7 +66297,7 @@ var init_flow2 = __esm(() => {
|
|
|
66361
66297
|
init_analytics2();
|
|
66362
66298
|
init_rules_step();
|
|
66363
66299
|
init_styles();
|
|
66364
|
-
|
|
66300
|
+
import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
66365
66301
|
OAUTH_ANALYTICS_REASONS = new Set([
|
|
66366
66302
|
"access_denied",
|
|
66367
66303
|
"bad_oauth_state",
|
|
@@ -66525,7 +66461,7 @@ Could not update Dosu automatically.`);
|
|
|
66525
66461
|
${plan.manualCommand}`);
|
|
66526
66462
|
return result.status && result.status > 0 ? result.status : 1;
|
|
66527
66463
|
}
|
|
66528
|
-
console.log(
|
|
66464
|
+
console.log(import_picocolors36.default.green(`
|
|
66529
66465
|
✓ Update command completed.`));
|
|
66530
66466
|
console.log('Run "dosu --version" to verify.');
|
|
66531
66467
|
return 0;
|
|
@@ -66567,12 +66503,13 @@ async function completeUpgrade(channel = INSTALL_CHANNEL, options = {}) {
|
|
|
66567
66503
|
finishWithNewBinary(channel, options);
|
|
66568
66504
|
return 0;
|
|
66569
66505
|
}
|
|
66570
|
-
async function finishUpgrade(
|
|
66571
|
-
const
|
|
66572
|
-
|
|
66506
|
+
async function finishUpgrade(_from, options = {}) {
|
|
66507
|
+
const cfg = loadConfigNonBlocking();
|
|
66508
|
+
const stale = staleProviders(cfg);
|
|
66509
|
+
if (stale.length === 0) {
|
|
66573
66510
|
checkForSkillUpdates();
|
|
66574
66511
|
writeMcpRefreshCache({ version: VERSION });
|
|
66575
|
-
console.log(
|
|
66512
|
+
console.log(import_picocolors36.default.green(`✓ Dosu ${VERSION} is ready. Your AI agents need no changes.`));
|
|
66576
66513
|
return 0;
|
|
66577
66514
|
}
|
|
66578
66515
|
if (options.interactive ?? isInteractiveTerminal()) {
|
|
@@ -66584,14 +66521,13 @@ This update changes how agents connect to Dosu. Running setup...
|
|
|
66584
66521
|
return 0;
|
|
66585
66522
|
}
|
|
66586
66523
|
checkForSkillUpdates();
|
|
66587
|
-
const cfg = loadConfigNonBlocking();
|
|
66588
66524
|
if (!cfg || !canRefreshMcp(cfg)) {
|
|
66589
66525
|
console.error(SETUP_FALLBACK);
|
|
66590
66526
|
return 0;
|
|
66591
66527
|
}
|
|
66592
66528
|
console.log(`
|
|
66593
66529
|
Refreshing agent MCP configs with the new version...`);
|
|
66594
|
-
const result =
|
|
66530
|
+
const result = refreshProviders(cfg, stale);
|
|
66595
66531
|
writeMcpRefreshCache({ version: VERSION });
|
|
66596
66532
|
for (const provider of result.updated)
|
|
66597
66533
|
console.log(` ✓ ${provider.name()}`);
|
|
@@ -66637,7 +66573,7 @@ function upgradeCommand() {
|
|
|
66637
66573
|
process.exitCode = status;
|
|
66638
66574
|
});
|
|
66639
66575
|
}
|
|
66640
|
-
var
|
|
66576
|
+
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
66577
|
var init_upgrade = __esm(() => {
|
|
66642
66578
|
init_commander();
|
|
66643
66579
|
init_config();
|
|
@@ -66645,7 +66581,7 @@ var init_upgrade = __esm(() => {
|
|
|
66645
66581
|
init_auto_update();
|
|
66646
66582
|
init_mcp_refresh_check();
|
|
66647
66583
|
init_skill_update_check();
|
|
66648
|
-
|
|
66584
|
+
import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
66649
66585
|
LATEST_PACKAGE = `${PACKAGE_NAME}@latest`;
|
|
66650
66586
|
PACKAGE_MANAGERS = {
|
|
66651
66587
|
npm: {
|
|
@@ -66664,31 +66600,30 @@ var init_upgrade = __esm(() => {
|
|
|
66664
66600
|
installArgs: ["global", "add", LATEST_PACKAGE]
|
|
66665
66601
|
}
|
|
66666
66602
|
};
|
|
66667
|
-
SEMVER = /^\d+\.\d+\.\d+/;
|
|
66668
66603
|
});
|
|
66669
66604
|
|
|
66670
66605
|
// src/version/incognito-backfill-check.ts
|
|
66671
|
-
import { existsSync as
|
|
66672
|
-
import { join as
|
|
66606
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync18, writeFileSync as writeFileSync20 } from "node:fs";
|
|
66607
|
+
import { join as join44 } from "node:path";
|
|
66673
66608
|
function markerPath() {
|
|
66674
|
-
return
|
|
66609
|
+
return join44(getConfigDir(), MARKER_FILENAME);
|
|
66675
66610
|
}
|
|
66676
66611
|
function writeMarker() {
|
|
66677
66612
|
const dir = getConfigDir();
|
|
66678
|
-
if (!
|
|
66679
|
-
|
|
66680
|
-
|
|
66613
|
+
if (!existsSync30(dir))
|
|
66614
|
+
mkdirSync18(dir, { recursive: true, mode: 448 });
|
|
66615
|
+
writeFileSync20(markerPath(), JSON.stringify({ done: true }), { mode: 384 });
|
|
66681
66616
|
}
|
|
66682
66617
|
function displayNotice3(names) {
|
|
66683
66618
|
console.error(`
|
|
66684
|
-
${
|
|
66685
|
-
` + `${
|
|
66619
|
+
${import_picocolors37.default.green(`✓ Dosu: added the /${INCOGNITO_COMMAND_NAME} command to ${names.join(", ")}`)}
|
|
66620
|
+
` + `${import_picocolors37.default.dim(` Type /${INCOGNITO_COMMAND_NAME} in a chat to keep that chat out of Dosu.`)}
|
|
66686
66621
|
`);
|
|
66687
66622
|
}
|
|
66688
66623
|
function checkForIncognitoBackfill(options = {}) {
|
|
66689
66624
|
const notify = options.notify ?? true;
|
|
66690
66625
|
try {
|
|
66691
|
-
if (
|
|
66626
|
+
if (existsSync30(markerPath()))
|
|
66692
66627
|
return;
|
|
66693
66628
|
const added = [];
|
|
66694
66629
|
let failed = false;
|
|
@@ -66715,14 +66650,187 @@ function checkForIncognitoBackfill(options = {}) {
|
|
|
66715
66650
|
logger.error("incognito-backfill", `Incognito backfill failed: ${err}`);
|
|
66716
66651
|
}
|
|
66717
66652
|
}
|
|
66718
|
-
var
|
|
66653
|
+
var import_picocolors37, MARKER_FILENAME = "incognito-backfill.json";
|
|
66719
66654
|
var init_incognito_backfill_check = __esm(() => {
|
|
66720
66655
|
init_config();
|
|
66721
66656
|
init_logger();
|
|
66722
66657
|
init_agents();
|
|
66723
66658
|
init_agents3();
|
|
66724
66659
|
init_incognito();
|
|
66660
|
+
import_picocolors37 = __toESM(require_picocolors(), 1);
|
|
66661
|
+
});
|
|
66662
|
+
|
|
66663
|
+
// src/version/update-check.ts
|
|
66664
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync19, readFileSync as readFileSync29, writeFileSync as writeFileSync21 } from "node:fs";
|
|
66665
|
+
import { join as join45 } from "node:path";
|
|
66666
|
+
function isValidVersion2(value) {
|
|
66667
|
+
return typeof value === "string" && SEMVER_PATTERN.test(value);
|
|
66668
|
+
}
|
|
66669
|
+
function stripPrerelease(version) {
|
|
66670
|
+
return version.replace(/[-+].*$/, "");
|
|
66671
|
+
}
|
|
66672
|
+
function isNewerVersion(latest, current) {
|
|
66673
|
+
const a = stripPrerelease(latest).split(".").map(Number);
|
|
66674
|
+
const b = stripPrerelease(current).split(".").map(Number);
|
|
66675
|
+
const len = Math.max(a.length, b.length);
|
|
66676
|
+
for (let i = 0;i < len; i++) {
|
|
66677
|
+
const av = a[i] ?? 0;
|
|
66678
|
+
const bv = b[i] ?? 0;
|
|
66679
|
+
if (av > bv)
|
|
66680
|
+
return true;
|
|
66681
|
+
if (av < bv)
|
|
66682
|
+
return false;
|
|
66683
|
+
}
|
|
66684
|
+
return false;
|
|
66685
|
+
}
|
|
66686
|
+
function getCachePath3() {
|
|
66687
|
+
return join45(getConfigDir(), CACHE_FILENAME5);
|
|
66688
|
+
}
|
|
66689
|
+
function readCache() {
|
|
66690
|
+
try {
|
|
66691
|
+
const path = getCachePath3();
|
|
66692
|
+
if (!existsSync31(path))
|
|
66693
|
+
return null;
|
|
66694
|
+
const data = JSON.parse(readFileSync29(path, "utf-8"));
|
|
66695
|
+
if (typeof data.lastCheck === "number" && isValidVersion2(data.latestVersion)) {
|
|
66696
|
+
return data;
|
|
66697
|
+
}
|
|
66698
|
+
return null;
|
|
66699
|
+
} catch {
|
|
66700
|
+
return null;
|
|
66701
|
+
}
|
|
66702
|
+
}
|
|
66703
|
+
function writeCache(cache) {
|
|
66704
|
+
try {
|
|
66705
|
+
const dir = getConfigDir();
|
|
66706
|
+
if (!existsSync31(dir)) {
|
|
66707
|
+
mkdirSync19(dir, { recursive: true, mode: 448 });
|
|
66708
|
+
}
|
|
66709
|
+
writeFileSync21(getCachePath3(), JSON.stringify(cache), { mode: 384 });
|
|
66710
|
+
} catch {}
|
|
66711
|
+
}
|
|
66712
|
+
async function fetchLatestVersion() {
|
|
66713
|
+
const controller = new AbortController;
|
|
66714
|
+
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS2);
|
|
66715
|
+
try {
|
|
66716
|
+
const resp = await fetch(REGISTRY_URL, { signal: controller.signal });
|
|
66717
|
+
if (!resp.ok)
|
|
66718
|
+
return null;
|
|
66719
|
+
const data = await resp.json();
|
|
66720
|
+
const latest = data.latest;
|
|
66721
|
+
return isValidVersion2(latest) ? latest : null;
|
|
66722
|
+
} catch {
|
|
66723
|
+
return null;
|
|
66724
|
+
} finally {
|
|
66725
|
+
clearTimeout(timeout);
|
|
66726
|
+
}
|
|
66727
|
+
}
|
|
66728
|
+
function buildUpdateHint(channel, npx = false) {
|
|
66729
|
+
if (channel === "npm" && npx) {
|
|
66730
|
+
return 'Use "npx -y @dosu/cli@latest" for the next Dosu command';
|
|
66731
|
+
}
|
|
66732
|
+
return 'Run "dosu upgrade"';
|
|
66733
|
+
}
|
|
66734
|
+
function styleHint(hint) {
|
|
66735
|
+
const match = hint.match(/^(.*)("[^"]+")(.*)$/);
|
|
66736
|
+
if (!match)
|
|
66737
|
+
return import_picocolors38.default.dim(hint);
|
|
66738
|
+
const [, before, command, after] = match;
|
|
66739
|
+
return [before && import_picocolors38.default.dim(before), import_picocolors38.default.cyan(command), after && import_picocolors38.default.dim(after)].filter(Boolean).join("");
|
|
66740
|
+
}
|
|
66741
|
+
function framedNotice(content, width) {
|
|
66742
|
+
const innerWidth = Math.max(...content.map(visibleWidth2)) + BOX_PADDING * 2;
|
|
66743
|
+
const framed = (line) => {
|
|
66744
|
+
const pad = innerWidth - visibleWidth2(line);
|
|
66745
|
+
const left = Math.floor(pad / 2);
|
|
66746
|
+
return `${import_picocolors38.default.yellow("│")}${" ".repeat(left)}${line}${" ".repeat(pad - left)}${import_picocolors38.default.yellow("│")}`;
|
|
66747
|
+
};
|
|
66748
|
+
const box = [
|
|
66749
|
+
import_picocolors38.default.yellow(`╭${"─".repeat(innerWidth)}╮`),
|
|
66750
|
+
framed(""),
|
|
66751
|
+
...content.map(framed),
|
|
66752
|
+
framed(""),
|
|
66753
|
+
import_picocolors38.default.yellow(`╰${"─".repeat(innerWidth)}╯`)
|
|
66754
|
+
];
|
|
66755
|
+
return `
|
|
66756
|
+
${centerBlock(box, width).join(`
|
|
66757
|
+
`)}
|
|
66758
|
+
`;
|
|
66759
|
+
}
|
|
66760
|
+
function versionArrow(current, latest) {
|
|
66761
|
+
return `${import_picocolors38.default.dim(current)} ${import_picocolors38.default.dim("→")} ${import_picocolors38.default.bold(brand(latest))}`;
|
|
66762
|
+
}
|
|
66763
|
+
function buildAutoUpdateNotice(current, latest, interactive, width = process.stderr.columns ?? 80) {
|
|
66764
|
+
if (interactive) {
|
|
66765
|
+
return framedNotice([
|
|
66766
|
+
`Updating Dosu: ${versionArrow(current, latest)}`,
|
|
66767
|
+
import_picocolors38.default.dim("Installing in the background; your next command uses it")
|
|
66768
|
+
], width);
|
|
66769
|
+
}
|
|
66770
|
+
return `
|
|
66771
|
+
[dosu:update] Installing Dosu ${latest} in the background (running ${current}). ` + `The next Dosu command uses it; no action needed.
|
|
66772
|
+
`;
|
|
66773
|
+
}
|
|
66774
|
+
function buildUpdateNotice(current, latest, channel, interactive, npx = false, width = process.stderr.columns ?? 80) {
|
|
66775
|
+
const hint = buildUpdateHint(channel, npx);
|
|
66776
|
+
if (interactive) {
|
|
66777
|
+
return framedNotice([`Update available: ${versionArrow(current, latest)}`, styleHint(hint)], width);
|
|
66778
|
+
}
|
|
66779
|
+
const agentAction = hint[0].toLowerCase() + hint.slice(1);
|
|
66780
|
+
const verifyCommand = npx ? "npx -y @dosu/cli@latest --version" : "dosu --version";
|
|
66781
|
+
return `
|
|
66782
|
+
[dosu:update] Update available: ${current} → ${latest}
|
|
66783
|
+
` + `Tell the user Dosu CLI is outdated. After they approve, ${agentAction}, ` + `then verify with "${verifyCommand}".
|
|
66784
|
+
`;
|
|
66785
|
+
}
|
|
66786
|
+
function getAvailableUpdate() {
|
|
66787
|
+
const cache = readCache();
|
|
66788
|
+
return cache && isNewerVersion(cache.latestVersion, VERSION) ? cache.latestVersion : null;
|
|
66789
|
+
}
|
|
66790
|
+
function handleNewerVersion(latest, notify) {
|
|
66791
|
+
const autoUpdate = startAutoUpdate(latest);
|
|
66792
|
+
if (!notify)
|
|
66793
|
+
return;
|
|
66794
|
+
const interactive = process.stderr.isTTY === true;
|
|
66795
|
+
console.error(autoUpdate === "unavailable" ? buildUpdateNotice(VERSION, latest, INSTALL_CHANNEL, interactive, isNpxInvocation()) : buildAutoUpdateNotice(VERSION, latest, interactive));
|
|
66796
|
+
}
|
|
66797
|
+
async function checkForUpdates(options = {}) {
|
|
66798
|
+
const notify = options.notify ?? true;
|
|
66799
|
+
try {
|
|
66800
|
+
const cache = readCache();
|
|
66801
|
+
const isStale = !cache || Date.now() - cache.lastCheck > CHECK_INTERVAL_MS2;
|
|
66802
|
+
if (!isStale) {
|
|
66803
|
+
if (isNewerVersion(cache.latestVersion, VERSION)) {
|
|
66804
|
+
handleNewerVersion(cache.latestVersion, notify);
|
|
66805
|
+
}
|
|
66806
|
+
return;
|
|
66807
|
+
}
|
|
66808
|
+
const latest = await fetchLatestVersion();
|
|
66809
|
+
const latestKnownVersion = latest ?? cache?.latestVersion ?? VERSION;
|
|
66810
|
+
writeCache({
|
|
66811
|
+
lastCheck: Date.now(),
|
|
66812
|
+
latestVersion: latestKnownVersion
|
|
66813
|
+
});
|
|
66814
|
+
if (latest) {
|
|
66815
|
+
logger.debug("update-check", `Cached latest version: ${latest}`);
|
|
66816
|
+
}
|
|
66817
|
+
if (isNewerVersion(latestKnownVersion, VERSION)) {
|
|
66818
|
+
handleNewerVersion(latestKnownVersion, notify);
|
|
66819
|
+
}
|
|
66820
|
+
} catch (err) {
|
|
66821
|
+
logger.error("update-check", `Update check failed: ${err}`);
|
|
66822
|
+
}
|
|
66823
|
+
}
|
|
66824
|
+
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;
|
|
66825
|
+
var init_update_check = __esm(() => {
|
|
66826
|
+
init_config();
|
|
66827
|
+
init_logger();
|
|
66828
|
+
init_styles();
|
|
66829
|
+
init_layout();
|
|
66830
|
+
init_auto_update();
|
|
66725
66831
|
import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
66832
|
+
CHECK_INTERVAL_MS2 = 6 * 60 * 60 * 1000;
|
|
66833
|
+
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
66834
|
});
|
|
66727
66835
|
|
|
66728
66836
|
// src/cli/fatal-error.ts
|
|
@@ -69109,4 +69217,4 @@ main().catch((err) => {
|
|
|
69109
69217
|
process.exit(1);
|
|
69110
69218
|
});
|
|
69111
69219
|
|
|
69112
|
-
//# debugId=
|
|
69220
|
+
//# debugId=fa693edb-14f4-abcb-6475-6e2164756e21
|