@dosu/cli 0.60.1 → 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 +639 -618
- 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";
|
|
@@ -61641,283 +61641,6 @@ var init_topics = __esm(() => {
|
|
|
61641
61641
|
import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
61642
61642
|
});
|
|
61643
61643
|
|
|
61644
|
-
// src/commands/upgrade.ts
|
|
61645
|
-
import { spawnSync } from "node:child_process";
|
|
61646
|
-
import { realpathSync as realpathSync2 } from "node:fs";
|
|
61647
|
-
import { homedir as homedir9 } from "node:os";
|
|
61648
|
-
import { posix, win32 as win322 } from "node:path";
|
|
61649
|
-
function isAbsoluteCommandProcessor(value) {
|
|
61650
|
-
return Boolean(value && win322.isAbsolute(value) && win322.basename(value).toLowerCase() === "cmd.exe");
|
|
61651
|
-
}
|
|
61652
|
-
function windowsCommandProcessor(env = process.env) {
|
|
61653
|
-
if (isAbsoluteCommandProcessor(env.ComSpec))
|
|
61654
|
-
return env.ComSpec;
|
|
61655
|
-
const systemRoot = env.SystemRoot && win322.isAbsolute(env.SystemRoot) ? env.SystemRoot : "C:\\Windows";
|
|
61656
|
-
return win322.join(systemRoot, "System32", "cmd.exe");
|
|
61657
|
-
}
|
|
61658
|
-
function safePackageManagerEnv(env) {
|
|
61659
|
-
return {
|
|
61660
|
-
...env,
|
|
61661
|
-
COREPACK_ENABLE_NETWORK: "0",
|
|
61662
|
-
COREPACK_ENABLE_PROJECT_SPEC: "0",
|
|
61663
|
-
YARN_IGNORE_PATH: "1"
|
|
61664
|
-
};
|
|
61665
|
-
}
|
|
61666
|
-
function buildPackageManagerInvocation(manager, action, platform = process.platform, comSpec, env = process.env) {
|
|
61667
|
-
const args = action === "locate" ? PACKAGE_MANAGERS[manager].locateArgs : PACKAGE_MANAGERS[manager].installArgs;
|
|
61668
|
-
const safeEnv = safePackageManagerEnv(env);
|
|
61669
|
-
if (platform === "win32") {
|
|
61670
|
-
return {
|
|
61671
|
-
command: isAbsoluteCommandProcessor(comSpec) ? comSpec : windowsCommandProcessor(env),
|
|
61672
|
-
args: ["/d", "/s", "/c", [manager, ...args].join(" ")],
|
|
61673
|
-
env: { ...safeEnv, NoDefaultCurrentDirectoryInExePath: "1" }
|
|
61674
|
-
};
|
|
61675
|
-
}
|
|
61676
|
-
return { command: manager, args: [...args], env: safeEnv };
|
|
61677
|
-
}
|
|
61678
|
-
function packageRoots(manager, platform, comSpec, env, cwd) {
|
|
61679
|
-
const invocation = buildPackageManagerInvocation(manager, "locate", platform, comSpec, env);
|
|
61680
|
-
const result = spawnSync(invocation.command, invocation.args, {
|
|
61681
|
-
cwd,
|
|
61682
|
-
encoding: "utf8",
|
|
61683
|
-
env: invocation.env,
|
|
61684
|
-
shell: false,
|
|
61685
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
61686
|
-
timeout: PROBE_TIMEOUT_MS
|
|
61687
|
-
});
|
|
61688
|
-
if (result.status !== 0 || typeof result.stdout !== "string")
|
|
61689
|
-
return [];
|
|
61690
|
-
const path = platform === "win32" ? win322 : posix;
|
|
61691
|
-
const lines = result.stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => path.isAbsolute(line));
|
|
61692
|
-
if (manager === "pnpm") {
|
|
61693
|
-
return lines.filter((line) => path.basename(line) === "cli" && path.basename(path.dirname(line)) === "@dosu" && path.basename(path.dirname(path.dirname(line))) === "node_modules");
|
|
61694
|
-
}
|
|
61695
|
-
if (lines.length !== 1)
|
|
61696
|
-
return [];
|
|
61697
|
-
return [
|
|
61698
|
-
manager === "npm" ? path.join(lines[0], "@dosu", "cli") : path.join(lines[0], "node_modules", "@dosu", "cli")
|
|
61699
|
-
];
|
|
61700
|
-
}
|
|
61701
|
-
function owningPackageManager(entrypoint, platform, comSpec, env = process.env, cwd = homedir9()) {
|
|
61702
|
-
const path = platform === "win32" ? win322 : posix;
|
|
61703
|
-
if (!entrypoint || !path.isAbsolute(entrypoint))
|
|
61704
|
-
return null;
|
|
61705
|
-
let realEntrypoint;
|
|
61706
|
-
try {
|
|
61707
|
-
realEntrypoint = realpathSync2(entrypoint);
|
|
61708
|
-
} catch {
|
|
61709
|
-
return null;
|
|
61710
|
-
}
|
|
61711
|
-
const owners = Object.keys(PACKAGE_MANAGERS).filter((manager) => packageRoots(manager, platform, comSpec, env, cwd).some((root) => {
|
|
61712
|
-
try {
|
|
61713
|
-
const relative = path.relative(realpathSync2(root), realEntrypoint);
|
|
61714
|
-
return relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
|
|
61715
|
-
} catch {
|
|
61716
|
-
return false;
|
|
61717
|
-
}
|
|
61718
|
-
}));
|
|
61719
|
-
return owners.length === 1 ? owners[0] : null;
|
|
61720
|
-
}
|
|
61721
|
-
function upgradePlan(channel, manager, platform, comSpec, env = process.env) {
|
|
61722
|
-
if (channel === "homebrew") {
|
|
61723
|
-
return {
|
|
61724
|
-
label: "Homebrew",
|
|
61725
|
-
command: "brew",
|
|
61726
|
-
args: ["upgrade", "dosu-ai/dosu/dosu"],
|
|
61727
|
-
manualCommand: BREW_MANUAL_COMMAND
|
|
61728
|
-
};
|
|
61729
|
-
}
|
|
61730
|
-
if (channel === "npm" && manager) {
|
|
61731
|
-
const invocation = buildPackageManagerInvocation(manager, "install", platform, comSpec, env);
|
|
61732
|
-
return {
|
|
61733
|
-
label: PACKAGE_MANAGERS[manager].label,
|
|
61734
|
-
...invocation,
|
|
61735
|
-
manualCommand: [manager, ...PACKAGE_MANAGERS[manager].installArgs].join(" ")
|
|
61736
|
-
};
|
|
61737
|
-
}
|
|
61738
|
-
return null;
|
|
61739
|
-
}
|
|
61740
|
-
function printNonGlobalPackageGuidance() {
|
|
61741
|
-
console.log("This Dosu copy is not a uniquely identified global package installation, so it was not changed.");
|
|
61742
|
-
console.log(`
|
|
61743
|
-
Run the latest version without installing:
|
|
61744
|
-
${NPX_COMMAND}`);
|
|
61745
|
-
console.log(`
|
|
61746
|
-
Or install Dosu globally with your package manager:`);
|
|
61747
|
-
for (const manager of Object.keys(PACKAGE_MANAGERS)) {
|
|
61748
|
-
console.log(` ${manager} ${PACKAGE_MANAGERS[manager].installArgs.join(" ")}`);
|
|
61749
|
-
}
|
|
61750
|
-
}
|
|
61751
|
-
function runUpgrade(channel = INSTALL_CHANNEL, options = {}) {
|
|
61752
|
-
const platform = options.platform ?? process.platform;
|
|
61753
|
-
const env = options.env ?? process.env;
|
|
61754
|
-
const cwd = options.cwd ?? homedir9();
|
|
61755
|
-
let manager = null;
|
|
61756
|
-
if (channel === "npm") {
|
|
61757
|
-
if (isNpxInvocation(channel, env)) {
|
|
61758
|
-
printNonGlobalPackageGuidance();
|
|
61759
|
-
return 1;
|
|
61760
|
-
}
|
|
61761
|
-
manager = owningPackageManager(options.entrypoint ?? process.argv[1], platform, options.comSpec, env, cwd);
|
|
61762
|
-
if (!manager) {
|
|
61763
|
-
if (env.DOSU_DEV === "true") {
|
|
61764
|
-
console.log("DOSU_DEV=true and this copy is not a global package: skipping the package install.");
|
|
61765
|
-
return 0;
|
|
61766
|
-
}
|
|
61767
|
-
printNonGlobalPackageGuidance();
|
|
61768
|
-
return 1;
|
|
61769
|
-
}
|
|
61770
|
-
}
|
|
61771
|
-
const plan = upgradePlan(channel, manager, platform, options.comSpec, env);
|
|
61772
|
-
if (!plan) {
|
|
61773
|
-
console.log("Automatic upgrades are not available for this installation yet.");
|
|
61774
|
-
console.log(`Download the latest release:
|
|
61775
|
-
${RELEASES_URL}`);
|
|
61776
|
-
return 1;
|
|
61777
|
-
}
|
|
61778
|
-
console.log(`Updating Dosu with ${plan.label}...`);
|
|
61779
|
-
console.log(` ${plan.manualCommand}
|
|
61780
|
-
`);
|
|
61781
|
-
const result = spawnSync(plan.command, plan.args, {
|
|
61782
|
-
...channel === "npm" ? { cwd } : {},
|
|
61783
|
-
...plan.env ? { env: plan.env } : {},
|
|
61784
|
-
shell: false,
|
|
61785
|
-
stdio: "inherit"
|
|
61786
|
-
});
|
|
61787
|
-
if (result.error || result.status !== 0) {
|
|
61788
|
-
console.error(`
|
|
61789
|
-
Could not update Dosu automatically.`);
|
|
61790
|
-
console.error(`Run manually:
|
|
61791
|
-
${plan.manualCommand}`);
|
|
61792
|
-
return result.status && result.status > 0 ? result.status : 1;
|
|
61793
|
-
}
|
|
61794
|
-
console.log(import_picocolors30.default.green(`
|
|
61795
|
-
✓ Update command completed.`));
|
|
61796
|
-
console.log('Run "dosu --version" to verify.');
|
|
61797
|
-
return 0;
|
|
61798
|
-
}
|
|
61799
|
-
function postUpgradeArgs(interactive) {
|
|
61800
|
-
return interactive ? ["setup"] : ["mcp", "refresh"];
|
|
61801
|
-
}
|
|
61802
|
-
function newBinaryInvocation(channel, args, entrypoint = process.argv[1], execPath = process.execPath) {
|
|
61803
|
-
if (channel === "npm") {
|
|
61804
|
-
return entrypoint ? { command: execPath, args: [entrypoint, ...args] } : null;
|
|
61805
|
-
}
|
|
61806
|
-
if (channel === "homebrew") {
|
|
61807
|
-
return { command: "dosu", args };
|
|
61808
|
-
}
|
|
61809
|
-
return null;
|
|
61810
|
-
}
|
|
61811
|
-
function isInteractiveTerminal() {
|
|
61812
|
-
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
61813
|
-
}
|
|
61814
|
-
function setupAgentsWithNewBinary(channel, interactive, options) {
|
|
61815
|
-
const invocation = newBinaryInvocation(channel, postUpgradeArgs(interactive), options.entrypoint ?? process.argv[1]);
|
|
61816
|
-
if (!invocation) {
|
|
61817
|
-
console.error(SETUP_FALLBACK);
|
|
61818
|
-
return;
|
|
61819
|
-
}
|
|
61820
|
-
console.log(interactive ? `
|
|
61821
|
-
Running setup with the new version to update your AI agents...
|
|
61822
|
-
` : `
|
|
61823
|
-
Refreshing agent MCP configs with the new version...`);
|
|
61824
|
-
const result = spawnSync(invocation.command, invocation.args, {
|
|
61825
|
-
cwd: options.cwd ?? homedir9(),
|
|
61826
|
-
shell: false,
|
|
61827
|
-
stdio: "inherit"
|
|
61828
|
-
});
|
|
61829
|
-
if (result.error || result.status !== 0) {
|
|
61830
|
-
console.error(SETUP_FALLBACK);
|
|
61831
|
-
}
|
|
61832
|
-
}
|
|
61833
|
-
async function completeUpgrade(channel = INSTALL_CHANNEL, options = {}) {
|
|
61834
|
-
const status = runUpgrade(channel, options);
|
|
61835
|
-
if (status !== 0)
|
|
61836
|
-
return status;
|
|
61837
|
-
const interactive = options.interactive ?? isInteractiveTerminal();
|
|
61838
|
-
if (!interactive) {
|
|
61839
|
-
console.log("Updating Dosu skills...");
|
|
61840
|
-
try {
|
|
61841
|
-
const result = await installSkill();
|
|
61842
|
-
if (result.success) {
|
|
61843
|
-
console.log(import_picocolors30.default.green("✓ Skills updated."));
|
|
61844
|
-
} else {
|
|
61845
|
-
console.error('Skills could not be refreshed. Run "dosu skill update" to retry.');
|
|
61846
|
-
}
|
|
61847
|
-
} catch {
|
|
61848
|
-
console.error('Skills could not be refreshed. Run "dosu skill update" to retry.');
|
|
61849
|
-
}
|
|
61850
|
-
}
|
|
61851
|
-
setupAgentsWithNewBinary(channel, interactive, options);
|
|
61852
|
-
return 0;
|
|
61853
|
-
}
|
|
61854
|
-
function upgradeCommand() {
|
|
61855
|
-
return new Command("upgrade").description("Update Dosu to the latest version, then re-run setup to update your AI agents").action(async () => {
|
|
61856
|
-
const status = await completeUpgrade();
|
|
61857
|
-
if (status !== 0)
|
|
61858
|
-
process.exitCode = status;
|
|
61859
|
-
});
|
|
61860
|
-
}
|
|
61861
|
-
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.';
|
|
61862
|
-
var init_upgrade = __esm(() => {
|
|
61863
|
-
init_commander();
|
|
61864
|
-
init_skill();
|
|
61865
|
-
import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
61866
|
-
LATEST_PACKAGE = `${PACKAGE_NAME}@latest`;
|
|
61867
|
-
PACKAGE_MANAGERS = {
|
|
61868
|
-
npm: {
|
|
61869
|
-
label: "npm",
|
|
61870
|
-
locateArgs: ["root", "-g"],
|
|
61871
|
-
installArgs: ["install", "-g", LATEST_PACKAGE]
|
|
61872
|
-
},
|
|
61873
|
-
pnpm: {
|
|
61874
|
-
label: "pnpm",
|
|
61875
|
-
locateArgs: ["list", "-g", "--depth=0", "--parseable", PACKAGE_NAME],
|
|
61876
|
-
installArgs: ["add", "-g", LATEST_PACKAGE]
|
|
61877
|
-
},
|
|
61878
|
-
yarn: {
|
|
61879
|
-
label: "Yarn Classic",
|
|
61880
|
-
locateArgs: ["--silent", "global", "dir"],
|
|
61881
|
-
installArgs: ["global", "add", LATEST_PACKAGE]
|
|
61882
|
-
}
|
|
61883
|
-
};
|
|
61884
|
-
});
|
|
61885
|
-
|
|
61886
|
-
// src/debug/follow.ts
|
|
61887
|
-
import { closeSync as closeSync6, openSync as openSync6, readSync as readSync5, statSync as statSync8 } from "node:fs";
|
|
61888
|
-
function createLogFollower(path, emit) {
|
|
61889
|
-
const sizeOf = () => {
|
|
61890
|
-
try {
|
|
61891
|
-
return statSync8(path).size;
|
|
61892
|
-
} catch {
|
|
61893
|
-
return 0;
|
|
61894
|
-
}
|
|
61895
|
-
};
|
|
61896
|
-
let offset = sizeOf();
|
|
61897
|
-
return {
|
|
61898
|
-
poll() {
|
|
61899
|
-
const size = sizeOf();
|
|
61900
|
-
if (size < offset)
|
|
61901
|
-
offset = 0;
|
|
61902
|
-
if (size === offset)
|
|
61903
|
-
return;
|
|
61904
|
-
try {
|
|
61905
|
-
const fd = openSync6(path, "r");
|
|
61906
|
-
try {
|
|
61907
|
-
const buf = Buffer.alloc(size - offset);
|
|
61908
|
-
const read = readSync5(fd, buf, 0, buf.length, offset);
|
|
61909
|
-
offset += read;
|
|
61910
|
-
if (read > 0)
|
|
61911
|
-
emit(buf.toString("utf-8", 0, read));
|
|
61912
|
-
} finally {
|
|
61913
|
-
closeSync6(fd);
|
|
61914
|
-
}
|
|
61915
|
-
} catch {}
|
|
61916
|
-
}
|
|
61917
|
-
};
|
|
61918
|
-
}
|
|
61919
|
-
var init_follow = () => {};
|
|
61920
|
-
|
|
61921
61644
|
// src/mcp/providers/base.ts
|
|
61922
61645
|
function createJSONProvider(opts) {
|
|
61923
61646
|
const buildServer = opts.buildServer ?? defaultBuildServer;
|
|
@@ -62449,15 +62172,15 @@ var init_vscode = __esm(() => {
|
|
|
62449
62172
|
});
|
|
62450
62173
|
|
|
62451
62174
|
// src/mcp/providers/windsurf.ts
|
|
62452
|
-
import { homedir as
|
|
62175
|
+
import { homedir as homedir9 } from "node:os";
|
|
62453
62176
|
import { join as join36 } from "node:path";
|
|
62454
62177
|
var WindsurfProvider = () => createJSONProvider({
|
|
62455
62178
|
providerName: "Windsurf",
|
|
62456
62179
|
providerID: "windsurf",
|
|
62457
62180
|
local: false,
|
|
62458
62181
|
priorityValue: 9,
|
|
62459
|
-
paths: [join36(
|
|
62460
|
-
globalPath: join36(
|
|
62182
|
+
paths: [join36(homedir9(), ".codeium", "windsurf")],
|
|
62183
|
+
globalPath: join36(homedir9(), ".codeium", "windsurf", "mcp_config.json"),
|
|
62461
62184
|
topKey: "mcpServers"
|
|
62462
62185
|
});
|
|
62463
62186
|
var init_windsurf = __esm(() => {
|
|
@@ -62466,14 +62189,14 @@ var init_windsurf = __esm(() => {
|
|
|
62466
62189
|
|
|
62467
62190
|
// src/mcp/providers/zed.ts
|
|
62468
62191
|
import { rmSync as rmSync6 } from "node:fs";
|
|
62469
|
-
import { homedir as
|
|
62192
|
+
import { homedir as homedir10, platform as platform3 } from "node:os";
|
|
62470
62193
|
import { join as join37 } from "node:path";
|
|
62471
62194
|
function zedConfigDir() {
|
|
62472
62195
|
const os = platform3();
|
|
62473
62196
|
if (os === "win32")
|
|
62474
62197
|
return join37(appSupportDir(), "Zed");
|
|
62475
62198
|
if (os === "darwin")
|
|
62476
|
-
return join37(
|
|
62199
|
+
return join37(homedir10(), ".config", "zed");
|
|
62477
62200
|
return join37(appSupportDir(), "zed");
|
|
62478
62201
|
}
|
|
62479
62202
|
function zedDataDir() {
|
|
@@ -62482,7 +62205,7 @@ function zedDataDir() {
|
|
|
62482
62205
|
return join37(appSupportDir(), "Zed");
|
|
62483
62206
|
if (os === "win32")
|
|
62484
62207
|
return join37(process.env.LOCALAPPDATA ?? "", "Zed");
|
|
62485
|
-
return join37(process.env.XDG_DATA_HOME ?? join37(
|
|
62208
|
+
return join37(process.env.XDG_DATA_HOME ?? join37(homedir10(), ".local", "share"), "zed");
|
|
62486
62209
|
}
|
|
62487
62210
|
function legacyDarwinSettingsPath() {
|
|
62488
62211
|
return platform3() === "darwin" ? join37(appSupportDir(), "Zed", "settings.json") : null;
|
|
@@ -62692,29 +62415,29 @@ function buildUpdateHint(channel, npx = false) {
|
|
|
62692
62415
|
function styleHint(hint) {
|
|
62693
62416
|
const match = hint.match(/^(.*)("[^"]+")(.*)$/);
|
|
62694
62417
|
if (!match)
|
|
62695
|
-
return
|
|
62418
|
+
return import_picocolors30.default.dim(hint);
|
|
62696
62419
|
const [, before, command, after] = match;
|
|
62697
|
-
return [before &&
|
|
62420
|
+
return [before && import_picocolors30.default.dim(before), import_picocolors30.default.cyan(command), after && import_picocolors30.default.dim(after)].filter(Boolean).join("");
|
|
62698
62421
|
}
|
|
62699
62422
|
function buildUpdateNotice(current, latest, channel, interactive, npx = false, width = process.stderr.columns ?? 80) {
|
|
62700
62423
|
const hint = buildUpdateHint(channel, npx);
|
|
62701
62424
|
if (interactive) {
|
|
62702
62425
|
const content = [
|
|
62703
|
-
`Update available: ${
|
|
62426
|
+
`Update available: ${import_picocolors30.default.dim(current)} ${import_picocolors30.default.dim("→")} ${import_picocolors30.default.bold(brand(latest))}`,
|
|
62704
62427
|
styleHint(hint)
|
|
62705
62428
|
];
|
|
62706
62429
|
const innerWidth = Math.max(...content.map(visibleWidth2)) + BOX_PADDING * 2;
|
|
62707
62430
|
const framed = (line) => {
|
|
62708
62431
|
const pad = innerWidth - visibleWidth2(line);
|
|
62709
62432
|
const left = Math.floor(pad / 2);
|
|
62710
|
-
return `${
|
|
62433
|
+
return `${import_picocolors30.default.yellow("│")}${" ".repeat(left)}${line}${" ".repeat(pad - left)}${import_picocolors30.default.yellow("│")}`;
|
|
62711
62434
|
};
|
|
62712
62435
|
const box = [
|
|
62713
|
-
|
|
62436
|
+
import_picocolors30.default.yellow(`╭${"─".repeat(innerWidth)}╮`),
|
|
62714
62437
|
framed(""),
|
|
62715
62438
|
...content.map(framed),
|
|
62716
62439
|
framed(""),
|
|
62717
|
-
|
|
62440
|
+
import_picocolors30.default.yellow(`╰${"─".repeat(innerWidth)}╯`)
|
|
62718
62441
|
];
|
|
62719
62442
|
return `
|
|
62720
62443
|
${centerBlock(box, width).join(`
|
|
@@ -62762,13 +62485,13 @@ async function checkForUpdates(options = {}) {
|
|
|
62762
62485
|
logger.error("update-check", `Update check failed: ${err}`);
|
|
62763
62486
|
}
|
|
62764
62487
|
}
|
|
62765
|
-
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;
|
|
62766
62489
|
var init_update_check = __esm(() => {
|
|
62767
62490
|
init_config();
|
|
62768
62491
|
init_logger();
|
|
62769
62492
|
init_styles();
|
|
62770
62493
|
init_layout();
|
|
62771
|
-
|
|
62494
|
+
import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
62772
62495
|
CHECK_INTERVAL_MS2 = 6 * 60 * 60 * 1000;
|
|
62773
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-]+)*)?$/;
|
|
62774
62497
|
});
|
|
@@ -62817,8 +62540,8 @@ function canRefreshMcp(cfg) {
|
|
|
62817
62540
|
}
|
|
62818
62541
|
function displayNotice2(names) {
|
|
62819
62542
|
console.error(`
|
|
62820
|
-
${
|
|
62821
|
-
` + `${
|
|
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.`)}
|
|
62822
62545
|
`);
|
|
62823
62546
|
}
|
|
62824
62547
|
function checkForMcpRefresh(options = {}) {
|
|
@@ -62846,21 +62569,21 @@ function checkForMcpRefresh(options = {}) {
|
|
|
62846
62569
|
logger.error("mcp-refresh", `MCP refresh check failed: ${err}`);
|
|
62847
62570
|
}
|
|
62848
62571
|
}
|
|
62849
|
-
var
|
|
62572
|
+
var import_picocolors31, CACHE_FILENAME4 = "mcp-refresh.json", MCP_FORMAT_CHANGES;
|
|
62850
62573
|
var init_mcp_refresh_check = __esm(() => {
|
|
62851
62574
|
init_config();
|
|
62852
62575
|
init_logger();
|
|
62853
62576
|
init_refresh();
|
|
62854
62577
|
init_update_check();
|
|
62855
|
-
|
|
62578
|
+
import_picocolors31 = __toESM(require_picocolors(), 1);
|
|
62856
62579
|
MCP_FORMAT_CHANGES = ["0.53.0"];
|
|
62857
62580
|
});
|
|
62858
62581
|
|
|
62859
62582
|
// src/version/skill-update-check.ts
|
|
62860
62583
|
function displayNotice3() {
|
|
62861
62584
|
console.error(`
|
|
62862
|
-
${
|
|
62863
|
-
` + `${
|
|
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.")}
|
|
62864
62587
|
`);
|
|
62865
62588
|
}
|
|
62866
62589
|
function checkForSkillUpdates(options = {}) {
|
|
@@ -62881,289 +62604,11 @@ function checkForSkillUpdates(options = {}) {
|
|
|
62881
62604
|
logger.error("skill-update-check", `Skill update check failed: ${err}`);
|
|
62882
62605
|
}
|
|
62883
62606
|
}
|
|
62884
|
-
var
|
|
62607
|
+
var import_picocolors32;
|
|
62885
62608
|
var init_skill_update_check = __esm(() => {
|
|
62886
62609
|
init_skill();
|
|
62887
62610
|
init_logger();
|
|
62888
|
-
|
|
62889
|
-
});
|
|
62890
|
-
|
|
62891
|
-
// src/rules/installer.ts
|
|
62892
|
-
import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync24, unlinkSync as unlinkSync5, writeFileSync as writeFileSync16 } from "node:fs";
|
|
62893
|
-
import { homedir as homedir12 } from "node:os";
|
|
62894
|
-
import { dirname as dirname12, join as join40 } from "node:path";
|
|
62895
|
-
function claudeConfigDir4() {
|
|
62896
|
-
return process.env.CLAUDE_CONFIG_DIR || join40(homedir12(), ".claude");
|
|
62897
|
-
}
|
|
62898
|
-
function codexHome4() {
|
|
62899
|
-
return process.env.CODEX_HOME || join40(homedir12(), ".codex");
|
|
62900
|
-
}
|
|
62901
|
-
function isRuleAgent(agent) {
|
|
62902
|
-
return Object.hasOwn(RULE_TARGETS, agent);
|
|
62903
|
-
}
|
|
62904
|
-
function rulePathForAgent(agent) {
|
|
62905
|
-
return isRuleAgent(agent) ? RULE_TARGETS[agent].path() : null;
|
|
62906
|
-
}
|
|
62907
|
-
function normalizeRule(content) {
|
|
62908
|
-
return `${content.trim()}
|
|
62909
|
-
`;
|
|
62910
|
-
}
|
|
62911
|
-
async function fetchDosuRule(fetchImpl = globalThis.fetch) {
|
|
62912
|
-
for (const url of DOSU_RULE_URLS) {
|
|
62913
|
-
try {
|
|
62914
|
-
const response = await fetchImpl(url);
|
|
62915
|
-
if (!response.ok)
|
|
62916
|
-
continue;
|
|
62917
|
-
const content = await response.text();
|
|
62918
|
-
if (content.trim())
|
|
62919
|
-
return normalizeRule(content);
|
|
62920
|
-
} catch {}
|
|
62921
|
-
}
|
|
62922
|
-
return normalizeRule(FALLBACK_DOSU_RULE);
|
|
62923
|
-
}
|
|
62924
|
-
function ensureParent(path) {
|
|
62925
|
-
mkdirSync15(dirname12(path), { recursive: true });
|
|
62926
|
-
}
|
|
62927
|
-
function writeIfChanged(path, content) {
|
|
62928
|
-
if (!existsSync25(path)) {
|
|
62929
|
-
ensureParent(path);
|
|
62930
|
-
writeFileSync16(path, content, "utf-8");
|
|
62931
|
-
return "created";
|
|
62932
|
-
}
|
|
62933
|
-
if (readFileSync24(path, "utf-8") === content)
|
|
62934
|
-
return "unchanged";
|
|
62935
|
-
writeFileSync16(path, content, "utf-8");
|
|
62936
|
-
return "updated";
|
|
62937
|
-
}
|
|
62938
|
-
function findSection(content) {
|
|
62939
|
-
const startMatch = content.match(DOSU_RULE_SECTION_START_RE);
|
|
62940
|
-
const start = startMatch?.index ?? -1;
|
|
62941
|
-
const end = content.indexOf(DOSU_RULE_SECTION_END, Math.max(start, 0));
|
|
62942
|
-
if (start === -1 && end === -1)
|
|
62943
|
-
return null;
|
|
62944
|
-
if (start === -1 || end < start) {
|
|
62945
|
-
throw new Error("Dosu rule markers are incomplete; refusing to overwrite the instruction file");
|
|
62946
|
-
}
|
|
62947
|
-
return { start, end };
|
|
62948
|
-
}
|
|
62949
|
-
function lineEndingFor(content) {
|
|
62950
|
-
return content.includes(`\r
|
|
62951
|
-
`) ? `\r
|
|
62952
|
-
` : `
|
|
62953
|
-
`;
|
|
62954
|
-
}
|
|
62955
|
-
function buildSection(content, lineEnding = `
|
|
62956
|
-
`) {
|
|
62957
|
-
const body = content.trimEnd().replace(/\r?\n/g, lineEnding);
|
|
62958
|
-
return `${DOSU_RULE_SECTION_START}${lineEnding}${body}${lineEnding}${DOSU_RULE_SECTION_END}`;
|
|
62959
|
-
}
|
|
62960
|
-
function upsertSection(path, content) {
|
|
62961
|
-
if (!existsSync25(path)) {
|
|
62962
|
-
const section = buildSection(content);
|
|
62963
|
-
ensureParent(path);
|
|
62964
|
-
writeFileSync16(path, `${section}
|
|
62965
|
-
`, "utf-8");
|
|
62966
|
-
return "created";
|
|
62967
|
-
}
|
|
62968
|
-
const existing = readFileSync24(path, "utf-8");
|
|
62969
|
-
const lineEnding = lineEndingFor(existing);
|
|
62970
|
-
const section = buildSection(content, lineEnding);
|
|
62971
|
-
const location = findSection(existing);
|
|
62972
|
-
let next;
|
|
62973
|
-
if (location) {
|
|
62974
|
-
next = existing.slice(0, location.start) + section + existing.slice(location.end + DOSU_RULE_SECTION_END.length);
|
|
62975
|
-
} else {
|
|
62976
|
-
const separator = existing.length > 0 && !existing.endsWith(lineEnding) ? `${lineEnding}${lineEnding}` : existing.length > 0 ? lineEnding : "";
|
|
62977
|
-
next = `${existing}${separator}${section}${lineEnding}`;
|
|
62978
|
-
}
|
|
62979
|
-
if (next === existing)
|
|
62980
|
-
return "unchanged";
|
|
62981
|
-
writeFileSync16(path, next, "utf-8");
|
|
62982
|
-
return "updated";
|
|
62983
|
-
}
|
|
62984
|
-
function installRuleForAgent(agent, content) {
|
|
62985
|
-
if (!isRuleAgent(agent))
|
|
62986
|
-
return null;
|
|
62987
|
-
const target = RULE_TARGETS[agent];
|
|
62988
|
-
const path = target.path();
|
|
62989
|
-
const normalized = normalizeRule(content);
|
|
62990
|
-
const action = target.kind === "file" ? writeIfChanged(path, target.cursorFrontmatter ? `${CURSOR_FRONTMATTER}${normalized}` : normalized) : upsertSection(path, normalized);
|
|
62991
|
-
return { agent, path, action };
|
|
62992
|
-
}
|
|
62993
|
-
function removeRuleForAgent(agent) {
|
|
62994
|
-
if (!isRuleAgent(agent))
|
|
62995
|
-
return null;
|
|
62996
|
-
const target = RULE_TARGETS[agent];
|
|
62997
|
-
const path = target.path();
|
|
62998
|
-
if (!existsSync25(path))
|
|
62999
|
-
return { agent, path, action: "not_found" };
|
|
63000
|
-
if (target.kind === "file") {
|
|
63001
|
-
unlinkSync5(path);
|
|
63002
|
-
return { agent, path, action: "removed" };
|
|
63003
|
-
}
|
|
63004
|
-
const existing = readFileSync24(path, "utf-8");
|
|
63005
|
-
const lineEnding = lineEndingFor(existing);
|
|
63006
|
-
const location = findSection(existing);
|
|
63007
|
-
if (!location)
|
|
63008
|
-
return { agent, path, action: "not_found" };
|
|
63009
|
-
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();
|
|
63010
|
-
if (!next) {
|
|
63011
|
-
unlinkSync5(path);
|
|
63012
|
-
} else {
|
|
63013
|
-
writeFileSync16(path, `${next}${lineEnding}`, "utf-8");
|
|
63014
|
-
}
|
|
63015
|
-
return { agent, path, action: "removed" };
|
|
63016
|
-
}
|
|
63017
|
-
var DOSU_RULE_SECTION_VERSION = 1, DOSU_RULE_SECTION_START, DOSU_RULE_SECTION_END = "<!-- dosu:rules:end -->", DOSU_RULE_SECTION_START_RE, CURSOR_FRONTMATTER = `---
|
|
63018
|
-
alwaysApply: true
|
|
63019
|
-
---
|
|
63020
|
-
|
|
63021
|
-
`, 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.
|
|
63022
|
-
|
|
63023
|
-
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.
|
|
63024
|
-
|
|
63025
|
-
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.**
|
|
63026
|
-
|
|
63027
|
-
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.
|
|
63028
|
-
|
|
63029
|
-
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.
|
|
63030
|
-
`, RULE_TARGETS;
|
|
63031
|
-
var init_installer = __esm(() => {
|
|
63032
|
-
DOSU_RULE_SECTION_START = `<!-- dosu:rules:start v${DOSU_RULE_SECTION_VERSION} -->`;
|
|
63033
|
-
DOSU_RULE_SECTION_START_RE = /<!-- dosu:rules:start(?: v\d+)? -->/;
|
|
63034
|
-
DOSU_RULE_URLS = [
|
|
63035
|
-
"https://raw.githubusercontent.com/dosu-ai/dosu-cli/main/rules/dosu.md",
|
|
63036
|
-
"https://raw.githubusercontent.com/dosu-ai/dosu-cli/master/rules/dosu.md"
|
|
63037
|
-
];
|
|
63038
|
-
RULE_TARGETS = {
|
|
63039
|
-
claude: {
|
|
63040
|
-
kind: "file",
|
|
63041
|
-
path: () => join40(claudeConfigDir4(), "rules", "dosu.md")
|
|
63042
|
-
},
|
|
63043
|
-
cursor: {
|
|
63044
|
-
kind: "file",
|
|
63045
|
-
path: () => join40(homedir12(), ".cursor", "rules", "dosu.mdc"),
|
|
63046
|
-
cursorFrontmatter: true
|
|
63047
|
-
},
|
|
63048
|
-
codex: {
|
|
63049
|
-
kind: "section",
|
|
63050
|
-
path: () => join40(codexHome4(), "AGENTS.md")
|
|
63051
|
-
},
|
|
63052
|
-
opencode: {
|
|
63053
|
-
kind: "section",
|
|
63054
|
-
path: () => join40(homedir12(), ".config", "opencode", "AGENTS.md")
|
|
63055
|
-
},
|
|
63056
|
-
gemini: {
|
|
63057
|
-
kind: "section",
|
|
63058
|
-
path: () => join40(homedir12(), ".gemini", "GEMINI.md")
|
|
63059
|
-
},
|
|
63060
|
-
antigravity: {
|
|
63061
|
-
kind: "section",
|
|
63062
|
-
path: () => join40(homedir12(), ".gemini", "GEMINI.md")
|
|
63063
|
-
}
|
|
63064
|
-
};
|
|
63065
|
-
});
|
|
63066
|
-
|
|
63067
|
-
// src/setup/agents-md-step.ts
|
|
63068
|
-
import { execSync as execSync2 } from "node:child_process";
|
|
63069
|
-
import { existsSync as existsSync26, readFileSync as readFileSync25, writeFileSync as writeFileSync17 } from "node:fs";
|
|
63070
|
-
import { join as join41 } from "node:path";
|
|
63071
|
-
function inGitWorkTree(cwd = process.cwd()) {
|
|
63072
|
-
try {
|
|
63073
|
-
const stdout = execSync2("git rev-parse --is-inside-work-tree", {
|
|
63074
|
-
cwd,
|
|
63075
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
63076
|
-
});
|
|
63077
|
-
return stdout.toString().trim() === "true";
|
|
63078
|
-
} catch {
|
|
63079
|
-
return false;
|
|
63080
|
-
}
|
|
63081
|
-
}
|
|
63082
|
-
function dosuAgentsSectionState(cwd = process.cwd()) {
|
|
63083
|
-
try {
|
|
63084
|
-
const path = join41(cwd, "AGENTS.md");
|
|
63085
|
-
if (!existsSync26(path))
|
|
63086
|
-
return "missing";
|
|
63087
|
-
const content = readFileSync25(path, "utf-8");
|
|
63088
|
-
const startMatch = content.match(SECTION_START_RE);
|
|
63089
|
-
if (!startMatch || !content.includes(DOSU_SECTION_END))
|
|
63090
|
-
return "missing";
|
|
63091
|
-
return Number(startMatch[1] ?? 0) >= DOSU_SECTION_VERSION ? "current" : "outdated";
|
|
63092
|
-
} catch {
|
|
63093
|
-
return "missing";
|
|
63094
|
-
}
|
|
63095
|
-
}
|
|
63096
|
-
function lineEndingFor2(content) {
|
|
63097
|
-
return content.includes(`\r
|
|
63098
|
-
`) ? `\r
|
|
63099
|
-
` : `
|
|
63100
|
-
`;
|
|
63101
|
-
}
|
|
63102
|
-
function renderDosuAgentsSection(content, lineEnding) {
|
|
63103
|
-
const body = content.trim().replace(/\r?\n/g, lineEnding);
|
|
63104
|
-
return `${DOSU_SECTION_START}${lineEnding}${body}${lineEnding}${DOSU_SECTION_END}`;
|
|
63105
|
-
}
|
|
63106
|
-
function buildDosuAgentsSection(content = FALLBACK_DOSU_RULE) {
|
|
63107
|
-
return renderDosuAgentsSection(content, `
|
|
63108
|
-
`);
|
|
63109
|
-
}
|
|
63110
|
-
function findSection2(content) {
|
|
63111
|
-
const startMatch = content.match(SECTION_START_RE);
|
|
63112
|
-
const start = startMatch?.index ?? -1;
|
|
63113
|
-
const end = content.indexOf(DOSU_SECTION_END, Math.max(start, 0));
|
|
63114
|
-
if (start === -1 && end === -1)
|
|
63115
|
-
return null;
|
|
63116
|
-
if (start === -1 || end < start) {
|
|
63117
|
-
throw new Error("Dosu AGENTS.md markers are incomplete; refusing to overwrite the file");
|
|
63118
|
-
}
|
|
63119
|
-
return { start, end };
|
|
63120
|
-
}
|
|
63121
|
-
function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RULE) {
|
|
63122
|
-
const path = join41(cwd, "AGENTS.md");
|
|
63123
|
-
if (!existsSync26(path)) {
|
|
63124
|
-
const section = buildDosuAgentsSection(content);
|
|
63125
|
-
writeFileSync17(path, `${section}
|
|
63126
|
-
`);
|
|
63127
|
-
return { path, action: "created" };
|
|
63128
|
-
}
|
|
63129
|
-
const existing = readFileSync25(path, "utf-8");
|
|
63130
|
-
const lineEnding = lineEndingFor2(existing);
|
|
63131
|
-
const section = renderDosuAgentsSection(content, lineEnding);
|
|
63132
|
-
const location = findSection2(existing);
|
|
63133
|
-
let next;
|
|
63134
|
-
if (location) {
|
|
63135
|
-
next = existing.slice(0, location.start) + section + existing.slice(location.end + DOSU_SECTION_END.length);
|
|
63136
|
-
} else {
|
|
63137
|
-
next = `${existing.trimEnd()}${lineEnding}${lineEnding}${section}${lineEnding}`;
|
|
63138
|
-
}
|
|
63139
|
-
if (next === existing)
|
|
63140
|
-
return { path, action: "unchanged" };
|
|
63141
|
-
writeFileSync17(path, next);
|
|
63142
|
-
return { path, action: "updated" };
|
|
63143
|
-
}
|
|
63144
|
-
async function stepUpdateAgentsMd(cwd = process.cwd(), content) {
|
|
63145
|
-
logger.info("setup", "Step: update AGENTS.md");
|
|
63146
|
-
try {
|
|
63147
|
-
const result = upsertDosuAgentsSection(cwd, content ?? await fetchDosuRule());
|
|
63148
|
-
logger.info("setup", `AGENTS.md ${result.action} at ${result.path}`);
|
|
63149
|
-
const status = result.action === "unchanged" ? "already up to date" : result.action;
|
|
63150
|
-
log2.success(formatSetupSummary("AGENTS.md", [{ path: result.path, status }]));
|
|
63151
|
-
return true;
|
|
63152
|
-
} catch (err) {
|
|
63153
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
63154
|
-
logger.error("setup", `AGENTS.md update failed: ${msg}`);
|
|
63155
|
-
log2.error(`Could not update AGENTS.md: ${msg}`);
|
|
63156
|
-
return false;
|
|
63157
|
-
}
|
|
63158
|
-
}
|
|
63159
|
-
var DOSU_SECTION_VERSION = 2, DOSU_SECTION_START, DOSU_SECTION_END = "<!-- dosu:mcp:end -->", SECTION_START_RE;
|
|
63160
|
-
var init_agents_md_step = __esm(() => {
|
|
63161
|
-
init_logger();
|
|
63162
|
-
init_installer();
|
|
63163
|
-
init_prompts();
|
|
63164
|
-
init_styles();
|
|
63165
|
-
DOSU_SECTION_START = `<!-- dosu:mcp:start v${DOSU_SECTION_VERSION} -->`;
|
|
63166
|
-
SECTION_START_RE = /<!-- dosu:mcp:start(?: v(\d+))? -->/;
|
|
62611
|
+
import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
63167
62612
|
});
|
|
63168
62613
|
|
|
63169
62614
|
// src/auth/errors.ts
|
|
@@ -63193,16 +62638,51 @@ var init_errors3 = __esm(() => {
|
|
|
63193
62638
|
// src/mcp/constants.ts
|
|
63194
62639
|
var MCP_PROVIDER_SLUG2 = "dosu_mcp";
|
|
63195
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
|
+
|
|
63196
62676
|
// src/sessions/session-title.ts
|
|
63197
|
-
import { existsSync as
|
|
63198
|
-
import { homedir as
|
|
63199
|
-
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";
|
|
63200
62680
|
function cachePath2(configDir) {
|
|
63201
|
-
return
|
|
62681
|
+
return join40(configDir, CACHE_FILENAME5);
|
|
63202
62682
|
}
|
|
63203
62683
|
function loadCacheFile2(configDir) {
|
|
63204
62684
|
try {
|
|
63205
|
-
const raw = JSON.parse(
|
|
62685
|
+
const raw = JSON.parse(readFileSync24(cachePath2(configDir), "utf-8"));
|
|
63206
62686
|
if (raw.schema_version !== CACHE_SCHEMA_VERSION2 || typeof raw.entries !== "object")
|
|
63207
62687
|
return {};
|
|
63208
62688
|
return raw.entries;
|
|
@@ -63212,12 +62692,12 @@ function loadCacheFile2(configDir) {
|
|
|
63212
62692
|
}
|
|
63213
62693
|
function saveCacheFile2(configDir, entries) {
|
|
63214
62694
|
try {
|
|
63215
|
-
if (!
|
|
63216
|
-
|
|
62695
|
+
if (!existsSync25(configDir))
|
|
62696
|
+
mkdirSync15(configDir, { recursive: true, mode: 448 });
|
|
63217
62697
|
const path = cachePath2(configDir);
|
|
63218
62698
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
63219
62699
|
const file = { schema_version: CACHE_SCHEMA_VERSION2, entries };
|
|
63220
|
-
|
|
62700
|
+
writeFileSync16(tmp, JSON.stringify(file), { mode: 384 });
|
|
63221
62701
|
renameSync6(tmp, path);
|
|
63222
62702
|
} catch {}
|
|
63223
62703
|
}
|
|
@@ -63250,15 +62730,15 @@ function claudeSummaryFromHead(text) {
|
|
|
63250
62730
|
}
|
|
63251
62731
|
return null;
|
|
63252
62732
|
}
|
|
63253
|
-
function reconstructSession(harness, id, slug, home =
|
|
62733
|
+
function reconstructSession(harness, id, slug, home = homedir11(), exists = existsSync25) {
|
|
63254
62734
|
if (!slug)
|
|
63255
62735
|
return null;
|
|
63256
62736
|
const candidates = [];
|
|
63257
62737
|
if (harness === "claude") {
|
|
63258
|
-
candidates.push(
|
|
62738
|
+
candidates.push(join40(home, ".claude", "projects", slug, `${id}.jsonl`));
|
|
63259
62739
|
} else if (harness === "cursor") {
|
|
63260
|
-
const project =
|
|
63261
|
-
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`));
|
|
63262
62742
|
} else {
|
|
63263
62743
|
return null;
|
|
63264
62744
|
}
|
|
@@ -63270,7 +62750,7 @@ function reconstructSession(harness, id, slug, home = homedir13(), exists = exis
|
|
|
63270
62750
|
}
|
|
63271
62751
|
function readHead2(path) {
|
|
63272
62752
|
try {
|
|
63273
|
-
return
|
|
62753
|
+
return readFileSync24(path, "utf-8").slice(0, 128 * 1024);
|
|
63274
62754
|
} catch {
|
|
63275
62755
|
return null;
|
|
63276
62756
|
}
|
|
@@ -63350,7 +62830,7 @@ var init_alt_screen = __esm(() => {
|
|
|
63350
62830
|
});
|
|
63351
62831
|
|
|
63352
62832
|
// src/tui/activity-view.ts
|
|
63353
|
-
import { existsSync as
|
|
62833
|
+
import { existsSync as existsSync26, readFileSync as readFileSync25 } from "node:fs";
|
|
63354
62834
|
import { basename as basename5 } from "node:path";
|
|
63355
62835
|
function reduceActivityViewKey(key) {
|
|
63356
62836
|
if (key === "q" || key === ESC7 || key === CTRL_C4)
|
|
@@ -63491,15 +62971,15 @@ function statusLine(status) {
|
|
|
63491
62971
|
if (status.running) {
|
|
63492
62972
|
const since = status.startedAt ? ` · since ${localTime(status.startedAt)}` : "";
|
|
63493
62973
|
const pid = status.pid !== undefined ? ` (pid ${status.pid})` : "";
|
|
63494
|
-
return `\uD83D\uDCDA ${
|
|
62974
|
+
return `\uD83D\uDCDA ${import_picocolors33.default.bold(brand("Studying sessions..."))}${import_picocolors33.default.dim(`${pid}${since}`)}`;
|
|
63495
62975
|
}
|
|
63496
62976
|
if (status.state.paused) {
|
|
63497
|
-
return `${
|
|
62977
|
+
return `${import_picocolors33.default.yellow("○")} ${import_picocolors33.default.bold("Paused")} ${import_picocolors33.default.dim("· studying stays off until you resume")}`;
|
|
63498
62978
|
}
|
|
63499
62979
|
if (status.staleLock) {
|
|
63500
|
-
return `${
|
|
62980
|
+
return `${import_picocolors33.default.yellow("○")} ${import_picocolors33.default.bold("Not running")} ${import_picocolors33.default.dim("· a previous run exited without cleaning up")}`;
|
|
63501
62981
|
}
|
|
63502
|
-
return `${
|
|
62982
|
+
return `${import_picocolors33.default.dim("○")} ${import_picocolors33.default.bold("Idle")} ${import_picocolors33.default.dim("· hooks study new sessions automatically")}`;
|
|
63503
62983
|
}
|
|
63504
62984
|
function progressLine(done, ready, width, notes = 0) {
|
|
63505
62985
|
const total = done + ready;
|
|
@@ -63508,7 +62988,7 @@ function progressLine(done, ready, width, notes = 0) {
|
|
|
63508
62988
|
const cells = Math.max(10, Math.min(30, width - 44));
|
|
63509
62989
|
const ratio = Math.max(0, Math.min(1, done / total));
|
|
63510
62990
|
const filled = Math.min(cells, Math.round(ratio * cells));
|
|
63511
|
-
const bar = brand("█".repeat(filled)) +
|
|
62991
|
+
const bar = brand("█".repeat(filled)) + import_picocolors33.default.dim("░".repeat(cells - filled));
|
|
63512
62992
|
const pct = Math.floor(ratio * 100);
|
|
63513
62993
|
const suffix = notes > 0 ? ` · ${notes} suggested page${notes === 1 ? "" : "s"}` : "";
|
|
63514
62994
|
return `${bar} ${done}/${total} studied · ${pct}%${suffix}`;
|
|
@@ -63547,17 +63027,17 @@ function confirmBox(queuedCount, backlog, width, mode = "start") {
|
|
|
63547
63027
|
const verb = mode === "clear" ? "clear" : mode === "stop" ? "stop" : mode === "resume" ? "resume" : "start";
|
|
63548
63028
|
const maxInner = Math.max(20, Math.min(width, contentWidth()) - 4);
|
|
63549
63029
|
const rows = [
|
|
63550
|
-
|
|
63551
|
-
...wrapLine(scope, maxInner, "").map((line) =>
|
|
63030
|
+
import_picocolors33.default.bold(brand(title)),
|
|
63031
|
+
...wrapLine(scope, maxInner, "").map((line) => import_picocolors33.default.dim(line)),
|
|
63552
63032
|
"",
|
|
63553
|
-
`${
|
|
63033
|
+
`${import_picocolors33.default.bold("enter")} ${verb} · ${import_picocolors33.default.bold("esc")} cancel`
|
|
63554
63034
|
];
|
|
63555
63035
|
const inner = Math.min(maxInner, Math.max(...rows.map(visibleWidth2)));
|
|
63556
63036
|
const pad = (row) => row + " ".repeat(Math.max(0, inner - visibleWidth2(row)));
|
|
63557
63037
|
return [
|
|
63558
|
-
|
|
63559
|
-
...rows.map((row) => `${
|
|
63560
|
-
|
|
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)}╯`)
|
|
63561
63041
|
];
|
|
63562
63042
|
}
|
|
63563
63043
|
function buildActivityFrame(status, activity, width, backlog = null, pane = DEFAULT_PANE, queued = [], studiedBeforeRun = 0, open = [], runProgress = null, projectNames = {}, sessionNames = {}, frameLines) {
|
|
@@ -63573,7 +63053,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
63573
63053
|
progress = progressLine(studiedDelta + stepDone, Math.max(0, backlog.ready - stepDone), width, runProgress?.notes ?? 0);
|
|
63574
63054
|
}
|
|
63575
63055
|
const refusal = !status.running && status.state.last_refusal;
|
|
63576
|
-
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)) : [];
|
|
63577
63057
|
const fullRows = Boolean(pane.fullRows);
|
|
63578
63058
|
const withName = (item, key) => projectNames[key] ? { ...item, project: projectNames[key] } : item;
|
|
63579
63059
|
const latestPass = new Map;
|
|
@@ -63599,8 +63079,8 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
63599
63079
|
breadcrumb(["home", "activity"], width),
|
|
63600
63080
|
"",
|
|
63601
63081
|
statusLine(status),
|
|
63602
|
-
|
|
63603
|
-
...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)) : [],
|
|
63604
63084
|
...progress ? [progress] : [],
|
|
63605
63085
|
...refusalLines,
|
|
63606
63086
|
"",
|
|
@@ -63616,7 +63096,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
63616
63096
|
status.running ? "s stop" : status.state.paused ? "s resume" : "s sync now",
|
|
63617
63097
|
...!status.running && status.state.watermark ? ["c clear"] : [],
|
|
63618
63098
|
"esc back"
|
|
63619
|
-
].join(" · "), width, "").map((line) =>
|
|
63099
|
+
].join(" · "), width, "").map((line) => import_picocolors33.default.dim(line))
|
|
63620
63100
|
]
|
|
63621
63101
|
];
|
|
63622
63102
|
const defaultHeight = fullRows ? ACTIVITY_VIEW_FULL_LIST_ROWS : ACTIVITY_VIEW_LIST_LINES;
|
|
@@ -63629,7 +63109,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
63629
63109
|
({ visible, above, below } = windowList(source, pane.scroll, height));
|
|
63630
63110
|
display = visible.flatMap((row) => wrapRow(row, width));
|
|
63631
63111
|
}
|
|
63632
|
-
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)];
|
|
63633
63113
|
const scrollParts = [];
|
|
63634
63114
|
if (above > 0)
|
|
63635
63115
|
scrollParts.push(`↑ ${above} earlier`);
|
|
@@ -63638,7 +63118,7 @@ function buildActivityFrame(status, activity, width, backlog = null, pane = DEFA
|
|
|
63638
63118
|
const lines = [
|
|
63639
63119
|
...header,
|
|
63640
63120
|
...listRows,
|
|
63641
|
-
...scrollParts.length > 0 ? [
|
|
63121
|
+
...scrollParts.length > 0 ? [import_picocolors33.default.dim(clip(scrollParts.join(" · "), width))] : [],
|
|
63642
63122
|
...footer
|
|
63643
63123
|
];
|
|
63644
63124
|
return { lines, listHeight: height };
|
|
@@ -63671,7 +63151,7 @@ function createRowNamer() {
|
|
|
63671
63151
|
names.titles[key] = t;
|
|
63672
63152
|
};
|
|
63673
63153
|
for (const s of [...backlog.queued, ...backlog.open]) {
|
|
63674
|
-
if (!
|
|
63154
|
+
if (!existsSync26(s.path))
|
|
63675
63155
|
continue;
|
|
63676
63156
|
const key = `${s.harness}/${s.id}`;
|
|
63677
63157
|
const dir = dirs.resolve(s);
|
|
@@ -63708,7 +63188,7 @@ function createRowNamer() {
|
|
|
63708
63188
|
}
|
|
63709
63189
|
function defaultReadLog2() {
|
|
63710
63190
|
try {
|
|
63711
|
-
return
|
|
63191
|
+
return readFileSync25(logger.getLogPath(), "utf-8");
|
|
63712
63192
|
} catch {
|
|
63713
63193
|
return "";
|
|
63714
63194
|
}
|
|
@@ -63893,7 +63373,7 @@ ${CLEAR_BELOW}`);
|
|
|
63893
63373
|
input.on("data", onData);
|
|
63894
63374
|
});
|
|
63895
63375
|
}
|
|
63896
|
-
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;
|
|
63897
63377
|
var init_activity_view = __esm(() => {
|
|
63898
63378
|
init_follow();
|
|
63899
63379
|
init_logger();
|
|
@@ -63908,7 +63388,7 @@ var init_activity_view = __esm(() => {
|
|
|
63908
63388
|
init_alt_screen();
|
|
63909
63389
|
init_layout();
|
|
63910
63390
|
init_menu();
|
|
63911
|
-
|
|
63391
|
+
import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
63912
63392
|
ESC7 = String.fromCharCode(27);
|
|
63913
63393
|
HIDE_CURSOR3 = `${ESC7}[?25l`;
|
|
63914
63394
|
SHOW_CURSOR3 = `${ESC7}[?25h`;
|
|
@@ -63924,6 +63404,284 @@ var init_activity_view = __esm(() => {
|
|
|
63924
63404
|
DEFAULT_PANE = { tab: "activity", scroll: 0 };
|
|
63925
63405
|
});
|
|
63926
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
|
+
|
|
63927
63685
|
// src/setup/analytics.ts
|
|
63928
63686
|
async function trackCliOnboardingEvent(cfg, onboardingRunID, event, properties = {}) {
|
|
63929
63687
|
try {
|
|
@@ -65391,7 +65149,7 @@ async function stepSelectTools(detected) {
|
|
|
65391
65149
|
initialValues: preselected,
|
|
65392
65150
|
statusFor: (id, picked) => {
|
|
65393
65151
|
if (configuredMap.get(id))
|
|
65394
|
-
return picked ? dim("configured") :
|
|
65152
|
+
return picked ? dim("configured") : import_picocolors34.default.yellow("will remove");
|
|
65395
65153
|
return picked ? brand("will configure") : undefined;
|
|
65396
65154
|
},
|
|
65397
65155
|
summary: (picked) => {
|
|
@@ -65566,7 +65324,7 @@ ${dim(wrapLog("Run it inside a session to keep that session out of studying. Rem
|
|
|
65566
65324
|
log2.success("All agents already configured. No changes needed.");
|
|
65567
65325
|
}
|
|
65568
65326
|
}
|
|
65569
|
-
var
|
|
65327
|
+
var import_picocolors34, OAUTH_ANALYTICS_REASONS, SETUP_HANDSHAKE_TIMEOUT_MS = 1800000, LIBRARY_SELECT_CANCELLED;
|
|
65570
65328
|
var init_flow2 = __esm(() => {
|
|
65571
65329
|
init_dist();
|
|
65572
65330
|
init_errors3();
|
|
@@ -65591,7 +65349,7 @@ var init_flow2 = __esm(() => {
|
|
|
65591
65349
|
init_github_step();
|
|
65592
65350
|
init_rules_step();
|
|
65593
65351
|
init_styles();
|
|
65594
|
-
|
|
65352
|
+
import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
65595
65353
|
OAUTH_ANALYTICS_REASONS = new Set([
|
|
65596
65354
|
"access_denied",
|
|
65597
65355
|
"bad_oauth_state",
|
|
@@ -65605,6 +65363,269 @@ var init_flow2 = __esm(() => {
|
|
|
65605
65363
|
LIBRARY_SELECT_CANCELLED = Symbol("library-select-cancelled");
|
|
65606
65364
|
});
|
|
65607
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
|
+
|
|
65608
65629
|
// src/tui/analytics-view.ts
|
|
65609
65630
|
function analyticsListHeight(rows) {
|
|
65610
65631
|
const room = frameMaxLines(rows) - ANALYTICS_VIEW_CHROME_LINES;
|
|
@@ -67851,4 +67872,4 @@ main().catch((err) => {
|
|
|
67851
67872
|
process.exit(1);
|
|
67852
67873
|
});
|
|
67853
67874
|
|
|
67854
|
-
//# debugId=
|
|
67875
|
+
//# debugId=49fa5d82-a4a1-8b36-6475-6e2164756e21
|