@dosu/cli 0.29.0 → 0.30.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 +401 -241
- 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.30.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 = "888669da10bd";
|
|
4715
4715
|
|
|
4716
4716
|
// src/client/trpc.ts
|
|
4717
4717
|
var exports_trpc = {};
|
|
@@ -8328,7 +8328,7 @@ var require_cjs = __commonJS((exports) => {
|
|
|
8328
8328
|
var require_lib = __commonJS((exports, module) => {
|
|
8329
8329
|
var __filename = "/home/runner/work/dosu-cli/dosu-cli/node_modules/write-file-atomic/lib/index.js";
|
|
8330
8330
|
module.exports = writeFile;
|
|
8331
|
-
module.exports.sync =
|
|
8331
|
+
module.exports.sync = writeFileSync6;
|
|
8332
8332
|
module.exports._getTmpname = getTmpname;
|
|
8333
8333
|
module.exports._cleanupOnExit = cleanupOnExit;
|
|
8334
8334
|
var fs7 = __require("fs");
|
|
@@ -8461,7 +8461,7 @@ var require_lib = __commonJS((exports, module) => {
|
|
|
8461
8461
|
}
|
|
8462
8462
|
return promise;
|
|
8463
8463
|
}
|
|
8464
|
-
function
|
|
8464
|
+
function writeFileSync6(filename, data, options) {
|
|
8465
8465
|
if (typeof options === "string") {
|
|
8466
8466
|
options = { encoding: options };
|
|
8467
8467
|
} else if (!options) {
|
|
@@ -8538,7 +8538,7 @@ var require_lib = __commonJS((exports, module) => {
|
|
|
8538
8538
|
|
|
8539
8539
|
// src/mcp/config-helpers.ts
|
|
8540
8540
|
import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync7 } from "node:fs";
|
|
8541
|
-
import { dirname as
|
|
8541
|
+
import { dirname as dirname3 } from "node:path";
|
|
8542
8542
|
function mcpURL(deploymentID) {
|
|
8543
8543
|
return `${getBackendURL()}/v1/mcp/deployments/${deploymentID}`;
|
|
8544
8544
|
}
|
|
@@ -8616,7 +8616,7 @@ function saveJSONConfig(path3, cfg) {
|
|
|
8616
8616
|
writeSecureFile(path3, JSON.stringify(cfg, null, 2));
|
|
8617
8617
|
}
|
|
8618
8618
|
function writeSecureFile(path3, content) {
|
|
8619
|
-
const dir =
|
|
8619
|
+
const dir = dirname3(path3);
|
|
8620
8620
|
if (!existsSync6(dir)) {
|
|
8621
8621
|
mkdirSync5(dir, { recursive: true, mode: 448 });
|
|
8622
8622
|
}
|
|
@@ -8658,6 +8658,57 @@ var init_config_helpers = __esm(() => {
|
|
|
8658
8658
|
writeFileAtomic = import_write_file_atomic.default;
|
|
8659
8659
|
});
|
|
8660
8660
|
|
|
8661
|
+
// src/hooks/runtime.ts
|
|
8662
|
+
var exports_runtime = {};
|
|
8663
|
+
__export(exports_runtime, {
|
|
8664
|
+
resolveHookCommandPrefix: () => resolveHookCommandPrefix,
|
|
8665
|
+
materializedRuntimePath: () => materializedRuntimePath,
|
|
8666
|
+
dosuOnPath: () => dosuOnPath
|
|
8667
|
+
});
|
|
8668
|
+
import { spawnSync } from "node:child_process";
|
|
8669
|
+
import { copyFileSync, existsSync as existsSync7, mkdirSync as mkdirSync6 } from "node:fs";
|
|
8670
|
+
import { dirname as dirname4, join as join6 } from "node:path";
|
|
8671
|
+
function dosuOnPath() {
|
|
8672
|
+
const cmd = process.platform === "win32" ? "where" : "which";
|
|
8673
|
+
try {
|
|
8674
|
+
return spawnSync(cmd, ["dosu"], { stdio: "ignore" }).status === 0;
|
|
8675
|
+
} catch {
|
|
8676
|
+
return false;
|
|
8677
|
+
}
|
|
8678
|
+
}
|
|
8679
|
+
function materializedRuntimePath() {
|
|
8680
|
+
return join6(getConfigDir(), "bin", "dosu.js");
|
|
8681
|
+
}
|
|
8682
|
+
function currentBundlePath() {
|
|
8683
|
+
const entry = process.argv[1];
|
|
8684
|
+
if (!entry || !/\.(c|m)?js$/.test(entry) || !existsSync7(entry))
|
|
8685
|
+
return null;
|
|
8686
|
+
return entry;
|
|
8687
|
+
}
|
|
8688
|
+
function resolveHookCommandPrefix() {
|
|
8689
|
+
if (dosuOnPath())
|
|
8690
|
+
return "dosu";
|
|
8691
|
+
const bundle = currentBundlePath();
|
|
8692
|
+
if (!bundle) {
|
|
8693
|
+
logger.warn("hooks", "dosu not on PATH and no bundle to materialize; using bare 'dosu'");
|
|
8694
|
+
return "dosu";
|
|
8695
|
+
}
|
|
8696
|
+
const target = materializedRuntimePath();
|
|
8697
|
+
try {
|
|
8698
|
+
mkdirSync6(dirname4(target), { recursive: true, mode: 448 });
|
|
8699
|
+
copyFileSync(bundle, target);
|
|
8700
|
+
} catch (err) {
|
|
8701
|
+
logger.warn("hooks", `failed to materialize runtime: ${err instanceof Error ? err.message : String(err)}`);
|
|
8702
|
+
return "dosu";
|
|
8703
|
+
}
|
|
8704
|
+
logger.info("hooks", `materialized hook runtime at ${target}`);
|
|
8705
|
+
return `node "${target}"`;
|
|
8706
|
+
}
|
|
8707
|
+
var init_runtime = __esm(() => {
|
|
8708
|
+
init_config();
|
|
8709
|
+
init_logger();
|
|
8710
|
+
});
|
|
8711
|
+
|
|
8661
8712
|
// src/hooks/claude-code.ts
|
|
8662
8713
|
var exports_claude_code = {};
|
|
8663
8714
|
__export(exports_claude_code, {
|
|
@@ -8669,13 +8720,13 @@ __export(exports_claude_code, {
|
|
|
8669
8720
|
claudeLocalSettingsPath: () => claudeLocalSettingsPath,
|
|
8670
8721
|
DEFAULT_HOOK_EVENTS: () => DEFAULT_HOOK_EVENTS
|
|
8671
8722
|
});
|
|
8672
|
-
import { existsSync as
|
|
8673
|
-
import { join as
|
|
8723
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8 } from "node:fs";
|
|
8724
|
+
import { join as join7 } from "node:path";
|
|
8674
8725
|
function claudeLocalSettingsPath(dir) {
|
|
8675
|
-
return
|
|
8726
|
+
return join7(dir, ".claude", "settings.local.json");
|
|
8676
8727
|
}
|
|
8677
|
-
function hookCommand(subcommand) {
|
|
8678
|
-
return
|
|
8728
|
+
function hookCommand(subcommand, prefix = resolveHookCommandPrefix()) {
|
|
8729
|
+
return `${prefix} hooks ${subcommand}`;
|
|
8679
8730
|
}
|
|
8680
8731
|
function dosuGroup(event) {
|
|
8681
8732
|
const entry = {
|
|
@@ -8690,6 +8741,9 @@ function isDosuHookCommand(command) {
|
|
|
8690
8741
|
return false;
|
|
8691
8742
|
if (/@dosu\/cli/.test(command))
|
|
8692
8743
|
return true;
|
|
8744
|
+
if (/^([^\s]*[/\\])?node(\.exe)?\s+("[^"]*dosu\.(c|m)?js"|[^\s]*dosu\.(c|m)?js)\s/.test(command.trimStart())) {
|
|
8745
|
+
return true;
|
|
8746
|
+
}
|
|
8693
8747
|
return /^([^\s]*\/)?dosu\s/.test(command.trimStart());
|
|
8694
8748
|
}
|
|
8695
8749
|
function isDosuGroup(group) {
|
|
@@ -8701,7 +8755,7 @@ function isDosuGroup(group) {
|
|
|
8701
8755
|
return hooks.some((h2) => !!h2 && typeof h2 === "object" && (h2[MARKER] === true || typeof h2.command === "string" && isDosuHookCommand(h2.command)));
|
|
8702
8756
|
}
|
|
8703
8757
|
function readSettingsOrThrow(path3) {
|
|
8704
|
-
if (!
|
|
8758
|
+
if (!existsSync8(path3))
|
|
8705
8759
|
return {};
|
|
8706
8760
|
const raw = readFileSync8(path3, "utf-8").trim();
|
|
8707
8761
|
if (!raw)
|
|
@@ -8763,7 +8817,7 @@ function removeClaudeHooks(configPath) {
|
|
|
8763
8817
|
return { removed };
|
|
8764
8818
|
}
|
|
8765
8819
|
function inspectClaudeHooks(configPath) {
|
|
8766
|
-
if (!
|
|
8820
|
+
if (!existsSync8(configPath))
|
|
8767
8821
|
return { fileExists: false, parseError: false, events: [] };
|
|
8768
8822
|
let cfg;
|
|
8769
8823
|
try {
|
|
@@ -8778,6 +8832,7 @@ function inspectClaudeHooks(configPath) {
|
|
|
8778
8832
|
var DEFAULT_HOOK_EVENTS, MARKER = "__dosu", EVENT_SUBCOMMAND;
|
|
8779
8833
|
var init_claude_code = __esm(() => {
|
|
8780
8834
|
init_config_helpers();
|
|
8835
|
+
init_runtime();
|
|
8781
8836
|
DEFAULT_HOOK_EVENTS = ["UserPromptSubmit", "PostToolUse", "Stop"];
|
|
8782
8837
|
EVENT_SUBCOMMAND = {
|
|
8783
8838
|
UserPromptSubmit: "user-prompt-submit",
|
|
@@ -8795,13 +8850,13 @@ __export(exports_codex, {
|
|
|
8795
8850
|
codexHooksPath: () => codexHooksPath,
|
|
8796
8851
|
codexHookCommand: () => codexHookCommand
|
|
8797
8852
|
});
|
|
8798
|
-
import { existsSync as
|
|
8799
|
-
import { join as
|
|
8853
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9 } from "node:fs";
|
|
8854
|
+
import { join as join8 } from "node:path";
|
|
8800
8855
|
function codexHooksPath(dir) {
|
|
8801
|
-
return
|
|
8856
|
+
return join8(dir, ".codex", "hooks.json");
|
|
8802
8857
|
}
|
|
8803
|
-
function codexHookCommand(subcommand) {
|
|
8804
|
-
return
|
|
8858
|
+
function codexHookCommand(subcommand, prefix = resolveHookCommandPrefix()) {
|
|
8859
|
+
return `${prefix} hooks ${subcommand} --agent codex`;
|
|
8805
8860
|
}
|
|
8806
8861
|
function dosuGroup2(event) {
|
|
8807
8862
|
return {
|
|
@@ -8816,7 +8871,7 @@ function dosuGroup2(event) {
|
|
|
8816
8871
|
};
|
|
8817
8872
|
}
|
|
8818
8873
|
function readHooksFileOrThrow(path3) {
|
|
8819
|
-
if (!
|
|
8874
|
+
if (!existsSync9(path3))
|
|
8820
8875
|
return {};
|
|
8821
8876
|
const raw = readFileSync9(path3, "utf-8").trim();
|
|
8822
8877
|
if (!raw)
|
|
@@ -8851,7 +8906,7 @@ function installCodexHooks(configPath, opts = {}) {
|
|
|
8851
8906
|
return { events: [...events] };
|
|
8852
8907
|
}
|
|
8853
8908
|
function removeCodexHooks(configPath) {
|
|
8854
|
-
if (!
|
|
8909
|
+
if (!existsSync9(configPath))
|
|
8855
8910
|
return { removed: false };
|
|
8856
8911
|
let config;
|
|
8857
8912
|
try {
|
|
@@ -8880,7 +8935,7 @@ function removeCodexHooks(configPath) {
|
|
|
8880
8935
|
return { removed };
|
|
8881
8936
|
}
|
|
8882
8937
|
function inspectCodexHooks(configPath) {
|
|
8883
|
-
if (!
|
|
8938
|
+
if (!existsSync9(configPath))
|
|
8884
8939
|
return { fileExists: false, events: [] };
|
|
8885
8940
|
let config;
|
|
8886
8941
|
try {
|
|
@@ -8898,6 +8953,7 @@ var EVENT_SUBCOMMAND2, EVENT_TIMEOUT_SEC, EVENT_STATUS_MESSAGE;
|
|
|
8898
8953
|
var init_codex = __esm(() => {
|
|
8899
8954
|
init_config_helpers();
|
|
8900
8955
|
init_claude_code();
|
|
8956
|
+
init_runtime();
|
|
8901
8957
|
EVENT_SUBCOMMAND2 = {
|
|
8902
8958
|
UserPromptSubmit: "user-prompt-submit",
|
|
8903
8959
|
PostToolUse: "post-tool-use",
|
|
@@ -8924,13 +8980,13 @@ __export(exports_factory, {
|
|
|
8924
8980
|
factoryHooksPath: () => factoryHooksPath,
|
|
8925
8981
|
factoryHookCommand: () => factoryHookCommand
|
|
8926
8982
|
});
|
|
8927
|
-
import { existsSync as
|
|
8928
|
-
import { join as
|
|
8983
|
+
import { existsSync as existsSync10, readFileSync as readFileSync10 } from "node:fs";
|
|
8984
|
+
import { join as join9 } from "node:path";
|
|
8929
8985
|
function factoryHooksPath(dir) {
|
|
8930
|
-
return
|
|
8986
|
+
return join9(dir, ".factory", "hooks.json");
|
|
8931
8987
|
}
|
|
8932
|
-
function factoryHookCommand(subcommand) {
|
|
8933
|
-
return
|
|
8988
|
+
function factoryHookCommand(subcommand, prefix = resolveHookCommandPrefix()) {
|
|
8989
|
+
return `${prefix} hooks ${subcommand} --agent factory`;
|
|
8934
8990
|
}
|
|
8935
8991
|
function dosuGroup3(event) {
|
|
8936
8992
|
const group = {
|
|
@@ -8941,7 +8997,7 @@ function dosuGroup3(event) {
|
|
|
8941
8997
|
return group;
|
|
8942
8998
|
}
|
|
8943
8999
|
function readHooksFileOrThrow2(path3) {
|
|
8944
|
-
if (!
|
|
9000
|
+
if (!existsSync10(path3))
|
|
8945
9001
|
return {};
|
|
8946
9002
|
const raw = readFileSync10(path3, "utf-8").trim();
|
|
8947
9003
|
if (!raw)
|
|
@@ -8976,7 +9032,7 @@ function installFactoryHooks(configPath, opts = {}) {
|
|
|
8976
9032
|
return { events: [...events] };
|
|
8977
9033
|
}
|
|
8978
9034
|
function removeFactoryHooks(configPath) {
|
|
8979
|
-
if (!
|
|
9035
|
+
if (!existsSync10(configPath))
|
|
8980
9036
|
return { removed: false };
|
|
8981
9037
|
let config;
|
|
8982
9038
|
try {
|
|
@@ -9005,7 +9061,7 @@ function removeFactoryHooks(configPath) {
|
|
|
9005
9061
|
return { removed };
|
|
9006
9062
|
}
|
|
9007
9063
|
function inspectFactoryHooks(configPath) {
|
|
9008
|
-
if (!
|
|
9064
|
+
if (!existsSync10(configPath))
|
|
9009
9065
|
return { fileExists: false, events: [] };
|
|
9010
9066
|
let config;
|
|
9011
9067
|
try {
|
|
@@ -9023,6 +9079,7 @@ var EVENT_SUBCOMMAND3;
|
|
|
9023
9079
|
var init_factory = __esm(() => {
|
|
9024
9080
|
init_config_helpers();
|
|
9025
9081
|
init_claude_code();
|
|
9082
|
+
init_runtime();
|
|
9026
9083
|
EVENT_SUBCOMMAND3 = {
|
|
9027
9084
|
UserPromptSubmit: "user-prompt-submit",
|
|
9028
9085
|
PostToolUse: "post-tool-use",
|
|
@@ -10118,15 +10175,15 @@ var init_insights2 = __esm(() => {
|
|
|
10118
10175
|
});
|
|
10119
10176
|
|
|
10120
10177
|
// src/version/skill-update-check.ts
|
|
10121
|
-
import { existsSync as
|
|
10122
|
-
import { join as
|
|
10178
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync12, writeFileSync as writeFileSync6 } from "node:fs";
|
|
10179
|
+
import { join as join10 } from "node:path";
|
|
10123
10180
|
function getCachePath2() {
|
|
10124
|
-
return
|
|
10181
|
+
return join10(getConfigDir(), CACHE_FILENAME2);
|
|
10125
10182
|
}
|
|
10126
10183
|
function readSkillCache() {
|
|
10127
10184
|
try {
|
|
10128
10185
|
const path3 = getCachePath2();
|
|
10129
|
-
if (!
|
|
10186
|
+
if (!existsSync12(path3))
|
|
10130
10187
|
return null;
|
|
10131
10188
|
const data = JSON.parse(readFileSync12(path3, "utf-8"));
|
|
10132
10189
|
if (typeof data.lastCheck === "number" && typeof data.latestSha === "string" && typeof data.installedSha === "string") {
|
|
@@ -10140,10 +10197,10 @@ function readSkillCache() {
|
|
|
10140
10197
|
function writeSkillCache(cache) {
|
|
10141
10198
|
try {
|
|
10142
10199
|
const dir = getConfigDir();
|
|
10143
|
-
if (!
|
|
10144
|
-
|
|
10200
|
+
if (!existsSync12(dir)) {
|
|
10201
|
+
mkdirSync7(dir, { recursive: true, mode: 448 });
|
|
10145
10202
|
}
|
|
10146
|
-
|
|
10203
|
+
writeFileSync6(getCachePath2(), JSON.stringify(cache), { mode: 384 });
|
|
10147
10204
|
} catch {}
|
|
10148
10205
|
}
|
|
10149
10206
|
async function fetchLatestSha() {
|
|
@@ -10168,19 +10225,6 @@ async function fetchLatestSha() {
|
|
|
10168
10225
|
clearTimeout(timeout);
|
|
10169
10226
|
}
|
|
10170
10227
|
}
|
|
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
10228
|
function displayNotice() {
|
|
10185
10229
|
const msg = `
|
|
10186
10230
|
${import_picocolors12.default.yellow(" Dosu skill update available")}
|
|
@@ -10278,16 +10322,12 @@ Failed to remove skill.`));
|
|
|
10278
10322
|
});
|
|
10279
10323
|
cmd.command("update").description("Update the Dosu skill to the latest version").action(async () => {
|
|
10280
10324
|
console.log(`Updating ${SKILL_NAME} skill...`);
|
|
10281
|
-
|
|
10282
|
-
|
|
10283
|
-
stdio: "inherit"
|
|
10284
|
-
});
|
|
10285
|
-
} catch {
|
|
10325
|
+
const result = await installSkill();
|
|
10326
|
+
if (!result.success) {
|
|
10286
10327
|
console.error(import_picocolors13.default.red(`
|
|
10287
10328
|
Failed to update skill.`));
|
|
10288
10329
|
process.exit(1);
|
|
10289
10330
|
}
|
|
10290
|
-
await refreshInstalledSha();
|
|
10291
10331
|
console.log(import_picocolors13.default.green(`
|
|
10292
10332
|
✓ Skill "${SKILL_NAME}" updated.`));
|
|
10293
10333
|
});
|
|
@@ -10317,21 +10357,21 @@ var init_skill = __esm(() => {
|
|
|
10317
10357
|
var MCP_PROVIDER_SLUG = "dosu_mcp";
|
|
10318
10358
|
|
|
10319
10359
|
// src/mcp/detect.ts
|
|
10320
|
-
import { existsSync as
|
|
10360
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
10321
10361
|
import { homedir, platform as platform2 } from "node:os";
|
|
10322
|
-
import { join as
|
|
10362
|
+
import { join as join11 } from "node:path";
|
|
10323
10363
|
function isInstalled(paths) {
|
|
10324
|
-
return paths.some((p2) =>
|
|
10364
|
+
return paths.some((p2) => existsSync13(expandHome(p2)));
|
|
10325
10365
|
}
|
|
10326
10366
|
function expandHome(path3) {
|
|
10327
10367
|
if (!path3.startsWith("~"))
|
|
10328
10368
|
return path3;
|
|
10329
|
-
return
|
|
10369
|
+
return join11(homedir(), path3.slice(1));
|
|
10330
10370
|
}
|
|
10331
10371
|
function appSupportDir() {
|
|
10332
10372
|
switch (platform2()) {
|
|
10333
10373
|
case "darwin": {
|
|
10334
|
-
return
|
|
10374
|
+
return join11(homedir(), "Library", "Application Support");
|
|
10335
10375
|
}
|
|
10336
10376
|
case "win32": {
|
|
10337
10377
|
return process.env.APPDATA ?? "";
|
|
@@ -10340,7 +10380,7 @@ function appSupportDir() {
|
|
|
10340
10380
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
10341
10381
|
if (xdg)
|
|
10342
10382
|
return xdg;
|
|
10343
|
-
return
|
|
10383
|
+
return join11(homedir(), ".config");
|
|
10344
10384
|
}
|
|
10345
10385
|
}
|
|
10346
10386
|
}
|
|
@@ -10421,7 +10461,7 @@ var init_antigravity = __esm(() => {
|
|
|
10421
10461
|
});
|
|
10422
10462
|
|
|
10423
10463
|
// src/mcp/providers/claude.ts
|
|
10424
|
-
import { join as
|
|
10464
|
+
import { join as join12 } from "node:path";
|
|
10425
10465
|
var ClaudeProvider = () => createJSONProvider({
|
|
10426
10466
|
providerName: "Claude Code",
|
|
10427
10467
|
providerID: "claude",
|
|
@@ -10430,22 +10470,22 @@ var ClaudeProvider = () => createJSONProvider({
|
|
|
10430
10470
|
paths: ["~/.claude"],
|
|
10431
10471
|
globalPath: "~/.claude.json",
|
|
10432
10472
|
topKey: "mcpServers",
|
|
10433
|
-
localConfigPath: (cwd) =>
|
|
10473
|
+
localConfigPath: (cwd) => join12(cwd, ".mcp.json")
|
|
10434
10474
|
});
|
|
10435
10475
|
var init_claude = __esm(() => {
|
|
10436
10476
|
init_base();
|
|
10437
10477
|
});
|
|
10438
10478
|
|
|
10439
10479
|
// src/mcp/providers/claude-desktop.ts
|
|
10440
|
-
import { join as
|
|
10480
|
+
import { join as join13 } from "node:path";
|
|
10441
10481
|
var ClaudeDesktopProvider = () => ({
|
|
10442
10482
|
name: () => "Claude Desktop",
|
|
10443
10483
|
id: () => "claude-desktop",
|
|
10444
10484
|
supportsLocal: () => false,
|
|
10445
10485
|
priority: () => 2,
|
|
10446
|
-
detectPaths: () => [
|
|
10447
|
-
isInstalled: () => isInstalled([
|
|
10448
|
-
globalConfigPath: () =>
|
|
10486
|
+
detectPaths: () => [join13(appSupportDir(), "Claude")],
|
|
10487
|
+
isInstalled: () => isInstalled([join13(appSupportDir(), "Claude")]),
|
|
10488
|
+
globalConfigPath: () => join13(appSupportDir(), "Claude", "claude_desktop_config.json"),
|
|
10449
10489
|
isConfigured: () => false,
|
|
10450
10490
|
install() {
|
|
10451
10491
|
throw new Error("this tool only supports local (stdio) servers and cannot be configured for remote MCP");
|
|
@@ -10459,14 +10499,14 @@ var init_claude_desktop = __esm(() => {
|
|
|
10459
10499
|
});
|
|
10460
10500
|
|
|
10461
10501
|
// src/mcp/providers/cline.ts
|
|
10462
|
-
import { join as
|
|
10463
|
-
var extensionDir = () =>
|
|
10502
|
+
import { join as join14 } from "node:path";
|
|
10503
|
+
var extensionDir = () => join14(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
|
|
10464
10504
|
providerName: "Cline",
|
|
10465
10505
|
providerID: "cline",
|
|
10466
10506
|
local: false,
|
|
10467
10507
|
priorityValue: 11,
|
|
10468
10508
|
paths: [extensionDir()],
|
|
10469
|
-
globalPath:
|
|
10509
|
+
globalPath: join14(extensionDir(), "settings", "cline_mcp_settings.json"),
|
|
10470
10510
|
topKey: "mcpServers",
|
|
10471
10511
|
buildServer: (cfg) => ({
|
|
10472
10512
|
url: mcpURL(cfg.deployment_id),
|
|
@@ -10482,7 +10522,7 @@ var init_cline = __esm(() => {
|
|
|
10482
10522
|
});
|
|
10483
10523
|
|
|
10484
10524
|
// src/mcp/providers/cline-cli.ts
|
|
10485
|
-
import { join as
|
|
10525
|
+
import { join as join15 } from "node:path";
|
|
10486
10526
|
function clineDir() {
|
|
10487
10527
|
return process.env.CLINE_DIR ?? expandHome("~/.cline");
|
|
10488
10528
|
}
|
|
@@ -10492,7 +10532,7 @@ var ClineCliProvider = () => createJSONProvider({
|
|
|
10492
10532
|
local: false,
|
|
10493
10533
|
priorityValue: 12,
|
|
10494
10534
|
paths: [clineDir()],
|
|
10495
|
-
globalPath:
|
|
10535
|
+
globalPath: join15(clineDir(), "data", "settings", "cline_mcp_settings.json"),
|
|
10496
10536
|
topKey: "mcpServers",
|
|
10497
10537
|
buildServer: (cfg) => ({
|
|
10498
10538
|
url: mcpURL(cfg.deployment_id),
|
|
@@ -10508,18 +10548,18 @@ var init_cline_cli = __esm(() => {
|
|
|
10508
10548
|
});
|
|
10509
10549
|
|
|
10510
10550
|
// src/mcp/providers/codex.ts
|
|
10511
|
-
import { existsSync as
|
|
10512
|
-
import { join as
|
|
10551
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13 } from "node:fs";
|
|
10552
|
+
import { join as join16 } from "node:path";
|
|
10513
10553
|
function codexHome() {
|
|
10514
10554
|
return process.env.CODEX_HOME ?? expandHome("~/.codex");
|
|
10515
10555
|
}
|
|
10516
10556
|
function getConfigPath2(global) {
|
|
10517
10557
|
if (global)
|
|
10518
|
-
return
|
|
10519
|
-
return
|
|
10558
|
+
return join16(codexHome(), "config.toml");
|
|
10559
|
+
return join16(process.cwd(), ".codex", "config.toml");
|
|
10520
10560
|
}
|
|
10521
10561
|
function readTOML(path3) {
|
|
10522
|
-
if (!
|
|
10562
|
+
if (!existsSync14(path3))
|
|
10523
10563
|
return "";
|
|
10524
10564
|
return readFileSync13(path3, "utf-8");
|
|
10525
10565
|
}
|
|
@@ -10579,9 +10619,9 @@ var CodexProvider = () => ({
|
|
|
10579
10619
|
priority: () => 8,
|
|
10580
10620
|
detectPaths: () => ["~/.codex"],
|
|
10581
10621
|
isInstalled: () => isInstalled(["~/.codex"]),
|
|
10582
|
-
globalConfigPath: () =>
|
|
10622
|
+
globalConfigPath: () => join16(codexHome(), "config.toml"),
|
|
10583
10623
|
isConfigured: () => {
|
|
10584
|
-
const content = readTOML(
|
|
10624
|
+
const content = readTOML(join16(codexHome(), "config.toml"));
|
|
10585
10625
|
return content.includes("[mcp_servers.dosu]");
|
|
10586
10626
|
},
|
|
10587
10627
|
install(cfg, global) {
|
|
@@ -10603,10 +10643,10 @@ var init_codex2 = __esm(() => {
|
|
|
10603
10643
|
});
|
|
10604
10644
|
|
|
10605
10645
|
// src/mcp/providers/copilot.ts
|
|
10606
|
-
import { join as
|
|
10646
|
+
import { join as join17 } from "node:path";
|
|
10607
10647
|
function globalPath() {
|
|
10608
10648
|
if (process.env.XDG_CONFIG_HOME) {
|
|
10609
|
-
return
|
|
10649
|
+
return join17(process.env.XDG_CONFIG_HOME, "mcp-config.json");
|
|
10610
10650
|
}
|
|
10611
10651
|
return expandHome("~/.copilot/mcp-config.json");
|
|
10612
10652
|
}
|
|
@@ -10637,7 +10677,7 @@ var CopilotProvider = () => ({
|
|
|
10637
10677
|
};
|
|
10638
10678
|
installJSONServer(globalPath(), "mcpServers", server);
|
|
10639
10679
|
} else {
|
|
10640
|
-
const configPath =
|
|
10680
|
+
const configPath = join17(process.cwd(), ".vscode", "mcp.json");
|
|
10641
10681
|
const server = {
|
|
10642
10682
|
type: "http",
|
|
10643
10683
|
url,
|
|
@@ -10650,7 +10690,7 @@ var CopilotProvider = () => ({
|
|
|
10650
10690
|
if (global) {
|
|
10651
10691
|
removeJSONServer(globalPath(), "mcpServers");
|
|
10652
10692
|
} else {
|
|
10653
|
-
const configPath =
|
|
10693
|
+
const configPath = join17(process.cwd(), ".vscode", "mcp.json");
|
|
10654
10694
|
removeJSONServer(configPath, "servers");
|
|
10655
10695
|
}
|
|
10656
10696
|
}
|
|
@@ -10662,7 +10702,7 @@ var init_copilot = __esm(() => {
|
|
|
10662
10702
|
});
|
|
10663
10703
|
|
|
10664
10704
|
// src/mcp/providers/cursor.ts
|
|
10665
|
-
import { join as
|
|
10705
|
+
import { join as join18 } from "node:path";
|
|
10666
10706
|
var CursorProvider = () => createJSONProvider({
|
|
10667
10707
|
providerName: "Cursor",
|
|
10668
10708
|
providerID: "cursor",
|
|
@@ -10675,7 +10715,7 @@ var CursorProvider = () => createJSONProvider({
|
|
|
10675
10715
|
url: mcpURL(cfg.deployment_id),
|
|
10676
10716
|
headers: mcpHeaders(cfg.api_key)
|
|
10677
10717
|
}),
|
|
10678
|
-
localConfigPath: (cwd) =>
|
|
10718
|
+
localConfigPath: (cwd) => join18(cwd, ".cursor", "mcp.json")
|
|
10679
10719
|
});
|
|
10680
10720
|
var init_cursor = __esm(() => {
|
|
10681
10721
|
init_config_helpers();
|
|
@@ -10683,7 +10723,7 @@ var init_cursor = __esm(() => {
|
|
|
10683
10723
|
});
|
|
10684
10724
|
|
|
10685
10725
|
// src/mcp/providers/factory.ts
|
|
10686
|
-
import { join as
|
|
10726
|
+
import { join as join19 } from "node:path";
|
|
10687
10727
|
var FactoryProvider = () => createJSONProvider({
|
|
10688
10728
|
providerName: "Factory",
|
|
10689
10729
|
providerID: "factory",
|
|
@@ -10692,14 +10732,14 @@ var FactoryProvider = () => createJSONProvider({
|
|
|
10692
10732
|
paths: ["~/.factory"],
|
|
10693
10733
|
globalPath: "~/.factory/mcp.json",
|
|
10694
10734
|
topKey: "mcpServers",
|
|
10695
|
-
localConfigPath: (cwd) =>
|
|
10735
|
+
localConfigPath: (cwd) => join19(cwd, ".factory", "mcp.json")
|
|
10696
10736
|
});
|
|
10697
10737
|
var init_factory2 = __esm(() => {
|
|
10698
10738
|
init_base();
|
|
10699
10739
|
});
|
|
10700
10740
|
|
|
10701
10741
|
// src/mcp/providers/gemini.ts
|
|
10702
|
-
import { join as
|
|
10742
|
+
import { join as join20 } from "node:path";
|
|
10703
10743
|
var GeminiProvider = () => createJSONProvider({
|
|
10704
10744
|
providerName: "Gemini CLI",
|
|
10705
10745
|
providerID: "gemini",
|
|
@@ -10708,7 +10748,7 @@ var GeminiProvider = () => createJSONProvider({
|
|
|
10708
10748
|
paths: ["~/.gemini"],
|
|
10709
10749
|
globalPath: "~/.gemini/settings.json",
|
|
10710
10750
|
topKey: "mcpServers",
|
|
10711
|
-
localConfigPath: (cwd) =>
|
|
10751
|
+
localConfigPath: (cwd) => join20(cwd, ".gemini", "settings.json")
|
|
10712
10752
|
});
|
|
10713
10753
|
var init_gemini = __esm(() => {
|
|
10714
10754
|
init_base();
|
|
@@ -10758,14 +10798,14 @@ var init_manual = __esm(() => {
|
|
|
10758
10798
|
});
|
|
10759
10799
|
|
|
10760
10800
|
// src/mcp/providers/mcporter.ts
|
|
10761
|
-
import { existsSync as
|
|
10762
|
-
import { join as
|
|
10801
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
10802
|
+
import { join as join21 } from "node:path";
|
|
10763
10803
|
function resolveGlobalConfigPath() {
|
|
10764
10804
|
const jsonPath = expandHome("~/.mcporter/mcporter.json");
|
|
10765
|
-
if (
|
|
10805
|
+
if (existsSync15(jsonPath))
|
|
10766
10806
|
return jsonPath;
|
|
10767
10807
|
const jsoncPath = expandHome("~/.mcporter/mcporter.jsonc");
|
|
10768
|
-
if (
|
|
10808
|
+
if (existsSync15(jsoncPath))
|
|
10769
10809
|
return jsoncPath;
|
|
10770
10810
|
return jsonPath;
|
|
10771
10811
|
}
|
|
@@ -10786,7 +10826,7 @@ var MCPorterProvider = () => ({
|
|
|
10786
10826
|
globalConfigPath: () => resolveGlobalConfigPath(),
|
|
10787
10827
|
isConfigured: () => isJSONKeyConfigured(resolveGlobalConfigPath(), "mcpServers"),
|
|
10788
10828
|
install(cfg, global) {
|
|
10789
|
-
const configPath = global ? resolveGlobalConfigPath() :
|
|
10829
|
+
const configPath = global ? resolveGlobalConfigPath() : join21(process.cwd(), "config", "mcporter.json");
|
|
10790
10830
|
const server = {
|
|
10791
10831
|
type: "http",
|
|
10792
10832
|
url: mcpEndpoint4(cfg),
|
|
@@ -10795,7 +10835,7 @@ var MCPorterProvider = () => ({
|
|
|
10795
10835
|
installJSONServer(configPath, "mcpServers", server);
|
|
10796
10836
|
},
|
|
10797
10837
|
remove(global) {
|
|
10798
|
-
const configPath = global ? resolveGlobalConfigPath() :
|
|
10838
|
+
const configPath = global ? resolveGlobalConfigPath() : join21(process.cwd(), "config", "mcporter.json");
|
|
10799
10839
|
removeJSONServer(configPath, "mcpServers");
|
|
10800
10840
|
}
|
|
10801
10841
|
});
|
|
@@ -10806,7 +10846,7 @@ var init_mcporter = __esm(() => {
|
|
|
10806
10846
|
});
|
|
10807
10847
|
|
|
10808
10848
|
// src/mcp/providers/opencode.ts
|
|
10809
|
-
import { join as
|
|
10849
|
+
import { join as join22 } from "node:path";
|
|
10810
10850
|
var OpenCodeProvider = () => createJSONProvider({
|
|
10811
10851
|
providerName: "OpenCode",
|
|
10812
10852
|
providerID: "opencode",
|
|
@@ -10821,7 +10861,7 @@ var OpenCodeProvider = () => createJSONProvider({
|
|
|
10821
10861
|
enabled: true,
|
|
10822
10862
|
headers: mcpHeaders(cfg.api_key)
|
|
10823
10863
|
}),
|
|
10824
|
-
localConfigPath: (cwd) =>
|
|
10864
|
+
localConfigPath: (cwd) => join22(cwd, "opencode.json")
|
|
10825
10865
|
});
|
|
10826
10866
|
var init_opencode = __esm(() => {
|
|
10827
10867
|
init_config_helpers();
|
|
@@ -10829,16 +10869,16 @@ var init_opencode = __esm(() => {
|
|
|
10829
10869
|
});
|
|
10830
10870
|
|
|
10831
10871
|
// src/mcp/providers/vscode.ts
|
|
10832
|
-
import { join as
|
|
10872
|
+
import { join as join23 } from "node:path";
|
|
10833
10873
|
var VSCodeProvider = () => createJSONProvider({
|
|
10834
10874
|
providerName: "VS Code",
|
|
10835
10875
|
providerID: "vscode",
|
|
10836
10876
|
local: true,
|
|
10837
10877
|
priorityValue: 6,
|
|
10838
|
-
paths: [
|
|
10839
|
-
globalPath:
|
|
10878
|
+
paths: [join23(appSupportDir(), "Code")],
|
|
10879
|
+
globalPath: join23(appSupportDir(), "Code", "User", "mcp.json"),
|
|
10840
10880
|
topKey: "servers",
|
|
10841
|
-
localConfigPath: (cwd) =>
|
|
10881
|
+
localConfigPath: (cwd) => join23(cwd, ".vscode", "mcp.json")
|
|
10842
10882
|
});
|
|
10843
10883
|
var init_vscode = __esm(() => {
|
|
10844
10884
|
init_detect();
|
|
@@ -10847,14 +10887,14 @@ var init_vscode = __esm(() => {
|
|
|
10847
10887
|
|
|
10848
10888
|
// src/mcp/providers/windsurf.ts
|
|
10849
10889
|
import { homedir as homedir2 } from "node:os";
|
|
10850
|
-
import { join as
|
|
10890
|
+
import { join as join24 } from "node:path";
|
|
10851
10891
|
var WindsurfProvider = () => createJSONProvider({
|
|
10852
10892
|
providerName: "Windsurf",
|
|
10853
10893
|
providerID: "windsurf",
|
|
10854
10894
|
local: false,
|
|
10855
10895
|
priorityValue: 9,
|
|
10856
|
-
paths: [
|
|
10857
|
-
globalPath:
|
|
10896
|
+
paths: [join24(homedir2(), ".codeium", "windsurf")],
|
|
10897
|
+
globalPath: join24(homedir2(), ".codeium", "windsurf", "mcp_config.json"),
|
|
10858
10898
|
topKey: "mcpServers"
|
|
10859
10899
|
});
|
|
10860
10900
|
var init_windsurf = __esm(() => {
|
|
@@ -10863,12 +10903,12 @@ var init_windsurf = __esm(() => {
|
|
|
10863
10903
|
|
|
10864
10904
|
// src/mcp/providers/zed.ts
|
|
10865
10905
|
import { platform as platform3 } from "node:os";
|
|
10866
|
-
import { join as
|
|
10906
|
+
import { join as join25 } from "node:path";
|
|
10867
10907
|
function zedConfigDir() {
|
|
10868
10908
|
const os2 = platform3();
|
|
10869
10909
|
if (os2 === "darwin" || os2 === "win32")
|
|
10870
|
-
return
|
|
10871
|
-
return
|
|
10910
|
+
return join25(appSupportDir(), "Zed");
|
|
10911
|
+
return join25(appSupportDir(), "zed");
|
|
10872
10912
|
}
|
|
10873
10913
|
var ZedProvider = () => createJSONProvider({
|
|
10874
10914
|
providerName: "Zed",
|
|
@@ -10876,7 +10916,7 @@ var ZedProvider = () => createJSONProvider({
|
|
|
10876
10916
|
local: true,
|
|
10877
10917
|
priorityValue: 10,
|
|
10878
10918
|
paths: [zedConfigDir()],
|
|
10879
|
-
globalPath:
|
|
10919
|
+
globalPath: join25(zedConfigDir(), "settings.json"),
|
|
10880
10920
|
topKey: "context_servers",
|
|
10881
10921
|
buildServer: (cfg) => ({
|
|
10882
10922
|
source: "custom",
|
|
@@ -10884,7 +10924,7 @@ var ZedProvider = () => createJSONProvider({
|
|
|
10884
10924
|
url: mcpURL(cfg.deployment_id),
|
|
10885
10925
|
headers: mcpHeaders(cfg.api_key)
|
|
10886
10926
|
}),
|
|
10887
|
-
localConfigPath: (cwd) =>
|
|
10927
|
+
localConfigPath: (cwd) => join25(cwd, ".zed", "settings.json")
|
|
10888
10928
|
});
|
|
10889
10929
|
var init_zed = __esm(() => {
|
|
10890
10930
|
init_config_helpers();
|
|
@@ -11027,6 +11067,74 @@ var init_analytics = __esm(() => {
|
|
|
11027
11067
|
init_logger();
|
|
11028
11068
|
});
|
|
11029
11069
|
|
|
11070
|
+
// src/setup/audit-handoff.ts
|
|
11071
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
11072
|
+
function buildAuditHandoffPrompt(dosuCmd = dosuInvocation()) {
|
|
11073
|
+
return [
|
|
11074
|
+
"Audit this repository to see what docs Dosu can generate for it.",
|
|
11075
|
+
"1. Run the codebase audit from the Dosu skill. It writes findings to .dosu/audit.json.",
|
|
11076
|
+
"2. Show me the findings and which docs you recommend Dosu generate.",
|
|
11077
|
+
`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.`
|
|
11078
|
+
].join(`
|
|
11079
|
+
`);
|
|
11080
|
+
}
|
|
11081
|
+
function binOnPath(bin) {
|
|
11082
|
+
const cmd = process.platform === "win32" ? "where" : "which";
|
|
11083
|
+
try {
|
|
11084
|
+
return spawnSync2(cmd, [bin], { stdio: "ignore" }).status === 0;
|
|
11085
|
+
} catch {
|
|
11086
|
+
return false;
|
|
11087
|
+
}
|
|
11088
|
+
}
|
|
11089
|
+
function claudeCliAvailable() {
|
|
11090
|
+
return binOnPath("claude");
|
|
11091
|
+
}
|
|
11092
|
+
function dosuInvocation() {
|
|
11093
|
+
return binOnPath("dosu") ? "dosu" : "npx -y @dosu/cli";
|
|
11094
|
+
}
|
|
11095
|
+
function printManualAuditNudge() {
|
|
11096
|
+
log.message(`See what docs Dosu can generate for this repo:
|
|
11097
|
+
|
|
11098
|
+
${info("Ask Dosu to audit this repo and show what docs it can generate.")}
|
|
11099
|
+
|
|
11100
|
+
Or run ${info(`${dosuInvocation()} audit`)} after your agent writes the audit.`);
|
|
11101
|
+
}
|
|
11102
|
+
async function offerAuditHandoff() {
|
|
11103
|
+
if (!detectGitRepo())
|
|
11104
|
+
return false;
|
|
11105
|
+
if (!claudeCliAvailable()) {
|
|
11106
|
+
printManualAuditNudge();
|
|
11107
|
+
return false;
|
|
11108
|
+
}
|
|
11109
|
+
const go = await confirm({
|
|
11110
|
+
message: "Kick off the codebase audit in Claude Code now?",
|
|
11111
|
+
initialValue: true
|
|
11112
|
+
});
|
|
11113
|
+
if (isCancel(go) || !go) {
|
|
11114
|
+
printManualAuditNudge();
|
|
11115
|
+
return false;
|
|
11116
|
+
}
|
|
11117
|
+
return true;
|
|
11118
|
+
}
|
|
11119
|
+
function launchAuditAgent() {
|
|
11120
|
+
logger.info("setup", "Handing off to Claude Code for the codebase audit");
|
|
11121
|
+
const result = spawnSync2("claude", ["--model", AUDIT_AGENT_MODEL, buildAuditHandoffPrompt()], {
|
|
11122
|
+
stdio: "inherit",
|
|
11123
|
+
shell: process.platform === "win32"
|
|
11124
|
+
});
|
|
11125
|
+
if (result.error) {
|
|
11126
|
+
logger.warn("setup", `Claude Code launch failed: ${result.error.message}`);
|
|
11127
|
+
printManualAuditNudge();
|
|
11128
|
+
}
|
|
11129
|
+
}
|
|
11130
|
+
var AUDIT_AGENT_MODEL = "haiku";
|
|
11131
|
+
var init_audit_handoff = __esm(() => {
|
|
11132
|
+
init_dist8();
|
|
11133
|
+
init_logger();
|
|
11134
|
+
init_github_step();
|
|
11135
|
+
init_styles();
|
|
11136
|
+
});
|
|
11137
|
+
|
|
11030
11138
|
// src/setup/github-doc-import-prompt.ts
|
|
11031
11139
|
async function promptGitHubDocsImport({
|
|
11032
11140
|
repositories
|
|
@@ -12068,8 +12176,8 @@ __export(exports_flow2, {
|
|
|
12068
12176
|
isStdioOnly: () => isStdioOnly
|
|
12069
12177
|
});
|
|
12070
12178
|
import { randomUUID } from "node:crypto";
|
|
12071
|
-
import { existsSync as
|
|
12072
|
-
import { join as
|
|
12179
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
12180
|
+
import { join as join26 } from "node:path";
|
|
12073
12181
|
async function runSetup(opts = {}) {
|
|
12074
12182
|
const onboardingRunID = randomUUID();
|
|
12075
12183
|
logger.info("setup", `Setup flow started${opts.deploymentID ? ` deployment=${opts.deploymentID}` : ""}${opts.mode ? ` mode=${opts.mode}` : ""}`);
|
|
@@ -12237,12 +12345,16 @@ async function runSetup(opts = {}) {
|
|
|
12237
12345
|
log.warn("Could not mark onboarding complete on the server — you can retry later by running `dosu setup` again.");
|
|
12238
12346
|
}
|
|
12239
12347
|
}
|
|
12348
|
+
let handoffToAudit = false;
|
|
12240
12349
|
if (mcpConfiguredThisRun) {
|
|
12241
12350
|
showTryItOutPrompt({
|
|
12242
12351
|
mode: cfg.mode,
|
|
12243
12352
|
docsImported: choices.connectGitHub && githubOnboardingDone,
|
|
12244
|
-
hasAgentsMd:
|
|
12353
|
+
hasAgentsMd: existsSync16(join26(process.cwd(), "AGENTS.md"))
|
|
12245
12354
|
});
|
|
12355
|
+
if (cfg.mode !== MODE_OSS) {
|
|
12356
|
+
handoffToAudit = await offerAuditHandoff();
|
|
12357
|
+
}
|
|
12246
12358
|
}
|
|
12247
12359
|
if (mcpCompleted || skillCompleted || docsImported) {
|
|
12248
12360
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_completed", {
|
|
@@ -12256,6 +12368,9 @@ async function runSetup(opts = {}) {
|
|
|
12256
12368
|
} else {
|
|
12257
12369
|
outro("\uD83C\uDF89 Setup complete!");
|
|
12258
12370
|
}
|
|
12371
|
+
if (handoffToAudit) {
|
|
12372
|
+
launchAuditAgent();
|
|
12373
|
+
}
|
|
12259
12374
|
}
|
|
12260
12375
|
function applyDeployment(cfg, d) {
|
|
12261
12376
|
cfg.deployment_id = d.deployment_id;
|
|
@@ -12728,13 +12843,6 @@ function showTryItOutPrompt(opts = {}) {
|
|
|
12728
12843
|
log.message(`Try it out! Paste this into your agent:
|
|
12729
12844
|
|
|
12730
12845
|
${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
12846
|
}
|
|
12739
12847
|
var init_flow2 = __esm(() => {
|
|
12740
12848
|
init_dist8();
|
|
@@ -12744,12 +12852,13 @@ var init_flow2 = __esm(() => {
|
|
|
12744
12852
|
init_logger();
|
|
12745
12853
|
init_providers();
|
|
12746
12854
|
init_analytics();
|
|
12855
|
+
init_audit_handoff();
|
|
12747
12856
|
init_styles();
|
|
12748
12857
|
});
|
|
12749
12858
|
|
|
12750
12859
|
// src/commands/insights.ts
|
|
12751
|
-
import { existsSync as
|
|
12752
|
-
import { dirname as
|
|
12860
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync8, readdirSync, unlinkSync, writeFileSync as writeFileSync7 } from "node:fs";
|
|
12861
|
+
import { dirname as dirname5, join as join27 } from "node:path";
|
|
12753
12862
|
function shuffled(arr) {
|
|
12754
12863
|
const copy2 = [...arr];
|
|
12755
12864
|
for (let i2 = copy2.length - 1;i2 > 0; i2--) {
|
|
@@ -12853,17 +12962,17 @@ function makeAskFn(cfg) {
|
|
|
12853
12962
|
};
|
|
12854
12963
|
}
|
|
12855
12964
|
function insightsDir() {
|
|
12856
|
-
return
|
|
12965
|
+
return join27(getConfigDir(), "insights");
|
|
12857
12966
|
}
|
|
12858
12967
|
function reportPath(timestamp) {
|
|
12859
12968
|
const dir = insightsDir();
|
|
12860
12969
|
if (!timestamp)
|
|
12861
|
-
return
|
|
12970
|
+
return join27(dir, "latest.html");
|
|
12862
12971
|
const iso = timestamp.toISOString().slice(0, 19).replace(/:/g, "-");
|
|
12863
|
-
return
|
|
12972
|
+
return join27(dir, `report-${iso}Z.html`);
|
|
12864
12973
|
}
|
|
12865
12974
|
function pruneOldReports(dir, keepN) {
|
|
12866
|
-
if (!
|
|
12975
|
+
if (!existsSync17(dir))
|
|
12867
12976
|
return;
|
|
12868
12977
|
let entries;
|
|
12869
12978
|
try {
|
|
@@ -12875,7 +12984,7 @@ function pruneOldReports(dir, keepN) {
|
|
|
12875
12984
|
const reports = entries.filter((f2) => REPORT_FILE_PATTERN.test(f2)).sort().reverse();
|
|
12876
12985
|
for (const f2 of reports.slice(keepN)) {
|
|
12877
12986
|
try {
|
|
12878
|
-
unlinkSync(
|
|
12987
|
+
unlinkSync(join27(dir, f2));
|
|
12879
12988
|
} catch (err) {
|
|
12880
12989
|
logger.debug("insights", `failed to prune ${f2}: ${err instanceof Error ? err.message : err}`);
|
|
12881
12990
|
}
|
|
@@ -12947,10 +13056,10 @@ function defaultRunner(cfg) {
|
|
|
12947
13056
|
build: buildInsights,
|
|
12948
13057
|
render: renderHTML,
|
|
12949
13058
|
writeFile: (path3, content) => {
|
|
12950
|
-
const dir =
|
|
12951
|
-
if (!
|
|
12952
|
-
|
|
12953
|
-
|
|
13059
|
+
const dir = dirname5(path3);
|
|
13060
|
+
if (!existsSync17(dir))
|
|
13061
|
+
mkdirSync8(dir, { recursive: true, mode: 448 });
|
|
13062
|
+
writeFileSync7(path3, content, { mode: 384 });
|
|
12954
13063
|
},
|
|
12955
13064
|
prune: pruneOldReports,
|
|
12956
13065
|
openInBrowser: async (path3) => {
|
|
@@ -13889,8 +13998,8 @@ init_trpc();
|
|
|
13889
13998
|
init_logger();
|
|
13890
13999
|
init_github_step();
|
|
13891
14000
|
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";
|
|
14001
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, rmSync, writeFileSync as writeFileSync4 } from "node:fs";
|
|
14002
|
+
import { dirname, join as join4 } from "node:path";
|
|
13894
14003
|
|
|
13895
14004
|
// src/version/pending-tasks-check.ts
|
|
13896
14005
|
init_config();
|
|
@@ -14174,6 +14283,33 @@ function loadFindings(findingsPath) {
|
|
|
14174
14283
|
}
|
|
14175
14284
|
return parsed;
|
|
14176
14285
|
}
|
|
14286
|
+
function cleanupFindings(findingsPath, cwd = process.cwd()) {
|
|
14287
|
+
const gitignorePath = join4(cwd, ".gitignore");
|
|
14288
|
+
try {
|
|
14289
|
+
const content = existsSync4(gitignorePath) ? readFileSync4(gitignorePath, "utf-8") : "";
|
|
14290
|
+
const hasEntry = content.split(/\r?\n/).some((line) => /^\.dosu\/?$/.test(line.trim()));
|
|
14291
|
+
if (!hasEntry) {
|
|
14292
|
+
const sep = content === "" || content.endsWith(`
|
|
14293
|
+
`) ? "" : `
|
|
14294
|
+
`;
|
|
14295
|
+
writeFileSync4(gitignorePath, `${content}${sep}.dosu/
|
|
14296
|
+
`);
|
|
14297
|
+
}
|
|
14298
|
+
} catch (err) {
|
|
14299
|
+
logger.warn("audit", `could not update .gitignore: ${errText(err)}`);
|
|
14300
|
+
}
|
|
14301
|
+
const defaultDir = join4(cwd, ".dosu");
|
|
14302
|
+
if (dirname(findingsPath) !== defaultDir)
|
|
14303
|
+
return;
|
|
14304
|
+
try {
|
|
14305
|
+
rmSync(defaultDir, { recursive: true, force: true });
|
|
14306
|
+
} catch (err) {
|
|
14307
|
+
logger.warn("audit", `could not remove ${defaultDir}: ${errText(err)}`);
|
|
14308
|
+
}
|
|
14309
|
+
}
|
|
14310
|
+
function errText(err) {
|
|
14311
|
+
return err instanceof Error ? err.message : String(err);
|
|
14312
|
+
}
|
|
14177
14313
|
function intersectActionable(items, capabilities) {
|
|
14178
14314
|
const known = new Set(capabilities.map((c3) => c3.id));
|
|
14179
14315
|
return items.filter((item) => known.has(item.task));
|
|
@@ -14182,9 +14318,21 @@ function isPreselected(item) {
|
|
|
14182
14318
|
return item.can_help && item.action !== "skip";
|
|
14183
14319
|
}
|
|
14184
14320
|
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) => {
|
|
14321
|
+
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
14322
|
const cfg = requireConfig3();
|
|
14187
14323
|
const apiKey = requireAPIKey(cfg);
|
|
14324
|
+
if (opts.listTasks) {
|
|
14325
|
+
const resp = await backendGet("/v1/cli/tasks", apiKey);
|
|
14326
|
+
const tasks = resp.tasks ?? [];
|
|
14327
|
+
if (opts.json) {
|
|
14328
|
+
printResult({ tasks }, opts);
|
|
14329
|
+
return;
|
|
14330
|
+
}
|
|
14331
|
+
for (const t2 of tasks) {
|
|
14332
|
+
console.log(`${t2.id} ${import_picocolors9.default.dim(`(${t2.doc_type})`)} ${t2.label} — ${t2.description}`);
|
|
14333
|
+
}
|
|
14334
|
+
return;
|
|
14335
|
+
}
|
|
14188
14336
|
const detected = detectGitRepo();
|
|
14189
14337
|
if (!detected) {
|
|
14190
14338
|
console.error(import_picocolors9.default.red("Not a GitHub repo. Run 'dosu audit' from a GitHub repository."));
|
|
@@ -14265,6 +14413,9 @@ function auditCommand() {
|
|
|
14265
14413
|
repo: detected.slug
|
|
14266
14414
|
});
|
|
14267
14415
|
}
|
|
14416
|
+
if (taskIds.length > 0) {
|
|
14417
|
+
cleanupFindings(findingsPath);
|
|
14418
|
+
}
|
|
14268
14419
|
if (opts.json) {
|
|
14269
14420
|
printResult({ task_ids: taskIds }, opts);
|
|
14270
14421
|
return;
|
|
@@ -14761,13 +14912,13 @@ init_commander();
|
|
|
14761
14912
|
init_config();
|
|
14762
14913
|
init_logger();
|
|
14763
14914
|
init_prompts();
|
|
14764
|
-
import { readFileSync as readFileSync11 } from "node:fs";
|
|
14915
|
+
import { existsSync as existsSync11, readFileSync as readFileSync11 } from "node:fs";
|
|
14765
14916
|
import { basename } from "node:path";
|
|
14766
14917
|
|
|
14767
14918
|
// src/hooks/state.ts
|
|
14768
14919
|
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";
|
|
14920
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync6, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
14921
|
+
import { dirname as dirname2, join as join5 } from "node:path";
|
|
14771
14922
|
function getStateDir() {
|
|
14772
14923
|
return process.env.DOSU_HOOK_STATE_DIR ?? join5(getConfigDir(), "hooks");
|
|
14773
14924
|
}
|
|
@@ -14787,11 +14938,11 @@ function loadState(sessionId) {
|
|
|
14787
14938
|
function saveState(state) {
|
|
14788
14939
|
try {
|
|
14789
14940
|
const file = stateFile(state.sessionId);
|
|
14790
|
-
const dir =
|
|
14941
|
+
const dir = dirname2(file);
|
|
14791
14942
|
if (!existsSync5(dir)) {
|
|
14792
14943
|
mkdirSync4(dir, { recursive: true, mode: 448 });
|
|
14793
14944
|
}
|
|
14794
|
-
|
|
14945
|
+
writeFileSync5(file, JSON.stringify(state, null, 2), { mode: 384 });
|
|
14795
14946
|
} catch {}
|
|
14796
14947
|
}
|
|
14797
14948
|
|
|
@@ -15230,6 +15381,21 @@ async function collectDoctorChecks(opts) {
|
|
|
15230
15381
|
});
|
|
15231
15382
|
}
|
|
15232
15383
|
}
|
|
15384
|
+
if (hasSubmit && hasPostTool || alternativeInstalled) {
|
|
15385
|
+
const { dosuOnPath: dosuOnPath2, materializedRuntimePath: materializedRuntimePath2 } = await Promise.resolve().then(() => (init_runtime(), exports_runtime));
|
|
15386
|
+
const materialized = materializedRuntimePath2();
|
|
15387
|
+
if (dosuOnPath2()) {
|
|
15388
|
+
checks.push({ name: "runtime", status: "ok", detail: "dosu on PATH" });
|
|
15389
|
+
} else if (existsSync11(materialized)) {
|
|
15390
|
+
checks.push({ name: "runtime", status: "ok", detail: `materialized: ${materialized}` });
|
|
15391
|
+
} else {
|
|
15392
|
+
checks.push({
|
|
15393
|
+
name: "runtime",
|
|
15394
|
+
status: "fail",
|
|
15395
|
+
detail: "dosu is not on PATH and no materialized runtime exists — re-run 'npx -y @dosu/cli hooks install <agent>'"
|
|
15396
|
+
});
|
|
15397
|
+
}
|
|
15398
|
+
}
|
|
15233
15399
|
const cfg = loadConfig();
|
|
15234
15400
|
if (isAuthenticated(cfg)) {
|
|
15235
15401
|
checks.push({ name: "auth", status: "ok", detail: "logged in" });
|
|
@@ -15787,12 +15953,13 @@ function reviewCommand() {
|
|
|
15787
15953
|
}
|
|
15788
15954
|
const client = createTypedClient(cfg);
|
|
15789
15955
|
const ksId = await getKnowledgeStoreId2(client, cfg.space_id);
|
|
15790
|
-
const
|
|
15956
|
+
const result = await client.review.listPending.query({
|
|
15791
15957
|
knowledgeStoreId: ksId,
|
|
15792
15958
|
deploymentId: cfg.deployment_id
|
|
15793
15959
|
});
|
|
15960
|
+
const { items, truncated, total } = result;
|
|
15794
15961
|
if (opts.json) {
|
|
15795
|
-
printResult(
|
|
15962
|
+
printResult(result, opts);
|
|
15796
15963
|
return;
|
|
15797
15964
|
}
|
|
15798
15965
|
if (!items || items.length === 0) {
|
|
@@ -15814,6 +15981,9 @@ function reviewCommand() {
|
|
|
15814
15981
|
i2.pendingStatus,
|
|
15815
15982
|
formatDate(i2.createdAt)
|
|
15816
15983
|
]), { rawData: items });
|
|
15984
|
+
if (truncated) {
|
|
15985
|
+
console.log(import_picocolors20.default.dim(`Showing ${items.length} of ${total}+ pending items (list truncated).`));
|
|
15986
|
+
}
|
|
15817
15987
|
});
|
|
15818
15988
|
cmd.command("diff").description("Show a pending review item (doc-change diff or draft reply body)").argument("<id>", "Review item ID (from `dosu review list`)").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
15819
15989
|
const cfg = requireConfig10();
|
|
@@ -16169,7 +16339,7 @@ function suggestCommand() {
|
|
|
16169
16339
|
return cmd;
|
|
16170
16340
|
}
|
|
16171
16341
|
|
|
16172
|
-
// src/commands/
|
|
16342
|
+
// src/commands/threads.ts
|
|
16173
16343
|
init_commander();
|
|
16174
16344
|
init_trpc();
|
|
16175
16345
|
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
@@ -16181,92 +16351,10 @@ function requireConfig13() {
|
|
|
16181
16351
|
}
|
|
16182
16352
|
return cfg;
|
|
16183
16353
|
}
|
|
16184
|
-
async function getKnowledgeStoreId4(client, spaceId) {
|
|
16185
|
-
const store = await client.knowledgeStore.getBySpaceId.query({
|
|
16186
|
-
space_id: spaceId
|
|
16187
|
-
});
|
|
16188
|
-
if (!store) {
|
|
16189
|
-
console.error(import_picocolors23.default.red("No knowledge store found for this deployment."));
|
|
16190
|
-
process.exit(1);
|
|
16191
|
-
}
|
|
16192
|
-
return store.id;
|
|
16193
|
-
}
|
|
16194
|
-
function tagsCommand() {
|
|
16195
|
-
const cmd = new Command("tags").description("Manage knowledge base tags");
|
|
16196
|
-
cmd.command("list").description("List all tags").option("--json", "Output as JSON").action(async (opts) => {
|
|
16197
|
-
const cfg = requireConfig13();
|
|
16198
|
-
const client = createTypedClient(cfg);
|
|
16199
|
-
const ksId = await getKnowledgeStoreId4(client, cfg.space_id);
|
|
16200
|
-
const tags = await client.topic.listTopicsByKnowledgeStore.query({
|
|
16201
|
-
knowledge_store_id: ksId
|
|
16202
|
-
});
|
|
16203
|
-
if (opts.json) {
|
|
16204
|
-
printResult(tags, opts);
|
|
16205
|
-
return;
|
|
16206
|
-
}
|
|
16207
|
-
if (!tags || tags.length === 0) {
|
|
16208
|
-
console.log(import_picocolors23.default.dim("No tags found."));
|
|
16209
|
-
return;
|
|
16210
|
-
}
|
|
16211
|
-
printTable(["ID", "Name", "Description"], tags.map((t2) => [
|
|
16212
|
-
t2.topic_id.slice(0, 8),
|
|
16213
|
-
t2.name,
|
|
16214
|
-
t2.description ?? "—"
|
|
16215
|
-
]), { rawData: tags });
|
|
16216
|
-
});
|
|
16217
|
-
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) => {
|
|
16218
|
-
const cfg = requireConfig13();
|
|
16219
|
-
const client = createTypedClient(cfg);
|
|
16220
|
-
await client.topic.removeFromPage.mutate({ topic_id: tagId, page_id: pageId });
|
|
16221
|
-
if (opts.json) {
|
|
16222
|
-
printResult({ success: true, tag_id: tagId, page_id: pageId }, opts);
|
|
16223
|
-
return;
|
|
16224
|
-
}
|
|
16225
|
-
console.log(import_picocolors23.default.green("Tag removed from page."));
|
|
16226
|
-
});
|
|
16227
|
-
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) => {
|
|
16228
|
-
const cfg = requireConfig13();
|
|
16229
|
-
const client = createTypedClient(cfg);
|
|
16230
|
-
const ksId = await getKnowledgeStoreId4(client, cfg.space_id);
|
|
16231
|
-
const result = await client.topic.getPagesByTopicId.query({
|
|
16232
|
-
knowledge_store_id: ksId,
|
|
16233
|
-
topic_id: tagId,
|
|
16234
|
-
searchTerm: opts.search,
|
|
16235
|
-
limit: Number.parseInt(opts.limit ?? "10", 10)
|
|
16236
|
-
});
|
|
16237
|
-
const pages = result.data;
|
|
16238
|
-
if (opts.json) {
|
|
16239
|
-
printResult(pages, opts);
|
|
16240
|
-
return;
|
|
16241
|
-
}
|
|
16242
|
-
if (!pages || pages.length === 0) {
|
|
16243
|
-
console.log(import_picocolors23.default.dim("No pages found with this tag."));
|
|
16244
|
-
return;
|
|
16245
|
-
}
|
|
16246
|
-
printTable(["ID", "Title"], pages.map((p2) => [
|
|
16247
|
-
p2.id.slice(0, 8),
|
|
16248
|
-
p2.title ?? "(untitled)"
|
|
16249
|
-
]), { rawData: pages });
|
|
16250
|
-
});
|
|
16251
|
-
return cmd;
|
|
16252
|
-
}
|
|
16253
|
-
|
|
16254
|
-
// src/commands/threads.ts
|
|
16255
|
-
init_commander();
|
|
16256
|
-
init_trpc();
|
|
16257
|
-
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
16258
|
-
function requireConfig14() {
|
|
16259
|
-
const cfg = requireLoginConfig();
|
|
16260
|
-
if (!cfg.space_id) {
|
|
16261
|
-
console.error(import_picocolors24.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
|
|
16262
|
-
process.exit(1);
|
|
16263
|
-
}
|
|
16264
|
-
return cfg;
|
|
16265
|
-
}
|
|
16266
16354
|
function threadsCommand() {
|
|
16267
16355
|
const cmd = new Command("threads").description("List and manage conversation threads");
|
|
16268
16356
|
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) => {
|
|
16269
|
-
const cfg =
|
|
16357
|
+
const cfg = requireConfig13();
|
|
16270
16358
|
const client = createTypedClient(cfg);
|
|
16271
16359
|
const input = {
|
|
16272
16360
|
__testing_scope__: undefined,
|
|
@@ -16305,7 +16393,7 @@ function threadsCommand() {
|
|
|
16305
16393
|
return;
|
|
16306
16394
|
}
|
|
16307
16395
|
if (!threads || threads.length === 0) {
|
|
16308
|
-
console.log(
|
|
16396
|
+
console.log(import_picocolors23.default.dim("No threads found."));
|
|
16309
16397
|
return;
|
|
16310
16398
|
}
|
|
16311
16399
|
printTable(["ID", "Title", "Status", "Created"], threads.map((t2) => [
|
|
@@ -16316,7 +16404,7 @@ function threadsCommand() {
|
|
|
16316
16404
|
]), { rawData: threads });
|
|
16317
16405
|
});
|
|
16318
16406
|
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) => {
|
|
16319
|
-
const cfg =
|
|
16407
|
+
const cfg = requireConfig13();
|
|
16320
16408
|
const client = createTypedClient(cfg);
|
|
16321
16409
|
const [thread, messagesData] = await Promise.all([
|
|
16322
16410
|
client.thread.get.query(id),
|
|
@@ -16330,10 +16418,10 @@ function threadsCommand() {
|
|
|
16330
16418
|
return;
|
|
16331
16419
|
}
|
|
16332
16420
|
if (!thread) {
|
|
16333
|
-
console.log(
|
|
16421
|
+
console.log(import_picocolors23.default.dim("Thread not found."));
|
|
16334
16422
|
return;
|
|
16335
16423
|
}
|
|
16336
|
-
console.log(
|
|
16424
|
+
console.log(import_picocolors23.default.bold(thread.generated_title ?? "(untitled thread)"));
|
|
16337
16425
|
printInfo([
|
|
16338
16426
|
["ID", thread.id],
|
|
16339
16427
|
["Created", formatDate(thread.created_at)],
|
|
@@ -16344,13 +16432,13 @@ function threadsCommand() {
|
|
|
16344
16432
|
if (messages && messages.length > 0) {
|
|
16345
16433
|
const allMessages = messages.flatMap((group) => group.messages);
|
|
16346
16434
|
console.log(`
|
|
16347
|
-
${
|
|
16348
|
-
console.log(
|
|
16435
|
+
${import_picocolors23.default.bold("Messages")} (${allMessages.length})`);
|
|
16436
|
+
console.log(import_picocolors23.default.dim("─".repeat(60)));
|
|
16349
16437
|
for (const msg of allMessages) {
|
|
16350
16438
|
const role = msg.author_role ?? "unknown";
|
|
16351
16439
|
const date = formatDate(msg.created_at);
|
|
16352
16440
|
console.log(`
|
|
16353
|
-
${
|
|
16441
|
+
${import_picocolors23.default.bold(role)} ${import_picocolors23.default.dim(date)}`);
|
|
16354
16442
|
if (msg.body) {
|
|
16355
16443
|
console.log(truncate(msg.body, 500));
|
|
16356
16444
|
}
|
|
@@ -16358,14 +16446,86 @@ ${import_picocolors24.default.bold(role)} ${import_picocolors24.default.dim(date
|
|
|
16358
16446
|
}
|
|
16359
16447
|
});
|
|
16360
16448
|
cmd.command("archive").description("Archive a thread").argument("<id>", "Thread ID").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
16361
|
-
const cfg =
|
|
16449
|
+
const cfg = requireConfig13();
|
|
16362
16450
|
const client = createTypedClient(cfg);
|
|
16363
16451
|
await client.thread.archive.mutate({ threadId: id, archived: true });
|
|
16364
16452
|
if (opts.json) {
|
|
16365
16453
|
printResult({ success: true, id }, opts);
|
|
16366
16454
|
return;
|
|
16367
16455
|
}
|
|
16368
|
-
console.log(
|
|
16456
|
+
console.log(import_picocolors23.default.green(`Thread ${id.slice(0, 8)} archived.`));
|
|
16457
|
+
});
|
|
16458
|
+
return cmd;
|
|
16459
|
+
}
|
|
16460
|
+
|
|
16461
|
+
// src/commands/topics.ts
|
|
16462
|
+
init_commander();
|
|
16463
|
+
init_trpc();
|
|
16464
|
+
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
16465
|
+
function requireConfig14() {
|
|
16466
|
+
const cfg = requireLoginConfig();
|
|
16467
|
+
if (!cfg.space_id) {
|
|
16468
|
+
console.error(import_picocolors24.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
|
|
16469
|
+
process.exit(1);
|
|
16470
|
+
}
|
|
16471
|
+
return cfg;
|
|
16472
|
+
}
|
|
16473
|
+
async function getKnowledgeStoreId4(client, spaceId) {
|
|
16474
|
+
const store = await client.knowledgeStore.getBySpaceId.query({
|
|
16475
|
+
space_id: spaceId
|
|
16476
|
+
});
|
|
16477
|
+
if (!store) {
|
|
16478
|
+
console.error(import_picocolors24.default.red("No knowledge store found for this deployment."));
|
|
16479
|
+
process.exit(1);
|
|
16480
|
+
}
|
|
16481
|
+
return store.id;
|
|
16482
|
+
}
|
|
16483
|
+
function topicsCommand() {
|
|
16484
|
+
const cmd = new Command("topics").alias("tags").description("Browse Topics in your knowledge base");
|
|
16485
|
+
cmd.command("list").description("List all topics").option("--json", "Output as JSON").action(async (opts) => {
|
|
16486
|
+
const cfg = requireConfig14();
|
|
16487
|
+
const client = createTypedClient(cfg);
|
|
16488
|
+
const ksId = await getKnowledgeStoreId4(client, cfg.space_id);
|
|
16489
|
+
const topics = await client.topic.listTopicsByKnowledgeStore.query({
|
|
16490
|
+
knowledge_store_id: ksId
|
|
16491
|
+
});
|
|
16492
|
+
if (opts.json) {
|
|
16493
|
+
printResult(topics, opts);
|
|
16494
|
+
return;
|
|
16495
|
+
}
|
|
16496
|
+
if (!topics || topics.length === 0) {
|
|
16497
|
+
console.log(import_picocolors24.default.dim("No topics found."));
|
|
16498
|
+
return;
|
|
16499
|
+
}
|
|
16500
|
+
printTable(["ID", "Name", "Description"], topics.map((t2) => [
|
|
16501
|
+
t2.topic_id.slice(0, 8),
|
|
16502
|
+
t2.name,
|
|
16503
|
+
t2.description ?? "—"
|
|
16504
|
+
]), { rawData: topics });
|
|
16505
|
+
});
|
|
16506
|
+
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) => {
|
|
16507
|
+
const cfg = requireConfig14();
|
|
16508
|
+
const client = createTypedClient(cfg);
|
|
16509
|
+
const ksId = await getKnowledgeStoreId4(client, cfg.space_id);
|
|
16510
|
+
const result = await client.topic.getPagesByTopicId.query({
|
|
16511
|
+
knowledge_store_id: ksId,
|
|
16512
|
+
topic_id: topicId,
|
|
16513
|
+
searchTerm: opts.search,
|
|
16514
|
+
limit: Number.parseInt(opts.limit ?? "10", 10)
|
|
16515
|
+
});
|
|
16516
|
+
const pages = result.data;
|
|
16517
|
+
if (opts.json) {
|
|
16518
|
+
printResult(pages, opts);
|
|
16519
|
+
return;
|
|
16520
|
+
}
|
|
16521
|
+
if (!pages || pages.length === 0) {
|
|
16522
|
+
console.log(import_picocolors24.default.dim("No pages found with this topic."));
|
|
16523
|
+
return;
|
|
16524
|
+
}
|
|
16525
|
+
printTable(["ID", "Title"], pages.map((p2) => [
|
|
16526
|
+
p2.id.slice(0, 8),
|
|
16527
|
+
p2.title ?? "(untitled)"
|
|
16528
|
+
]), { rawData: pages });
|
|
16369
16529
|
});
|
|
16370
16530
|
return cmd;
|
|
16371
16531
|
}
|
|
@@ -16380,8 +16540,8 @@ init_skill_update_check();
|
|
|
16380
16540
|
init_config();
|
|
16381
16541
|
init_logger();
|
|
16382
16542
|
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
16383
|
-
import { existsSync as
|
|
16384
|
-
import { join as
|
|
16543
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "node:fs";
|
|
16544
|
+
import { join as join28 } from "node:path";
|
|
16385
16545
|
var CACHE_FILENAME3 = "update-check.json";
|
|
16386
16546
|
var CHECK_INTERVAL_MS3 = 24 * 60 * 60 * 1000;
|
|
16387
16547
|
var FETCH_TIMEOUT_MS3 = 5000;
|
|
@@ -16404,12 +16564,12 @@ function isNewerVersion(latest, current) {
|
|
|
16404
16564
|
return false;
|
|
16405
16565
|
}
|
|
16406
16566
|
function getCachePath3() {
|
|
16407
|
-
return
|
|
16567
|
+
return join28(getConfigDir(), CACHE_FILENAME3);
|
|
16408
16568
|
}
|
|
16409
16569
|
function readCache() {
|
|
16410
16570
|
try {
|
|
16411
16571
|
const path3 = getCachePath3();
|
|
16412
|
-
if (!
|
|
16572
|
+
if (!existsSync18(path3))
|
|
16413
16573
|
return null;
|
|
16414
16574
|
const data = JSON.parse(readFileSync15(path3, "utf-8"));
|
|
16415
16575
|
if (typeof data.lastCheck === "number" && typeof data.latestVersion === "string") {
|
|
@@ -16423,10 +16583,10 @@ function readCache() {
|
|
|
16423
16583
|
function writeCache(cache) {
|
|
16424
16584
|
try {
|
|
16425
16585
|
const dir = getConfigDir();
|
|
16426
|
-
if (!
|
|
16427
|
-
|
|
16586
|
+
if (!existsSync18(dir)) {
|
|
16587
|
+
mkdirSync9(dir, { recursive: true, mode: 448 });
|
|
16428
16588
|
}
|
|
16429
|
-
|
|
16589
|
+
writeFileSync8(getCachePath3(), JSON.stringify(cache), { mode: 384 });
|
|
16430
16590
|
} catch {}
|
|
16431
16591
|
}
|
|
16432
16592
|
async function fetchLatestVersion() {
|
|
@@ -16697,7 +16857,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
|
|
|
16697
16857
|
program2.addCommand(reviewCommand());
|
|
16698
16858
|
program2.addCommand(sourcesCommand());
|
|
16699
16859
|
program2.addCommand(suggestCommand());
|
|
16700
|
-
program2.addCommand(
|
|
16860
|
+
program2.addCommand(topicsCommand());
|
|
16701
16861
|
program2.addCommand(threadsCommand());
|
|
16702
16862
|
program2.addCommand(skillCommand());
|
|
16703
16863
|
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) => {
|