@dosu/cli 0.29.1 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/dosu.js +415 -245
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -4577,7 +4577,7 @@ var init_dist4 = __esm(() => {
|
|
|
4577
4577
|
function getVersionString() {
|
|
4578
4578
|
return `v${VERSION}`;
|
|
4579
4579
|
}
|
|
4580
|
-
var VERSION = "0.
|
|
4580
|
+
var VERSION = "0.31.0", INSTALL_CHANNEL = "npm";
|
|
4581
4581
|
|
|
4582
4582
|
// src/debug/logger.ts
|
|
4583
4583
|
import {
|
|
@@ -4711,7 +4711,7 @@ var init_logger = __esm(() => {
|
|
|
4711
4711
|
});
|
|
4712
4712
|
|
|
4713
4713
|
// src/client/contract.ts
|
|
4714
|
-
var CLI_CONTRACT_HASH = "
|
|
4714
|
+
var CLI_CONTRACT_HASH = "f5c0727a7884";
|
|
4715
4715
|
|
|
4716
4716
|
// src/client/trpc.ts
|
|
4717
4717
|
var exports_trpc = {};
|
|
@@ -6961,6 +6961,10 @@ var init_installation_server = __esm(() => {
|
|
|
6961
6961
|
function dim(msg) {
|
|
6962
6962
|
return import_picocolors7.default.dim(msg);
|
|
6963
6963
|
}
|
|
6964
|
+
function browserFallbackHint(url) {
|
|
6965
|
+
return dim(`If your browser doesn't open automatically, visit:
|
|
6966
|
+
${url}`);
|
|
6967
|
+
}
|
|
6964
6968
|
function info(msg) {
|
|
6965
6969
|
return import_picocolors7.default.cyan(msg);
|
|
6966
6970
|
}
|
|
@@ -7722,6 +7726,7 @@ async function openGitHubInstallFlow(onInstalled, opts) {
|
|
|
7722
7726
|
middleURL.searchParams.set("callback", callbackURL);
|
|
7723
7727
|
log.info(`Opening your browser to GitHub.
|
|
7724
7728
|
` + "Add repositories or install the Dosu GitHub App, and we'll pick up automatically.");
|
|
7729
|
+
log.message(browserFallbackHint(middleURL.toString()));
|
|
7725
7730
|
try {
|
|
7726
7731
|
const open2 = await Promise.resolve().then(() => (init_open(), exports_open));
|
|
7727
7732
|
await open2.default(middleURL.toString());
|
|
@@ -8328,7 +8333,7 @@ var require_cjs = __commonJS((exports) => {
|
|
|
8328
8333
|
var require_lib = __commonJS((exports, module) => {
|
|
8329
8334
|
var __filename = "/home/runner/work/dosu-cli/dosu-cli/node_modules/write-file-atomic/lib/index.js";
|
|
8330
8335
|
module.exports = writeFile;
|
|
8331
|
-
module.exports.sync =
|
|
8336
|
+
module.exports.sync = writeFileSync6;
|
|
8332
8337
|
module.exports._getTmpname = getTmpname;
|
|
8333
8338
|
module.exports._cleanupOnExit = cleanupOnExit;
|
|
8334
8339
|
var fs7 = __require("fs");
|
|
@@ -8461,7 +8466,7 @@ var require_lib = __commonJS((exports, module) => {
|
|
|
8461
8466
|
}
|
|
8462
8467
|
return promise;
|
|
8463
8468
|
}
|
|
8464
|
-
function
|
|
8469
|
+
function writeFileSync6(filename, data, options) {
|
|
8465
8470
|
if (typeof options === "string") {
|
|
8466
8471
|
options = { encoding: options };
|
|
8467
8472
|
} else if (!options) {
|
|
@@ -8538,7 +8543,7 @@ var require_lib = __commonJS((exports, module) => {
|
|
|
8538
8543
|
|
|
8539
8544
|
// src/mcp/config-helpers.ts
|
|
8540
8545
|
import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync7 } from "node:fs";
|
|
8541
|
-
import { dirname as
|
|
8546
|
+
import { dirname as dirname3 } from "node:path";
|
|
8542
8547
|
function mcpURL(deploymentID) {
|
|
8543
8548
|
return `${getBackendURL()}/v1/mcp/deployments/${deploymentID}`;
|
|
8544
8549
|
}
|
|
@@ -8616,7 +8621,7 @@ function saveJSONConfig(path3, cfg) {
|
|
|
8616
8621
|
writeSecureFile(path3, JSON.stringify(cfg, null, 2));
|
|
8617
8622
|
}
|
|
8618
8623
|
function writeSecureFile(path3, content) {
|
|
8619
|
-
const dir =
|
|
8624
|
+
const dir = dirname3(path3);
|
|
8620
8625
|
if (!existsSync6(dir)) {
|
|
8621
8626
|
mkdirSync5(dir, { recursive: true, mode: 448 });
|
|
8622
8627
|
}
|
|
@@ -8658,6 +8663,57 @@ var init_config_helpers = __esm(() => {
|
|
|
8658
8663
|
writeFileAtomic = import_write_file_atomic.default;
|
|
8659
8664
|
});
|
|
8660
8665
|
|
|
8666
|
+
// src/hooks/runtime.ts
|
|
8667
|
+
var exports_runtime = {};
|
|
8668
|
+
__export(exports_runtime, {
|
|
8669
|
+
resolveHookCommandPrefix: () => resolveHookCommandPrefix,
|
|
8670
|
+
materializedRuntimePath: () => materializedRuntimePath,
|
|
8671
|
+
dosuOnPath: () => dosuOnPath
|
|
8672
|
+
});
|
|
8673
|
+
import { spawnSync } from "node:child_process";
|
|
8674
|
+
import { copyFileSync, existsSync as existsSync7, mkdirSync as mkdirSync6 } from "node:fs";
|
|
8675
|
+
import { dirname as dirname4, join as join6 } from "node:path";
|
|
8676
|
+
function dosuOnPath() {
|
|
8677
|
+
const cmd = process.platform === "win32" ? "where" : "which";
|
|
8678
|
+
try {
|
|
8679
|
+
return spawnSync(cmd, ["dosu"], { stdio: "ignore" }).status === 0;
|
|
8680
|
+
} catch {
|
|
8681
|
+
return false;
|
|
8682
|
+
}
|
|
8683
|
+
}
|
|
8684
|
+
function materializedRuntimePath() {
|
|
8685
|
+
return join6(getConfigDir(), "bin", "dosu.js");
|
|
8686
|
+
}
|
|
8687
|
+
function currentBundlePath() {
|
|
8688
|
+
const entry = process.argv[1];
|
|
8689
|
+
if (!entry || !/\.(c|m)?js$/.test(entry) || !existsSync7(entry))
|
|
8690
|
+
return null;
|
|
8691
|
+
return entry;
|
|
8692
|
+
}
|
|
8693
|
+
function resolveHookCommandPrefix() {
|
|
8694
|
+
if (dosuOnPath())
|
|
8695
|
+
return "dosu";
|
|
8696
|
+
const bundle = currentBundlePath();
|
|
8697
|
+
if (!bundle) {
|
|
8698
|
+
logger.warn("hooks", "dosu not on PATH and no bundle to materialize; using bare 'dosu'");
|
|
8699
|
+
return "dosu";
|
|
8700
|
+
}
|
|
8701
|
+
const target = materializedRuntimePath();
|
|
8702
|
+
try {
|
|
8703
|
+
mkdirSync6(dirname4(target), { recursive: true, mode: 448 });
|
|
8704
|
+
copyFileSync(bundle, target);
|
|
8705
|
+
} catch (err) {
|
|
8706
|
+
logger.warn("hooks", `failed to materialize runtime: ${err instanceof Error ? err.message : String(err)}`);
|
|
8707
|
+
return "dosu";
|
|
8708
|
+
}
|
|
8709
|
+
logger.info("hooks", `materialized hook runtime at ${target}`);
|
|
8710
|
+
return `node "${target}"`;
|
|
8711
|
+
}
|
|
8712
|
+
var init_runtime = __esm(() => {
|
|
8713
|
+
init_config();
|
|
8714
|
+
init_logger();
|
|
8715
|
+
});
|
|
8716
|
+
|
|
8661
8717
|
// src/hooks/claude-code.ts
|
|
8662
8718
|
var exports_claude_code = {};
|
|
8663
8719
|
__export(exports_claude_code, {
|
|
@@ -8669,13 +8725,13 @@ __export(exports_claude_code, {
|
|
|
8669
8725
|
claudeLocalSettingsPath: () => claudeLocalSettingsPath,
|
|
8670
8726
|
DEFAULT_HOOK_EVENTS: () => DEFAULT_HOOK_EVENTS
|
|
8671
8727
|
});
|
|
8672
|
-
import { existsSync as
|
|
8673
|
-
import { join as
|
|
8728
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8 } from "node:fs";
|
|
8729
|
+
import { join as join7 } from "node:path";
|
|
8674
8730
|
function claudeLocalSettingsPath(dir) {
|
|
8675
|
-
return
|
|
8731
|
+
return join7(dir, ".claude", "settings.local.json");
|
|
8676
8732
|
}
|
|
8677
|
-
function hookCommand(subcommand) {
|
|
8678
|
-
return
|
|
8733
|
+
function hookCommand(subcommand, prefix = resolveHookCommandPrefix()) {
|
|
8734
|
+
return `${prefix} hooks ${subcommand}`;
|
|
8679
8735
|
}
|
|
8680
8736
|
function dosuGroup(event) {
|
|
8681
8737
|
const entry = {
|
|
@@ -8690,6 +8746,9 @@ function isDosuHookCommand(command) {
|
|
|
8690
8746
|
return false;
|
|
8691
8747
|
if (/@dosu\/cli/.test(command))
|
|
8692
8748
|
return true;
|
|
8749
|
+
if (/^([^\s]*[/\\])?node(\.exe)?\s+("[^"]*dosu\.(c|m)?js"|[^\s]*dosu\.(c|m)?js)\s/.test(command.trimStart())) {
|
|
8750
|
+
return true;
|
|
8751
|
+
}
|
|
8693
8752
|
return /^([^\s]*\/)?dosu\s/.test(command.trimStart());
|
|
8694
8753
|
}
|
|
8695
8754
|
function isDosuGroup(group) {
|
|
@@ -8701,7 +8760,7 @@ function isDosuGroup(group) {
|
|
|
8701
8760
|
return hooks.some((h2) => !!h2 && typeof h2 === "object" && (h2[MARKER] === true || typeof h2.command === "string" && isDosuHookCommand(h2.command)));
|
|
8702
8761
|
}
|
|
8703
8762
|
function readSettingsOrThrow(path3) {
|
|
8704
|
-
if (!
|
|
8763
|
+
if (!existsSync8(path3))
|
|
8705
8764
|
return {};
|
|
8706
8765
|
const raw = readFileSync8(path3, "utf-8").trim();
|
|
8707
8766
|
if (!raw)
|
|
@@ -8763,7 +8822,7 @@ function removeClaudeHooks(configPath) {
|
|
|
8763
8822
|
return { removed };
|
|
8764
8823
|
}
|
|
8765
8824
|
function inspectClaudeHooks(configPath) {
|
|
8766
|
-
if (!
|
|
8825
|
+
if (!existsSync8(configPath))
|
|
8767
8826
|
return { fileExists: false, parseError: false, events: [] };
|
|
8768
8827
|
let cfg;
|
|
8769
8828
|
try {
|
|
@@ -8778,6 +8837,7 @@ function inspectClaudeHooks(configPath) {
|
|
|
8778
8837
|
var DEFAULT_HOOK_EVENTS, MARKER = "__dosu", EVENT_SUBCOMMAND;
|
|
8779
8838
|
var init_claude_code = __esm(() => {
|
|
8780
8839
|
init_config_helpers();
|
|
8840
|
+
init_runtime();
|
|
8781
8841
|
DEFAULT_HOOK_EVENTS = ["UserPromptSubmit", "PostToolUse", "Stop"];
|
|
8782
8842
|
EVENT_SUBCOMMAND = {
|
|
8783
8843
|
UserPromptSubmit: "user-prompt-submit",
|
|
@@ -8795,13 +8855,13 @@ __export(exports_codex, {
|
|
|
8795
8855
|
codexHooksPath: () => codexHooksPath,
|
|
8796
8856
|
codexHookCommand: () => codexHookCommand
|
|
8797
8857
|
});
|
|
8798
|
-
import { existsSync as
|
|
8799
|
-
import { join as
|
|
8858
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9 } from "node:fs";
|
|
8859
|
+
import { join as join8 } from "node:path";
|
|
8800
8860
|
function codexHooksPath(dir) {
|
|
8801
|
-
return
|
|
8861
|
+
return join8(dir, ".codex", "hooks.json");
|
|
8802
8862
|
}
|
|
8803
|
-
function codexHookCommand(subcommand) {
|
|
8804
|
-
return
|
|
8863
|
+
function codexHookCommand(subcommand, prefix = resolveHookCommandPrefix()) {
|
|
8864
|
+
return `${prefix} hooks ${subcommand} --agent codex`;
|
|
8805
8865
|
}
|
|
8806
8866
|
function dosuGroup2(event) {
|
|
8807
8867
|
return {
|
|
@@ -8816,7 +8876,7 @@ function dosuGroup2(event) {
|
|
|
8816
8876
|
};
|
|
8817
8877
|
}
|
|
8818
8878
|
function readHooksFileOrThrow(path3) {
|
|
8819
|
-
if (!
|
|
8879
|
+
if (!existsSync9(path3))
|
|
8820
8880
|
return {};
|
|
8821
8881
|
const raw = readFileSync9(path3, "utf-8").trim();
|
|
8822
8882
|
if (!raw)
|
|
@@ -8851,7 +8911,7 @@ function installCodexHooks(configPath, opts = {}) {
|
|
|
8851
8911
|
return { events: [...events] };
|
|
8852
8912
|
}
|
|
8853
8913
|
function removeCodexHooks(configPath) {
|
|
8854
|
-
if (!
|
|
8914
|
+
if (!existsSync9(configPath))
|
|
8855
8915
|
return { removed: false };
|
|
8856
8916
|
let config;
|
|
8857
8917
|
try {
|
|
@@ -8880,7 +8940,7 @@ function removeCodexHooks(configPath) {
|
|
|
8880
8940
|
return { removed };
|
|
8881
8941
|
}
|
|
8882
8942
|
function inspectCodexHooks(configPath) {
|
|
8883
|
-
if (!
|
|
8943
|
+
if (!existsSync9(configPath))
|
|
8884
8944
|
return { fileExists: false, events: [] };
|
|
8885
8945
|
let config;
|
|
8886
8946
|
try {
|
|
@@ -8898,6 +8958,7 @@ var EVENT_SUBCOMMAND2, EVENT_TIMEOUT_SEC, EVENT_STATUS_MESSAGE;
|
|
|
8898
8958
|
var init_codex = __esm(() => {
|
|
8899
8959
|
init_config_helpers();
|
|
8900
8960
|
init_claude_code();
|
|
8961
|
+
init_runtime();
|
|
8901
8962
|
EVENT_SUBCOMMAND2 = {
|
|
8902
8963
|
UserPromptSubmit: "user-prompt-submit",
|
|
8903
8964
|
PostToolUse: "post-tool-use",
|
|
@@ -8924,13 +8985,13 @@ __export(exports_factory, {
|
|
|
8924
8985
|
factoryHooksPath: () => factoryHooksPath,
|
|
8925
8986
|
factoryHookCommand: () => factoryHookCommand
|
|
8926
8987
|
});
|
|
8927
|
-
import { existsSync as
|
|
8928
|
-
import { join as
|
|
8988
|
+
import { existsSync as existsSync10, readFileSync as readFileSync10 } from "node:fs";
|
|
8989
|
+
import { join as join9 } from "node:path";
|
|
8929
8990
|
function factoryHooksPath(dir) {
|
|
8930
|
-
return
|
|
8991
|
+
return join9(dir, ".factory", "hooks.json");
|
|
8931
8992
|
}
|
|
8932
|
-
function factoryHookCommand(subcommand) {
|
|
8933
|
-
return
|
|
8993
|
+
function factoryHookCommand(subcommand, prefix = resolveHookCommandPrefix()) {
|
|
8994
|
+
return `${prefix} hooks ${subcommand} --agent factory`;
|
|
8934
8995
|
}
|
|
8935
8996
|
function dosuGroup3(event) {
|
|
8936
8997
|
const group = {
|
|
@@ -8941,7 +9002,7 @@ function dosuGroup3(event) {
|
|
|
8941
9002
|
return group;
|
|
8942
9003
|
}
|
|
8943
9004
|
function readHooksFileOrThrow2(path3) {
|
|
8944
|
-
if (!
|
|
9005
|
+
if (!existsSync10(path3))
|
|
8945
9006
|
return {};
|
|
8946
9007
|
const raw = readFileSync10(path3, "utf-8").trim();
|
|
8947
9008
|
if (!raw)
|
|
@@ -8976,7 +9037,7 @@ function installFactoryHooks(configPath, opts = {}) {
|
|
|
8976
9037
|
return { events: [...events] };
|
|
8977
9038
|
}
|
|
8978
9039
|
function removeFactoryHooks(configPath) {
|
|
8979
|
-
if (!
|
|
9040
|
+
if (!existsSync10(configPath))
|
|
8980
9041
|
return { removed: false };
|
|
8981
9042
|
let config;
|
|
8982
9043
|
try {
|
|
@@ -9005,7 +9066,7 @@ function removeFactoryHooks(configPath) {
|
|
|
9005
9066
|
return { removed };
|
|
9006
9067
|
}
|
|
9007
9068
|
function inspectFactoryHooks(configPath) {
|
|
9008
|
-
if (!
|
|
9069
|
+
if (!existsSync10(configPath))
|
|
9009
9070
|
return { fileExists: false, events: [] };
|
|
9010
9071
|
let config;
|
|
9011
9072
|
try {
|
|
@@ -9023,6 +9084,7 @@ var EVENT_SUBCOMMAND3;
|
|
|
9023
9084
|
var init_factory = __esm(() => {
|
|
9024
9085
|
init_config_helpers();
|
|
9025
9086
|
init_claude_code();
|
|
9087
|
+
init_runtime();
|
|
9026
9088
|
EVENT_SUBCOMMAND3 = {
|
|
9027
9089
|
UserPromptSubmit: "user-prompt-submit",
|
|
9028
9090
|
PostToolUse: "post-tool-use",
|
|
@@ -10118,15 +10180,15 @@ var init_insights2 = __esm(() => {
|
|
|
10118
10180
|
});
|
|
10119
10181
|
|
|
10120
10182
|
// src/version/skill-update-check.ts
|
|
10121
|
-
import { existsSync as
|
|
10122
|
-
import { join as
|
|
10183
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync12, writeFileSync as writeFileSync6 } from "node:fs";
|
|
10184
|
+
import { join as join10 } from "node:path";
|
|
10123
10185
|
function getCachePath2() {
|
|
10124
|
-
return
|
|
10186
|
+
return join10(getConfigDir(), CACHE_FILENAME2);
|
|
10125
10187
|
}
|
|
10126
10188
|
function readSkillCache() {
|
|
10127
10189
|
try {
|
|
10128
10190
|
const path3 = getCachePath2();
|
|
10129
|
-
if (!
|
|
10191
|
+
if (!existsSync12(path3))
|
|
10130
10192
|
return null;
|
|
10131
10193
|
const data = JSON.parse(readFileSync12(path3, "utf-8"));
|
|
10132
10194
|
if (typeof data.lastCheck === "number" && typeof data.latestSha === "string" && typeof data.installedSha === "string") {
|
|
@@ -10140,10 +10202,10 @@ function readSkillCache() {
|
|
|
10140
10202
|
function writeSkillCache(cache) {
|
|
10141
10203
|
try {
|
|
10142
10204
|
const dir = getConfigDir();
|
|
10143
|
-
if (!
|
|
10144
|
-
|
|
10205
|
+
if (!existsSync12(dir)) {
|
|
10206
|
+
mkdirSync7(dir, { recursive: true, mode: 448 });
|
|
10145
10207
|
}
|
|
10146
|
-
|
|
10208
|
+
writeFileSync6(getCachePath2(), JSON.stringify(cache), { mode: 384 });
|
|
10147
10209
|
} catch {}
|
|
10148
10210
|
}
|
|
10149
10211
|
async function fetchLatestSha() {
|
|
@@ -10168,19 +10230,6 @@ async function fetchLatestSha() {
|
|
|
10168
10230
|
clearTimeout(timeout);
|
|
10169
10231
|
}
|
|
10170
10232
|
}
|
|
10171
|
-
async function refreshInstalledSha() {
|
|
10172
|
-
const sha = await fetchLatestSha();
|
|
10173
|
-
if (!sha) {
|
|
10174
|
-
logger.debug("skill-update-check", "Failed to fetch latest SHA during refresh");
|
|
10175
|
-
return;
|
|
10176
|
-
}
|
|
10177
|
-
writeSkillCache({
|
|
10178
|
-
lastCheck: Date.now(),
|
|
10179
|
-
latestSha: sha,
|
|
10180
|
-
installedSha: sha
|
|
10181
|
-
});
|
|
10182
|
-
logger.debug("skill-update-check", `Refreshed installedSha=${sha}`);
|
|
10183
|
-
}
|
|
10184
10233
|
function displayNotice() {
|
|
10185
10234
|
const msg = `
|
|
10186
10235
|
${import_picocolors12.default.yellow(" Dosu skill update available")}
|
|
@@ -10278,16 +10327,12 @@ Failed to remove skill.`));
|
|
|
10278
10327
|
});
|
|
10279
10328
|
cmd.command("update").description("Update the Dosu skill to the latest version").action(async () => {
|
|
10280
10329
|
console.log(`Updating ${SKILL_NAME} skill...`);
|
|
10281
|
-
|
|
10282
|
-
|
|
10283
|
-
stdio: "inherit"
|
|
10284
|
-
});
|
|
10285
|
-
} catch {
|
|
10330
|
+
const result = await installSkill();
|
|
10331
|
+
if (!result.success) {
|
|
10286
10332
|
console.error(import_picocolors13.default.red(`
|
|
10287
10333
|
Failed to update skill.`));
|
|
10288
10334
|
process.exit(1);
|
|
10289
10335
|
}
|
|
10290
|
-
await refreshInstalledSha();
|
|
10291
10336
|
console.log(import_picocolors13.default.green(`
|
|
10292
10337
|
✓ Skill "${SKILL_NAME}" updated.`));
|
|
10293
10338
|
});
|
|
@@ -10317,21 +10362,21 @@ var init_skill = __esm(() => {
|
|
|
10317
10362
|
var MCP_PROVIDER_SLUG = "dosu_mcp";
|
|
10318
10363
|
|
|
10319
10364
|
// src/mcp/detect.ts
|
|
10320
|
-
import { existsSync as
|
|
10365
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
10321
10366
|
import { homedir, platform as platform2 } from "node:os";
|
|
10322
|
-
import { join as
|
|
10367
|
+
import { join as join11 } from "node:path";
|
|
10323
10368
|
function isInstalled(paths) {
|
|
10324
|
-
return paths.some((p2) =>
|
|
10369
|
+
return paths.some((p2) => existsSync13(expandHome(p2)));
|
|
10325
10370
|
}
|
|
10326
10371
|
function expandHome(path3) {
|
|
10327
10372
|
if (!path3.startsWith("~"))
|
|
10328
10373
|
return path3;
|
|
10329
|
-
return
|
|
10374
|
+
return join11(homedir(), path3.slice(1));
|
|
10330
10375
|
}
|
|
10331
10376
|
function appSupportDir() {
|
|
10332
10377
|
switch (platform2()) {
|
|
10333
10378
|
case "darwin": {
|
|
10334
|
-
return
|
|
10379
|
+
return join11(homedir(), "Library", "Application Support");
|
|
10335
10380
|
}
|
|
10336
10381
|
case "win32": {
|
|
10337
10382
|
return process.env.APPDATA ?? "";
|
|
@@ -10340,7 +10385,7 @@ function appSupportDir() {
|
|
|
10340
10385
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
10341
10386
|
if (xdg)
|
|
10342
10387
|
return xdg;
|
|
10343
|
-
return
|
|
10388
|
+
return join11(homedir(), ".config");
|
|
10344
10389
|
}
|
|
10345
10390
|
}
|
|
10346
10391
|
}
|
|
@@ -10421,7 +10466,7 @@ var init_antigravity = __esm(() => {
|
|
|
10421
10466
|
});
|
|
10422
10467
|
|
|
10423
10468
|
// src/mcp/providers/claude.ts
|
|
10424
|
-
import { join as
|
|
10469
|
+
import { join as join12 } from "node:path";
|
|
10425
10470
|
var ClaudeProvider = () => createJSONProvider({
|
|
10426
10471
|
providerName: "Claude Code",
|
|
10427
10472
|
providerID: "claude",
|
|
@@ -10430,22 +10475,22 @@ var ClaudeProvider = () => createJSONProvider({
|
|
|
10430
10475
|
paths: ["~/.claude"],
|
|
10431
10476
|
globalPath: "~/.claude.json",
|
|
10432
10477
|
topKey: "mcpServers",
|
|
10433
|
-
localConfigPath: (cwd) =>
|
|
10478
|
+
localConfigPath: (cwd) => join12(cwd, ".mcp.json")
|
|
10434
10479
|
});
|
|
10435
10480
|
var init_claude = __esm(() => {
|
|
10436
10481
|
init_base();
|
|
10437
10482
|
});
|
|
10438
10483
|
|
|
10439
10484
|
// src/mcp/providers/claude-desktop.ts
|
|
10440
|
-
import { join as
|
|
10485
|
+
import { join as join13 } from "node:path";
|
|
10441
10486
|
var ClaudeDesktopProvider = () => ({
|
|
10442
10487
|
name: () => "Claude Desktop",
|
|
10443
10488
|
id: () => "claude-desktop",
|
|
10444
10489
|
supportsLocal: () => false,
|
|
10445
10490
|
priority: () => 2,
|
|
10446
|
-
detectPaths: () => [
|
|
10447
|
-
isInstalled: () => isInstalled([
|
|
10448
|
-
globalConfigPath: () =>
|
|
10491
|
+
detectPaths: () => [join13(appSupportDir(), "Claude")],
|
|
10492
|
+
isInstalled: () => isInstalled([join13(appSupportDir(), "Claude")]),
|
|
10493
|
+
globalConfigPath: () => join13(appSupportDir(), "Claude", "claude_desktop_config.json"),
|
|
10449
10494
|
isConfigured: () => false,
|
|
10450
10495
|
install() {
|
|
10451
10496
|
throw new Error("this tool only supports local (stdio) servers and cannot be configured for remote MCP");
|
|
@@ -10459,14 +10504,14 @@ var init_claude_desktop = __esm(() => {
|
|
|
10459
10504
|
});
|
|
10460
10505
|
|
|
10461
10506
|
// src/mcp/providers/cline.ts
|
|
10462
|
-
import { join as
|
|
10463
|
-
var extensionDir = () =>
|
|
10507
|
+
import { join as join14 } from "node:path";
|
|
10508
|
+
var extensionDir = () => join14(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
|
|
10464
10509
|
providerName: "Cline",
|
|
10465
10510
|
providerID: "cline",
|
|
10466
10511
|
local: false,
|
|
10467
10512
|
priorityValue: 11,
|
|
10468
10513
|
paths: [extensionDir()],
|
|
10469
|
-
globalPath:
|
|
10514
|
+
globalPath: join14(extensionDir(), "settings", "cline_mcp_settings.json"),
|
|
10470
10515
|
topKey: "mcpServers",
|
|
10471
10516
|
buildServer: (cfg) => ({
|
|
10472
10517
|
url: mcpURL(cfg.deployment_id),
|
|
@@ -10482,7 +10527,7 @@ var init_cline = __esm(() => {
|
|
|
10482
10527
|
});
|
|
10483
10528
|
|
|
10484
10529
|
// src/mcp/providers/cline-cli.ts
|
|
10485
|
-
import { join as
|
|
10530
|
+
import { join as join15 } from "node:path";
|
|
10486
10531
|
function clineDir() {
|
|
10487
10532
|
return process.env.CLINE_DIR ?? expandHome("~/.cline");
|
|
10488
10533
|
}
|
|
@@ -10492,7 +10537,7 @@ var ClineCliProvider = () => createJSONProvider({
|
|
|
10492
10537
|
local: false,
|
|
10493
10538
|
priorityValue: 12,
|
|
10494
10539
|
paths: [clineDir()],
|
|
10495
|
-
globalPath:
|
|
10540
|
+
globalPath: join15(clineDir(), "data", "settings", "cline_mcp_settings.json"),
|
|
10496
10541
|
topKey: "mcpServers",
|
|
10497
10542
|
buildServer: (cfg) => ({
|
|
10498
10543
|
url: mcpURL(cfg.deployment_id),
|
|
@@ -10508,18 +10553,18 @@ var init_cline_cli = __esm(() => {
|
|
|
10508
10553
|
});
|
|
10509
10554
|
|
|
10510
10555
|
// src/mcp/providers/codex.ts
|
|
10511
|
-
import { existsSync as
|
|
10512
|
-
import { join as
|
|
10556
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13 } from "node:fs";
|
|
10557
|
+
import { join as join16 } from "node:path";
|
|
10513
10558
|
function codexHome() {
|
|
10514
10559
|
return process.env.CODEX_HOME ?? expandHome("~/.codex");
|
|
10515
10560
|
}
|
|
10516
10561
|
function getConfigPath2(global) {
|
|
10517
10562
|
if (global)
|
|
10518
|
-
return
|
|
10519
|
-
return
|
|
10563
|
+
return join16(codexHome(), "config.toml");
|
|
10564
|
+
return join16(process.cwd(), ".codex", "config.toml");
|
|
10520
10565
|
}
|
|
10521
10566
|
function readTOML(path3) {
|
|
10522
|
-
if (!
|
|
10567
|
+
if (!existsSync14(path3))
|
|
10523
10568
|
return "";
|
|
10524
10569
|
return readFileSync13(path3, "utf-8");
|
|
10525
10570
|
}
|
|
@@ -10579,9 +10624,9 @@ var CodexProvider = () => ({
|
|
|
10579
10624
|
priority: () => 8,
|
|
10580
10625
|
detectPaths: () => ["~/.codex"],
|
|
10581
10626
|
isInstalled: () => isInstalled(["~/.codex"]),
|
|
10582
|
-
globalConfigPath: () =>
|
|
10627
|
+
globalConfigPath: () => join16(codexHome(), "config.toml"),
|
|
10583
10628
|
isConfigured: () => {
|
|
10584
|
-
const content = readTOML(
|
|
10629
|
+
const content = readTOML(join16(codexHome(), "config.toml"));
|
|
10585
10630
|
return content.includes("[mcp_servers.dosu]");
|
|
10586
10631
|
},
|
|
10587
10632
|
install(cfg, global) {
|
|
@@ -10603,10 +10648,10 @@ var init_codex2 = __esm(() => {
|
|
|
10603
10648
|
});
|
|
10604
10649
|
|
|
10605
10650
|
// src/mcp/providers/copilot.ts
|
|
10606
|
-
import { join as
|
|
10651
|
+
import { join as join17 } from "node:path";
|
|
10607
10652
|
function globalPath() {
|
|
10608
10653
|
if (process.env.XDG_CONFIG_HOME) {
|
|
10609
|
-
return
|
|
10654
|
+
return join17(process.env.XDG_CONFIG_HOME, "mcp-config.json");
|
|
10610
10655
|
}
|
|
10611
10656
|
return expandHome("~/.copilot/mcp-config.json");
|
|
10612
10657
|
}
|
|
@@ -10637,7 +10682,7 @@ var CopilotProvider = () => ({
|
|
|
10637
10682
|
};
|
|
10638
10683
|
installJSONServer(globalPath(), "mcpServers", server);
|
|
10639
10684
|
} else {
|
|
10640
|
-
const configPath =
|
|
10685
|
+
const configPath = join17(process.cwd(), ".vscode", "mcp.json");
|
|
10641
10686
|
const server = {
|
|
10642
10687
|
type: "http",
|
|
10643
10688
|
url,
|
|
@@ -10650,7 +10695,7 @@ var CopilotProvider = () => ({
|
|
|
10650
10695
|
if (global) {
|
|
10651
10696
|
removeJSONServer(globalPath(), "mcpServers");
|
|
10652
10697
|
} else {
|
|
10653
|
-
const configPath =
|
|
10698
|
+
const configPath = join17(process.cwd(), ".vscode", "mcp.json");
|
|
10654
10699
|
removeJSONServer(configPath, "servers");
|
|
10655
10700
|
}
|
|
10656
10701
|
}
|
|
@@ -10662,7 +10707,7 @@ var init_copilot = __esm(() => {
|
|
|
10662
10707
|
});
|
|
10663
10708
|
|
|
10664
10709
|
// src/mcp/providers/cursor.ts
|
|
10665
|
-
import { join as
|
|
10710
|
+
import { join as join18 } from "node:path";
|
|
10666
10711
|
var CursorProvider = () => createJSONProvider({
|
|
10667
10712
|
providerName: "Cursor",
|
|
10668
10713
|
providerID: "cursor",
|
|
@@ -10675,7 +10720,7 @@ var CursorProvider = () => createJSONProvider({
|
|
|
10675
10720
|
url: mcpURL(cfg.deployment_id),
|
|
10676
10721
|
headers: mcpHeaders(cfg.api_key)
|
|
10677
10722
|
}),
|
|
10678
|
-
localConfigPath: (cwd) =>
|
|
10723
|
+
localConfigPath: (cwd) => join18(cwd, ".cursor", "mcp.json")
|
|
10679
10724
|
});
|
|
10680
10725
|
var init_cursor = __esm(() => {
|
|
10681
10726
|
init_config_helpers();
|
|
@@ -10683,7 +10728,7 @@ var init_cursor = __esm(() => {
|
|
|
10683
10728
|
});
|
|
10684
10729
|
|
|
10685
10730
|
// src/mcp/providers/factory.ts
|
|
10686
|
-
import { join as
|
|
10731
|
+
import { join as join19 } from "node:path";
|
|
10687
10732
|
var FactoryProvider = () => createJSONProvider({
|
|
10688
10733
|
providerName: "Factory",
|
|
10689
10734
|
providerID: "factory",
|
|
@@ -10692,14 +10737,14 @@ var FactoryProvider = () => createJSONProvider({
|
|
|
10692
10737
|
paths: ["~/.factory"],
|
|
10693
10738
|
globalPath: "~/.factory/mcp.json",
|
|
10694
10739
|
topKey: "mcpServers",
|
|
10695
|
-
localConfigPath: (cwd) =>
|
|
10740
|
+
localConfigPath: (cwd) => join19(cwd, ".factory", "mcp.json")
|
|
10696
10741
|
});
|
|
10697
10742
|
var init_factory2 = __esm(() => {
|
|
10698
10743
|
init_base();
|
|
10699
10744
|
});
|
|
10700
10745
|
|
|
10701
10746
|
// src/mcp/providers/gemini.ts
|
|
10702
|
-
import { join as
|
|
10747
|
+
import { join as join20 } from "node:path";
|
|
10703
10748
|
var GeminiProvider = () => createJSONProvider({
|
|
10704
10749
|
providerName: "Gemini CLI",
|
|
10705
10750
|
providerID: "gemini",
|
|
@@ -10708,7 +10753,7 @@ var GeminiProvider = () => createJSONProvider({
|
|
|
10708
10753
|
paths: ["~/.gemini"],
|
|
10709
10754
|
globalPath: "~/.gemini/settings.json",
|
|
10710
10755
|
topKey: "mcpServers",
|
|
10711
|
-
localConfigPath: (cwd) =>
|
|
10756
|
+
localConfigPath: (cwd) => join20(cwd, ".gemini", "settings.json")
|
|
10712
10757
|
});
|
|
10713
10758
|
var init_gemini = __esm(() => {
|
|
10714
10759
|
init_base();
|
|
@@ -10758,14 +10803,14 @@ var init_manual = __esm(() => {
|
|
|
10758
10803
|
});
|
|
10759
10804
|
|
|
10760
10805
|
// src/mcp/providers/mcporter.ts
|
|
10761
|
-
import { existsSync as
|
|
10762
|
-
import { join as
|
|
10806
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
10807
|
+
import { join as join21 } from "node:path";
|
|
10763
10808
|
function resolveGlobalConfigPath() {
|
|
10764
10809
|
const jsonPath = expandHome("~/.mcporter/mcporter.json");
|
|
10765
|
-
if (
|
|
10810
|
+
if (existsSync15(jsonPath))
|
|
10766
10811
|
return jsonPath;
|
|
10767
10812
|
const jsoncPath = expandHome("~/.mcporter/mcporter.jsonc");
|
|
10768
|
-
if (
|
|
10813
|
+
if (existsSync15(jsoncPath))
|
|
10769
10814
|
return jsoncPath;
|
|
10770
10815
|
return jsonPath;
|
|
10771
10816
|
}
|
|
@@ -10786,7 +10831,7 @@ var MCPorterProvider = () => ({
|
|
|
10786
10831
|
globalConfigPath: () => resolveGlobalConfigPath(),
|
|
10787
10832
|
isConfigured: () => isJSONKeyConfigured(resolveGlobalConfigPath(), "mcpServers"),
|
|
10788
10833
|
install(cfg, global) {
|
|
10789
|
-
const configPath = global ? resolveGlobalConfigPath() :
|
|
10834
|
+
const configPath = global ? resolveGlobalConfigPath() : join21(process.cwd(), "config", "mcporter.json");
|
|
10790
10835
|
const server = {
|
|
10791
10836
|
type: "http",
|
|
10792
10837
|
url: mcpEndpoint4(cfg),
|
|
@@ -10795,7 +10840,7 @@ var MCPorterProvider = () => ({
|
|
|
10795
10840
|
installJSONServer(configPath, "mcpServers", server);
|
|
10796
10841
|
},
|
|
10797
10842
|
remove(global) {
|
|
10798
|
-
const configPath = global ? resolveGlobalConfigPath() :
|
|
10843
|
+
const configPath = global ? resolveGlobalConfigPath() : join21(process.cwd(), "config", "mcporter.json");
|
|
10799
10844
|
removeJSONServer(configPath, "mcpServers");
|
|
10800
10845
|
}
|
|
10801
10846
|
});
|
|
@@ -10806,7 +10851,7 @@ var init_mcporter = __esm(() => {
|
|
|
10806
10851
|
});
|
|
10807
10852
|
|
|
10808
10853
|
// src/mcp/providers/opencode.ts
|
|
10809
|
-
import { join as
|
|
10854
|
+
import { join as join22 } from "node:path";
|
|
10810
10855
|
var OpenCodeProvider = () => createJSONProvider({
|
|
10811
10856
|
providerName: "OpenCode",
|
|
10812
10857
|
providerID: "opencode",
|
|
@@ -10821,7 +10866,7 @@ var OpenCodeProvider = () => createJSONProvider({
|
|
|
10821
10866
|
enabled: true,
|
|
10822
10867
|
headers: mcpHeaders(cfg.api_key)
|
|
10823
10868
|
}),
|
|
10824
|
-
localConfigPath: (cwd) =>
|
|
10869
|
+
localConfigPath: (cwd) => join22(cwd, "opencode.json")
|
|
10825
10870
|
});
|
|
10826
10871
|
var init_opencode = __esm(() => {
|
|
10827
10872
|
init_config_helpers();
|
|
@@ -10829,16 +10874,16 @@ var init_opencode = __esm(() => {
|
|
|
10829
10874
|
});
|
|
10830
10875
|
|
|
10831
10876
|
// src/mcp/providers/vscode.ts
|
|
10832
|
-
import { join as
|
|
10877
|
+
import { join as join23 } from "node:path";
|
|
10833
10878
|
var VSCodeProvider = () => createJSONProvider({
|
|
10834
10879
|
providerName: "VS Code",
|
|
10835
10880
|
providerID: "vscode",
|
|
10836
10881
|
local: true,
|
|
10837
10882
|
priorityValue: 6,
|
|
10838
|
-
paths: [
|
|
10839
|
-
globalPath:
|
|
10883
|
+
paths: [join23(appSupportDir(), "Code")],
|
|
10884
|
+
globalPath: join23(appSupportDir(), "Code", "User", "mcp.json"),
|
|
10840
10885
|
topKey: "servers",
|
|
10841
|
-
localConfigPath: (cwd) =>
|
|
10886
|
+
localConfigPath: (cwd) => join23(cwd, ".vscode", "mcp.json")
|
|
10842
10887
|
});
|
|
10843
10888
|
var init_vscode = __esm(() => {
|
|
10844
10889
|
init_detect();
|
|
@@ -10847,14 +10892,14 @@ var init_vscode = __esm(() => {
|
|
|
10847
10892
|
|
|
10848
10893
|
// src/mcp/providers/windsurf.ts
|
|
10849
10894
|
import { homedir as homedir2 } from "node:os";
|
|
10850
|
-
import { join as
|
|
10895
|
+
import { join as join24 } from "node:path";
|
|
10851
10896
|
var WindsurfProvider = () => createJSONProvider({
|
|
10852
10897
|
providerName: "Windsurf",
|
|
10853
10898
|
providerID: "windsurf",
|
|
10854
10899
|
local: false,
|
|
10855
10900
|
priorityValue: 9,
|
|
10856
|
-
paths: [
|
|
10857
|
-
globalPath:
|
|
10901
|
+
paths: [join24(homedir2(), ".codeium", "windsurf")],
|
|
10902
|
+
globalPath: join24(homedir2(), ".codeium", "windsurf", "mcp_config.json"),
|
|
10858
10903
|
topKey: "mcpServers"
|
|
10859
10904
|
});
|
|
10860
10905
|
var init_windsurf = __esm(() => {
|
|
@@ -10863,12 +10908,12 @@ var init_windsurf = __esm(() => {
|
|
|
10863
10908
|
|
|
10864
10909
|
// src/mcp/providers/zed.ts
|
|
10865
10910
|
import { platform as platform3 } from "node:os";
|
|
10866
|
-
import { join as
|
|
10911
|
+
import { join as join25 } from "node:path";
|
|
10867
10912
|
function zedConfigDir() {
|
|
10868
10913
|
const os2 = platform3();
|
|
10869
10914
|
if (os2 === "darwin" || os2 === "win32")
|
|
10870
|
-
return
|
|
10871
|
-
return
|
|
10915
|
+
return join25(appSupportDir(), "Zed");
|
|
10916
|
+
return join25(appSupportDir(), "zed");
|
|
10872
10917
|
}
|
|
10873
10918
|
var ZedProvider = () => createJSONProvider({
|
|
10874
10919
|
providerName: "Zed",
|
|
@@ -10876,7 +10921,7 @@ var ZedProvider = () => createJSONProvider({
|
|
|
10876
10921
|
local: true,
|
|
10877
10922
|
priorityValue: 10,
|
|
10878
10923
|
paths: [zedConfigDir()],
|
|
10879
|
-
globalPath:
|
|
10924
|
+
globalPath: join25(zedConfigDir(), "settings.json"),
|
|
10880
10925
|
topKey: "context_servers",
|
|
10881
10926
|
buildServer: (cfg) => ({
|
|
10882
10927
|
source: "custom",
|
|
@@ -10884,7 +10929,7 @@ var ZedProvider = () => createJSONProvider({
|
|
|
10884
10929
|
url: mcpURL(cfg.deployment_id),
|
|
10885
10930
|
headers: mcpHeaders(cfg.api_key)
|
|
10886
10931
|
}),
|
|
10887
|
-
localConfigPath: (cwd) =>
|
|
10932
|
+
localConfigPath: (cwd) => join25(cwd, ".zed", "settings.json")
|
|
10888
10933
|
});
|
|
10889
10934
|
var init_zed = __esm(() => {
|
|
10890
10935
|
init_config_helpers();
|
|
@@ -11027,6 +11072,74 @@ var init_analytics = __esm(() => {
|
|
|
11027
11072
|
init_logger();
|
|
11028
11073
|
});
|
|
11029
11074
|
|
|
11075
|
+
// src/setup/audit-handoff.ts
|
|
11076
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
11077
|
+
function buildAuditHandoffPrompt(dosuCmd = dosuInvocation()) {
|
|
11078
|
+
return [
|
|
11079
|
+
"Audit this repository to see what docs Dosu can generate for it.",
|
|
11080
|
+
"1. Run the codebase audit from the Dosu skill. It writes findings to .dosu/audit.json.",
|
|
11081
|
+
"2. Show me the findings and which docs you recommend Dosu generate.",
|
|
11082
|
+
`3. Once I confirm, run \`${dosuCmd} audit --tasks <comma-separated task ids> --json\` to kick off generation. Dosu opens a PR and the CLI notifies me when it's ready.`
|
|
11083
|
+
].join(`
|
|
11084
|
+
`);
|
|
11085
|
+
}
|
|
11086
|
+
function binOnPath(bin) {
|
|
11087
|
+
const cmd = process.platform === "win32" ? "where" : "which";
|
|
11088
|
+
try {
|
|
11089
|
+
return spawnSync2(cmd, [bin], { stdio: "ignore" }).status === 0;
|
|
11090
|
+
} catch {
|
|
11091
|
+
return false;
|
|
11092
|
+
}
|
|
11093
|
+
}
|
|
11094
|
+
function claudeCliAvailable() {
|
|
11095
|
+
return binOnPath("claude");
|
|
11096
|
+
}
|
|
11097
|
+
function dosuInvocation() {
|
|
11098
|
+
return binOnPath("dosu") ? "dosu" : "npx -y @dosu/cli";
|
|
11099
|
+
}
|
|
11100
|
+
function printManualAuditNudge() {
|
|
11101
|
+
log.message(`See what docs Dosu can generate for this repo:
|
|
11102
|
+
|
|
11103
|
+
${info("Ask Dosu to audit this repo and show what docs it can generate.")}
|
|
11104
|
+
|
|
11105
|
+
Or run ${info(`${dosuInvocation()} audit`)} after your agent writes the audit.`);
|
|
11106
|
+
}
|
|
11107
|
+
async function offerAuditHandoff() {
|
|
11108
|
+
if (!detectGitRepo())
|
|
11109
|
+
return false;
|
|
11110
|
+
if (!claudeCliAvailable()) {
|
|
11111
|
+
printManualAuditNudge();
|
|
11112
|
+
return false;
|
|
11113
|
+
}
|
|
11114
|
+
const go = await confirm({
|
|
11115
|
+
message: "Kick off the codebase audit in Claude Code now?",
|
|
11116
|
+
initialValue: true
|
|
11117
|
+
});
|
|
11118
|
+
if (isCancel(go) || !go) {
|
|
11119
|
+
printManualAuditNudge();
|
|
11120
|
+
return false;
|
|
11121
|
+
}
|
|
11122
|
+
return true;
|
|
11123
|
+
}
|
|
11124
|
+
function launchAuditAgent() {
|
|
11125
|
+
logger.info("setup", "Handing off to Claude Code for the codebase audit");
|
|
11126
|
+
const result = spawnSync2("claude", ["--model", AUDIT_AGENT_MODEL, buildAuditHandoffPrompt()], {
|
|
11127
|
+
stdio: "inherit",
|
|
11128
|
+
shell: process.platform === "win32"
|
|
11129
|
+
});
|
|
11130
|
+
if (result.error) {
|
|
11131
|
+
logger.warn("setup", `Claude Code launch failed: ${result.error.message}`);
|
|
11132
|
+
printManualAuditNudge();
|
|
11133
|
+
}
|
|
11134
|
+
}
|
|
11135
|
+
var AUDIT_AGENT_MODEL = "haiku";
|
|
11136
|
+
var init_audit_handoff = __esm(() => {
|
|
11137
|
+
init_dist8();
|
|
11138
|
+
init_logger();
|
|
11139
|
+
init_github_step();
|
|
11140
|
+
init_styles();
|
|
11141
|
+
});
|
|
11142
|
+
|
|
11030
11143
|
// src/setup/github-doc-import-prompt.ts
|
|
11031
11144
|
async function promptGitHubDocsImport({
|
|
11032
11145
|
repositories
|
|
@@ -12004,7 +12117,7 @@ var exports_flow = {};
|
|
|
12004
12117
|
__export(exports_flow, {
|
|
12005
12118
|
startOAuthFlow: () => startOAuthFlow
|
|
12006
12119
|
});
|
|
12007
|
-
async function startOAuthFlow(signal, path3 = "/cli/auth", params = {}) {
|
|
12120
|
+
async function startOAuthFlow(signal, path3 = "/cli/auth", params = {}, onAuthURL) {
|
|
12008
12121
|
const { server, tokenPromise } = await startCallbackServer();
|
|
12009
12122
|
let timeoutId;
|
|
12010
12123
|
try {
|
|
@@ -12018,6 +12131,7 @@ async function startOAuthFlow(signal, path3 = "/cli/auth", params = {}) {
|
|
|
12018
12131
|
await open2.default(authURL);
|
|
12019
12132
|
browserOpened = true;
|
|
12020
12133
|
logger.info("auth.flow", "Browser open command executed");
|
|
12134
|
+
onAuthURL?.(authURL);
|
|
12021
12135
|
} catch (openErr) {
|
|
12022
12136
|
logger.warn("auth.flow", `Could not open browser automatically: ${openErr instanceof Error ? openErr.message : String(openErr)}`);
|
|
12023
12137
|
}
|
|
@@ -12068,8 +12182,8 @@ __export(exports_flow2, {
|
|
|
12068
12182
|
isStdioOnly: () => isStdioOnly
|
|
12069
12183
|
});
|
|
12070
12184
|
import { randomUUID } from "node:crypto";
|
|
12071
|
-
import { existsSync as
|
|
12072
|
-
import { join as
|
|
12185
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
12186
|
+
import { join as join26 } from "node:path";
|
|
12073
12187
|
async function runSetup(opts = {}) {
|
|
12074
12188
|
const onboardingRunID = randomUUID();
|
|
12075
12189
|
logger.info("setup", `Setup flow started${opts.deploymentID ? ` deployment=${opts.deploymentID}` : ""}${opts.mode ? ` mode=${opts.mode}` : ""}`);
|
|
@@ -12237,12 +12351,16 @@ async function runSetup(opts = {}) {
|
|
|
12237
12351
|
log.warn("Could not mark onboarding complete on the server — you can retry later by running `dosu setup` again.");
|
|
12238
12352
|
}
|
|
12239
12353
|
}
|
|
12354
|
+
let handoffToAudit = false;
|
|
12240
12355
|
if (mcpConfiguredThisRun) {
|
|
12241
12356
|
showTryItOutPrompt({
|
|
12242
12357
|
mode: cfg.mode,
|
|
12243
12358
|
docsImported: choices.connectGitHub && githubOnboardingDone,
|
|
12244
|
-
hasAgentsMd:
|
|
12359
|
+
hasAgentsMd: existsSync16(join26(process.cwd(), "AGENTS.md"))
|
|
12245
12360
|
});
|
|
12361
|
+
if (cfg.mode !== MODE_OSS) {
|
|
12362
|
+
handoffToAudit = await offerAuditHandoff();
|
|
12363
|
+
}
|
|
12246
12364
|
}
|
|
12247
12365
|
if (mcpCompleted || skillCompleted || docsImported) {
|
|
12248
12366
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_completed", {
|
|
@@ -12256,6 +12374,9 @@ async function runSetup(opts = {}) {
|
|
|
12256
12374
|
} else {
|
|
12257
12375
|
outro("\uD83C\uDF89 Setup complete!");
|
|
12258
12376
|
}
|
|
12377
|
+
if (handoffToAudit) {
|
|
12378
|
+
launchAuditAgent();
|
|
12379
|
+
}
|
|
12259
12380
|
}
|
|
12260
12381
|
function applyDeployment(cfg, d) {
|
|
12261
12382
|
cfg.deployment_id = d.deployment_id;
|
|
@@ -12382,8 +12503,10 @@ async function openBrowserForSetup(cfg, onboardingRunID) {
|
|
|
12382
12503
|
try {
|
|
12383
12504
|
const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
|
|
12384
12505
|
const s = spinner();
|
|
12385
|
-
|
|
12386
|
-
|
|
12506
|
+
const result = await startOAuthFlow2(undefined, "/cli/auth", onboardingRunID ? { onboarding_run_id: onboardingRunID } : {}, (url) => {
|
|
12507
|
+
log.message(browserFallbackHint(url));
|
|
12508
|
+
s.start("Waiting for authentication...");
|
|
12509
|
+
});
|
|
12387
12510
|
if (!result.browserOpened) {
|
|
12388
12511
|
s.stop("Could not open a browser");
|
|
12389
12512
|
log.error("Run 'dosu login --no-browser' from the terminal to authenticate over SSH.");
|
|
@@ -12728,13 +12851,6 @@ function showTryItOutPrompt(opts = {}) {
|
|
|
12728
12851
|
log.message(`Try it out! Paste this into your agent:
|
|
12729
12852
|
|
|
12730
12853
|
${info(prompt)}`);
|
|
12731
|
-
if (opts.mode !== MODE_OSS) {
|
|
12732
|
-
log.message(`See what docs Dosu can generate for this repo:
|
|
12733
|
-
|
|
12734
|
-
${info("Ask Dosu to audit this repo and show what docs it can generate.")}
|
|
12735
|
-
|
|
12736
|
-
Or run ${info("dosu audit")} after your agent writes the audit.`);
|
|
12737
|
-
}
|
|
12738
12854
|
}
|
|
12739
12855
|
var init_flow2 = __esm(() => {
|
|
12740
12856
|
init_dist8();
|
|
@@ -12744,12 +12860,13 @@ var init_flow2 = __esm(() => {
|
|
|
12744
12860
|
init_logger();
|
|
12745
12861
|
init_providers();
|
|
12746
12862
|
init_analytics();
|
|
12863
|
+
init_audit_handoff();
|
|
12747
12864
|
init_styles();
|
|
12748
12865
|
});
|
|
12749
12866
|
|
|
12750
12867
|
// src/commands/insights.ts
|
|
12751
|
-
import { existsSync as
|
|
12752
|
-
import { dirname as
|
|
12868
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync8, readdirSync, unlinkSync, writeFileSync as writeFileSync7 } from "node:fs";
|
|
12869
|
+
import { dirname as dirname5, join as join27 } from "node:path";
|
|
12753
12870
|
function shuffled(arr) {
|
|
12754
12871
|
const copy2 = [...arr];
|
|
12755
12872
|
for (let i2 = copy2.length - 1;i2 > 0; i2--) {
|
|
@@ -12853,17 +12970,17 @@ function makeAskFn(cfg) {
|
|
|
12853
12970
|
};
|
|
12854
12971
|
}
|
|
12855
12972
|
function insightsDir() {
|
|
12856
|
-
return
|
|
12973
|
+
return join27(getConfigDir(), "insights");
|
|
12857
12974
|
}
|
|
12858
12975
|
function reportPath(timestamp) {
|
|
12859
12976
|
const dir = insightsDir();
|
|
12860
12977
|
if (!timestamp)
|
|
12861
|
-
return
|
|
12978
|
+
return join27(dir, "latest.html");
|
|
12862
12979
|
const iso = timestamp.toISOString().slice(0, 19).replace(/:/g, "-");
|
|
12863
|
-
return
|
|
12980
|
+
return join27(dir, `report-${iso}Z.html`);
|
|
12864
12981
|
}
|
|
12865
12982
|
function pruneOldReports(dir, keepN) {
|
|
12866
|
-
if (!
|
|
12983
|
+
if (!existsSync17(dir))
|
|
12867
12984
|
return;
|
|
12868
12985
|
let entries;
|
|
12869
12986
|
try {
|
|
@@ -12875,7 +12992,7 @@ function pruneOldReports(dir, keepN) {
|
|
|
12875
12992
|
const reports = entries.filter((f2) => REPORT_FILE_PATTERN.test(f2)).sort().reverse();
|
|
12876
12993
|
for (const f2 of reports.slice(keepN)) {
|
|
12877
12994
|
try {
|
|
12878
|
-
unlinkSync(
|
|
12995
|
+
unlinkSync(join27(dir, f2));
|
|
12879
12996
|
} catch (err) {
|
|
12880
12997
|
logger.debug("insights", `failed to prune ${f2}: ${err instanceof Error ? err.message : err}`);
|
|
12881
12998
|
}
|
|
@@ -12947,10 +13064,10 @@ function defaultRunner(cfg) {
|
|
|
12947
13064
|
build: buildInsights,
|
|
12948
13065
|
render: renderHTML,
|
|
12949
13066
|
writeFile: (path3, content) => {
|
|
12950
|
-
const dir =
|
|
12951
|
-
if (!
|
|
12952
|
-
|
|
12953
|
-
|
|
13067
|
+
const dir = dirname5(path3);
|
|
13068
|
+
if (!existsSync17(dir))
|
|
13069
|
+
mkdirSync8(dir, { recursive: true, mode: 448 });
|
|
13070
|
+
writeFileSync7(path3, content, { mode: 384 });
|
|
12954
13071
|
},
|
|
12955
13072
|
prune: pruneOldReports,
|
|
12956
13073
|
openInBrowser: async (path3) => {
|
|
@@ -13094,8 +13211,10 @@ async function handleAuthenticate(cfg) {
|
|
|
13094
13211
|
try {
|
|
13095
13212
|
const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
|
|
13096
13213
|
const s = spinner();
|
|
13097
|
-
|
|
13098
|
-
|
|
13214
|
+
const result = await startOAuthFlow2(undefined, "/cli/auth", {}, (url) => {
|
|
13215
|
+
log.message(browserFallbackHint(url));
|
|
13216
|
+
s.start("Waiting for authentication...");
|
|
13217
|
+
});
|
|
13099
13218
|
if (!result.browserOpened) {
|
|
13100
13219
|
s.stop("Could not open a browser");
|
|
13101
13220
|
log.error("Run 'dosu login --no-browser' from the terminal to authenticate over SSH.");
|
|
@@ -13147,6 +13266,7 @@ var init_tui = __esm(() => {
|
|
|
13147
13266
|
init_insights3();
|
|
13148
13267
|
init_config();
|
|
13149
13268
|
init_flow2();
|
|
13269
|
+
init_styles();
|
|
13150
13270
|
import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
13151
13271
|
});
|
|
13152
13272
|
|
|
@@ -13889,8 +14009,8 @@ init_trpc();
|
|
|
13889
14009
|
init_logger();
|
|
13890
14010
|
init_github_step();
|
|
13891
14011
|
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
13892
|
-
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
13893
|
-
import { join as join4 } from "node:path";
|
|
14012
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, rmSync, writeFileSync as writeFileSync4 } from "node:fs";
|
|
14013
|
+
import { dirname, join as join4 } from "node:path";
|
|
13894
14014
|
|
|
13895
14015
|
// src/version/pending-tasks-check.ts
|
|
13896
14016
|
init_config();
|
|
@@ -14174,6 +14294,33 @@ function loadFindings(findingsPath) {
|
|
|
14174
14294
|
}
|
|
14175
14295
|
return parsed;
|
|
14176
14296
|
}
|
|
14297
|
+
function cleanupFindings(findingsPath, cwd = process.cwd()) {
|
|
14298
|
+
const gitignorePath = join4(cwd, ".gitignore");
|
|
14299
|
+
try {
|
|
14300
|
+
const content = existsSync4(gitignorePath) ? readFileSync4(gitignorePath, "utf-8") : "";
|
|
14301
|
+
const hasEntry = content.split(/\r?\n/).some((line) => /^\.dosu\/?$/.test(line.trim()));
|
|
14302
|
+
if (!hasEntry) {
|
|
14303
|
+
const sep = content === "" || content.endsWith(`
|
|
14304
|
+
`) ? "" : `
|
|
14305
|
+
`;
|
|
14306
|
+
writeFileSync4(gitignorePath, `${content}${sep}.dosu/
|
|
14307
|
+
`);
|
|
14308
|
+
}
|
|
14309
|
+
} catch (err) {
|
|
14310
|
+
logger.warn("audit", `could not update .gitignore: ${errText(err)}`);
|
|
14311
|
+
}
|
|
14312
|
+
const defaultDir = join4(cwd, ".dosu");
|
|
14313
|
+
if (dirname(findingsPath) !== defaultDir)
|
|
14314
|
+
return;
|
|
14315
|
+
try {
|
|
14316
|
+
rmSync(defaultDir, { recursive: true, force: true });
|
|
14317
|
+
} catch (err) {
|
|
14318
|
+
logger.warn("audit", `could not remove ${defaultDir}: ${errText(err)}`);
|
|
14319
|
+
}
|
|
14320
|
+
}
|
|
14321
|
+
function errText(err) {
|
|
14322
|
+
return err instanceof Error ? err.message : String(err);
|
|
14323
|
+
}
|
|
14177
14324
|
function intersectActionable(items, capabilities) {
|
|
14178
14325
|
const known = new Set(capabilities.map((c3) => c3.id));
|
|
14179
14326
|
return items.filter((item) => known.has(item.task));
|
|
@@ -14182,9 +14329,21 @@ function isPreselected(item) {
|
|
|
14182
14329
|
return item.can_help && item.action !== "skip";
|
|
14183
14330
|
}
|
|
14184
14331
|
function auditCommand() {
|
|
14185
|
-
const cmd = new Command("audit").description("Generate docs from a coding-agent audit (.dosu/audit.json)").option("--data-source-id <id>", "Skip auto-match and use this data source ID").option("--findings <path>", "Path to the audit findings JSON").option("--tasks <ids>", "Comma-separated task ids to generate (non-interactive; for agent-driven use)").option("--yes", "Skip the prompt and select all suggested items").option("--json", "Output as JSON").action(async (opts) => {
|
|
14332
|
+
const cmd = new Command("audit").description("Generate docs from a coding-agent audit (.dosu/audit.json)").option("--data-source-id <id>", "Skip auto-match and use this data source ID").option("--findings <path>", "Path to the audit findings JSON").option("--tasks <ids>", "Comma-separated task ids to generate (non-interactive; for agent-driven use)").option("--list-tasks", "List the doc-generation capabilities (valid task ids) and exit").option("--yes", "Skip the prompt and select all suggested items").option("--json", "Output as JSON").action(async (opts) => {
|
|
14186
14333
|
const cfg = requireConfig3();
|
|
14187
14334
|
const apiKey = requireAPIKey(cfg);
|
|
14335
|
+
if (opts.listTasks) {
|
|
14336
|
+
const resp = await backendGet("/v1/cli/tasks", apiKey);
|
|
14337
|
+
const tasks = resp.tasks ?? [];
|
|
14338
|
+
if (opts.json) {
|
|
14339
|
+
printResult({ tasks }, opts);
|
|
14340
|
+
return;
|
|
14341
|
+
}
|
|
14342
|
+
for (const t2 of tasks) {
|
|
14343
|
+
console.log(`${t2.id} ${import_picocolors9.default.dim(`(${t2.doc_type})`)} ${t2.label} — ${t2.description}`);
|
|
14344
|
+
}
|
|
14345
|
+
return;
|
|
14346
|
+
}
|
|
14188
14347
|
const detected = detectGitRepo();
|
|
14189
14348
|
if (!detected) {
|
|
14190
14349
|
console.error(import_picocolors9.default.red("Not a GitHub repo. Run 'dosu audit' from a GitHub repository."));
|
|
@@ -14265,6 +14424,9 @@ function auditCommand() {
|
|
|
14265
14424
|
repo: detected.slug
|
|
14266
14425
|
});
|
|
14267
14426
|
}
|
|
14427
|
+
if (taskIds.length > 0) {
|
|
14428
|
+
cleanupFindings(findingsPath);
|
|
14429
|
+
}
|
|
14268
14430
|
if (opts.json) {
|
|
14269
14431
|
printResult({ task_ids: taskIds }, opts);
|
|
14270
14432
|
return;
|
|
@@ -14761,13 +14923,13 @@ init_commander();
|
|
|
14761
14923
|
init_config();
|
|
14762
14924
|
init_logger();
|
|
14763
14925
|
init_prompts();
|
|
14764
|
-
import { readFileSync as readFileSync11 } from "node:fs";
|
|
14926
|
+
import { existsSync as existsSync11, readFileSync as readFileSync11 } from "node:fs";
|
|
14765
14927
|
import { basename } from "node:path";
|
|
14766
14928
|
|
|
14767
14929
|
// src/hooks/state.ts
|
|
14768
14930
|
init_config();
|
|
14769
|
-
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync6, rmSync, writeFileSync as
|
|
14770
|
-
import { dirname, join as join5 } from "node:path";
|
|
14931
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync6, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
14932
|
+
import { dirname as dirname2, join as join5 } from "node:path";
|
|
14771
14933
|
function getStateDir() {
|
|
14772
14934
|
return process.env.DOSU_HOOK_STATE_DIR ?? join5(getConfigDir(), "hooks");
|
|
14773
14935
|
}
|
|
@@ -14787,11 +14949,11 @@ function loadState(sessionId) {
|
|
|
14787
14949
|
function saveState(state) {
|
|
14788
14950
|
try {
|
|
14789
14951
|
const file = stateFile(state.sessionId);
|
|
14790
|
-
const dir =
|
|
14952
|
+
const dir = dirname2(file);
|
|
14791
14953
|
if (!existsSync5(dir)) {
|
|
14792
14954
|
mkdirSync4(dir, { recursive: true, mode: 448 });
|
|
14793
14955
|
}
|
|
14794
|
-
|
|
14956
|
+
writeFileSync5(file, JSON.stringify(state, null, 2), { mode: 384 });
|
|
14795
14957
|
} catch {}
|
|
14796
14958
|
}
|
|
14797
14959
|
|
|
@@ -15230,6 +15392,21 @@ async function collectDoctorChecks(opts) {
|
|
|
15230
15392
|
});
|
|
15231
15393
|
}
|
|
15232
15394
|
}
|
|
15395
|
+
if (hasSubmit && hasPostTool || alternativeInstalled) {
|
|
15396
|
+
const { dosuOnPath: dosuOnPath2, materializedRuntimePath: materializedRuntimePath2 } = await Promise.resolve().then(() => (init_runtime(), exports_runtime));
|
|
15397
|
+
const materialized = materializedRuntimePath2();
|
|
15398
|
+
if (dosuOnPath2()) {
|
|
15399
|
+
checks.push({ name: "runtime", status: "ok", detail: "dosu on PATH" });
|
|
15400
|
+
} else if (existsSync11(materialized)) {
|
|
15401
|
+
checks.push({ name: "runtime", status: "ok", detail: `materialized: ${materialized}` });
|
|
15402
|
+
} else {
|
|
15403
|
+
checks.push({
|
|
15404
|
+
name: "runtime",
|
|
15405
|
+
status: "fail",
|
|
15406
|
+
detail: "dosu is not on PATH and no materialized runtime exists — re-run 'npx -y @dosu/cli hooks install <agent>'"
|
|
15407
|
+
});
|
|
15408
|
+
}
|
|
15409
|
+
}
|
|
15233
15410
|
const cfg = loadConfig();
|
|
15234
15411
|
if (isAuthenticated(cfg)) {
|
|
15235
15412
|
checks.push({ name: "auth", status: "ok", detail: "logged in" });
|
|
@@ -16173,7 +16350,7 @@ function suggestCommand() {
|
|
|
16173
16350
|
return cmd;
|
|
16174
16351
|
}
|
|
16175
16352
|
|
|
16176
|
-
// src/commands/
|
|
16353
|
+
// src/commands/threads.ts
|
|
16177
16354
|
init_commander();
|
|
16178
16355
|
init_trpc();
|
|
16179
16356
|
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
@@ -16185,92 +16362,10 @@ function requireConfig13() {
|
|
|
16185
16362
|
}
|
|
16186
16363
|
return cfg;
|
|
16187
16364
|
}
|
|
16188
|
-
async function getKnowledgeStoreId4(client, spaceId) {
|
|
16189
|
-
const store = await client.knowledgeStore.getBySpaceId.query({
|
|
16190
|
-
space_id: spaceId
|
|
16191
|
-
});
|
|
16192
|
-
if (!store) {
|
|
16193
|
-
console.error(import_picocolors23.default.red("No knowledge store found for this deployment."));
|
|
16194
|
-
process.exit(1);
|
|
16195
|
-
}
|
|
16196
|
-
return store.id;
|
|
16197
|
-
}
|
|
16198
|
-
function tagsCommand() {
|
|
16199
|
-
const cmd = new Command("tags").description("Manage knowledge base tags");
|
|
16200
|
-
cmd.command("list").description("List all tags").option("--json", "Output as JSON").action(async (opts) => {
|
|
16201
|
-
const cfg = requireConfig13();
|
|
16202
|
-
const client = createTypedClient(cfg);
|
|
16203
|
-
const ksId = await getKnowledgeStoreId4(client, cfg.space_id);
|
|
16204
|
-
const tags = await client.topic.listTopicsByKnowledgeStore.query({
|
|
16205
|
-
knowledge_store_id: ksId
|
|
16206
|
-
});
|
|
16207
|
-
if (opts.json) {
|
|
16208
|
-
printResult(tags, opts);
|
|
16209
|
-
return;
|
|
16210
|
-
}
|
|
16211
|
-
if (!tags || tags.length === 0) {
|
|
16212
|
-
console.log(import_picocolors23.default.dim("No tags found."));
|
|
16213
|
-
return;
|
|
16214
|
-
}
|
|
16215
|
-
printTable(["ID", "Name", "Description"], tags.map((t2) => [
|
|
16216
|
-
t2.topic_id.slice(0, 8),
|
|
16217
|
-
t2.name,
|
|
16218
|
-
t2.description ?? "—"
|
|
16219
|
-
]), { rawData: tags });
|
|
16220
|
-
});
|
|
16221
|
-
cmd.command("remove").description("Remove a tag from a page").argument("<tag-id>", "Tag ID").argument("<page-id>", "Page ID").option("--json", "Output as JSON").action(async (tagId, pageId, opts) => {
|
|
16222
|
-
const cfg = requireConfig13();
|
|
16223
|
-
const client = createTypedClient(cfg);
|
|
16224
|
-
await client.topic.removeFromPage.mutate({ topic_id: tagId, page_id: pageId });
|
|
16225
|
-
if (opts.json) {
|
|
16226
|
-
printResult({ success: true, tag_id: tagId, page_id: pageId }, opts);
|
|
16227
|
-
return;
|
|
16228
|
-
}
|
|
16229
|
-
console.log(import_picocolors23.default.green("Tag removed from page."));
|
|
16230
|
-
});
|
|
16231
|
-
cmd.command("pages").description("List pages with a specific tag").argument("<tag-id>", "Tag ID").option("--search <query>", "Search within tagged pages").option("--limit <n>", "Maximum results", "10").option("--json", "Output as JSON").action(async (tagId, opts) => {
|
|
16232
|
-
const cfg = requireConfig13();
|
|
16233
|
-
const client = createTypedClient(cfg);
|
|
16234
|
-
const ksId = await getKnowledgeStoreId4(client, cfg.space_id);
|
|
16235
|
-
const result = await client.topic.getPagesByTopicId.query({
|
|
16236
|
-
knowledge_store_id: ksId,
|
|
16237
|
-
topic_id: tagId,
|
|
16238
|
-
searchTerm: opts.search,
|
|
16239
|
-
limit: Number.parseInt(opts.limit ?? "10", 10)
|
|
16240
|
-
});
|
|
16241
|
-
const pages = result.data;
|
|
16242
|
-
if (opts.json) {
|
|
16243
|
-
printResult(pages, opts);
|
|
16244
|
-
return;
|
|
16245
|
-
}
|
|
16246
|
-
if (!pages || pages.length === 0) {
|
|
16247
|
-
console.log(import_picocolors23.default.dim("No pages found with this tag."));
|
|
16248
|
-
return;
|
|
16249
|
-
}
|
|
16250
|
-
printTable(["ID", "Title"], pages.map((p2) => [
|
|
16251
|
-
p2.id.slice(0, 8),
|
|
16252
|
-
p2.title ?? "(untitled)"
|
|
16253
|
-
]), { rawData: pages });
|
|
16254
|
-
});
|
|
16255
|
-
return cmd;
|
|
16256
|
-
}
|
|
16257
|
-
|
|
16258
|
-
// src/commands/threads.ts
|
|
16259
|
-
init_commander();
|
|
16260
|
-
init_trpc();
|
|
16261
|
-
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
16262
|
-
function requireConfig14() {
|
|
16263
|
-
const cfg = requireLoginConfig();
|
|
16264
|
-
if (!cfg.space_id) {
|
|
16265
|
-
console.error(import_picocolors24.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
|
|
16266
|
-
process.exit(1);
|
|
16267
|
-
}
|
|
16268
|
-
return cfg;
|
|
16269
|
-
}
|
|
16270
16365
|
function threadsCommand() {
|
|
16271
16366
|
const cmd = new Command("threads").description("List and manage conversation threads");
|
|
16272
16367
|
cmd.command("list").description("List threads").option("--status <status>", "Filter by status: pending, resolved, archived").option("--search <query>", "Search threads").option("--limit <n>", "Maximum results (default: 20)", "20").option("--json", "Output as JSON").action(async (opts) => {
|
|
16273
|
-
const cfg =
|
|
16368
|
+
const cfg = requireConfig13();
|
|
16274
16369
|
const client = createTypedClient(cfg);
|
|
16275
16370
|
const input = {
|
|
16276
16371
|
__testing_scope__: undefined,
|
|
@@ -16309,7 +16404,7 @@ function threadsCommand() {
|
|
|
16309
16404
|
return;
|
|
16310
16405
|
}
|
|
16311
16406
|
if (!threads || threads.length === 0) {
|
|
16312
|
-
console.log(
|
|
16407
|
+
console.log(import_picocolors23.default.dim("No threads found."));
|
|
16313
16408
|
return;
|
|
16314
16409
|
}
|
|
16315
16410
|
printTable(["ID", "Title", "Status", "Created"], threads.map((t2) => [
|
|
@@ -16320,7 +16415,7 @@ function threadsCommand() {
|
|
|
16320
16415
|
]), { rawData: threads });
|
|
16321
16416
|
});
|
|
16322
16417
|
cmd.command("get").description("View a thread and its messages").argument("<id>", "Thread ID").option("--limit <n>", "Number of messages to show (default: 20)", "20").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
16323
|
-
const cfg =
|
|
16418
|
+
const cfg = requireConfig13();
|
|
16324
16419
|
const client = createTypedClient(cfg);
|
|
16325
16420
|
const [thread, messagesData] = await Promise.all([
|
|
16326
16421
|
client.thread.get.query(id),
|
|
@@ -16334,10 +16429,10 @@ function threadsCommand() {
|
|
|
16334
16429
|
return;
|
|
16335
16430
|
}
|
|
16336
16431
|
if (!thread) {
|
|
16337
|
-
console.log(
|
|
16432
|
+
console.log(import_picocolors23.default.dim("Thread not found."));
|
|
16338
16433
|
return;
|
|
16339
16434
|
}
|
|
16340
|
-
console.log(
|
|
16435
|
+
console.log(import_picocolors23.default.bold(thread.generated_title ?? "(untitled thread)"));
|
|
16341
16436
|
printInfo([
|
|
16342
16437
|
["ID", thread.id],
|
|
16343
16438
|
["Created", formatDate(thread.created_at)],
|
|
@@ -16348,13 +16443,13 @@ function threadsCommand() {
|
|
|
16348
16443
|
if (messages && messages.length > 0) {
|
|
16349
16444
|
const allMessages = messages.flatMap((group) => group.messages);
|
|
16350
16445
|
console.log(`
|
|
16351
|
-
${
|
|
16352
|
-
console.log(
|
|
16446
|
+
${import_picocolors23.default.bold("Messages")} (${allMessages.length})`);
|
|
16447
|
+
console.log(import_picocolors23.default.dim("─".repeat(60)));
|
|
16353
16448
|
for (const msg of allMessages) {
|
|
16354
16449
|
const role = msg.author_role ?? "unknown";
|
|
16355
16450
|
const date = formatDate(msg.created_at);
|
|
16356
16451
|
console.log(`
|
|
16357
|
-
${
|
|
16452
|
+
${import_picocolors23.default.bold(role)} ${import_picocolors23.default.dim(date)}`);
|
|
16358
16453
|
if (msg.body) {
|
|
16359
16454
|
console.log(truncate(msg.body, 500));
|
|
16360
16455
|
}
|
|
@@ -16362,14 +16457,86 @@ ${import_picocolors24.default.bold(role)} ${import_picocolors24.default.dim(date
|
|
|
16362
16457
|
}
|
|
16363
16458
|
});
|
|
16364
16459
|
cmd.command("archive").description("Archive a thread").argument("<id>", "Thread ID").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
16365
|
-
const cfg =
|
|
16460
|
+
const cfg = requireConfig13();
|
|
16366
16461
|
const client = createTypedClient(cfg);
|
|
16367
16462
|
await client.thread.archive.mutate({ threadId: id, archived: true });
|
|
16368
16463
|
if (opts.json) {
|
|
16369
16464
|
printResult({ success: true, id }, opts);
|
|
16370
16465
|
return;
|
|
16371
16466
|
}
|
|
16372
|
-
console.log(
|
|
16467
|
+
console.log(import_picocolors23.default.green(`Thread ${id.slice(0, 8)} archived.`));
|
|
16468
|
+
});
|
|
16469
|
+
return cmd;
|
|
16470
|
+
}
|
|
16471
|
+
|
|
16472
|
+
// src/commands/topics.ts
|
|
16473
|
+
init_commander();
|
|
16474
|
+
init_trpc();
|
|
16475
|
+
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
16476
|
+
function requireConfig14() {
|
|
16477
|
+
const cfg = requireLoginConfig();
|
|
16478
|
+
if (!cfg.space_id) {
|
|
16479
|
+
console.error(import_picocolors24.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
|
|
16480
|
+
process.exit(1);
|
|
16481
|
+
}
|
|
16482
|
+
return cfg;
|
|
16483
|
+
}
|
|
16484
|
+
async function getKnowledgeStoreId4(client, spaceId) {
|
|
16485
|
+
const store = await client.knowledgeStore.getBySpaceId.query({
|
|
16486
|
+
space_id: spaceId
|
|
16487
|
+
});
|
|
16488
|
+
if (!store) {
|
|
16489
|
+
console.error(import_picocolors24.default.red("No knowledge store found for this deployment."));
|
|
16490
|
+
process.exit(1);
|
|
16491
|
+
}
|
|
16492
|
+
return store.id;
|
|
16493
|
+
}
|
|
16494
|
+
function topicsCommand() {
|
|
16495
|
+
const cmd = new Command("topics").alias("tags").description("Browse Topics in your knowledge base");
|
|
16496
|
+
cmd.command("list").description("List all topics").option("--json", "Output as JSON").action(async (opts) => {
|
|
16497
|
+
const cfg = requireConfig14();
|
|
16498
|
+
const client = createTypedClient(cfg);
|
|
16499
|
+
const ksId = await getKnowledgeStoreId4(client, cfg.space_id);
|
|
16500
|
+
const topics = await client.topic.listTopicsByKnowledgeStore.query({
|
|
16501
|
+
knowledge_store_id: ksId
|
|
16502
|
+
});
|
|
16503
|
+
if (opts.json) {
|
|
16504
|
+
printResult(topics, opts);
|
|
16505
|
+
return;
|
|
16506
|
+
}
|
|
16507
|
+
if (!topics || topics.length === 0) {
|
|
16508
|
+
console.log(import_picocolors24.default.dim("No topics found."));
|
|
16509
|
+
return;
|
|
16510
|
+
}
|
|
16511
|
+
printTable(["ID", "Name", "Description"], topics.map((t2) => [
|
|
16512
|
+
t2.topic_id.slice(0, 8),
|
|
16513
|
+
t2.name,
|
|
16514
|
+
t2.description ?? "—"
|
|
16515
|
+
]), { rawData: topics });
|
|
16516
|
+
});
|
|
16517
|
+
cmd.command("pages").description("List pages with a specific topic").argument("<topic-id>", "Topic ID").option("--search <query>", "Search within the topic's pages").option("--limit <n>", "Maximum results", "10").option("--json", "Output as JSON").action(async (topicId, opts) => {
|
|
16518
|
+
const cfg = requireConfig14();
|
|
16519
|
+
const client = createTypedClient(cfg);
|
|
16520
|
+
const ksId = await getKnowledgeStoreId4(client, cfg.space_id);
|
|
16521
|
+
const result = await client.topic.getPagesByTopicId.query({
|
|
16522
|
+
knowledge_store_id: ksId,
|
|
16523
|
+
topic_id: topicId,
|
|
16524
|
+
searchTerm: opts.search,
|
|
16525
|
+
limit: Number.parseInt(opts.limit ?? "10", 10)
|
|
16526
|
+
});
|
|
16527
|
+
const pages = result.data;
|
|
16528
|
+
if (opts.json) {
|
|
16529
|
+
printResult(pages, opts);
|
|
16530
|
+
return;
|
|
16531
|
+
}
|
|
16532
|
+
if (!pages || pages.length === 0) {
|
|
16533
|
+
console.log(import_picocolors24.default.dim("No pages found with this topic."));
|
|
16534
|
+
return;
|
|
16535
|
+
}
|
|
16536
|
+
printTable(["ID", "Title"], pages.map((p2) => [
|
|
16537
|
+
p2.id.slice(0, 8),
|
|
16538
|
+
p2.title ?? "(untitled)"
|
|
16539
|
+
]), { rawData: pages });
|
|
16373
16540
|
});
|
|
16374
16541
|
return cmd;
|
|
16375
16542
|
}
|
|
@@ -16378,14 +16545,15 @@ ${import_picocolors24.default.bold(role)} ${import_picocolors24.default.dim(date
|
|
|
16378
16545
|
init_config();
|
|
16379
16546
|
init_logger();
|
|
16380
16547
|
init_providers();
|
|
16548
|
+
init_styles();
|
|
16381
16549
|
init_skill_update_check();
|
|
16382
16550
|
|
|
16383
16551
|
// src/version/update-check.ts
|
|
16384
16552
|
init_config();
|
|
16385
16553
|
init_logger();
|
|
16386
16554
|
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
16387
|
-
import { existsSync as
|
|
16388
|
-
import { join as
|
|
16555
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "node:fs";
|
|
16556
|
+
import { join as join28 } from "node:path";
|
|
16389
16557
|
var CACHE_FILENAME3 = "update-check.json";
|
|
16390
16558
|
var CHECK_INTERVAL_MS3 = 24 * 60 * 60 * 1000;
|
|
16391
16559
|
var FETCH_TIMEOUT_MS3 = 5000;
|
|
@@ -16408,12 +16576,12 @@ function isNewerVersion(latest, current) {
|
|
|
16408
16576
|
return false;
|
|
16409
16577
|
}
|
|
16410
16578
|
function getCachePath3() {
|
|
16411
|
-
return
|
|
16579
|
+
return join28(getConfigDir(), CACHE_FILENAME3);
|
|
16412
16580
|
}
|
|
16413
16581
|
function readCache() {
|
|
16414
16582
|
try {
|
|
16415
16583
|
const path3 = getCachePath3();
|
|
16416
|
-
if (!
|
|
16584
|
+
if (!existsSync18(path3))
|
|
16417
16585
|
return null;
|
|
16418
16586
|
const data = JSON.parse(readFileSync15(path3, "utf-8"));
|
|
16419
16587
|
if (typeof data.lastCheck === "number" && typeof data.latestVersion === "string") {
|
|
@@ -16427,10 +16595,10 @@ function readCache() {
|
|
|
16427
16595
|
function writeCache(cache) {
|
|
16428
16596
|
try {
|
|
16429
16597
|
const dir = getConfigDir();
|
|
16430
|
-
if (!
|
|
16431
|
-
|
|
16598
|
+
if (!existsSync18(dir)) {
|
|
16599
|
+
mkdirSync9(dir, { recursive: true, mode: 448 });
|
|
16432
16600
|
}
|
|
16433
|
-
|
|
16601
|
+
writeFileSync8(getCachePath3(), JSON.stringify(cache), { mode: 384 });
|
|
16434
16602
|
} catch {}
|
|
16435
16603
|
}
|
|
16436
16604
|
async function fetchLatestVersion() {
|
|
@@ -16558,7 +16726,9 @@ function createProgram() {
|
|
|
16558
16726
|
const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
|
|
16559
16727
|
let result;
|
|
16560
16728
|
try {
|
|
16561
|
-
result = await startOAuthFlow2()
|
|
16729
|
+
result = await startOAuthFlow2(undefined, undefined, undefined, (url) => {
|
|
16730
|
+
console.log(browserFallbackHint(url));
|
|
16731
|
+
});
|
|
16562
16732
|
} catch (err) {
|
|
16563
16733
|
if (err instanceof OAuthCallbackError2) {
|
|
16564
16734
|
console.error(err.userMessage);
|
|
@@ -16701,7 +16871,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
|
|
|
16701
16871
|
program2.addCommand(reviewCommand());
|
|
16702
16872
|
program2.addCommand(sourcesCommand());
|
|
16703
16873
|
program2.addCommand(suggestCommand());
|
|
16704
|
-
program2.addCommand(
|
|
16874
|
+
program2.addCommand(topicsCommand());
|
|
16705
16875
|
program2.addCommand(threadsCommand());
|
|
16706
16876
|
program2.addCommand(skillCommand());
|
|
16707
16877
|
program2.command("setup").description("Set up Dosu MCP for your AI tools").option("--deployment <id>", "Skip to tool configuration for a specific MCP").option("--mode <mode>", "Force OSS or Cloud mode, skipping the interactive prompt (oss|cloud)").option("--agent", "Run non-interactive setup designed for coding agents (requires --tool)").option("--tool <id>", "Configure a single AI tool by id (claude, cursor, codex, …). Required with --agent.").option("--login-ticket <ticket>", "Resume an --agent setup by redeeming a ticket from a previous run").action(async (opts) => {
|