@dosu/cli 0.60.0 → 0.60.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 +2 -2
- package/bin/dosu.js +650 -621
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -1083,7 +1083,7 @@ function isNpxInvocation(channel = INSTALL_CHANNEL, env = process.env) {
|
|
|
1083
1083
|
function getVersionString() {
|
|
1084
1084
|
return `v${VERSION}`;
|
|
1085
1085
|
}
|
|
1086
|
-
var VERSION = "0.60.
|
|
1086
|
+
var VERSION = "0.60.2", INSTALL_CHANNEL = "npm";
|
|
1087
1087
|
|
|
1088
1088
|
// src/debug/logger.ts
|
|
1089
1089
|
import {
|
|
@@ -13800,7 +13800,7 @@ var init_conflicts = __esm(() => {
|
|
|
13800
13800
|
});
|
|
13801
13801
|
|
|
13802
13802
|
// src/telemetry/debug-id.ts
|
|
13803
|
-
var BUNDLE_DEBUG_ID_PLACEHOLDER = "
|
|
13803
|
+
var BUNDLE_DEBUG_ID_PLACEHOLDER = "49fa5d82-a4a1-8b36-6475-6e2164756e21";
|
|
13804
13804
|
|
|
13805
13805
|
// src/telemetry/telemetry.ts
|
|
13806
13806
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -14708,6 +14708,11 @@ var init_telemetry = __esm(() => {
|
|
|
14708
14708
|
"quota_exceeded",
|
|
14709
14709
|
"gateway_rejected",
|
|
14710
14710
|
"claude_code_missing",
|
|
14711
|
+
"max_turns",
|
|
14712
|
+
"run_failed",
|
|
14713
|
+
"no_result",
|
|
14714
|
+
"timed_out",
|
|
14715
|
+
"sdk_error",
|
|
14711
14716
|
"error"
|
|
14712
14717
|
]);
|
|
14713
14718
|
GATEWAY_REASONS = new Set([
|
|
@@ -58603,13 +58608,16 @@ async function runLearner(options) {
|
|
|
58603
58608
|
}
|
|
58604
58609
|
if (message.subtype !== "success" || message.is_error) {
|
|
58605
58610
|
logger.debug("learner", `run ${runID} failed: ${text}`);
|
|
58606
|
-
|
|
58611
|
+
if (message.subtype === "error_max_turns") {
|
|
58612
|
+
return finish("max_turns", "Study run hit its turn limit before finishing.");
|
|
58613
|
+
}
|
|
58614
|
+
return finish("run_failed", "Study run failed; see debug log for details.");
|
|
58607
58615
|
}
|
|
58608
58616
|
logger.debug("learner", `run ${runID} completed: ${turns} turns, ${notesWritten} suggested pages`);
|
|
58609
58617
|
return finish("completed", text);
|
|
58610
58618
|
}
|
|
58611
58619
|
}
|
|
58612
|
-
return finish("
|
|
58620
|
+
return finish("no_result", "Study run ended without a result.");
|
|
58613
58621
|
} catch (error) {
|
|
58614
58622
|
const text = error instanceof Error ? error.message : String(error);
|
|
58615
58623
|
const gatewayError = classifyGatewayError(text) ?? classifyGatewayRejection(text);
|
|
@@ -58617,7 +58625,7 @@ async function runLearner(options) {
|
|
|
58617
58625
|
return finish(gatewayError.outcome, gatewayError.message, gatewayError.reason);
|
|
58618
58626
|
}
|
|
58619
58627
|
logger.debug("learner", `run ${runID} threw: ${text}`);
|
|
58620
|
-
return
|
|
58628
|
+
return abort.signal.aborted ? finish("timed_out", "Study run timed out and was aborted.") : finish("sdk_error", "Study run failed; see debug log for details.");
|
|
58621
58629
|
} finally {
|
|
58622
58630
|
clearTimeout(timer);
|
|
58623
58631
|
configDir.cleanup();
|
|
@@ -61633,283 +61641,6 @@ var init_topics = __esm(() => {
|
|
|
61633
61641
|
import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
61634
61642
|
});
|
|
61635
61643
|
|
|
61636
|
-
// src/commands/upgrade.ts
|
|
61637
|
-
import { spawnSync } from "node:child_process";
|
|
61638
|
-
import { realpathSync as realpathSync2 } from "node:fs";
|
|
61639
|
-
import { homedir as homedir9 } from "node:os";
|
|
61640
|
-
import { posix, win32 as win322 } from "node:path";
|
|
61641
|
-
function isAbsoluteCommandProcessor(value) {
|
|
61642
|
-
return Boolean(value && win322.isAbsolute(value) && win322.basename(value).toLowerCase() === "cmd.exe");
|
|
61643
|
-
}
|
|
61644
|
-
function windowsCommandProcessor(env = process.env) {
|
|
61645
|
-
if (isAbsoluteCommandProcessor(env.ComSpec))
|
|
61646
|
-
return env.ComSpec;
|
|
61647
|
-
const systemRoot = env.SystemRoot && win322.isAbsolute(env.SystemRoot) ? env.SystemRoot : "C:\\Windows";
|
|
61648
|
-
return win322.join(systemRoot, "System32", "cmd.exe");
|
|
61649
|
-
}
|
|
61650
|
-
function safePackageManagerEnv(env) {
|
|
61651
|
-
return {
|
|
61652
|
-
...env,
|
|
61653
|
-
COREPACK_ENABLE_NETWORK: "0",
|
|
61654
|
-
COREPACK_ENABLE_PROJECT_SPEC: "0",
|
|
61655
|
-
YARN_IGNORE_PATH: "1"
|
|
61656
|
-
};
|
|
61657
|
-
}
|
|
61658
|
-
function buildPackageManagerInvocation(manager, action, platform = process.platform, comSpec, env = process.env) {
|
|
61659
|
-
const args = action === "locate" ? PACKAGE_MANAGERS[manager].locateArgs : PACKAGE_MANAGERS[manager].installArgs;
|
|
61660
|
-
const safeEnv = safePackageManagerEnv(env);
|
|
61661
|
-
if (platform === "win32") {
|
|
61662
|
-
return {
|
|
61663
|
-
command: isAbsoluteCommandProcessor(comSpec) ? comSpec : windowsCommandProcessor(env),
|
|
61664
|
-
args: ["/d", "/s", "/c", [manager, ...args].join(" ")],
|
|
61665
|
-
env: { ...safeEnv, NoDefaultCurrentDirectoryInExePath: "1" }
|
|
61666
|
-
};
|
|
61667
|
-
}
|
|
61668
|
-
return { command: manager, args: [...args], env: safeEnv };
|
|
61669
|
-
}
|
|
61670
|
-
function packageRoots(manager, platform, comSpec, env, cwd) {
|
|
61671
|
-
const invocation = buildPackageManagerInvocation(manager, "locate", platform, comSpec, env);
|
|
61672
|
-
const result = spawnSync(invocation.command, invocation.args, {
|
|
61673
|
-
cwd,
|
|
61674
|
-
encoding: "utf8",
|
|
61675
|
-
env: invocation.env,
|
|
61676
|
-
shell: false,
|
|
61677
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
61678
|
-
timeout: PROBE_TIMEOUT_MS
|
|
61679
|
-
});
|
|
61680
|
-
if (result.status !== 0 || typeof result.stdout !== "string")
|
|
61681
|
-
return [];
|
|
61682
|
-
const path = platform === "win32" ? win322 : posix;
|
|
61683
|
-
const lines = result.stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => path.isAbsolute(line));
|
|
61684
|
-
if (manager === "pnpm") {
|
|
61685
|
-
return lines.filter((line) => path.basename(line) === "cli" && path.basename(path.dirname(line)) === "@dosu" && path.basename(path.dirname(path.dirname(line))) === "node_modules");
|
|
61686
|
-
}
|
|
61687
|
-
if (lines.length !== 1)
|
|
61688
|
-
return [];
|
|
61689
|
-
return [
|
|
61690
|
-
manager === "npm" ? path.join(lines[0], "@dosu", "cli") : path.join(lines[0], "node_modules", "@dosu", "cli")
|
|
61691
|
-
];
|
|
61692
|
-
}
|
|
61693
|
-
function owningPackageManager(entrypoint, platform, comSpec, env = process.env, cwd = homedir9()) {
|
|
61694
|
-
const path = platform === "win32" ? win322 : posix;
|
|
61695
|
-
if (!entrypoint || !path.isAbsolute(entrypoint))
|
|
61696
|
-
return null;
|
|
61697
|
-
let realEntrypoint;
|
|
61698
|
-
try {
|
|
61699
|
-
realEntrypoint = realpathSync2(entrypoint);
|
|
61700
|
-
} catch {
|
|
61701
|
-
return null;
|
|
61702
|
-
}
|
|
61703
|
-
const owners = Object.keys(PACKAGE_MANAGERS).filter((manager) => packageRoots(manager, platform, comSpec, env, cwd).some((root) => {
|
|
61704
|
-
try {
|
|
61705
|
-
const relative = path.relative(realpathSync2(root), realEntrypoint);
|
|
61706
|
-
return relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
|
|
61707
|
-
} catch {
|
|
61708
|
-
return false;
|
|
61709
|
-
}
|
|
61710
|
-
}));
|
|
61711
|
-
return owners.length === 1 ? owners[0] : null;
|
|
61712
|
-
}
|
|
61713
|
-
function upgradePlan(channel, manager, platform, comSpec, env = process.env) {
|
|
61714
|
-
if (channel === "homebrew") {
|
|
61715
|
-
return {
|
|
61716
|
-
label: "Homebrew",
|
|
61717
|
-
command: "brew",
|
|
61718
|
-
args: ["upgrade", "dosu-ai/dosu/dosu"],
|
|
61719
|
-
manualCommand: BREW_MANUAL_COMMAND
|
|
61720
|
-
};
|
|
61721
|
-
}
|
|
61722
|
-
if (channel === "npm" && manager) {
|
|
61723
|
-
const invocation = buildPackageManagerInvocation(manager, "install", platform, comSpec, env);
|
|
61724
|
-
return {
|
|
61725
|
-
label: PACKAGE_MANAGERS[manager].label,
|
|
61726
|
-
...invocation,
|
|
61727
|
-
manualCommand: [manager, ...PACKAGE_MANAGERS[manager].installArgs].join(" ")
|
|
61728
|
-
};
|
|
61729
|
-
}
|
|
61730
|
-
return null;
|
|
61731
|
-
}
|
|
61732
|
-
function printNonGlobalPackageGuidance() {
|
|
61733
|
-
console.log("This Dosu copy is not a uniquely identified global package installation, so it was not changed.");
|
|
61734
|
-
console.log(`
|
|
61735
|
-
Run the latest version without installing:
|
|
61736
|
-
${NPX_COMMAND}`);
|
|
61737
|
-
console.log(`
|
|
61738
|
-
Or install Dosu globally with your package manager:`);
|
|
61739
|
-
for (const manager of Object.keys(PACKAGE_MANAGERS)) {
|
|
61740
|
-
console.log(` ${manager} ${PACKAGE_MANAGERS[manager].installArgs.join(" ")}`);
|
|
61741
|
-
}
|
|
61742
|
-
}
|
|
61743
|
-
function runUpgrade(channel = INSTALL_CHANNEL, options = {}) {
|
|
61744
|
-
const platform = options.platform ?? process.platform;
|
|
61745
|
-
const env = options.env ?? process.env;
|
|
61746
|
-
const cwd = options.cwd ?? homedir9();
|
|
61747
|
-
let manager = null;
|
|
61748
|
-
if (channel === "npm") {
|
|
61749
|
-
if (isNpxInvocation(channel, env)) {
|
|
61750
|
-
printNonGlobalPackageGuidance();
|
|
61751
|
-
return 1;
|
|
61752
|
-
}
|
|
61753
|
-
manager = owningPackageManager(options.entrypoint ?? process.argv[1], platform, options.comSpec, env, cwd);
|
|
61754
|
-
if (!manager) {
|
|
61755
|
-
if (env.DOSU_DEV === "true") {
|
|
61756
|
-
console.log("DOSU_DEV=true and this copy is not a global package: skipping the package install.");
|
|
61757
|
-
return 0;
|
|
61758
|
-
}
|
|
61759
|
-
printNonGlobalPackageGuidance();
|
|
61760
|
-
return 1;
|
|
61761
|
-
}
|
|
61762
|
-
}
|
|
61763
|
-
const plan = upgradePlan(channel, manager, platform, options.comSpec, env);
|
|
61764
|
-
if (!plan) {
|
|
61765
|
-
console.log("Automatic upgrades are not available for this installation yet.");
|
|
61766
|
-
console.log(`Download the latest release:
|
|
61767
|
-
${RELEASES_URL}`);
|
|
61768
|
-
return 1;
|
|
61769
|
-
}
|
|
61770
|
-
console.log(`Updating Dosu with ${plan.label}...`);
|
|
61771
|
-
console.log(` ${plan.manualCommand}
|
|
61772
|
-
`);
|
|
61773
|
-
const result = spawnSync(plan.command, plan.args, {
|
|
61774
|
-
...channel === "npm" ? { cwd } : {},
|
|
61775
|
-
...plan.env ? { env: plan.env } : {},
|
|
61776
|
-
shell: false,
|
|
61777
|
-
stdio: "inherit"
|
|
61778
|
-
});
|
|
61779
|
-
if (result.error || result.status !== 0) {
|
|
61780
|
-
console.error(`
|
|
61781
|
-
Could not update Dosu automatically.`);
|
|
61782
|
-
console.error(`Run manually:
|
|
61783
|
-
${plan.manualCommand}`);
|
|
61784
|
-
return result.status && result.status > 0 ? result.status : 1;
|
|
61785
|
-
}
|
|
61786
|
-
console.log(import_picocolors30.default.green(`
|
|
61787
|
-
✓ Update command completed.`));
|
|
61788
|
-
console.log('Run "dosu --version" to verify.');
|
|
61789
|
-
return 0;
|
|
61790
|
-
}
|
|
61791
|
-
function postUpgradeArgs(interactive) {
|
|
61792
|
-
return interactive ? ["setup"] : ["mcp", "refresh"];
|
|
61793
|
-
}
|
|
61794
|
-
function newBinaryInvocation(channel, args, entrypoint = process.argv[1], execPath = process.execPath) {
|
|
61795
|
-
if (channel === "npm") {
|
|
61796
|
-
return entrypoint ? { command: execPath, args: [entrypoint, ...args] } : null;
|
|
61797
|
-
}
|
|
61798
|
-
if (channel === "homebrew") {
|
|
61799
|
-
return { command: "dosu", args };
|
|
61800
|
-
}
|
|
61801
|
-
return null;
|
|
61802
|
-
}
|
|
61803
|
-
function isInteractiveTerminal() {
|
|
61804
|
-
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
61805
|
-
}
|
|
61806
|
-
function setupAgentsWithNewBinary(channel, interactive, options) {
|
|
61807
|
-
const invocation = newBinaryInvocation(channel, postUpgradeArgs(interactive), options.entrypoint ?? process.argv[1]);
|
|
61808
|
-
if (!invocation) {
|
|
61809
|
-
console.error(SETUP_FALLBACK);
|
|
61810
|
-
return;
|
|
61811
|
-
}
|
|
61812
|
-
console.log(interactive ? `
|
|
61813
|
-
Running setup with the new version to update your AI agents...
|
|
61814
|
-
` : `
|
|
61815
|
-
Refreshing agent MCP configs with the new version...`);
|
|
61816
|
-
const result = spawnSync(invocation.command, invocation.args, {
|
|
61817
|
-
cwd: options.cwd ?? homedir9(),
|
|
61818
|
-
shell: false,
|
|
61819
|
-
stdio: "inherit"
|
|
61820
|
-
});
|
|
61821
|
-
if (result.error || result.status !== 0) {
|
|
61822
|
-
console.error(SETUP_FALLBACK);
|
|
61823
|
-
}
|
|
61824
|
-
}
|
|
61825
|
-
async function completeUpgrade(channel = INSTALL_CHANNEL, options = {}) {
|
|
61826
|
-
const status = runUpgrade(channel, options);
|
|
61827
|
-
if (status !== 0)
|
|
61828
|
-
return status;
|
|
61829
|
-
const interactive = options.interactive ?? isInteractiveTerminal();
|
|
61830
|
-
if (!interactive) {
|
|
61831
|
-
console.log("Updating Dosu skills...");
|
|
61832
|
-
try {
|
|
61833
|
-
const result = await installSkill();
|
|
61834
|
-
if (result.success) {
|
|
61835
|
-
console.log(import_picocolors30.default.green("✓ Skills updated."));
|
|
61836
|
-
} else {
|
|
61837
|
-
console.error('Skills could not be refreshed. Run "dosu skill update" to retry.');
|
|
61838
|
-
}
|
|
61839
|
-
} catch {
|
|
61840
|
-
console.error('Skills could not be refreshed. Run "dosu skill update" to retry.');
|
|
61841
|
-
}
|
|
61842
|
-
}
|
|
61843
|
-
setupAgentsWithNewBinary(channel, interactive, options);
|
|
61844
|
-
return 0;
|
|
61845
|
-
}
|
|
61846
|
-
function upgradeCommand() {
|
|
61847
|
-
return new Command("upgrade").description("Update Dosu to the latest version, then re-run setup to update your AI agents").action(async () => {
|
|
61848
|
-
const status = await completeUpgrade();
|
|
61849
|
-
if (status !== 0)
|
|
61850
|
-
process.exitCode = status;
|
|
61851
|
-
});
|
|
61852
|
-
}
|
|
61853
|
-
var import_picocolors30, 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.';
|
|
61854
|
-
var init_upgrade = __esm(() => {
|
|
61855
|
-
init_commander();
|
|
61856
|
-
init_skill();
|
|
61857
|
-
import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
61858
|
-
LATEST_PACKAGE = `${PACKAGE_NAME}@latest`;
|
|
61859
|
-
PACKAGE_MANAGERS = {
|
|
61860
|
-
npm: {
|
|
61861
|
-
label: "npm",
|
|
61862
|
-
locateArgs: ["root", "-g"],
|
|
61863
|
-
installArgs: ["install", "-g", LATEST_PACKAGE]
|
|
61864
|
-
},
|
|
61865
|
-
pnpm: {
|
|
61866
|
-
label: "pnpm",
|
|
61867
|
-
locateArgs: ["list", "-g", "--depth=0", "--parseable", PACKAGE_NAME],
|
|
61868
|
-
installArgs: ["add", "-g", LATEST_PACKAGE]
|
|
61869
|
-
},
|
|
61870
|
-
yarn: {
|
|
61871
|
-
label: "Yarn Classic",
|
|
61872
|
-
locateArgs: ["--silent", "global", "dir"],
|
|
61873
|
-
installArgs: ["global", "add", LATEST_PACKAGE]
|
|
61874
|
-
}
|
|
61875
|
-
};
|
|
61876
|
-
});
|
|
61877
|
-
|
|
61878
|
-
// src/debug/follow.ts
|
|
61879
|
-
import { closeSync as closeSync6, openSync as openSync6, readSync as readSync5, statSync as statSync8 } from "node:fs";
|
|
61880
|
-
function createLogFollower(path, emit) {
|
|
61881
|
-
const sizeOf = () => {
|
|
61882
|
-
try {
|
|
61883
|
-
return statSync8(path).size;
|
|
61884
|
-
} catch {
|
|
61885
|
-
return 0;
|
|
61886
|
-
}
|
|
61887
|
-
};
|
|
61888
|
-
let offset = sizeOf();
|
|
61889
|
-
return {
|
|
61890
|
-
poll() {
|
|
61891
|
-
const size = sizeOf();
|
|
61892
|
-
if (size < offset)
|
|
61893
|
-
offset = 0;
|
|
61894
|
-
if (size === offset)
|
|
61895
|
-
return;
|
|
61896
|
-
try {
|
|
61897
|
-
const fd = openSync6(path, "r");
|
|
61898
|
-
try {
|
|
61899
|
-
const buf = Buffer.alloc(size - offset);
|
|
61900
|
-
const read = readSync5(fd, buf, 0, buf.length, offset);
|
|
61901
|
-
offset += read;
|
|
61902
|
-
if (read > 0)
|
|
61903
|
-
emit(buf.toString("utf-8", 0, read));
|
|
61904
|
-
} finally {
|
|
61905
|
-
closeSync6(fd);
|
|
61906
|
-
}
|
|
61907
|
-
} catch {}
|
|
61908
|
-
}
|
|
61909
|
-
};
|
|
61910
|
-
}
|
|
61911
|
-
var init_follow = () => {};
|
|
61912
|
-
|
|
61913
61644
|
// src/mcp/providers/base.ts
|
|
61914
61645
|
function createJSONProvider(opts) {
|
|
61915
61646
|
const buildServer = opts.buildServer ?? defaultBuildServer;
|
|
@@ -62441,15 +62172,15 @@ var init_vscode = __esm(() => {
|
|
|
62441
62172
|
});
|
|
62442
62173
|
|
|
62443
62174
|
// src/mcp/providers/windsurf.ts
|
|
62444
|
-
import { homedir as
|
|
62175
|
+
import { homedir as homedir9 } from "node:os";
|
|
62445
62176
|
import { join as join36 } from "node:path";
|
|
62446
62177
|
var WindsurfProvider = () => createJSONProvider({
|
|
62447
62178
|
providerName: "Windsurf",
|
|
62448
62179
|
providerID: "windsurf",
|
|
62449
62180
|
local: false,
|
|
62450
62181
|
priorityValue: 9,
|
|
62451
|
-
paths: [join36(
|
|
62452
|
-
globalPath: join36(
|
|
62182
|
+
paths: [join36(homedir9(), ".codeium", "windsurf")],
|
|
62183
|
+
globalPath: join36(homedir9(), ".codeium", "windsurf", "mcp_config.json"),
|
|
62453
62184
|
topKey: "mcpServers"
|
|
62454
62185
|
});
|
|
62455
62186
|
var init_windsurf = __esm(() => {
|
|
@@ -62458,14 +62189,14 @@ var init_windsurf = __esm(() => {
|
|
|
62458
62189
|
|
|
62459
62190
|
// src/mcp/providers/zed.ts
|
|
62460
62191
|
import { rmSync as rmSync6 } from "node:fs";
|
|
62461
|
-
import { homedir as
|
|
62192
|
+
import { homedir as homedir10, platform as platform3 } from "node:os";
|
|
62462
62193
|
import { join as join37 } from "node:path";
|
|
62463
62194
|
function zedConfigDir() {
|
|
62464
62195
|
const os = platform3();
|
|
62465
62196
|
if (os === "win32")
|
|
62466
62197
|
return join37(appSupportDir(), "Zed");
|
|
62467
62198
|
if (os === "darwin")
|
|
62468
|
-
return join37(
|
|
62199
|
+
return join37(homedir10(), ".config", "zed");
|
|
62469
62200
|
return join37(appSupportDir(), "zed");
|
|
62470
62201
|
}
|
|
62471
62202
|
function zedDataDir() {
|
|
@@ -62474,7 +62205,7 @@ function zedDataDir() {
|
|
|
62474
62205
|
return join37(appSupportDir(), "Zed");
|
|
62475
62206
|
if (os === "win32")
|
|
62476
62207
|
return join37(process.env.LOCALAPPDATA ?? "", "Zed");
|
|
62477
|
-
return join37(process.env.XDG_DATA_HOME ?? join37(
|
|
62208
|
+
return join37(process.env.XDG_DATA_HOME ?? join37(homedir10(), ".local", "share"), "zed");
|
|
62478
62209
|
}
|
|
62479
62210
|
function legacyDarwinSettingsPath() {
|
|
62480
62211
|
return platform3() === "darwin" ? join37(appSupportDir(), "Zed", "settings.json") : null;
|
|
@@ -62684,29 +62415,29 @@ function buildUpdateHint(channel, npx = false) {
|
|
|
62684
62415
|
function styleHint(hint) {
|
|
62685
62416
|
const match = hint.match(/^(.*)("[^"]+")(.*)$/);
|
|
62686
62417
|
if (!match)
|
|
62687
|
-
return
|
|
62418
|
+
return import_picocolors30.default.dim(hint);
|
|
62688
62419
|
const [, before, command, after] = match;
|
|
62689
|
-
return [before &&
|
|
62420
|
+
return [before && import_picocolors30.default.dim(before), import_picocolors30.default.cyan(command), after && import_picocolors30.default.dim(after)].filter(Boolean).join("");
|
|
62690
62421
|
}
|
|
62691
62422
|
function buildUpdateNotice(current, latest, channel, interactive, npx = false, width = process.stderr.columns ?? 80) {
|
|
62692
62423
|
const hint = buildUpdateHint(channel, npx);
|
|
62693
62424
|
if (interactive) {
|
|
62694
62425
|
const content = [
|
|
62695
|
-
`Update available: ${
|
|
62426
|
+
`Update available: ${import_picocolors30.default.dim(current)} ${import_picocolors30.default.dim("→")} ${import_picocolors30.default.bold(brand(latest))}`,
|
|
62696
62427
|
styleHint(hint)
|
|
62697
62428
|
];
|
|
62698
62429
|
const innerWidth = Math.max(...content.map(visibleWidth2)) + BOX_PADDING * 2;
|
|
62699
62430
|
const framed = (line) => {
|
|
62700
62431
|
const pad = innerWidth - visibleWidth2(line);
|
|
62701
62432
|
const left = Math.floor(pad / 2);
|
|
62702
|
-
return `${
|
|
62433
|
+
return `${import_picocolors30.default.yellow("│")}${" ".repeat(left)}${line}${" ".repeat(pad - left)}${import_picocolors30.default.yellow("│")}`;
|
|
62703
62434
|
};
|
|
62704
62435
|
const box = [
|
|
62705
|
-
|
|
62436
|
+
import_picocolors30.default.yellow(`╭${"─".repeat(innerWidth)}╮`),
|
|
62706
62437
|
framed(""),
|
|
62707
62438
|
...content.map(framed),
|
|
62708
62439
|
framed(""),
|
|
62709
|
-
|
|
62440
|
+
import_picocolors30.default.yellow(`╰${"─".repeat(innerWidth)}╯`)
|
|
62710
62441
|
];
|
|
62711
62442
|
return `
|
|
62712
62443
|
${centerBlock(box, width).join(`
|
|
@@ -62754,13 +62485,13 @@ async function checkForUpdates(options = {}) {
|
|
|
62754
62485
|
logger.error("update-check", `Update check failed: ${err}`);
|
|
62755
62486
|
}
|
|
62756
62487
|
}
|
|
62757
|
-
var
|
|
62488
|
+
var import_picocolors30, 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;
|
|
62758
62489
|
var init_update_check = __esm(() => {
|
|
62759
62490
|
init_config();
|
|
62760
62491
|
init_logger();
|
|
62761
62492
|
init_styles();
|
|
62762
62493
|
init_layout();
|
|
62763
|
-
|
|
62494
|
+
import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
62764
62495
|
CHECK_INTERVAL_MS2 = 6 * 60 * 60 * 1000;
|
|
62765
62496
|
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-]+)*)?$/;
|
|
62766
62497
|
});
|
|
@@ -62809,8 +62540,8 @@ function canRefreshMcp(cfg) {
|
|
|
62809
62540
|
}
|
|
62810
62541
|
function displayNotice2(names) {
|
|
62811
62542
|
console.error(`
|
|
62812
|
-
${
|
|
62813
|
-
` + `${
|
|
62543
|
+
${import_picocolors31.default.green(`✓ Dosu ${VERSION}: refreshed MCP config for ${names.join(", ")}`)}
|
|
62544
|
+
` + `${import_picocolors31.default.dim(` Run ${import_picocolors31.default.cyan('"dosu setup"')} to also update hooks and rules, then restart your AI agents.`)}
|
|
62814
62545
|
`);
|
|
62815
62546
|
}
|
|
62816
62547
|
function checkForMcpRefresh(options = {}) {
|
|
@@ -62838,21 +62569,21 @@ function checkForMcpRefresh(options = {}) {
|
|
|
62838
62569
|
logger.error("mcp-refresh", `MCP refresh check failed: ${err}`);
|
|
62839
62570
|
}
|
|
62840
62571
|
}
|
|
62841
|
-
var
|
|
62572
|
+
var import_picocolors31, CACHE_FILENAME4 = "mcp-refresh.json", MCP_FORMAT_CHANGES;
|
|
62842
62573
|
var init_mcp_refresh_check = __esm(() => {
|
|
62843
62574
|
init_config();
|
|
62844
62575
|
init_logger();
|
|
62845
62576
|
init_refresh();
|
|
62846
62577
|
init_update_check();
|
|
62847
|
-
|
|
62578
|
+
import_picocolors31 = __toESM(require_picocolors(), 1);
|
|
62848
62579
|
MCP_FORMAT_CHANGES = ["0.53.0"];
|
|
62849
62580
|
});
|
|
62850
62581
|
|
|
62851
62582
|
// src/version/skill-update-check.ts
|
|
62852
62583
|
function displayNotice3() {
|
|
62853
62584
|
console.error(`
|
|
62854
|
-
${
|
|
62855
|
-
` + `${
|
|
62585
|
+
${import_picocolors32.default.green(`✓ Dosu ${VERSION}: refreshed the bundled agent skills`)}
|
|
62586
|
+
` + `${import_picocolors32.default.dim(" Restart your AI agents to pick up the new skill content.")}
|
|
62856
62587
|
`);
|
|
62857
62588
|
}
|
|
62858
62589
|
function checkForSkillUpdates(options = {}) {
|
|
@@ -62873,289 +62604,11 @@ function checkForSkillUpdates(options = {}) {
|
|
|
62873
62604
|
logger.error("skill-update-check", `Skill update check failed: ${err}`);
|
|
62874
62605
|
}
|
|
62875
62606
|
}
|
|
62876
|
-
var
|
|
62607
|
+
var import_picocolors32;
|
|
62877
62608
|
var init_skill_update_check = __esm(() => {
|
|
62878
62609
|
init_skill();
|
|
62879
62610
|
init_logger();
|
|
62880
|
-
|
|
62881
|
-
});
|
|
62882
|
-
|
|
62883
|
-
// src/rules/installer.ts
|
|
62884
|
-
import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync24, unlinkSync as unlinkSync5, writeFileSync as writeFileSync16 } from "node:fs";
|
|
62885
|
-
import { homedir as homedir12 } from "node:os";
|
|
62886
|
-
import { dirname as dirname12, join as join40 } from "node:path";
|
|
62887
|
-
function claudeConfigDir4() {
|
|
62888
|
-
return process.env.CLAUDE_CONFIG_DIR || join40(homedir12(), ".claude");
|
|
62889
|
-
}
|
|
62890
|
-
function codexHome4() {
|
|
62891
|
-
return process.env.CODEX_HOME || join40(homedir12(), ".codex");
|
|
62892
|
-
}
|
|
62893
|
-
function isRuleAgent(agent) {
|
|
62894
|
-
return Object.hasOwn(RULE_TARGETS, agent);
|
|
62895
|
-
}
|
|
62896
|
-
function rulePathForAgent(agent) {
|
|
62897
|
-
return isRuleAgent(agent) ? RULE_TARGETS[agent].path() : null;
|
|
62898
|
-
}
|
|
62899
|
-
function normalizeRule(content) {
|
|
62900
|
-
return `${content.trim()}
|
|
62901
|
-
`;
|
|
62902
|
-
}
|
|
62903
|
-
async function fetchDosuRule(fetchImpl = globalThis.fetch) {
|
|
62904
|
-
for (const url of DOSU_RULE_URLS) {
|
|
62905
|
-
try {
|
|
62906
|
-
const response = await fetchImpl(url);
|
|
62907
|
-
if (!response.ok)
|
|
62908
|
-
continue;
|
|
62909
|
-
const content = await response.text();
|
|
62910
|
-
if (content.trim())
|
|
62911
|
-
return normalizeRule(content);
|
|
62912
|
-
} catch {}
|
|
62913
|
-
}
|
|
62914
|
-
return normalizeRule(FALLBACK_DOSU_RULE);
|
|
62915
|
-
}
|
|
62916
|
-
function ensureParent(path) {
|
|
62917
|
-
mkdirSync15(dirname12(path), { recursive: true });
|
|
62918
|
-
}
|
|
62919
|
-
function writeIfChanged(path, content) {
|
|
62920
|
-
if (!existsSync25(path)) {
|
|
62921
|
-
ensureParent(path);
|
|
62922
|
-
writeFileSync16(path, content, "utf-8");
|
|
62923
|
-
return "created";
|
|
62924
|
-
}
|
|
62925
|
-
if (readFileSync24(path, "utf-8") === content)
|
|
62926
|
-
return "unchanged";
|
|
62927
|
-
writeFileSync16(path, content, "utf-8");
|
|
62928
|
-
return "updated";
|
|
62929
|
-
}
|
|
62930
|
-
function findSection(content) {
|
|
62931
|
-
const startMatch = content.match(DOSU_RULE_SECTION_START_RE);
|
|
62932
|
-
const start = startMatch?.index ?? -1;
|
|
62933
|
-
const end = content.indexOf(DOSU_RULE_SECTION_END, Math.max(start, 0));
|
|
62934
|
-
if (start === -1 && end === -1)
|
|
62935
|
-
return null;
|
|
62936
|
-
if (start === -1 || end < start) {
|
|
62937
|
-
throw new Error("Dosu rule markers are incomplete; refusing to overwrite the instruction file");
|
|
62938
|
-
}
|
|
62939
|
-
return { start, end };
|
|
62940
|
-
}
|
|
62941
|
-
function lineEndingFor(content) {
|
|
62942
|
-
return content.includes(`\r
|
|
62943
|
-
`) ? `\r
|
|
62944
|
-
` : `
|
|
62945
|
-
`;
|
|
62946
|
-
}
|
|
62947
|
-
function buildSection(content, lineEnding = `
|
|
62948
|
-
`) {
|
|
62949
|
-
const body = content.trimEnd().replace(/\r?\n/g, lineEnding);
|
|
62950
|
-
return `${DOSU_RULE_SECTION_START}${lineEnding}${body}${lineEnding}${DOSU_RULE_SECTION_END}`;
|
|
62951
|
-
}
|
|
62952
|
-
function upsertSection(path, content) {
|
|
62953
|
-
if (!existsSync25(path)) {
|
|
62954
|
-
const section = buildSection(content);
|
|
62955
|
-
ensureParent(path);
|
|
62956
|
-
writeFileSync16(path, `${section}
|
|
62957
|
-
`, "utf-8");
|
|
62958
|
-
return "created";
|
|
62959
|
-
}
|
|
62960
|
-
const existing = readFileSync24(path, "utf-8");
|
|
62961
|
-
const lineEnding = lineEndingFor(existing);
|
|
62962
|
-
const section = buildSection(content, lineEnding);
|
|
62963
|
-
const location = findSection(existing);
|
|
62964
|
-
let next;
|
|
62965
|
-
if (location) {
|
|
62966
|
-
next = existing.slice(0, location.start) + section + existing.slice(location.end + DOSU_RULE_SECTION_END.length);
|
|
62967
|
-
} else {
|
|
62968
|
-
const separator = existing.length > 0 && !existing.endsWith(lineEnding) ? `${lineEnding}${lineEnding}` : existing.length > 0 ? lineEnding : "";
|
|
62969
|
-
next = `${existing}${separator}${section}${lineEnding}`;
|
|
62970
|
-
}
|
|
62971
|
-
if (next === existing)
|
|
62972
|
-
return "unchanged";
|
|
62973
|
-
writeFileSync16(path, next, "utf-8");
|
|
62974
|
-
return "updated";
|
|
62975
|
-
}
|
|
62976
|
-
function installRuleForAgent(agent, content) {
|
|
62977
|
-
if (!isRuleAgent(agent))
|
|
62978
|
-
return null;
|
|
62979
|
-
const target = RULE_TARGETS[agent];
|
|
62980
|
-
const path = target.path();
|
|
62981
|
-
const normalized = normalizeRule(content);
|
|
62982
|
-
const action = target.kind === "file" ? writeIfChanged(path, target.cursorFrontmatter ? `${CURSOR_FRONTMATTER}${normalized}` : normalized) : upsertSection(path, normalized);
|
|
62983
|
-
return { agent, path, action };
|
|
62984
|
-
}
|
|
62985
|
-
function removeRuleForAgent(agent) {
|
|
62986
|
-
if (!isRuleAgent(agent))
|
|
62987
|
-
return null;
|
|
62988
|
-
const target = RULE_TARGETS[agent];
|
|
62989
|
-
const path = target.path();
|
|
62990
|
-
if (!existsSync25(path))
|
|
62991
|
-
return { agent, path, action: "not_found" };
|
|
62992
|
-
if (target.kind === "file") {
|
|
62993
|
-
unlinkSync5(path);
|
|
62994
|
-
return { agent, path, action: "removed" };
|
|
62995
|
-
}
|
|
62996
|
-
const existing = readFileSync24(path, "utf-8");
|
|
62997
|
-
const lineEnding = lineEndingFor(existing);
|
|
62998
|
-
const location = findSection(existing);
|
|
62999
|
-
if (!location)
|
|
63000
|
-
return { agent, path, action: "not_found" };
|
|
63001
|
-
const next = (existing.slice(0, location.start) + existing.slice(location.end + DOSU_RULE_SECTION_END.length)).replace(/(?:\r?\n){3,}/g, `${lineEnding}${lineEnding}`).replace(/^(?:\r?\n)+/, "").trimEnd();
|
|
63002
|
-
if (!next) {
|
|
63003
|
-
unlinkSync5(path);
|
|
63004
|
-
} else {
|
|
63005
|
-
writeFileSync16(path, `${next}${lineEnding}`, "utf-8");
|
|
63006
|
-
}
|
|
63007
|
-
return { agent, path, action: "removed" };
|
|
63008
|
-
}
|
|
63009
|
-
var DOSU_RULE_SECTION_VERSION = 1, DOSU_RULE_SECTION_START, DOSU_RULE_SECTION_END = "<!-- dosu:rules:end -->", DOSU_RULE_SECTION_START_RE, CURSOR_FRONTMATTER = `---
|
|
63010
|
-
alwaysApply: true
|
|
63011
|
-
---
|
|
63012
|
-
|
|
63013
|
-
`, DOSU_RULE_URLS, FALLBACK_DOSU_RULE = `The team you are assisting maintains shared knowledge in Dosu: consult it to build on prior work, and contribute durable knowledge so future teammates and agents do not have to rediscover it. Always use only tools currently listed by the server.
|
|
63014
|
-
|
|
63015
|
-
When \`read_knowledge\` is listed, call it before non-trivial code or documentation work involving architecture, conventions, prior decisions, gotchas, incidents, ownership, or branch history. **If unsure whether relevant context exists, read first.** Pass \`repo\` and \`branch\` when available. Skip generic questions, trivial or self-contained edits, and context already injected by Dosu.
|
|
63016
|
-
|
|
63017
|
-
When \`write_knowledge\` is listed, use it after the task for durable, non-obvious knowledge that future work would otherwise have to rediscover. Do not save task or PR summaries, progress, test results, obvious facts, speculation, duplicates, or sensitive data. **If nothing durable was learned, do not write.**
|
|
63018
|
-
|
|
63019
|
-
Use \`review_knowledge\` only when the user asks to inspect or manage pending knowledge. Preview one item at a time and require explicit confirmation before making changes.
|
|
63020
|
-
|
|
63021
|
-
When \`read_knowledge\` or \`write_knowledge\` returned a \`receipt_item_id\` this turn, call \`finalize_session_knowledge\` exactly once at the end of the turn — after completing the task, immediately before your final reply — passing all receipt_item_ids from this turn. Never call it when the current turn produced no receipt_item_id, and never call it more than once per turn.
|
|
63022
|
-
`, RULE_TARGETS;
|
|
63023
|
-
var init_installer = __esm(() => {
|
|
63024
|
-
DOSU_RULE_SECTION_START = `<!-- dosu:rules:start v${DOSU_RULE_SECTION_VERSION} -->`;
|
|
63025
|
-
DOSU_RULE_SECTION_START_RE = /<!-- dosu:rules:start(?: v\d+)? -->/;
|
|
63026
|
-
DOSU_RULE_URLS = [
|
|
63027
|
-
"https://raw.githubusercontent.com/dosu-ai/dosu-cli/main/rules/dosu.md",
|
|
63028
|
-
"https://raw.githubusercontent.com/dosu-ai/dosu-cli/master/rules/dosu.md"
|
|
63029
|
-
];
|
|
63030
|
-
RULE_TARGETS = {
|
|
63031
|
-
claude: {
|
|
63032
|
-
kind: "file",
|
|
63033
|
-
path: () => join40(claudeConfigDir4(), "rules", "dosu.md")
|
|
63034
|
-
},
|
|
63035
|
-
cursor: {
|
|
63036
|
-
kind: "file",
|
|
63037
|
-
path: () => join40(homedir12(), ".cursor", "rules", "dosu.mdc"),
|
|
63038
|
-
cursorFrontmatter: true
|
|
63039
|
-
},
|
|
63040
|
-
codex: {
|
|
63041
|
-
kind: "section",
|
|
63042
|
-
path: () => join40(codexHome4(), "AGENTS.md")
|
|
63043
|
-
},
|
|
63044
|
-
opencode: {
|
|
63045
|
-
kind: "section",
|
|
63046
|
-
path: () => join40(homedir12(), ".config", "opencode", "AGENTS.md")
|
|
63047
|
-
},
|
|
63048
|
-
gemini: {
|
|
63049
|
-
kind: "section",
|
|
63050
|
-
path: () => join40(homedir12(), ".gemini", "GEMINI.md")
|
|
63051
|
-
},
|
|
63052
|
-
antigravity: {
|
|
63053
|
-
kind: "section",
|
|
63054
|
-
path: () => join40(homedir12(), ".gemini", "GEMINI.md")
|
|
63055
|
-
}
|
|
63056
|
-
};
|
|
63057
|
-
});
|
|
63058
|
-
|
|
63059
|
-
// src/setup/agents-md-step.ts
|
|
63060
|
-
import { execSync as execSync2 } from "node:child_process";
|
|
63061
|
-
import { existsSync as existsSync26, readFileSync as readFileSync25, writeFileSync as writeFileSync17 } from "node:fs";
|
|
63062
|
-
import { join as join41 } from "node:path";
|
|
63063
|
-
function inGitWorkTree(cwd = process.cwd()) {
|
|
63064
|
-
try {
|
|
63065
|
-
const stdout = execSync2("git rev-parse --is-inside-work-tree", {
|
|
63066
|
-
cwd,
|
|
63067
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
63068
|
-
});
|
|
63069
|
-
return stdout.toString().trim() === "true";
|
|
63070
|
-
} catch {
|
|
63071
|
-
return false;
|
|
63072
|
-
}
|
|
63073
|
-
}
|
|
63074
|
-
function dosuAgentsSectionState(cwd = process.cwd()) {
|
|
63075
|
-
try {
|
|
63076
|
-
const path = join41(cwd, "AGENTS.md");
|
|
63077
|
-
if (!existsSync26(path))
|
|
63078
|
-
return "missing";
|
|
63079
|
-
const content = readFileSync25(path, "utf-8");
|
|
63080
|
-
const startMatch = content.match(SECTION_START_RE);
|
|
63081
|
-
if (!startMatch || !content.includes(DOSU_SECTION_END))
|
|
63082
|
-
return "missing";
|
|
63083
|
-
return Number(startMatch[1] ?? 0) >= DOSU_SECTION_VERSION ? "current" : "outdated";
|
|
63084
|
-
} catch {
|
|
63085
|
-
return "missing";
|
|
63086
|
-
}
|
|
63087
|
-
}
|
|
63088
|
-
function lineEndingFor2(content) {
|
|
63089
|
-
return content.includes(`\r
|
|
63090
|
-
`) ? `\r
|
|
63091
|
-
` : `
|
|
63092
|
-
`;
|
|
63093
|
-
}
|
|
63094
|
-
function renderDosuAgentsSection(content, lineEnding) {
|
|
63095
|
-
const body = content.trim().replace(/\r?\n/g, lineEnding);
|
|
63096
|
-
return `${DOSU_SECTION_START}${lineEnding}${body}${lineEnding}${DOSU_SECTION_END}`;
|
|
63097
|
-
}
|
|
63098
|
-
function buildDosuAgentsSection(content = FALLBACK_DOSU_RULE) {
|
|
63099
|
-
return renderDosuAgentsSection(content, `
|
|
63100
|
-
`);
|
|
63101
|
-
}
|
|
63102
|
-
function findSection2(content) {
|
|
63103
|
-
const startMatch = content.match(SECTION_START_RE);
|
|
63104
|
-
const start = startMatch?.index ?? -1;
|
|
63105
|
-
const end = content.indexOf(DOSU_SECTION_END, Math.max(start, 0));
|
|
63106
|
-
if (start === -1 && end === -1)
|
|
63107
|
-
return null;
|
|
63108
|
-
if (start === -1 || end < start) {
|
|
63109
|
-
throw new Error("Dosu AGENTS.md markers are incomplete; refusing to overwrite the file");
|
|
63110
|
-
}
|
|
63111
|
-
return { start, end };
|
|
63112
|
-
}
|
|
63113
|
-
function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RULE) {
|
|
63114
|
-
const path = join41(cwd, "AGENTS.md");
|
|
63115
|
-
if (!existsSync26(path)) {
|
|
63116
|
-
const section = buildDosuAgentsSection(content);
|
|
63117
|
-
writeFileSync17(path, `${section}
|
|
63118
|
-
`);
|
|
63119
|
-
return { path, action: "created" };
|
|
63120
|
-
}
|
|
63121
|
-
const existing = readFileSync25(path, "utf-8");
|
|
63122
|
-
const lineEnding = lineEndingFor2(existing);
|
|
63123
|
-
const section = renderDosuAgentsSection(content, lineEnding);
|
|
63124
|
-
const location = findSection2(existing);
|
|
63125
|
-
let next;
|
|
63126
|
-
if (location) {
|
|
63127
|
-
next = existing.slice(0, location.start) + section + existing.slice(location.end + DOSU_SECTION_END.length);
|
|
63128
|
-
} else {
|
|
63129
|
-
next = `${existing.trimEnd()}${lineEnding}${lineEnding}${section}${lineEnding}`;
|
|
63130
|
-
}
|
|
63131
|
-
if (next === existing)
|
|
63132
|
-
return { path, action: "unchanged" };
|
|
63133
|
-
writeFileSync17(path, next);
|
|
63134
|
-
return { path, action: "updated" };
|
|
63135
|
-
}
|
|
63136
|
-
async function stepUpdateAgentsMd(cwd = process.cwd(), content) {
|
|
63137
|
-
logger.info("setup", "Step: update AGENTS.md");
|
|
63138
|
-
try {
|
|
63139
|
-
const result = upsertDosuAgentsSection(cwd, content ?? await fetchDosuRule());
|
|
63140
|
-
logger.info("setup", `AGENTS.md ${result.action} at ${result.path}`);
|
|
63141
|
-
const status = result.action === "unchanged" ? "already up to date" : result.action;
|
|
63142
|
-
log2.success(formatSetupSummary("AGENTS.md", [{ path: result.path, status }]));
|
|
63143
|
-
return true;
|
|
63144
|
-
} catch (err) {
|
|
63145
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
63146
|
-
logger.error("setup", `AGENTS.md update failed: ${msg}`);
|
|
63147
|
-
log2.error(`Could not update AGENTS.md: ${msg}`);
|
|
63148
|
-
return false;
|
|
63149
|
-
}
|
|
63150
|
-
}
|
|
63151
|
-
var DOSU_SECTION_VERSION = 2, DOSU_SECTION_START, DOSU_SECTION_END = "<!-- dosu:mcp:end -->", SECTION_START_RE;
|
|
63152
|
-
var init_agents_md_step = __esm(() => {
|
|
63153
|
-
init_logger();
|
|
63154
|
-
init_installer();
|
|
63155
|
-
init_prompts();
|
|
63156
|
-
init_styles();
|
|
63157
|
-
DOSU_SECTION_START = `<!-- dosu:mcp:start v${DOSU_SECTION_VERSION} -->`;
|
|
63158
|
-
SECTION_START_RE = /<!-- dosu:mcp:start(?: v(\d+))? -->/;
|
|
62611
|
+
import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
63159
62612
|
});
|
|
63160
62613
|
|
|
63161
62614
|
// src/auth/errors.ts
|
|
@@ -63185,16 +62638,51 @@ var init_errors3 = __esm(() => {
|
|
|
63185
62638
|
// src/mcp/constants.ts
|
|
63186
62639
|
var MCP_PROVIDER_SLUG2 = "dosu_mcp";
|
|
63187
62640
|
|
|
62641
|
+
// src/debug/follow.ts
|
|
62642
|
+
import { closeSync as closeSync6, openSync as openSync6, readSync as readSync5, statSync as statSync8 } from "node:fs";
|
|
62643
|
+
function createLogFollower(path, emit) {
|
|
62644
|
+
const sizeOf = () => {
|
|
62645
|
+
try {
|
|
62646
|
+
return statSync8(path).size;
|
|
62647
|
+
} catch {
|
|
62648
|
+
return 0;
|
|
62649
|
+
}
|
|
62650
|
+
};
|
|
62651
|
+
let offset = sizeOf();
|
|
62652
|
+
return {
|
|
62653
|
+
poll() {
|
|
62654
|
+
const size = sizeOf();
|
|
62655
|
+
if (size < offset)
|
|
62656
|
+
offset = 0;
|
|
62657
|
+
if (size === offset)
|
|
62658
|
+
return;
|
|
62659
|
+
try {
|
|
62660
|
+
const fd = openSync6(path, "r");
|
|
62661
|
+
try {
|
|
62662
|
+
const buf = Buffer.alloc(size - offset);
|
|
62663
|
+
const read = readSync5(fd, buf, 0, buf.length, offset);
|
|
62664
|
+
offset += read;
|
|
62665
|
+
if (read > 0)
|
|
62666
|
+
emit(buf.toString("utf-8", 0, read));
|
|
62667
|
+
} finally {
|
|
62668
|
+
closeSync6(fd);
|
|
62669
|
+
}
|
|
62670
|
+
} catch {}
|
|
62671
|
+
}
|
|
62672
|
+
};
|
|
62673
|
+
}
|
|
62674
|
+
var init_follow = () => {};
|
|
62675
|
+
|
|
63188
62676
|
// src/sessions/session-title.ts
|
|
63189
|
-
import { existsSync as
|
|
63190
|
-
import { homedir as
|
|
63191
|
-
import { join as
|
|
62677
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync24, renameSync as renameSync6, statSync as statSync9, writeFileSync as writeFileSync16 } from "node:fs";
|
|
62678
|
+
import { homedir as homedir11 } from "node:os";
|
|
62679
|
+
import { join as join40 } from "node:path";
|
|
63192
62680
|
function cachePath2(configDir) {
|
|
63193
|
-
return
|
|
62681
|
+
return join40(configDir, CACHE_FILENAME5);
|
|
63194
62682
|
}
|
|
63195
62683
|
function loadCacheFile2(configDir) {
|
|
63196
62684
|
try {
|
|
63197
|
-
const raw = JSON.parse(
|
|
62685
|
+
const raw = JSON.parse(readFileSync24(cachePath2(configDir), "utf-8"));
|
|
63198
62686
|
if (raw.schema_version !== CACHE_SCHEMA_VERSION2 || typeof raw.entries !== "object")
|
|
63199
62687
|
return {};
|
|
63200
62688
|
return raw.entries;
|
|
@@ -63204,12 +62692,12 @@ function loadCacheFile2(configDir) {
|
|
|
63204
62692
|
}
|
|
63205
62693
|
function saveCacheFile2(configDir, entries) {
|
|
63206
62694
|
try {
|
|
63207
|
-
if (!
|
|
63208
|
-
|
|
62695
|
+
if (!existsSync25(configDir))
|
|
62696
|
+
mkdirSync15(configDir, { recursive: true, mode: 448 });
|
|
63209
62697
|
const path = cachePath2(configDir);
|
|
63210
62698
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
63211
62699
|
const file = { schema_version: CACHE_SCHEMA_VERSION2, entries };
|
|
63212
|
-
|
|
62700
|
+
writeFileSync16(tmp, JSON.stringify(file), { mode: 384 });
|
|
63213
62701
|
renameSync6(tmp, path);
|
|
63214
62702
|
} catch {}
|
|
63215
62703
|
}
|
|
@@ -63242,15 +62730,15 @@ function claudeSummaryFromHead(text) {
|
|
|
63242
62730
|
}
|
|
63243
62731
|
return null;
|
|
63244
62732
|
}
|
|
63245
|
-
function reconstructSession(harness, id, slug, home =
|
|
62733
|
+
function reconstructSession(harness, id, slug, home = homedir11(), exists = existsSync25) {
|
|
63246
62734
|
if (!slug)
|
|
63247
62735
|
return null;
|
|
63248
62736
|
const candidates = [];
|
|
63249
62737
|
if (harness === "claude") {
|
|
63250
|
-
candidates.push(
|
|
62738
|
+
candidates.push(join40(home, ".claude", "projects", slug, `${id}.jsonl`));
|
|
63251
62739
|
} else if (harness === "cursor") {
|
|
63252
|
-
const project =
|
|
63253
|
-
candidates.push(
|
|
62740
|
+
const project = join40(home, ".cursor", "projects", slug);
|
|
62741
|
+
candidates.push(join40(project, "agent-transcripts", id, `${id}.jsonl`), join40(project, "agent-transcripts", `${id}.jsonl`));
|
|
63254
62742
|
} else {
|
|
63255
62743
|
return null;
|
|
63256
62744
|
}
|
|
@@ -63262,7 +62750,7 @@ function reconstructSession(harness, id, slug, home = homedir13(), exists = exis
|
|
|
63262
62750
|
}
|
|
63263
62751
|
function readHead2(path) {
|
|
63264
62752
|
try {
|
|
63265
|
-
return
|
|
62753
|
+
return readFileSync24(path, "utf-8").slice(0, 128 * 1024);
|
|
63266
62754
|
} catch {
|
|
63267
62755
|
return null;
|
|
63268
62756
|
}
|
|
@@ -63342,7 +62830,7 @@ var init_alt_screen = __esm(() => {
|
|
|
63342
62830
|
});
|
|
63343
62831
|
|
|
63344
62832
|
// src/tui/activity-view.ts
|
|
63345
|
-
import { existsSync as
|
|
62833
|
+
import { existsSync as existsSync26, readFileSync as readFileSync25 } from "node:fs";
|
|
63346
62834
|
import { basename as basename5 } from "node:path";
|
|
63347
62835
|
function reduceActivityViewKey(key) {
|
|
63348
62836
|
if (key === "q" || key === ESC7 || key === CTRL_C4)
|
|
@@ -63483,15 +62971,15 @@ function statusLine(status) {
|
|
|
63483
62971
|
if (status.running) {
|
|
63484
62972
|
const since = status.startedAt ? ` · since ${localTime(status.startedAt)}` : "";
|
|
63485
62973
|
const pid = status.pid !== undefined ? ` (pid ${status.pid})` : "";
|
|
63486
|
-
return `\uD83D\uDCDA ${
|
|
62974
|
+
return `\uD83D\uDCDA ${import_picocolors33.default.bold(brand("Studying sessions..."))}${import_picocolors33.default.dim(`${pid}${since}`)}`;
|
|
63487
62975
|
}
|
|
63488
62976
|
if (status.state.paused) {
|
|
63489
|
-
return `${
|
|
62977
|
+
return `${import_picocolors33.default.yellow("○")} ${import_picocolors33.default.bold("Paused")} ${import_picocolors33.default.dim("· studying stays off until you resume")}`;
|
|
63490
62978
|
}
|
|
63491
62979
|
if (status.staleLock) {
|
|
63492
|
-
return `${
|
|
62980
|
+
return `${import_picocolors33.default.yellow("○")} ${import_picocolors33.default.bold("Not running")} ${import_picocolors33.default.dim("· a previous run exited without cleaning up")}`;
|
|
63493
62981
|
}
|
|
63494
|
-
return `${
|
|
62982
|
+
return `${import_picocolors33.default.dim("○")} ${import_picocolors33.default.bold("Idle")} ${import_picocolors33.default.dim("· hooks study new sessions automatically")}`;
|
|
63495
62983
|
}
|
|
63496
62984
|
function progressLine(done, ready, width, notes = 0) {
|
|
63497
62985
|
const total = done + ready;
|
|
@@ -63500,7 +62988,7 @@ function progressLine(done, ready, width, notes = 0) {
|
|
|
63500
62988
|
const cells = Math.max(10, Math.min(30, width - 44));
|
|
63501
62989
|
const ratio = Math.max(0, Math.min(1, done / total));
|
|
63502
62990
|
const filled = Math.min(cells, Math.round(ratio * cells));
|
|
63503
|
-
const bar = brand("█".repeat(filled)) +
|
|
62991
|
+
const bar = brand("█".repeat(filled)) + import_picocolors33.default.dim("░".repeat(cells - filled));
|
|
63504
62992
|
const pct = Math.floor(ratio * 100);
|
|
63505
62993
|
const suffix = notes > 0 ? ` · ${notes} suggested page${notes === 1 ? "" : "s"}` : "";
|
|
63506
62994
|
return `${bar} ${done}/${total} studied · ${pct}%${suffix}`;
|
|
@@ -63539,17 +63027,17 @@ function confirmBox(queuedCount, backlog, width, mode = "start") {
|
|
|
63539
63027
|
const verb = mode === "clear" ? "clear" : mode === "stop" ? "stop" : mode === "resume" ? "resume" : "start";
|
|
63540
63028
|
const maxInner = Math.max(20, Math.min(width, contentWidth()) - 4);
|
|
63541
63029
|
const rows = [
|
|
63542
|
-
|
|
63543
|
-
...wrapLine(scope, maxInner, "").map((line) =>
|
|
63030
|
+
import_picocolors33.default.bold(brand(title)),
|
|
63031
|
+
...wrapLine(scope, maxInner, "").map((line) => import_picocolors33.default.dim(line)),
|
|
63544
63032
|
"",
|
|
63545
|
-
`${
|
|
63033
|
+
`${import_picocolors33.default.bold("enter")} ${verb} · ${import_picocolors33.default.bold("esc")} cancel`
|
|
63546
63034
|
];
|
|
63547
63035
|
const inner = Math.min(maxInner, Math.max(...rows.map(visibleWidth2)));
|
|
63548
63036
|
const pad = (row) => row + " ".repeat(Math.max(0, inner - visibleWidth2(row)));
|
|
63549
63037
|
return [
|
|
63550
|
-
|
|
63551
|
-
...rows.map((row) => `${
|
|
63552
|
-
|
|
63038
|
+
import_picocolors33.default.dim(`╭${"─".repeat(inner + 2)}╮`),
|
|
63039
|
+
...rows.map((row) => `${import_picocolors33.default.dim("│")} ${pad(row)} ${import_picocolors33.default.dim("│")}`),
|
|
63040
|
+
import_picocolors33.default.dim(`╰${"─".repeat(inner + 2)}╯`)
|
|
63553
63041
|
];
|
|
63554
63042
|
}
|
|
63555
63043
|
function buildActivityFrame(status, activity, width, backlog = null, pane = DEFAULT_PANE, queued = [], studiedBeforeRun = 0, open = [], runProgress = null, projectNames = {}, sessionNames = {}, frameLines) {
|
|
@@ -63565,7 +63053,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
63565
63053
|
progress = progressLine(studiedDelta + stepDone, Math.max(0, backlog.ready - stepDone), width, runProgress?.notes ?? 0);
|
|
63566
63054
|
}
|
|
63567
63055
|
const refusal = !status.running && status.state.last_refusal;
|
|
63568
|
-
const refusalLines = refusal ? wrapLine(`! Studying paused: ${refusal.message} (${localTime(refusal.at)})`, width).map((line) =>
|
|
63056
|
+
const refusalLines = refusal ? wrapLine(`! Studying paused: ${refusal.message} (${localTime(refusal.at)})`, width).map((line) => import_picocolors33.default.yellow(line)) : [];
|
|
63569
63057
|
const fullRows = Boolean(pane.fullRows);
|
|
63570
63058
|
const withName = (item, key) => projectNames[key] ? { ...item, project: projectNames[key] } : item;
|
|
63571
63059
|
const latestPass = new Map;
|
|
@@ -63591,8 +63079,8 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
63591
63079
|
breadcrumb(["home", "activity"], width),
|
|
63592
63080
|
"",
|
|
63593
63081
|
statusLine(status),
|
|
63594
|
-
|
|
63595
|
-
...queueDetail.length > 0 ? wrapLine(queueDetail.join(" · "), width).map((line) =>
|
|
63082
|
+
import_picocolors33.default.dim(studied),
|
|
63083
|
+
...queueDetail.length > 0 ? wrapLine(queueDetail.join(" · "), width).map((line) => import_picocolors33.default.dim(line)) : [],
|
|
63596
63084
|
...progress ? [progress] : [],
|
|
63597
63085
|
...refusalLines,
|
|
63598
63086
|
"",
|
|
@@ -63608,7 +63096,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
63608
63096
|
status.running ? "s stop" : status.state.paused ? "s resume" : "s sync now",
|
|
63609
63097
|
...!status.running && status.state.watermark ? ["c clear"] : [],
|
|
63610
63098
|
"esc back"
|
|
63611
|
-
].join(" · "), width, "").map((line) =>
|
|
63099
|
+
].join(" · "), width, "").map((line) => import_picocolors33.default.dim(line))
|
|
63612
63100
|
]
|
|
63613
63101
|
];
|
|
63614
63102
|
const defaultHeight = fullRows ? ACTIVITY_VIEW_FULL_LIST_ROWS : ACTIVITY_VIEW_LIST_LINES;
|
|
@@ -63621,7 +63109,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
63621
63109
|
({ visible, above, below } = windowList(source, pane.scroll, height));
|
|
63622
63110
|
display = visible.flatMap((row) => wrapRow(row, width));
|
|
63623
63111
|
}
|
|
63624
|
-
const listRows = display.length > 0 ? display.map((row) =>
|
|
63112
|
+
const listRows = display.length > 0 ? display.map((row) => import_picocolors33.default.dim(row)) : [import_picocolors33.default.dim(empty)];
|
|
63625
63113
|
const scrollParts = [];
|
|
63626
63114
|
if (above > 0)
|
|
63627
63115
|
scrollParts.push(`↑ ${above} earlier`);
|
|
@@ -63630,7 +63118,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
63630
63118
|
const lines = [
|
|
63631
63119
|
...header,
|
|
63632
63120
|
...listRows,
|
|
63633
|
-
...scrollParts.length > 0 ? [
|
|
63121
|
+
...scrollParts.length > 0 ? [import_picocolors33.default.dim(clip(scrollParts.join(" · "), width))] : [],
|
|
63634
63122
|
...footer
|
|
63635
63123
|
];
|
|
63636
63124
|
return { lines, listHeight: height };
|
|
@@ -63663,7 +63151,7 @@ function createRowNamer() {
|
|
|
63663
63151
|
names.titles[key] = t;
|
|
63664
63152
|
};
|
|
63665
63153
|
for (const s of [...backlog.queued, ...backlog.open]) {
|
|
63666
|
-
if (!
|
|
63154
|
+
if (!existsSync26(s.path))
|
|
63667
63155
|
continue;
|
|
63668
63156
|
const key = `${s.harness}/${s.id}`;
|
|
63669
63157
|
const dir = dirs.resolve(s);
|
|
@@ -63700,7 +63188,7 @@ function createRowNamer() {
|
|
|
63700
63188
|
}
|
|
63701
63189
|
function defaultReadLog2() {
|
|
63702
63190
|
try {
|
|
63703
|
-
return
|
|
63191
|
+
return readFileSync25(logger.getLogPath(), "utf-8");
|
|
63704
63192
|
} catch {
|
|
63705
63193
|
return "";
|
|
63706
63194
|
}
|
|
@@ -63885,7 +63373,7 @@ ${CLEAR_BELOW}`);
|
|
|
63885
63373
|
input.on("data", onData);
|
|
63886
63374
|
});
|
|
63887
63375
|
}
|
|
63888
|
-
var
|
|
63376
|
+
var import_picocolors33, 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;
|
|
63889
63377
|
var init_activity_view = __esm(() => {
|
|
63890
63378
|
init_follow();
|
|
63891
63379
|
init_logger();
|
|
@@ -63900,7 +63388,7 @@ var init_activity_view = __esm(() => {
|
|
|
63900
63388
|
init_alt_screen();
|
|
63901
63389
|
init_layout();
|
|
63902
63390
|
init_menu();
|
|
63903
|
-
|
|
63391
|
+
import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
63904
63392
|
ESC7 = String.fromCharCode(27);
|
|
63905
63393
|
HIDE_CURSOR3 = `${ESC7}[?25l`;
|
|
63906
63394
|
SHOW_CURSOR3 = `${ESC7}[?25h`;
|
|
@@ -63916,6 +63404,284 @@ var init_activity_view = __esm(() => {
|
|
|
63916
63404
|
DEFAULT_PANE = { tab: "activity", scroll: 0 };
|
|
63917
63405
|
});
|
|
63918
63406
|
|
|
63407
|
+
// src/rules/installer.ts
|
|
63408
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync26, unlinkSync as unlinkSync5, writeFileSync as writeFileSync17 } from "node:fs";
|
|
63409
|
+
import { homedir as homedir12 } from "node:os";
|
|
63410
|
+
import { dirname as dirname12, join as join41 } from "node:path";
|
|
63411
|
+
function claudeConfigDir4() {
|
|
63412
|
+
return process.env.CLAUDE_CONFIG_DIR || join41(homedir12(), ".claude");
|
|
63413
|
+
}
|
|
63414
|
+
function codexHome4() {
|
|
63415
|
+
return process.env.CODEX_HOME || join41(homedir12(), ".codex");
|
|
63416
|
+
}
|
|
63417
|
+
function isRuleAgent(agent) {
|
|
63418
|
+
return Object.hasOwn(RULE_TARGETS, agent);
|
|
63419
|
+
}
|
|
63420
|
+
function rulePathForAgent(agent) {
|
|
63421
|
+
return isRuleAgent(agent) ? RULE_TARGETS[agent].path() : null;
|
|
63422
|
+
}
|
|
63423
|
+
function normalizeRule(content) {
|
|
63424
|
+
return `${content.trim()}
|
|
63425
|
+
`;
|
|
63426
|
+
}
|
|
63427
|
+
async function fetchDosuRule(fetchImpl = globalThis.fetch) {
|
|
63428
|
+
for (const url of DOSU_RULE_URLS) {
|
|
63429
|
+
try {
|
|
63430
|
+
const response = await fetchImpl(url);
|
|
63431
|
+
if (!response.ok)
|
|
63432
|
+
continue;
|
|
63433
|
+
const content = await response.text();
|
|
63434
|
+
if (content.trim())
|
|
63435
|
+
return normalizeRule(content);
|
|
63436
|
+
} catch {}
|
|
63437
|
+
}
|
|
63438
|
+
return normalizeRule(FALLBACK_DOSU_RULE);
|
|
63439
|
+
}
|
|
63440
|
+
function ensureParent(path) {
|
|
63441
|
+
mkdirSync16(dirname12(path), { recursive: true });
|
|
63442
|
+
}
|
|
63443
|
+
function writeIfChanged(path, content) {
|
|
63444
|
+
if (!existsSync27(path)) {
|
|
63445
|
+
ensureParent(path);
|
|
63446
|
+
writeFileSync17(path, content, "utf-8");
|
|
63447
|
+
return "created";
|
|
63448
|
+
}
|
|
63449
|
+
if (readFileSync26(path, "utf-8") === content)
|
|
63450
|
+
return "unchanged";
|
|
63451
|
+
writeFileSync17(path, content, "utf-8");
|
|
63452
|
+
return "updated";
|
|
63453
|
+
}
|
|
63454
|
+
function findSection(content) {
|
|
63455
|
+
const startMatch = content.match(DOSU_RULE_SECTION_START_RE);
|
|
63456
|
+
const start = startMatch?.index ?? -1;
|
|
63457
|
+
const end = content.indexOf(DOSU_RULE_SECTION_END, Math.max(start, 0));
|
|
63458
|
+
if (start === -1 && end === -1)
|
|
63459
|
+
return null;
|
|
63460
|
+
if (start === -1 || end < start) {
|
|
63461
|
+
throw new Error("Dosu rule markers are incomplete; refusing to overwrite the instruction file");
|
|
63462
|
+
}
|
|
63463
|
+
return { start, end };
|
|
63464
|
+
}
|
|
63465
|
+
function lineEndingFor(content) {
|
|
63466
|
+
return content.includes(`\r
|
|
63467
|
+
`) ? `\r
|
|
63468
|
+
` : `
|
|
63469
|
+
`;
|
|
63470
|
+
}
|
|
63471
|
+
function buildSection(content, lineEnding = `
|
|
63472
|
+
`) {
|
|
63473
|
+
const body = content.trimEnd().replace(/\r?\n/g, lineEnding);
|
|
63474
|
+
return `${DOSU_RULE_SECTION_START}${lineEnding}${body}${lineEnding}${DOSU_RULE_SECTION_END}`;
|
|
63475
|
+
}
|
|
63476
|
+
function upsertSection(path, content) {
|
|
63477
|
+
if (!existsSync27(path)) {
|
|
63478
|
+
const section = buildSection(content);
|
|
63479
|
+
ensureParent(path);
|
|
63480
|
+
writeFileSync17(path, `${section}
|
|
63481
|
+
`, "utf-8");
|
|
63482
|
+
return "created";
|
|
63483
|
+
}
|
|
63484
|
+
const existing = readFileSync26(path, "utf-8");
|
|
63485
|
+
const lineEnding = lineEndingFor(existing);
|
|
63486
|
+
const section = buildSection(content, lineEnding);
|
|
63487
|
+
const location = findSection(existing);
|
|
63488
|
+
let next;
|
|
63489
|
+
if (location) {
|
|
63490
|
+
next = existing.slice(0, location.start) + section + existing.slice(location.end + DOSU_RULE_SECTION_END.length);
|
|
63491
|
+
} else {
|
|
63492
|
+
const separator = existing.length > 0 && !existing.endsWith(lineEnding) ? `${lineEnding}${lineEnding}` : existing.length > 0 ? lineEnding : "";
|
|
63493
|
+
next = `${existing}${separator}${section}${lineEnding}`;
|
|
63494
|
+
}
|
|
63495
|
+
if (next === existing)
|
|
63496
|
+
return "unchanged";
|
|
63497
|
+
writeFileSync17(path, next, "utf-8");
|
|
63498
|
+
return "updated";
|
|
63499
|
+
}
|
|
63500
|
+
function installRuleForAgent(agent, content) {
|
|
63501
|
+
if (!isRuleAgent(agent))
|
|
63502
|
+
return null;
|
|
63503
|
+
const target = RULE_TARGETS[agent];
|
|
63504
|
+
const path = target.path();
|
|
63505
|
+
const normalized = normalizeRule(content);
|
|
63506
|
+
const action = target.kind === "file" ? writeIfChanged(path, target.cursorFrontmatter ? `${CURSOR_FRONTMATTER}${normalized}` : normalized) : upsertSection(path, normalized);
|
|
63507
|
+
return { agent, path, action };
|
|
63508
|
+
}
|
|
63509
|
+
function removeRuleForAgent(agent) {
|
|
63510
|
+
if (!isRuleAgent(agent))
|
|
63511
|
+
return null;
|
|
63512
|
+
const target = RULE_TARGETS[agent];
|
|
63513
|
+
const path = target.path();
|
|
63514
|
+
if (!existsSync27(path))
|
|
63515
|
+
return { agent, path, action: "not_found" };
|
|
63516
|
+
if (target.kind === "file") {
|
|
63517
|
+
unlinkSync5(path);
|
|
63518
|
+
return { agent, path, action: "removed" };
|
|
63519
|
+
}
|
|
63520
|
+
const existing = readFileSync26(path, "utf-8");
|
|
63521
|
+
const lineEnding = lineEndingFor(existing);
|
|
63522
|
+
const location = findSection(existing);
|
|
63523
|
+
if (!location)
|
|
63524
|
+
return { agent, path, action: "not_found" };
|
|
63525
|
+
const next = (existing.slice(0, location.start) + existing.slice(location.end + DOSU_RULE_SECTION_END.length)).replace(/(?:\r?\n){3,}/g, `${lineEnding}${lineEnding}`).replace(/^(?:\r?\n)+/, "").trimEnd();
|
|
63526
|
+
if (!next) {
|
|
63527
|
+
unlinkSync5(path);
|
|
63528
|
+
} else {
|
|
63529
|
+
writeFileSync17(path, `${next}${lineEnding}`, "utf-8");
|
|
63530
|
+
}
|
|
63531
|
+
return { agent, path, action: "removed" };
|
|
63532
|
+
}
|
|
63533
|
+
var DOSU_RULE_SECTION_VERSION = 1, DOSU_RULE_SECTION_START, DOSU_RULE_SECTION_END = "<!-- dosu:rules:end -->", DOSU_RULE_SECTION_START_RE, CURSOR_FRONTMATTER = `---
|
|
63534
|
+
alwaysApply: true
|
|
63535
|
+
---
|
|
63536
|
+
|
|
63537
|
+
`, DOSU_RULE_URLS, FALLBACK_DOSU_RULE = `The team you are assisting maintains shared knowledge in Dosu: consult it to build on prior work, and contribute durable knowledge so future teammates and agents do not have to rediscover it. Always use only tools currently listed by the server.
|
|
63538
|
+
|
|
63539
|
+
When \`read_knowledge\` is listed, call it before non-trivial code or documentation work involving architecture, conventions, prior decisions, gotchas, incidents, ownership, or branch history. **If unsure whether relevant context exists, read first.** Pass \`repo\` and \`branch\` when available. Skip generic questions, trivial or self-contained edits, and context already injected by Dosu.
|
|
63540
|
+
|
|
63541
|
+
When \`write_knowledge\` is listed, use it after the task for durable, non-obvious knowledge that future work would otherwise have to rediscover. Do not save task or PR summaries, progress, test results, obvious facts, speculation, duplicates, or sensitive data. **If nothing durable was learned, do not write.**
|
|
63542
|
+
|
|
63543
|
+
Use \`review_knowledge\` only when the user asks to inspect or manage pending knowledge. Preview one item at a time and require explicit confirmation before making changes.
|
|
63544
|
+
|
|
63545
|
+
When \`read_knowledge\` or \`write_knowledge\` returned a \`receipt_item_id\` this turn, call \`finalize_session_knowledge\` exactly once at the end of the turn — after completing the task, immediately before your final reply — passing all receipt_item_ids from this turn. Never call it when the current turn produced no receipt_item_id, and never call it more than once per turn.
|
|
63546
|
+
`, RULE_TARGETS;
|
|
63547
|
+
var init_installer = __esm(() => {
|
|
63548
|
+
DOSU_RULE_SECTION_START = `<!-- dosu:rules:start v${DOSU_RULE_SECTION_VERSION} -->`;
|
|
63549
|
+
DOSU_RULE_SECTION_START_RE = /<!-- dosu:rules:start(?: v\d+)? -->/;
|
|
63550
|
+
DOSU_RULE_URLS = [
|
|
63551
|
+
"https://raw.githubusercontent.com/dosu-ai/dosu-cli/main/rules/dosu.md",
|
|
63552
|
+
"https://raw.githubusercontent.com/dosu-ai/dosu-cli/master/rules/dosu.md"
|
|
63553
|
+
];
|
|
63554
|
+
RULE_TARGETS = {
|
|
63555
|
+
claude: {
|
|
63556
|
+
kind: "file",
|
|
63557
|
+
path: () => join41(claudeConfigDir4(), "rules", "dosu.md")
|
|
63558
|
+
},
|
|
63559
|
+
cursor: {
|
|
63560
|
+
kind: "file",
|
|
63561
|
+
path: () => join41(homedir12(), ".cursor", "rules", "dosu.mdc"),
|
|
63562
|
+
cursorFrontmatter: true
|
|
63563
|
+
},
|
|
63564
|
+
codex: {
|
|
63565
|
+
kind: "section",
|
|
63566
|
+
path: () => join41(codexHome4(), "AGENTS.md")
|
|
63567
|
+
},
|
|
63568
|
+
opencode: {
|
|
63569
|
+
kind: "section",
|
|
63570
|
+
path: () => join41(homedir12(), ".config", "opencode", "AGENTS.md")
|
|
63571
|
+
},
|
|
63572
|
+
gemini: {
|
|
63573
|
+
kind: "section",
|
|
63574
|
+
path: () => join41(homedir12(), ".gemini", "GEMINI.md")
|
|
63575
|
+
},
|
|
63576
|
+
antigravity: {
|
|
63577
|
+
kind: "section",
|
|
63578
|
+
path: () => join41(homedir12(), ".gemini", "GEMINI.md")
|
|
63579
|
+
}
|
|
63580
|
+
};
|
|
63581
|
+
});
|
|
63582
|
+
|
|
63583
|
+
// src/setup/agents-md-step.ts
|
|
63584
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
63585
|
+
import { existsSync as existsSync28, readFileSync as readFileSync27, writeFileSync as writeFileSync18 } from "node:fs";
|
|
63586
|
+
import { join as join42 } from "node:path";
|
|
63587
|
+
function inGitWorkTree(cwd = process.cwd()) {
|
|
63588
|
+
try {
|
|
63589
|
+
const stdout = execSync2("git rev-parse --is-inside-work-tree", {
|
|
63590
|
+
cwd,
|
|
63591
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
63592
|
+
});
|
|
63593
|
+
return stdout.toString().trim() === "true";
|
|
63594
|
+
} catch {
|
|
63595
|
+
return false;
|
|
63596
|
+
}
|
|
63597
|
+
}
|
|
63598
|
+
function dosuAgentsSectionState(cwd = process.cwd()) {
|
|
63599
|
+
try {
|
|
63600
|
+
const path = join42(cwd, "AGENTS.md");
|
|
63601
|
+
if (!existsSync28(path))
|
|
63602
|
+
return "missing";
|
|
63603
|
+
const content = readFileSync27(path, "utf-8");
|
|
63604
|
+
const startMatch = content.match(SECTION_START_RE);
|
|
63605
|
+
if (!startMatch || !content.includes(DOSU_SECTION_END))
|
|
63606
|
+
return "missing";
|
|
63607
|
+
return Number(startMatch[1] ?? 0) >= DOSU_SECTION_VERSION ? "current" : "outdated";
|
|
63608
|
+
} catch {
|
|
63609
|
+
return "missing";
|
|
63610
|
+
}
|
|
63611
|
+
}
|
|
63612
|
+
function lineEndingFor2(content) {
|
|
63613
|
+
return content.includes(`\r
|
|
63614
|
+
`) ? `\r
|
|
63615
|
+
` : `
|
|
63616
|
+
`;
|
|
63617
|
+
}
|
|
63618
|
+
function renderDosuAgentsSection(content, lineEnding) {
|
|
63619
|
+
const body = content.trim().replace(/\r?\n/g, lineEnding);
|
|
63620
|
+
return `${DOSU_SECTION_START}${lineEnding}${body}${lineEnding}${DOSU_SECTION_END}`;
|
|
63621
|
+
}
|
|
63622
|
+
function buildDosuAgentsSection(content = FALLBACK_DOSU_RULE) {
|
|
63623
|
+
return renderDosuAgentsSection(content, `
|
|
63624
|
+
`);
|
|
63625
|
+
}
|
|
63626
|
+
function findSection2(content) {
|
|
63627
|
+
const startMatch = content.match(SECTION_START_RE);
|
|
63628
|
+
const start = startMatch?.index ?? -1;
|
|
63629
|
+
const end = content.indexOf(DOSU_SECTION_END, Math.max(start, 0));
|
|
63630
|
+
if (start === -1 && end === -1)
|
|
63631
|
+
return null;
|
|
63632
|
+
if (start === -1 || end < start) {
|
|
63633
|
+
throw new Error("Dosu AGENTS.md markers are incomplete; refusing to overwrite the file");
|
|
63634
|
+
}
|
|
63635
|
+
return { start, end };
|
|
63636
|
+
}
|
|
63637
|
+
function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RULE) {
|
|
63638
|
+
const path = join42(cwd, "AGENTS.md");
|
|
63639
|
+
if (!existsSync28(path)) {
|
|
63640
|
+
const section = buildDosuAgentsSection(content);
|
|
63641
|
+
writeFileSync18(path, `${section}
|
|
63642
|
+
`);
|
|
63643
|
+
return { path, action: "created" };
|
|
63644
|
+
}
|
|
63645
|
+
const existing = readFileSync27(path, "utf-8");
|
|
63646
|
+
const lineEnding = lineEndingFor2(existing);
|
|
63647
|
+
const section = renderDosuAgentsSection(content, lineEnding);
|
|
63648
|
+
const location = findSection2(existing);
|
|
63649
|
+
let next;
|
|
63650
|
+
if (location) {
|
|
63651
|
+
next = existing.slice(0, location.start) + section + existing.slice(location.end + DOSU_SECTION_END.length);
|
|
63652
|
+
} else {
|
|
63653
|
+
next = `${existing.trimEnd()}${lineEnding}${lineEnding}${section}${lineEnding}`;
|
|
63654
|
+
}
|
|
63655
|
+
if (next === existing)
|
|
63656
|
+
return { path, action: "unchanged" };
|
|
63657
|
+
writeFileSync18(path, next);
|
|
63658
|
+
return { path, action: "updated" };
|
|
63659
|
+
}
|
|
63660
|
+
async function stepUpdateAgentsMd(cwd = process.cwd(), content) {
|
|
63661
|
+
logger.info("setup", "Step: update AGENTS.md");
|
|
63662
|
+
try {
|
|
63663
|
+
const result = upsertDosuAgentsSection(cwd, content ?? await fetchDosuRule());
|
|
63664
|
+
logger.info("setup", `AGENTS.md ${result.action} at ${result.path}`);
|
|
63665
|
+
const status = result.action === "unchanged" ? "already up to date" : result.action;
|
|
63666
|
+
log2.success(formatSetupSummary("AGENTS.md", [{ path: result.path, status }]));
|
|
63667
|
+
return true;
|
|
63668
|
+
} catch (err) {
|
|
63669
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
63670
|
+
logger.error("setup", `AGENTS.md update failed: ${msg}`);
|
|
63671
|
+
log2.error(`Could not update AGENTS.md: ${msg}`);
|
|
63672
|
+
return false;
|
|
63673
|
+
}
|
|
63674
|
+
}
|
|
63675
|
+
var DOSU_SECTION_VERSION = 2, DOSU_SECTION_START, DOSU_SECTION_END = "<!-- dosu:mcp:end -->", SECTION_START_RE;
|
|
63676
|
+
var init_agents_md_step = __esm(() => {
|
|
63677
|
+
init_logger();
|
|
63678
|
+
init_installer();
|
|
63679
|
+
init_prompts();
|
|
63680
|
+
init_styles();
|
|
63681
|
+
DOSU_SECTION_START = `<!-- dosu:mcp:start v${DOSU_SECTION_VERSION} -->`;
|
|
63682
|
+
SECTION_START_RE = /<!-- dosu:mcp:start(?: v(\d+))? -->/;
|
|
63683
|
+
});
|
|
63684
|
+
|
|
63919
63685
|
// src/setup/analytics.ts
|
|
63920
63686
|
async function trackCliOnboardingEvent(cfg, onboardingRunID, event, properties = {}) {
|
|
63921
63687
|
try {
|
|
@@ -65383,7 +65149,7 @@ async function stepSelectTools(detected) {
|
|
|
65383
65149
|
initialValues: preselected,
|
|
65384
65150
|
statusFor: (id, picked) => {
|
|
65385
65151
|
if (configuredMap.get(id))
|
|
65386
|
-
return picked ? dim("configured") :
|
|
65152
|
+
return picked ? dim("configured") : import_picocolors34.default.yellow("will remove");
|
|
65387
65153
|
return picked ? brand("will configure") : undefined;
|
|
65388
65154
|
},
|
|
65389
65155
|
summary: (picked) => {
|
|
@@ -65558,7 +65324,7 @@ ${dim(wrapLog("Run it inside a session to keep that session out of studying. Rem
|
|
|
65558
65324
|
log2.success("All agents already configured. No changes needed.");
|
|
65559
65325
|
}
|
|
65560
65326
|
}
|
|
65561
|
-
var
|
|
65327
|
+
var import_picocolors34, OAUTH_ANALYTICS_REASONS, SETUP_HANDSHAKE_TIMEOUT_MS = 1800000, LIBRARY_SELECT_CANCELLED;
|
|
65562
65328
|
var init_flow2 = __esm(() => {
|
|
65563
65329
|
init_dist();
|
|
65564
65330
|
init_errors3();
|
|
@@ -65583,7 +65349,7 @@ var init_flow2 = __esm(() => {
|
|
|
65583
65349
|
init_github_step();
|
|
65584
65350
|
init_rules_step();
|
|
65585
65351
|
init_styles();
|
|
65586
|
-
|
|
65352
|
+
import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
65587
65353
|
OAUTH_ANALYTICS_REASONS = new Set([
|
|
65588
65354
|
"access_denied",
|
|
65589
65355
|
"bad_oauth_state",
|
|
@@ -65597,6 +65363,269 @@ var init_flow2 = __esm(() => {
|
|
|
65597
65363
|
LIBRARY_SELECT_CANCELLED = Symbol("library-select-cancelled");
|
|
65598
65364
|
});
|
|
65599
65365
|
|
|
65366
|
+
// src/commands/upgrade.ts
|
|
65367
|
+
import { spawnSync } from "node:child_process";
|
|
65368
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
65369
|
+
import { homedir as homedir13 } from "node:os";
|
|
65370
|
+
import { posix, win32 as win322 } from "node:path";
|
|
65371
|
+
function isAbsoluteCommandProcessor(value) {
|
|
65372
|
+
return Boolean(value && win322.isAbsolute(value) && win322.basename(value).toLowerCase() === "cmd.exe");
|
|
65373
|
+
}
|
|
65374
|
+
function windowsCommandProcessor(env = process.env) {
|
|
65375
|
+
if (isAbsoluteCommandProcessor(env.ComSpec))
|
|
65376
|
+
return env.ComSpec;
|
|
65377
|
+
const systemRoot = env.SystemRoot && win322.isAbsolute(env.SystemRoot) ? env.SystemRoot : "C:\\Windows";
|
|
65378
|
+
return win322.join(systemRoot, "System32", "cmd.exe");
|
|
65379
|
+
}
|
|
65380
|
+
function safePackageManagerEnv(env) {
|
|
65381
|
+
return {
|
|
65382
|
+
...env,
|
|
65383
|
+
COREPACK_ENABLE_NETWORK: "0",
|
|
65384
|
+
COREPACK_ENABLE_PROJECT_SPEC: "0",
|
|
65385
|
+
YARN_IGNORE_PATH: "1"
|
|
65386
|
+
};
|
|
65387
|
+
}
|
|
65388
|
+
function buildPackageManagerInvocation(manager, action, platform = process.platform, comSpec, env = process.env) {
|
|
65389
|
+
const args = action === "locate" ? PACKAGE_MANAGERS[manager].locateArgs : PACKAGE_MANAGERS[manager].installArgs;
|
|
65390
|
+
const safeEnv = safePackageManagerEnv(env);
|
|
65391
|
+
if (platform === "win32") {
|
|
65392
|
+
return {
|
|
65393
|
+
command: isAbsoluteCommandProcessor(comSpec) ? comSpec : windowsCommandProcessor(env),
|
|
65394
|
+
args: ["/d", "/s", "/c", [manager, ...args].join(" ")],
|
|
65395
|
+
env: { ...safeEnv, NoDefaultCurrentDirectoryInExePath: "1" }
|
|
65396
|
+
};
|
|
65397
|
+
}
|
|
65398
|
+
return { command: manager, args: [...args], env: safeEnv };
|
|
65399
|
+
}
|
|
65400
|
+
function packageRoots(manager, platform, comSpec, env, cwd) {
|
|
65401
|
+
const invocation = buildPackageManagerInvocation(manager, "locate", platform, comSpec, env);
|
|
65402
|
+
const result = spawnSync(invocation.command, invocation.args, {
|
|
65403
|
+
cwd,
|
|
65404
|
+
encoding: "utf8",
|
|
65405
|
+
env: invocation.env,
|
|
65406
|
+
shell: false,
|
|
65407
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
65408
|
+
timeout: PROBE_TIMEOUT_MS
|
|
65409
|
+
});
|
|
65410
|
+
if (result.status !== 0 || typeof result.stdout !== "string")
|
|
65411
|
+
return [];
|
|
65412
|
+
const path = platform === "win32" ? win322 : posix;
|
|
65413
|
+
const lines = result.stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => path.isAbsolute(line));
|
|
65414
|
+
if (manager === "pnpm") {
|
|
65415
|
+
return lines.filter((line) => path.basename(line) === "cli" && path.basename(path.dirname(line)) === "@dosu" && path.basename(path.dirname(path.dirname(line))) === "node_modules");
|
|
65416
|
+
}
|
|
65417
|
+
if (lines.length !== 1)
|
|
65418
|
+
return [];
|
|
65419
|
+
return [
|
|
65420
|
+
manager === "npm" ? path.join(lines[0], "@dosu", "cli") : path.join(lines[0], "node_modules", "@dosu", "cli")
|
|
65421
|
+
];
|
|
65422
|
+
}
|
|
65423
|
+
function owningPackageManager(entrypoint, platform, comSpec, env = process.env, cwd = homedir13()) {
|
|
65424
|
+
const path = platform === "win32" ? win322 : posix;
|
|
65425
|
+
if (!entrypoint || !path.isAbsolute(entrypoint))
|
|
65426
|
+
return null;
|
|
65427
|
+
let realEntrypoint;
|
|
65428
|
+
try {
|
|
65429
|
+
realEntrypoint = realpathSync2(entrypoint);
|
|
65430
|
+
} catch {
|
|
65431
|
+
return null;
|
|
65432
|
+
}
|
|
65433
|
+
const owners = Object.keys(PACKAGE_MANAGERS).filter((manager) => packageRoots(manager, platform, comSpec, env, cwd).some((root) => {
|
|
65434
|
+
try {
|
|
65435
|
+
const relative = path.relative(realpathSync2(root), realEntrypoint);
|
|
65436
|
+
return relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
|
|
65437
|
+
} catch {
|
|
65438
|
+
return false;
|
|
65439
|
+
}
|
|
65440
|
+
}));
|
|
65441
|
+
return owners.length === 1 ? owners[0] : null;
|
|
65442
|
+
}
|
|
65443
|
+
function upgradePlan(channel, manager, platform, comSpec, env = process.env) {
|
|
65444
|
+
if (channel === "homebrew") {
|
|
65445
|
+
return {
|
|
65446
|
+
label: "Homebrew",
|
|
65447
|
+
command: "brew",
|
|
65448
|
+
args: ["upgrade", "dosu-ai/dosu/dosu"],
|
|
65449
|
+
manualCommand: BREW_MANUAL_COMMAND
|
|
65450
|
+
};
|
|
65451
|
+
}
|
|
65452
|
+
if (channel === "npm" && manager) {
|
|
65453
|
+
const invocation = buildPackageManagerInvocation(manager, "install", platform, comSpec, env);
|
|
65454
|
+
return {
|
|
65455
|
+
label: PACKAGE_MANAGERS[manager].label,
|
|
65456
|
+
...invocation,
|
|
65457
|
+
manualCommand: [manager, ...PACKAGE_MANAGERS[manager].installArgs].join(" ")
|
|
65458
|
+
};
|
|
65459
|
+
}
|
|
65460
|
+
return null;
|
|
65461
|
+
}
|
|
65462
|
+
function printNonGlobalPackageGuidance() {
|
|
65463
|
+
console.log("This Dosu copy is not a uniquely identified global package installation, so it was not changed.");
|
|
65464
|
+
console.log(`
|
|
65465
|
+
Run the latest version without installing:
|
|
65466
|
+
${NPX_COMMAND}`);
|
|
65467
|
+
console.log(`
|
|
65468
|
+
Or install Dosu globally with your package manager:`);
|
|
65469
|
+
for (const manager of Object.keys(PACKAGE_MANAGERS)) {
|
|
65470
|
+
console.log(` ${manager} ${PACKAGE_MANAGERS[manager].installArgs.join(" ")}`);
|
|
65471
|
+
}
|
|
65472
|
+
}
|
|
65473
|
+
function runUpgrade(channel = INSTALL_CHANNEL, options = {}) {
|
|
65474
|
+
const platform = options.platform ?? process.platform;
|
|
65475
|
+
const env = options.env ?? process.env;
|
|
65476
|
+
const cwd = options.cwd ?? homedir13();
|
|
65477
|
+
let manager = null;
|
|
65478
|
+
if (channel === "npm") {
|
|
65479
|
+
if (isNpxInvocation(channel, env)) {
|
|
65480
|
+
printNonGlobalPackageGuidance();
|
|
65481
|
+
return 1;
|
|
65482
|
+
}
|
|
65483
|
+
manager = owningPackageManager(options.entrypoint ?? process.argv[1], platform, options.comSpec, env, cwd);
|
|
65484
|
+
if (!manager) {
|
|
65485
|
+
if (env.DOSU_DEV === "true") {
|
|
65486
|
+
console.log("DOSU_DEV=true and this copy is not a global package: skipping the package install.");
|
|
65487
|
+
return 0;
|
|
65488
|
+
}
|
|
65489
|
+
printNonGlobalPackageGuidance();
|
|
65490
|
+
return 1;
|
|
65491
|
+
}
|
|
65492
|
+
}
|
|
65493
|
+
const plan = upgradePlan(channel, manager, platform, options.comSpec, env);
|
|
65494
|
+
if (!plan) {
|
|
65495
|
+
console.log("Automatic upgrades are not available for this installation yet.");
|
|
65496
|
+
console.log(`Download the latest release:
|
|
65497
|
+
${RELEASES_URL}`);
|
|
65498
|
+
return 1;
|
|
65499
|
+
}
|
|
65500
|
+
console.log(`Updating Dosu with ${plan.label}...`);
|
|
65501
|
+
console.log(` ${plan.manualCommand}
|
|
65502
|
+
`);
|
|
65503
|
+
const result = spawnSync(plan.command, plan.args, {
|
|
65504
|
+
...channel === "npm" ? { cwd } : {},
|
|
65505
|
+
...plan.env ? { env: plan.env } : {},
|
|
65506
|
+
shell: false,
|
|
65507
|
+
stdio: "inherit"
|
|
65508
|
+
});
|
|
65509
|
+
if (result.error || result.status !== 0) {
|
|
65510
|
+
console.error(`
|
|
65511
|
+
Could not update Dosu automatically.`);
|
|
65512
|
+
console.error(`Run manually:
|
|
65513
|
+
${plan.manualCommand}`);
|
|
65514
|
+
return result.status && result.status > 0 ? result.status : 1;
|
|
65515
|
+
}
|
|
65516
|
+
console.log(import_picocolors35.default.green(`
|
|
65517
|
+
✓ Update command completed.`));
|
|
65518
|
+
console.log('Run "dosu --version" to verify.');
|
|
65519
|
+
return 0;
|
|
65520
|
+
}
|
|
65521
|
+
function postUpgradeArgs(fromVersion = VERSION) {
|
|
65522
|
+
return ["upgrade", "--finish", fromVersion];
|
|
65523
|
+
}
|
|
65524
|
+
function newBinaryInvocation(channel, args, entrypoint = process.argv[1], execPath = process.execPath) {
|
|
65525
|
+
if (channel === "npm") {
|
|
65526
|
+
return entrypoint ? { command: execPath, args: [entrypoint, ...args] } : null;
|
|
65527
|
+
}
|
|
65528
|
+
if (channel === "homebrew") {
|
|
65529
|
+
return { command: "dosu", args };
|
|
65530
|
+
}
|
|
65531
|
+
return null;
|
|
65532
|
+
}
|
|
65533
|
+
function isInteractiveTerminal() {
|
|
65534
|
+
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
65535
|
+
}
|
|
65536
|
+
function finishWithNewBinary(channel, options) {
|
|
65537
|
+
const invocation = newBinaryInvocation(channel, postUpgradeArgs(), options.entrypoint ?? process.argv[1]);
|
|
65538
|
+
if (!invocation) {
|
|
65539
|
+
console.error(SETUP_FALLBACK);
|
|
65540
|
+
return;
|
|
65541
|
+
}
|
|
65542
|
+
const result = spawnSync(invocation.command, invocation.args, {
|
|
65543
|
+
cwd: options.cwd ?? homedir13(),
|
|
65544
|
+
shell: false,
|
|
65545
|
+
stdio: "inherit"
|
|
65546
|
+
});
|
|
65547
|
+
if (result.error || result.status !== 0) {
|
|
65548
|
+
console.error(SETUP_FALLBACK);
|
|
65549
|
+
}
|
|
65550
|
+
}
|
|
65551
|
+
async function completeUpgrade(channel = INSTALL_CHANNEL, options = {}) {
|
|
65552
|
+
const status = runUpgrade(channel, options);
|
|
65553
|
+
if (status !== 0)
|
|
65554
|
+
return status;
|
|
65555
|
+
finishWithNewBinary(channel, options);
|
|
65556
|
+
return 0;
|
|
65557
|
+
}
|
|
65558
|
+
async function finishUpgrade(from, options = {}) {
|
|
65559
|
+
const previous = SEMVER.test(from) ? from : null;
|
|
65560
|
+
if (!needsMcpRefresh(previous, VERSION)) {
|
|
65561
|
+
checkForSkillUpdates();
|
|
65562
|
+
writeMcpRefreshCache({ version: VERSION });
|
|
65563
|
+
console.log(import_picocolors35.default.green(`✓ Dosu ${VERSION} is ready. Your AI agents need no changes.`));
|
|
65564
|
+
return 0;
|
|
65565
|
+
}
|
|
65566
|
+
if (options.interactive ?? isInteractiveTerminal()) {
|
|
65567
|
+
console.log(`
|
|
65568
|
+
This update changes how agents connect to Dosu. Running setup...
|
|
65569
|
+
`);
|
|
65570
|
+
await Promise.resolve().then(() => init_flow2());
|
|
65571
|
+
await runSetup();
|
|
65572
|
+
return 0;
|
|
65573
|
+
}
|
|
65574
|
+
checkForSkillUpdates();
|
|
65575
|
+
const cfg = loadConfigNonBlocking();
|
|
65576
|
+
if (!cfg || !canRefreshMcp(cfg)) {
|
|
65577
|
+
console.error(SETUP_FALLBACK);
|
|
65578
|
+
return 0;
|
|
65579
|
+
}
|
|
65580
|
+
console.log(`
|
|
65581
|
+
Refreshing agent MCP configs with the new version...`);
|
|
65582
|
+
const result = refreshConfiguredProviders(cfg);
|
|
65583
|
+
writeMcpRefreshCache({ version: VERSION });
|
|
65584
|
+
for (const provider of result.updated)
|
|
65585
|
+
console.log(` ✓ ${provider.name()}`);
|
|
65586
|
+
for (const { provider, error } of result.failed) {
|
|
65587
|
+
console.log(` ✗ ${provider.name()}: ${error.message}`);
|
|
65588
|
+
}
|
|
65589
|
+
if (result.failed.length > 0)
|
|
65590
|
+
console.error(SETUP_FALLBACK);
|
|
65591
|
+
return 0;
|
|
65592
|
+
}
|
|
65593
|
+
function upgradeCommand() {
|
|
65594
|
+
return new Command("upgrade").description("Update Dosu to the latest version, re-running setup when the update changes agent config").addOption(new Option("--finish <from>").hideHelp()).action(async (opts) => {
|
|
65595
|
+
const status = opts.finish !== undefined ? await finishUpgrade(opts.finish) : await completeUpgrade();
|
|
65596
|
+
if (status !== 0)
|
|
65597
|
+
process.exitCode = status;
|
|
65598
|
+
});
|
|
65599
|
+
}
|
|
65600
|
+
var import_picocolors35, 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.', SEMVER;
|
|
65601
|
+
var init_upgrade = __esm(() => {
|
|
65602
|
+
init_commander();
|
|
65603
|
+
init_config();
|
|
65604
|
+
init_refresh();
|
|
65605
|
+
init_mcp_refresh_check();
|
|
65606
|
+
init_skill_update_check();
|
|
65607
|
+
import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
65608
|
+
LATEST_PACKAGE = `${PACKAGE_NAME}@latest`;
|
|
65609
|
+
PACKAGE_MANAGERS = {
|
|
65610
|
+
npm: {
|
|
65611
|
+
label: "npm",
|
|
65612
|
+
locateArgs: ["root", "-g"],
|
|
65613
|
+
installArgs: ["install", "-g", LATEST_PACKAGE]
|
|
65614
|
+
},
|
|
65615
|
+
pnpm: {
|
|
65616
|
+
label: "pnpm",
|
|
65617
|
+
locateArgs: ["list", "-g", "--depth=0", "--parseable", PACKAGE_NAME],
|
|
65618
|
+
installArgs: ["add", "-g", LATEST_PACKAGE]
|
|
65619
|
+
},
|
|
65620
|
+
yarn: {
|
|
65621
|
+
label: "Yarn Classic",
|
|
65622
|
+
locateArgs: ["--silent", "global", "dir"],
|
|
65623
|
+
installArgs: ["global", "add", LATEST_PACKAGE]
|
|
65624
|
+
}
|
|
65625
|
+
};
|
|
65626
|
+
SEMVER = /^\d+\.\d+\.\d+/;
|
|
65627
|
+
});
|
|
65628
|
+
|
|
65600
65629
|
// src/tui/analytics-view.ts
|
|
65601
65630
|
function analyticsListHeight(rows) {
|
|
65602
65631
|
const room = frameMaxLines(rows) - ANALYTICS_VIEW_CHROME_LINES;
|
|
@@ -67843,4 +67872,4 @@ main().catch((err) => {
|
|
|
67843
67872
|
process.exit(1);
|
|
67844
67873
|
});
|
|
67845
67874
|
|
|
67846
|
-
//# debugId=
|
|
67875
|
+
//# debugId=49fa5d82-a4a1-8b36-6475-6e2164756e21
|