@dosu/cli 0.19.3 → 0.20.1
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 +281 -88
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -4548,7 +4548,7 @@ var init_dist4 = __esm(() => {
|
|
|
4548
4548
|
function getVersionString() {
|
|
4549
4549
|
return `v${VERSION}`;
|
|
4550
4550
|
}
|
|
4551
|
-
var VERSION = "0.
|
|
4551
|
+
var VERSION = "0.20.1";
|
|
4552
4552
|
|
|
4553
4553
|
// src/debug/logger.ts
|
|
4554
4554
|
import {
|
|
@@ -6473,6 +6473,121 @@ var init_codex = __esm(() => {
|
|
|
6473
6473
|
};
|
|
6474
6474
|
});
|
|
6475
6475
|
|
|
6476
|
+
// src/hooks/factory.ts
|
|
6477
|
+
var exports_factory = {};
|
|
6478
|
+
__export(exports_factory, {
|
|
6479
|
+
removeFactoryHooks: () => removeFactoryHooks,
|
|
6480
|
+
installFactoryHooks: () => installFactoryHooks,
|
|
6481
|
+
inspectFactoryHooks: () => inspectFactoryHooks,
|
|
6482
|
+
factoryHooksPath: () => factoryHooksPath,
|
|
6483
|
+
factoryHookCommand: () => factoryHookCommand
|
|
6484
|
+
});
|
|
6485
|
+
import { existsSync as existsSync7, readFileSync as readFileSync8 } from "node:fs";
|
|
6486
|
+
import { join as join6 } from "node:path";
|
|
6487
|
+
function factoryHooksPath(dir) {
|
|
6488
|
+
return join6(dir, ".factory", "hooks.json");
|
|
6489
|
+
}
|
|
6490
|
+
function factoryHookCommand(subcommand) {
|
|
6491
|
+
return `dosu hooks ${subcommand} --agent factory`;
|
|
6492
|
+
}
|
|
6493
|
+
function dosuGroup3(event) {
|
|
6494
|
+
const group = {
|
|
6495
|
+
hooks: [{ type: "command", command: factoryHookCommand(EVENT_SUBCOMMAND3[event]) }]
|
|
6496
|
+
};
|
|
6497
|
+
if (event === "PostToolUse")
|
|
6498
|
+
group.matcher = "*";
|
|
6499
|
+
return group;
|
|
6500
|
+
}
|
|
6501
|
+
function readHooksFileOrThrow2(path) {
|
|
6502
|
+
if (!existsSync7(path))
|
|
6503
|
+
return {};
|
|
6504
|
+
const raw = readFileSync8(path, "utf-8").trim();
|
|
6505
|
+
if (!raw)
|
|
6506
|
+
return {};
|
|
6507
|
+
try {
|
|
6508
|
+
return JSON.parse(raw);
|
|
6509
|
+
} catch {
|
|
6510
|
+
throw new Error(`refusing to modify ${path}: file exists but is not valid JSON`);
|
|
6511
|
+
}
|
|
6512
|
+
}
|
|
6513
|
+
function installFactoryHooks(configPath, opts = {}) {
|
|
6514
|
+
const config = readHooksFileOrThrow2(configPath);
|
|
6515
|
+
const events = DEFAULT_HOOK_EVENTS.filter((e2) => e2 !== "Stop" || opts.stop !== false);
|
|
6516
|
+
const hooks = typeof config.hooks === "object" && config.hooks ? config.hooks : {};
|
|
6517
|
+
for (const event of events) {
|
|
6518
|
+
const groups = Array.isArray(hooks[event]) ? hooks[event] : [];
|
|
6519
|
+
const kept = groups.filter((g2) => !isDosuGroup(g2));
|
|
6520
|
+
kept.push(dosuGroup3(event));
|
|
6521
|
+
hooks[event] = kept;
|
|
6522
|
+
}
|
|
6523
|
+
for (const event of DEFAULT_HOOK_EVENTS) {
|
|
6524
|
+
if (!events.includes(event) && Array.isArray(hooks[event])) {
|
|
6525
|
+
const kept = hooks[event].filter((g2) => !isDosuGroup(g2));
|
|
6526
|
+
if (kept.length > 0)
|
|
6527
|
+
hooks[event] = kept;
|
|
6528
|
+
else
|
|
6529
|
+
delete hooks[event];
|
|
6530
|
+
}
|
|
6531
|
+
}
|
|
6532
|
+
config.hooks = hooks;
|
|
6533
|
+
saveJSONConfig(configPath, config);
|
|
6534
|
+
return { events: [...events] };
|
|
6535
|
+
}
|
|
6536
|
+
function removeFactoryHooks(configPath) {
|
|
6537
|
+
if (!existsSync7(configPath))
|
|
6538
|
+
return { removed: false };
|
|
6539
|
+
let config;
|
|
6540
|
+
try {
|
|
6541
|
+
config = readHooksFileOrThrow2(configPath);
|
|
6542
|
+
} catch {
|
|
6543
|
+
return { removed: false };
|
|
6544
|
+
}
|
|
6545
|
+
const hooks = config.hooks;
|
|
6546
|
+
if (typeof hooks !== "object" || !hooks)
|
|
6547
|
+
return { removed: false };
|
|
6548
|
+
let removed = false;
|
|
6549
|
+
for (const event of Object.keys(hooks)) {
|
|
6550
|
+
if (!Array.isArray(hooks[event]))
|
|
6551
|
+
continue;
|
|
6552
|
+
const kept = hooks[event].filter((g2) => !isDosuGroup(g2));
|
|
6553
|
+
if (kept.length !== hooks[event].length) {
|
|
6554
|
+
removed = true;
|
|
6555
|
+
if (kept.length > 0)
|
|
6556
|
+
hooks[event] = kept;
|
|
6557
|
+
else
|
|
6558
|
+
delete hooks[event];
|
|
6559
|
+
}
|
|
6560
|
+
}
|
|
6561
|
+
if (removed)
|
|
6562
|
+
saveJSONConfig(configPath, config);
|
|
6563
|
+
return { removed };
|
|
6564
|
+
}
|
|
6565
|
+
function inspectFactoryHooks(configPath) {
|
|
6566
|
+
if (!existsSync7(configPath))
|
|
6567
|
+
return { fileExists: false, events: [] };
|
|
6568
|
+
let config;
|
|
6569
|
+
try {
|
|
6570
|
+
config = readHooksFileOrThrow2(configPath);
|
|
6571
|
+
} catch {
|
|
6572
|
+
return { fileExists: true, parseError: true, events: [] };
|
|
6573
|
+
}
|
|
6574
|
+
const hooks = config.hooks;
|
|
6575
|
+
if (typeof hooks !== "object" || !hooks)
|
|
6576
|
+
return { fileExists: true, events: [] };
|
|
6577
|
+
const events = Object.keys(hooks).filter((event) => Array.isArray(hooks[event]) && hooks[event].some((g2) => isDosuGroup(g2)));
|
|
6578
|
+
return { fileExists: true, events };
|
|
6579
|
+
}
|
|
6580
|
+
var EVENT_SUBCOMMAND3;
|
|
6581
|
+
var init_factory = __esm(() => {
|
|
6582
|
+
init_config_helpers();
|
|
6583
|
+
init_claude_code();
|
|
6584
|
+
EVENT_SUBCOMMAND3 = {
|
|
6585
|
+
UserPromptSubmit: "user-prompt-submit",
|
|
6586
|
+
PostToolUse: "post-tool-use",
|
|
6587
|
+
Stop: "stop"
|
|
6588
|
+
};
|
|
6589
|
+
});
|
|
6590
|
+
|
|
6476
6591
|
// src/insights/insights.ts
|
|
6477
6592
|
async function buildInsights({
|
|
6478
6593
|
client,
|
|
@@ -7561,17 +7676,17 @@ var init_insights2 = __esm(() => {
|
|
|
7561
7676
|
});
|
|
7562
7677
|
|
|
7563
7678
|
// src/version/skill-update-check.ts
|
|
7564
|
-
import { existsSync as
|
|
7565
|
-
import { join as
|
|
7679
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync4 } from "node:fs";
|
|
7680
|
+
import { join as join7 } from "node:path";
|
|
7566
7681
|
function getCachePath() {
|
|
7567
|
-
return
|
|
7682
|
+
return join7(getConfigDir(), CACHE_FILENAME);
|
|
7568
7683
|
}
|
|
7569
7684
|
function readSkillCache() {
|
|
7570
7685
|
try {
|
|
7571
7686
|
const path = getCachePath();
|
|
7572
|
-
if (!
|
|
7687
|
+
if (!existsSync8(path))
|
|
7573
7688
|
return null;
|
|
7574
|
-
const data = JSON.parse(
|
|
7689
|
+
const data = JSON.parse(readFileSync10(path, "utf-8"));
|
|
7575
7690
|
if (typeof data.lastCheck === "number" && typeof data.latestSha === "string" && typeof data.installedSha === "string") {
|
|
7576
7691
|
return data;
|
|
7577
7692
|
}
|
|
@@ -7583,7 +7698,7 @@ function readSkillCache() {
|
|
|
7583
7698
|
function writeSkillCache(cache) {
|
|
7584
7699
|
try {
|
|
7585
7700
|
const dir = getConfigDir();
|
|
7586
|
-
if (!
|
|
7701
|
+
if (!existsSync8(dir)) {
|
|
7587
7702
|
mkdirSync5(dir, { recursive: true, mode: 448 });
|
|
7588
7703
|
}
|
|
7589
7704
|
writeFileSync4(getCachePath(), JSON.stringify(cache), { mode: 384 });
|
|
@@ -7760,21 +7875,21 @@ var init_skill = __esm(() => {
|
|
|
7760
7875
|
var MCP_PROVIDER_SLUG = "dosu_mcp";
|
|
7761
7876
|
|
|
7762
7877
|
// src/mcp/detect.ts
|
|
7763
|
-
import { existsSync as
|
|
7878
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
7764
7879
|
import { homedir, platform } from "node:os";
|
|
7765
|
-
import { join as
|
|
7880
|
+
import { join as join8 } from "node:path";
|
|
7766
7881
|
function isInstalled(paths) {
|
|
7767
|
-
return paths.some((p2) =>
|
|
7882
|
+
return paths.some((p2) => existsSync9(expandHome(p2)));
|
|
7768
7883
|
}
|
|
7769
7884
|
function expandHome(path) {
|
|
7770
7885
|
if (!path.startsWith("~"))
|
|
7771
7886
|
return path;
|
|
7772
|
-
return
|
|
7887
|
+
return join8(homedir(), path.slice(1));
|
|
7773
7888
|
}
|
|
7774
7889
|
function appSupportDir() {
|
|
7775
7890
|
switch (platform()) {
|
|
7776
7891
|
case "darwin": {
|
|
7777
|
-
return
|
|
7892
|
+
return join8(homedir(), "Library", "Application Support");
|
|
7778
7893
|
}
|
|
7779
7894
|
case "win32": {
|
|
7780
7895
|
return process.env.APPDATA ?? "";
|
|
@@ -7783,7 +7898,7 @@ function appSupportDir() {
|
|
|
7783
7898
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
7784
7899
|
if (xdg)
|
|
7785
7900
|
return xdg;
|
|
7786
|
-
return
|
|
7901
|
+
return join8(homedir(), ".config");
|
|
7787
7902
|
}
|
|
7788
7903
|
}
|
|
7789
7904
|
}
|
|
@@ -7864,7 +7979,7 @@ var init_antigravity = __esm(() => {
|
|
|
7864
7979
|
});
|
|
7865
7980
|
|
|
7866
7981
|
// src/mcp/providers/claude.ts
|
|
7867
|
-
import { join as
|
|
7982
|
+
import { join as join9 } from "node:path";
|
|
7868
7983
|
var ClaudeProvider = () => createJSONProvider({
|
|
7869
7984
|
providerName: "Claude Code",
|
|
7870
7985
|
providerID: "claude",
|
|
@@ -7873,22 +7988,22 @@ var ClaudeProvider = () => createJSONProvider({
|
|
|
7873
7988
|
paths: ["~/.claude"],
|
|
7874
7989
|
globalPath: "~/.claude.json",
|
|
7875
7990
|
topKey: "mcpServers",
|
|
7876
|
-
localConfigPath: (cwd) =>
|
|
7991
|
+
localConfigPath: (cwd) => join9(cwd, ".mcp.json")
|
|
7877
7992
|
});
|
|
7878
7993
|
var init_claude = __esm(() => {
|
|
7879
7994
|
init_base();
|
|
7880
7995
|
});
|
|
7881
7996
|
|
|
7882
7997
|
// src/mcp/providers/claude-desktop.ts
|
|
7883
|
-
import { join as
|
|
7998
|
+
import { join as join10 } from "node:path";
|
|
7884
7999
|
var ClaudeDesktopProvider = () => ({
|
|
7885
8000
|
name: () => "Claude Desktop",
|
|
7886
8001
|
id: () => "claude-desktop",
|
|
7887
8002
|
supportsLocal: () => false,
|
|
7888
8003
|
priority: () => 2,
|
|
7889
|
-
detectPaths: () => [
|
|
7890
|
-
isInstalled: () => isInstalled([
|
|
7891
|
-
globalConfigPath: () =>
|
|
8004
|
+
detectPaths: () => [join10(appSupportDir(), "Claude")],
|
|
8005
|
+
isInstalled: () => isInstalled([join10(appSupportDir(), "Claude")]),
|
|
8006
|
+
globalConfigPath: () => join10(appSupportDir(), "Claude", "claude_desktop_config.json"),
|
|
7892
8007
|
isConfigured: () => false,
|
|
7893
8008
|
install() {
|
|
7894
8009
|
throw new Error("this tool only supports local (stdio) servers and cannot be configured for remote MCP");
|
|
@@ -7902,14 +8017,14 @@ var init_claude_desktop = __esm(() => {
|
|
|
7902
8017
|
});
|
|
7903
8018
|
|
|
7904
8019
|
// src/mcp/providers/cline.ts
|
|
7905
|
-
import { join as
|
|
7906
|
-
var extensionDir = () =>
|
|
8020
|
+
import { join as join11 } from "node:path";
|
|
8021
|
+
var extensionDir = () => join11(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
|
|
7907
8022
|
providerName: "Cline",
|
|
7908
8023
|
providerID: "cline",
|
|
7909
8024
|
local: false,
|
|
7910
8025
|
priorityValue: 11,
|
|
7911
8026
|
paths: [extensionDir()],
|
|
7912
|
-
globalPath:
|
|
8027
|
+
globalPath: join11(extensionDir(), "settings", "cline_mcp_settings.json"),
|
|
7913
8028
|
topKey: "mcpServers",
|
|
7914
8029
|
buildServer: (cfg) => ({
|
|
7915
8030
|
url: mcpURL(cfg.deployment_id),
|
|
@@ -7925,7 +8040,7 @@ var init_cline = __esm(() => {
|
|
|
7925
8040
|
});
|
|
7926
8041
|
|
|
7927
8042
|
// src/mcp/providers/cline-cli.ts
|
|
7928
|
-
import { join as
|
|
8043
|
+
import { join as join12 } from "node:path";
|
|
7929
8044
|
function clineDir() {
|
|
7930
8045
|
return process.env.CLINE_DIR ?? expandHome("~/.cline");
|
|
7931
8046
|
}
|
|
@@ -7935,7 +8050,7 @@ var ClineCliProvider = () => createJSONProvider({
|
|
|
7935
8050
|
local: false,
|
|
7936
8051
|
priorityValue: 12,
|
|
7937
8052
|
paths: [clineDir()],
|
|
7938
|
-
globalPath:
|
|
8053
|
+
globalPath: join12(clineDir(), "data", "settings", "cline_mcp_settings.json"),
|
|
7939
8054
|
topKey: "mcpServers",
|
|
7940
8055
|
buildServer: (cfg) => ({
|
|
7941
8056
|
url: mcpURL(cfg.deployment_id),
|
|
@@ -7951,20 +8066,20 @@ var init_cline_cli = __esm(() => {
|
|
|
7951
8066
|
});
|
|
7952
8067
|
|
|
7953
8068
|
// src/mcp/providers/codex.ts
|
|
7954
|
-
import { existsSync as
|
|
7955
|
-
import { join as
|
|
8069
|
+
import { existsSync as existsSync10, readFileSync as readFileSync11 } from "node:fs";
|
|
8070
|
+
import { join as join13 } from "node:path";
|
|
7956
8071
|
function codexHome() {
|
|
7957
8072
|
return process.env.CODEX_HOME ?? expandHome("~/.codex");
|
|
7958
8073
|
}
|
|
7959
8074
|
function getConfigPath2(global) {
|
|
7960
8075
|
if (global)
|
|
7961
|
-
return
|
|
7962
|
-
return
|
|
8076
|
+
return join13(codexHome(), "config.toml");
|
|
8077
|
+
return join13(process.cwd(), ".codex", "config.toml");
|
|
7963
8078
|
}
|
|
7964
8079
|
function readTOML(path) {
|
|
7965
|
-
if (!
|
|
8080
|
+
if (!existsSync10(path))
|
|
7966
8081
|
return "";
|
|
7967
|
-
return
|
|
8082
|
+
return readFileSync11(path, "utf-8");
|
|
7968
8083
|
}
|
|
7969
8084
|
function writeTOML(path, content) {
|
|
7970
8085
|
writeSecureFile(path, content);
|
|
@@ -8022,9 +8137,9 @@ var CodexProvider = () => ({
|
|
|
8022
8137
|
priority: () => 8,
|
|
8023
8138
|
detectPaths: () => ["~/.codex"],
|
|
8024
8139
|
isInstalled: () => isInstalled(["~/.codex"]),
|
|
8025
|
-
globalConfigPath: () =>
|
|
8140
|
+
globalConfigPath: () => join13(codexHome(), "config.toml"),
|
|
8026
8141
|
isConfigured: () => {
|
|
8027
|
-
const content = readTOML(
|
|
8142
|
+
const content = readTOML(join13(codexHome(), "config.toml"));
|
|
8028
8143
|
return content.includes("[mcp_servers.dosu]");
|
|
8029
8144
|
},
|
|
8030
8145
|
install(cfg, global) {
|
|
@@ -8046,10 +8161,10 @@ var init_codex2 = __esm(() => {
|
|
|
8046
8161
|
});
|
|
8047
8162
|
|
|
8048
8163
|
// src/mcp/providers/copilot.ts
|
|
8049
|
-
import { join as
|
|
8164
|
+
import { join as join14 } from "node:path";
|
|
8050
8165
|
function globalPath() {
|
|
8051
8166
|
if (process.env.XDG_CONFIG_HOME) {
|
|
8052
|
-
return
|
|
8167
|
+
return join14(process.env.XDG_CONFIG_HOME, "mcp-config.json");
|
|
8053
8168
|
}
|
|
8054
8169
|
return expandHome("~/.copilot/mcp-config.json");
|
|
8055
8170
|
}
|
|
@@ -8080,7 +8195,7 @@ var CopilotProvider = () => ({
|
|
|
8080
8195
|
};
|
|
8081
8196
|
installJSONServer(globalPath(), "mcpServers", server);
|
|
8082
8197
|
} else {
|
|
8083
|
-
const configPath =
|
|
8198
|
+
const configPath = join14(process.cwd(), ".vscode", "mcp.json");
|
|
8084
8199
|
const server = {
|
|
8085
8200
|
type: "http",
|
|
8086
8201
|
url,
|
|
@@ -8093,7 +8208,7 @@ var CopilotProvider = () => ({
|
|
|
8093
8208
|
if (global) {
|
|
8094
8209
|
removeJSONServer(globalPath(), "mcpServers");
|
|
8095
8210
|
} else {
|
|
8096
|
-
const configPath =
|
|
8211
|
+
const configPath = join14(process.cwd(), ".vscode", "mcp.json");
|
|
8097
8212
|
removeJSONServer(configPath, "servers");
|
|
8098
8213
|
}
|
|
8099
8214
|
}
|
|
@@ -8105,7 +8220,7 @@ var init_copilot = __esm(() => {
|
|
|
8105
8220
|
});
|
|
8106
8221
|
|
|
8107
8222
|
// src/mcp/providers/cursor.ts
|
|
8108
|
-
import { join as
|
|
8223
|
+
import { join as join15 } from "node:path";
|
|
8109
8224
|
var CursorProvider = () => createJSONProvider({
|
|
8110
8225
|
providerName: "Cursor",
|
|
8111
8226
|
providerID: "cursor",
|
|
@@ -8118,15 +8233,31 @@ var CursorProvider = () => createJSONProvider({
|
|
|
8118
8233
|
url: mcpURL(cfg.deployment_id),
|
|
8119
8234
|
headers: mcpHeaders(cfg.api_key)
|
|
8120
8235
|
}),
|
|
8121
|
-
localConfigPath: (cwd) =>
|
|
8236
|
+
localConfigPath: (cwd) => join15(cwd, ".cursor", "mcp.json")
|
|
8122
8237
|
});
|
|
8123
8238
|
var init_cursor = __esm(() => {
|
|
8124
8239
|
init_config_helpers();
|
|
8125
8240
|
init_base();
|
|
8126
8241
|
});
|
|
8127
8242
|
|
|
8243
|
+
// src/mcp/providers/factory.ts
|
|
8244
|
+
import { join as join16 } from "node:path";
|
|
8245
|
+
var FactoryProvider = () => createJSONProvider({
|
|
8246
|
+
providerName: "Factory",
|
|
8247
|
+
providerID: "factory",
|
|
8248
|
+
local: true,
|
|
8249
|
+
priorityValue: 17,
|
|
8250
|
+
paths: ["~/.factory"],
|
|
8251
|
+
globalPath: "~/.factory/mcp.json",
|
|
8252
|
+
topKey: "mcpServers",
|
|
8253
|
+
localConfigPath: (cwd) => join16(cwd, ".factory", "mcp.json")
|
|
8254
|
+
});
|
|
8255
|
+
var init_factory2 = __esm(() => {
|
|
8256
|
+
init_base();
|
|
8257
|
+
});
|
|
8258
|
+
|
|
8128
8259
|
// src/mcp/providers/gemini.ts
|
|
8129
|
-
import { join as
|
|
8260
|
+
import { join as join17 } from "node:path";
|
|
8130
8261
|
var GeminiProvider = () => createJSONProvider({
|
|
8131
8262
|
providerName: "Gemini CLI",
|
|
8132
8263
|
providerID: "gemini",
|
|
@@ -8135,7 +8266,7 @@ var GeminiProvider = () => createJSONProvider({
|
|
|
8135
8266
|
paths: ["~/.gemini"],
|
|
8136
8267
|
globalPath: "~/.gemini/settings.json",
|
|
8137
8268
|
topKey: "mcpServers",
|
|
8138
|
-
localConfigPath: (cwd) =>
|
|
8269
|
+
localConfigPath: (cwd) => join17(cwd, ".gemini", "settings.json")
|
|
8139
8270
|
});
|
|
8140
8271
|
var init_gemini = __esm(() => {
|
|
8141
8272
|
init_base();
|
|
@@ -8185,14 +8316,14 @@ var init_manual = __esm(() => {
|
|
|
8185
8316
|
});
|
|
8186
8317
|
|
|
8187
8318
|
// src/mcp/providers/mcporter.ts
|
|
8188
|
-
import { existsSync as
|
|
8189
|
-
import { join as
|
|
8319
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
8320
|
+
import { join as join18 } from "node:path";
|
|
8190
8321
|
function resolveGlobalConfigPath() {
|
|
8191
8322
|
const jsonPath = expandHome("~/.mcporter/mcporter.json");
|
|
8192
|
-
if (
|
|
8323
|
+
if (existsSync11(jsonPath))
|
|
8193
8324
|
return jsonPath;
|
|
8194
8325
|
const jsoncPath = expandHome("~/.mcporter/mcporter.jsonc");
|
|
8195
|
-
if (
|
|
8326
|
+
if (existsSync11(jsoncPath))
|
|
8196
8327
|
return jsoncPath;
|
|
8197
8328
|
return jsonPath;
|
|
8198
8329
|
}
|
|
@@ -8213,7 +8344,7 @@ var MCPorterProvider = () => ({
|
|
|
8213
8344
|
globalConfigPath: () => resolveGlobalConfigPath(),
|
|
8214
8345
|
isConfigured: () => isJSONKeyConfigured(resolveGlobalConfigPath(), "mcpServers"),
|
|
8215
8346
|
install(cfg, global) {
|
|
8216
|
-
const configPath = global ? resolveGlobalConfigPath() :
|
|
8347
|
+
const configPath = global ? resolveGlobalConfigPath() : join18(process.cwd(), "config", "mcporter.json");
|
|
8217
8348
|
const server = {
|
|
8218
8349
|
type: "http",
|
|
8219
8350
|
url: mcpEndpoint4(cfg),
|
|
@@ -8222,7 +8353,7 @@ var MCPorterProvider = () => ({
|
|
|
8222
8353
|
installJSONServer(configPath, "mcpServers", server);
|
|
8223
8354
|
},
|
|
8224
8355
|
remove(global) {
|
|
8225
|
-
const configPath = global ? resolveGlobalConfigPath() :
|
|
8356
|
+
const configPath = global ? resolveGlobalConfigPath() : join18(process.cwd(), "config", "mcporter.json");
|
|
8226
8357
|
removeJSONServer(configPath, "mcpServers");
|
|
8227
8358
|
}
|
|
8228
8359
|
});
|
|
@@ -8233,7 +8364,7 @@ var init_mcporter = __esm(() => {
|
|
|
8233
8364
|
});
|
|
8234
8365
|
|
|
8235
8366
|
// src/mcp/providers/opencode.ts
|
|
8236
|
-
import { join as
|
|
8367
|
+
import { join as join19 } from "node:path";
|
|
8237
8368
|
var OpenCodeProvider = () => createJSONProvider({
|
|
8238
8369
|
providerName: "OpenCode",
|
|
8239
8370
|
providerID: "opencode",
|
|
@@ -8248,7 +8379,7 @@ var OpenCodeProvider = () => createJSONProvider({
|
|
|
8248
8379
|
enabled: true,
|
|
8249
8380
|
headers: mcpHeaders(cfg.api_key)
|
|
8250
8381
|
}),
|
|
8251
|
-
localConfigPath: (cwd) =>
|
|
8382
|
+
localConfigPath: (cwd) => join19(cwd, "opencode.json")
|
|
8252
8383
|
});
|
|
8253
8384
|
var init_opencode = __esm(() => {
|
|
8254
8385
|
init_config_helpers();
|
|
@@ -8256,16 +8387,16 @@ var init_opencode = __esm(() => {
|
|
|
8256
8387
|
});
|
|
8257
8388
|
|
|
8258
8389
|
// src/mcp/providers/vscode.ts
|
|
8259
|
-
import { join as
|
|
8390
|
+
import { join as join20 } from "node:path";
|
|
8260
8391
|
var VSCodeProvider = () => createJSONProvider({
|
|
8261
8392
|
providerName: "VS Code",
|
|
8262
8393
|
providerID: "vscode",
|
|
8263
8394
|
local: true,
|
|
8264
8395
|
priorityValue: 6,
|
|
8265
|
-
paths: [
|
|
8266
|
-
globalPath:
|
|
8396
|
+
paths: [join20(appSupportDir(), "Code")],
|
|
8397
|
+
globalPath: join20(appSupportDir(), "Code", "User", "mcp.json"),
|
|
8267
8398
|
topKey: "servers",
|
|
8268
|
-
localConfigPath: (cwd) =>
|
|
8399
|
+
localConfigPath: (cwd) => join20(cwd, ".vscode", "mcp.json")
|
|
8269
8400
|
});
|
|
8270
8401
|
var init_vscode = __esm(() => {
|
|
8271
8402
|
init_detect();
|
|
@@ -8274,14 +8405,14 @@ var init_vscode = __esm(() => {
|
|
|
8274
8405
|
|
|
8275
8406
|
// src/mcp/providers/windsurf.ts
|
|
8276
8407
|
import { homedir as homedir2 } from "node:os";
|
|
8277
|
-
import { join as
|
|
8408
|
+
import { join as join21 } from "node:path";
|
|
8278
8409
|
var WindsurfProvider = () => createJSONProvider({
|
|
8279
8410
|
providerName: "Windsurf",
|
|
8280
8411
|
providerID: "windsurf",
|
|
8281
8412
|
local: false,
|
|
8282
8413
|
priorityValue: 9,
|
|
8283
|
-
paths: [
|
|
8284
|
-
globalPath:
|
|
8414
|
+
paths: [join21(homedir2(), ".codeium", "windsurf")],
|
|
8415
|
+
globalPath: join21(homedir2(), ".codeium", "windsurf", "mcp_config.json"),
|
|
8285
8416
|
topKey: "mcpServers"
|
|
8286
8417
|
});
|
|
8287
8418
|
var init_windsurf = __esm(() => {
|
|
@@ -8290,12 +8421,12 @@ var init_windsurf = __esm(() => {
|
|
|
8290
8421
|
|
|
8291
8422
|
// src/mcp/providers/zed.ts
|
|
8292
8423
|
import { platform as platform2 } from "node:os";
|
|
8293
|
-
import { join as
|
|
8424
|
+
import { join as join22 } from "node:path";
|
|
8294
8425
|
function zedConfigDir() {
|
|
8295
8426
|
const os = platform2();
|
|
8296
8427
|
if (os === "darwin" || os === "win32")
|
|
8297
|
-
return
|
|
8298
|
-
return
|
|
8428
|
+
return join22(appSupportDir(), "Zed");
|
|
8429
|
+
return join22(appSupportDir(), "zed");
|
|
8299
8430
|
}
|
|
8300
8431
|
var ZedProvider = () => createJSONProvider({
|
|
8301
8432
|
providerName: "Zed",
|
|
@@ -8303,7 +8434,7 @@ var ZedProvider = () => createJSONProvider({
|
|
|
8303
8434
|
local: true,
|
|
8304
8435
|
priorityValue: 10,
|
|
8305
8436
|
paths: [zedConfigDir()],
|
|
8306
|
-
globalPath:
|
|
8437
|
+
globalPath: join22(zedConfigDir(), "settings.json"),
|
|
8307
8438
|
topKey: "context_servers",
|
|
8308
8439
|
buildServer: (cfg) => ({
|
|
8309
8440
|
source: "custom",
|
|
@@ -8311,7 +8442,7 @@ var ZedProvider = () => createJSONProvider({
|
|
|
8311
8442
|
url: mcpURL(cfg.deployment_id),
|
|
8312
8443
|
headers: mcpHeaders(cfg.api_key)
|
|
8313
8444
|
}),
|
|
8314
|
-
localConfigPath: (cwd) =>
|
|
8445
|
+
localConfigPath: (cwd) => join22(cwd, ".zed", "settings.json")
|
|
8315
8446
|
});
|
|
8316
8447
|
var init_zed = __esm(() => {
|
|
8317
8448
|
init_config_helpers();
|
|
@@ -8336,6 +8467,7 @@ function allProviders() {
|
|
|
8336
8467
|
OpenCodeProvider(),
|
|
8337
8468
|
AntigravityProvider(),
|
|
8338
8469
|
MCPorterProvider(),
|
|
8470
|
+
FactoryProvider(),
|
|
8339
8471
|
ManualProvider()
|
|
8340
8472
|
];
|
|
8341
8473
|
}
|
|
@@ -8358,6 +8490,7 @@ var init_providers = __esm(() => {
|
|
|
8358
8490
|
init_codex2();
|
|
8359
8491
|
init_copilot();
|
|
8360
8492
|
init_cursor();
|
|
8493
|
+
init_factory2();
|
|
8361
8494
|
init_gemini();
|
|
8362
8495
|
init_manual();
|
|
8363
8496
|
init_mcporter();
|
|
@@ -10859,8 +10992,22 @@ async function startOAuthFlow(signal, path2 = "/cli/auth", params = {}) {
|
|
|
10859
10992
|
const authURL = buildAuthURL(callbackURL, path2, params);
|
|
10860
10993
|
logger.info("auth.flow", `Auth URL: ${authURL}`);
|
|
10861
10994
|
const open2 = await Promise.resolve().then(() => (init_open(), exports_open));
|
|
10862
|
-
|
|
10863
|
-
|
|
10995
|
+
let browserOpened = false;
|
|
10996
|
+
try {
|
|
10997
|
+
await open2.default(authURL);
|
|
10998
|
+
browserOpened = true;
|
|
10999
|
+
logger.info("auth.flow", "Browser open command executed");
|
|
11000
|
+
} catch (openErr) {
|
|
11001
|
+
logger.warn("auth.flow", `Could not open browser automatically: ${openErr instanceof Error ? openErr.message : String(openErr)}`);
|
|
11002
|
+
}
|
|
11003
|
+
if (!browserOpened) {
|
|
11004
|
+
console.log(`
|
|
11005
|
+
Could not open a browser automatically.`);
|
|
11006
|
+
console.log(`Please open this URL in your browser to log in:
|
|
11007
|
+
`);
|
|
11008
|
+
console.log(` ${authURL}
|
|
11009
|
+
`);
|
|
11010
|
+
}
|
|
10864
11011
|
const timeout = new Promise((_3, reject) => {
|
|
10865
11012
|
timeoutId = setTimeout(() => {
|
|
10866
11013
|
logger.warn("auth.flow", "Authentication timed out (8min)");
|
|
@@ -10904,8 +11051,8 @@ __export(exports_flow2, {
|
|
|
10904
11051
|
isStdioOnly: () => isStdioOnly
|
|
10905
11052
|
});
|
|
10906
11053
|
import { randomUUID } from "node:crypto";
|
|
10907
|
-
import { existsSync as
|
|
10908
|
-
import { join as
|
|
11054
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
11055
|
+
import { join as join23 } from "node:path";
|
|
10909
11056
|
async function runSetup(opts = {}) {
|
|
10910
11057
|
const onboardingRunID = randomUUID();
|
|
10911
11058
|
logger.info("setup", `Setup flow started${opts.deploymentID ? ` deployment=${opts.deploymentID}` : ""}${opts.mode ? ` mode=${opts.mode}` : ""}`);
|
|
@@ -11077,7 +11224,7 @@ async function runSetup(opts = {}) {
|
|
|
11077
11224
|
showTryItOutPrompt({
|
|
11078
11225
|
mode: cfg.mode,
|
|
11079
11226
|
docsImported: choices.connectGitHub && githubOnboardingDone,
|
|
11080
|
-
hasAgentsMd:
|
|
11227
|
+
hasAgentsMd: existsSync12(join23(process.cwd(), "AGENTS.md"))
|
|
11081
11228
|
});
|
|
11082
11229
|
}
|
|
11083
11230
|
if (mcpCompleted || skillCompleted || docsImported) {
|
|
@@ -11571,8 +11718,8 @@ var init_flow2 = __esm(() => {
|
|
|
11571
11718
|
});
|
|
11572
11719
|
|
|
11573
11720
|
// src/commands/insights.ts
|
|
11574
|
-
import { existsSync as
|
|
11575
|
-
import { dirname as dirname3, join as
|
|
11721
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6, readdirSync, unlinkSync, writeFileSync as writeFileSync5 } from "node:fs";
|
|
11722
|
+
import { dirname as dirname3, join as join24 } from "node:path";
|
|
11576
11723
|
function shuffled(arr) {
|
|
11577
11724
|
const copy2 = [...arr];
|
|
11578
11725
|
for (let i = copy2.length - 1;i > 0; i--) {
|
|
@@ -11676,17 +11823,17 @@ function makeAskFn(cfg) {
|
|
|
11676
11823
|
};
|
|
11677
11824
|
}
|
|
11678
11825
|
function insightsDir() {
|
|
11679
|
-
return
|
|
11826
|
+
return join24(getConfigDir(), "insights");
|
|
11680
11827
|
}
|
|
11681
11828
|
function reportPath(timestamp) {
|
|
11682
11829
|
const dir = insightsDir();
|
|
11683
11830
|
if (!timestamp)
|
|
11684
|
-
return
|
|
11831
|
+
return join24(dir, "latest.html");
|
|
11685
11832
|
const iso = timestamp.toISOString().slice(0, 19).replace(/:/g, "-");
|
|
11686
|
-
return
|
|
11833
|
+
return join24(dir, `report-${iso}Z.html`);
|
|
11687
11834
|
}
|
|
11688
11835
|
function pruneOldReports(dir, keepN) {
|
|
11689
|
-
if (!
|
|
11836
|
+
if (!existsSync13(dir))
|
|
11690
11837
|
return;
|
|
11691
11838
|
let entries;
|
|
11692
11839
|
try {
|
|
@@ -11698,7 +11845,7 @@ function pruneOldReports(dir, keepN) {
|
|
|
11698
11845
|
const reports = entries.filter((f) => REPORT_FILE_PATTERN.test(f)).sort().reverse();
|
|
11699
11846
|
for (const f of reports.slice(keepN)) {
|
|
11700
11847
|
try {
|
|
11701
|
-
unlinkSync(
|
|
11848
|
+
unlinkSync(join24(dir, f));
|
|
11702
11849
|
} catch (err) {
|
|
11703
11850
|
logger.debug("insights", `failed to prune ${f}: ${err instanceof Error ? err.message : err}`);
|
|
11704
11851
|
}
|
|
@@ -11771,7 +11918,7 @@ function defaultRunner(cfg) {
|
|
|
11771
11918
|
render: renderHTML,
|
|
11772
11919
|
writeFile: (path2, content) => {
|
|
11773
11920
|
const dir = dirname3(path2);
|
|
11774
|
-
if (!
|
|
11921
|
+
if (!existsSync13(dir))
|
|
11775
11922
|
mkdirSync6(dir, { recursive: true, mode: 448 });
|
|
11776
11923
|
writeFileSync5(path2, content, { mode: 384 });
|
|
11777
11924
|
},
|
|
@@ -12436,7 +12583,7 @@ var init_flow3 = __esm(() => {
|
|
|
12436
12583
|
// src/cli/cli.ts
|
|
12437
12584
|
init_esm();
|
|
12438
12585
|
init_client();
|
|
12439
|
-
import { readFileSync as
|
|
12586
|
+
import { readFileSync as readFileSync13, unlinkSync as unlinkSync2 } from "node:fs";
|
|
12440
12587
|
|
|
12441
12588
|
// src/commands/analytics.ts
|
|
12442
12589
|
init_esm();
|
|
@@ -13122,7 +13269,7 @@ init_esm();
|
|
|
13122
13269
|
init_config();
|
|
13123
13270
|
init_logger();
|
|
13124
13271
|
init_prompts();
|
|
13125
|
-
import { readFileSync as
|
|
13272
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
13126
13273
|
import { basename } from "node:path";
|
|
13127
13274
|
|
|
13128
13275
|
// src/hooks/state.ts
|
|
@@ -13161,7 +13308,7 @@ var COOLDOWN_DEFAULT_MS = 3000;
|
|
|
13161
13308
|
var TTL_DEFAULT_MS = 10 * 60 * 1000;
|
|
13162
13309
|
var STOP_WAIT_DEFAULT_MS = 8000;
|
|
13163
13310
|
var STOP_POLL_DEFAULT_MS = 1000;
|
|
13164
|
-
var SUPPORTED_AGENTS = ["claude-code", "codex"];
|
|
13311
|
+
var SUPPORTED_AGENTS = ["claude-code", "codex", "factory"];
|
|
13165
13312
|
var DEFAULT_AGENT = "claude-code";
|
|
13166
13313
|
function cooldownMs() {
|
|
13167
13314
|
const n = Number.parseInt(process.env.DOSU_HOOK_CHECK_COOLDOWN_MS ?? "", 10);
|
|
@@ -13391,7 +13538,7 @@ async function runHookEntrypoint(event, raw, now = Date.now(), agent = DEFAULT_A
|
|
|
13391
13538
|
}
|
|
13392
13539
|
function readStdinRaw() {
|
|
13393
13540
|
try {
|
|
13394
|
-
return
|
|
13541
|
+
return readFileSync9(0, "utf8");
|
|
13395
13542
|
} catch {
|
|
13396
13543
|
return "";
|
|
13397
13544
|
}
|
|
@@ -13439,6 +13586,20 @@ async function runInstall(agent, opts) {
|
|
|
13439
13586
|
}
|
|
13440
13587
|
return;
|
|
13441
13588
|
}
|
|
13589
|
+
if (agent === "factory") {
|
|
13590
|
+
const { installFactoryHooks: installFactoryHooks2, factoryHooksPath: factoryHooksPath2 } = await Promise.resolve().then(() => (init_factory(), exports_factory));
|
|
13591
|
+
const configPath2 = factoryHooksPath2(resolveDir(opts.dir));
|
|
13592
|
+
const { events: events2 } = installFactoryHooks2(configPath2, { stop: opts.stop });
|
|
13593
|
+
if (opts.json) {
|
|
13594
|
+
const { emitStep: emitStep2 } = await Promise.resolve().then(() => exports_output);
|
|
13595
|
+
emitStep2({ step: "hooks-install", agent, path: configPath2, events: events2 });
|
|
13596
|
+
} else {
|
|
13597
|
+
console.log(`✓ Installed Dosu hooks for Factory (${events2.join(", ")}).`);
|
|
13598
|
+
console.log(` → ${configPath2}`);
|
|
13599
|
+
console.log(" Start a new Factory session in this project to use them.");
|
|
13600
|
+
}
|
|
13601
|
+
return;
|
|
13602
|
+
}
|
|
13442
13603
|
const { installClaudeHooks: installClaudeHooks2, claudeLocalSettingsPath: claudeLocalSettingsPath2 } = await Promise.resolve().then(() => (init_claude_code(), exports_claude_code));
|
|
13443
13604
|
const configPath = claudeLocalSettingsPath2(resolveDir(opts.dir));
|
|
13444
13605
|
const { events } = installClaudeHooks2(configPath, { stop: opts.stop });
|
|
@@ -13476,6 +13637,10 @@ async function runUninstall(agent, opts) {
|
|
|
13476
13637
|
const { removeCodexHooks: removeCodexHooks2, codexHooksPath: codexHooksPath2 } = await Promise.resolve().then(() => (init_codex(), exports_codex));
|
|
13477
13638
|
configPath = codexHooksPath2(resolveDir(opts.dir));
|
|
13478
13639
|
({ removed } = removeCodexHooks2(configPath));
|
|
13640
|
+
} else if (agent === "factory") {
|
|
13641
|
+
const { removeFactoryHooks: removeFactoryHooks2, factoryHooksPath: factoryHooksPath2 } = await Promise.resolve().then(() => (init_factory(), exports_factory));
|
|
13642
|
+
configPath = factoryHooksPath2(resolveDir(opts.dir));
|
|
13643
|
+
({ removed } = removeFactoryHooks2(configPath));
|
|
13479
13644
|
} else {
|
|
13480
13645
|
const { removeClaudeHooks: removeClaudeHooks2, claudeLocalSettingsPath: claudeLocalSettingsPath2 } = await Promise.resolve().then(() => (init_claude_code(), exports_claude_code));
|
|
13481
13646
|
configPath = claudeLocalSettingsPath2(resolveDir(opts.dir));
|
|
@@ -13494,15 +13659,20 @@ async function collectDoctorChecks(opts) {
|
|
|
13494
13659
|
const checks = [];
|
|
13495
13660
|
const { claudeLocalSettingsPath: claudeLocalSettingsPath2, inspectClaudeHooks: inspectClaudeHooks2 } = await Promise.resolve().then(() => (init_claude_code(), exports_claude_code));
|
|
13496
13661
|
const { codexHooksPath: codexHooksPath2, inspectCodexHooks: inspectCodexHooks2 } = await Promise.resolve().then(() => (init_codex(), exports_codex));
|
|
13662
|
+
const { factoryHooksPath: factoryHooksPath2, inspectFactoryHooks: inspectFactoryHooks2 } = await Promise.resolve().then(() => (init_factory(), exports_factory));
|
|
13497
13663
|
const configPath = claudeLocalSettingsPath2(resolveDir(opts.dir));
|
|
13498
13664
|
const inspection = inspectClaudeHooks2(configPath);
|
|
13499
13665
|
const codexPath = codexHooksPath2(resolveDir(opts.dir));
|
|
13500
13666
|
const codex = inspectCodexHooks2(codexPath);
|
|
13667
|
+
const factoryPath = factoryHooksPath2(resolveDir(opts.dir));
|
|
13668
|
+
const factory = inspectFactoryHooks2(factoryPath);
|
|
13501
13669
|
const codexInstalled = codex.events.includes("UserPromptSubmit") && codex.events.includes("PostToolUse");
|
|
13670
|
+
const factoryInstalled = factory.events.includes("UserPromptSubmit") && factory.events.includes("PostToolUse");
|
|
13671
|
+
const alternativeInstalled = codexInstalled || factoryInstalled;
|
|
13502
13672
|
if (!inspection.fileExists) {
|
|
13503
13673
|
checks.push({
|
|
13504
13674
|
name: "config",
|
|
13505
|
-
status:
|
|
13675
|
+
status: alternativeInstalled ? "warn" : "fail",
|
|
13506
13676
|
detail: `not found: ${configPath} (run 'dosu hooks install claude-code')`
|
|
13507
13677
|
});
|
|
13508
13678
|
} else if (inspection.parseError) {
|
|
@@ -13521,7 +13691,7 @@ async function collectDoctorChecks(opts) {
|
|
|
13521
13691
|
} else {
|
|
13522
13692
|
checks.push({
|
|
13523
13693
|
name: "hooks",
|
|
13524
|
-
status:
|
|
13694
|
+
status: alternativeInstalled ? "warn" : "fail",
|
|
13525
13695
|
detail: "UserPromptSubmit + PostToolUse not both installed"
|
|
13526
13696
|
});
|
|
13527
13697
|
}
|
|
@@ -13547,6 +13717,27 @@ async function collectDoctorChecks(opts) {
|
|
|
13547
13717
|
});
|
|
13548
13718
|
}
|
|
13549
13719
|
}
|
|
13720
|
+
if (factory.fileExists) {
|
|
13721
|
+
if (factory.parseError) {
|
|
13722
|
+
checks.push({
|
|
13723
|
+
name: "factory-config",
|
|
13724
|
+
status: "fail",
|
|
13725
|
+
detail: `invalid JSON: ${factoryPath}`
|
|
13726
|
+
});
|
|
13727
|
+
} else if (factoryInstalled) {
|
|
13728
|
+
checks.push({
|
|
13729
|
+
name: "factory-config",
|
|
13730
|
+
status: "ok",
|
|
13731
|
+
detail: `installed: ${factory.events.join(", ")} (${factoryPath})`
|
|
13732
|
+
});
|
|
13733
|
+
} else {
|
|
13734
|
+
checks.push({
|
|
13735
|
+
name: "factory-config",
|
|
13736
|
+
status: "fail",
|
|
13737
|
+
detail: "UserPromptSubmit + PostToolUse not both installed"
|
|
13738
|
+
});
|
|
13739
|
+
}
|
|
13740
|
+
}
|
|
13550
13741
|
const cfg = loadConfig();
|
|
13551
13742
|
if (isAuthenticated(cfg)) {
|
|
13552
13743
|
checks.push({ name: "auth", status: "ok", detail: "logged in" });
|
|
@@ -13601,7 +13792,7 @@ async function runDoctor(opts) {
|
|
|
13601
13792
|
}
|
|
13602
13793
|
}
|
|
13603
13794
|
function hooksCommand() {
|
|
13604
|
-
const cmd = new Command("hooks").description("Dosu knowledge-injection hooks for coding agents (Claude Code, Codex)");
|
|
13795
|
+
const cmd = new Command("hooks").description("Dosu knowledge-injection hooks for coding agents (Claude Code, Codex, Factory)");
|
|
13605
13796
|
cmd.command("user-prompt-submit").description("Hook entrypoint: create a knowledge ticket on prompt submit").option("--agent <agent>", "Calling agent for ticket attribution", DEFAULT_AGENT).action(async (opts) => {
|
|
13606
13797
|
await runHookEntrypoint("user-prompt-submit", readStdinRaw(), Date.now(), opts.agent);
|
|
13607
13798
|
});
|
|
@@ -13628,6 +13819,7 @@ function hooksCommand() {
|
|
|
13628
13819
|
"Examples:",
|
|
13629
13820
|
" $ dosu hooks install claude-code",
|
|
13630
13821
|
" $ dosu hooks install codex",
|
|
13822
|
+
" $ dosu hooks install factory",
|
|
13631
13823
|
" $ dosu hooks install claude-code --no-stop",
|
|
13632
13824
|
" $ dosu hooks install codex --dir ./my-project",
|
|
13633
13825
|
"",
|
|
@@ -13641,7 +13833,8 @@ function hooksCommand() {
|
|
|
13641
13833
|
"",
|
|
13642
13834
|
"Examples:",
|
|
13643
13835
|
" $ dosu hooks uninstall claude-code",
|
|
13644
|
-
" $ dosu hooks uninstall codex"
|
|
13836
|
+
" $ dosu hooks uninstall codex",
|
|
13837
|
+
" $ dosu hooks uninstall factory"
|
|
13645
13838
|
].join(`
|
|
13646
13839
|
`)).action((agent, opts) => runUninstall(agent, opts));
|
|
13647
13840
|
cmd.command("doctor").description("Diagnose Dosu hook config, auth, deployment, and backend connectivity").option("--dir <path>", "Project root (defaults to current directory)").option("--json", "Emit machine-readable JSON", false).action((opts) => runDoctor(opts));
|
|
@@ -14477,8 +14670,8 @@ init_skill_update_check();
|
|
|
14477
14670
|
init_config();
|
|
14478
14671
|
init_logger();
|
|
14479
14672
|
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
14480
|
-
import { existsSync as
|
|
14481
|
-
import { join as
|
|
14673
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync12, writeFileSync as writeFileSync6 } from "node:fs";
|
|
14674
|
+
import { join as join25 } from "node:path";
|
|
14482
14675
|
var CACHE_FILENAME2 = "update-check.json";
|
|
14483
14676
|
var CHECK_INTERVAL_MS2 = 24 * 60 * 60 * 1000;
|
|
14484
14677
|
var FETCH_TIMEOUT_MS2 = 5000;
|
|
@@ -14501,14 +14694,14 @@ function isNewerVersion(latest, current) {
|
|
|
14501
14694
|
return false;
|
|
14502
14695
|
}
|
|
14503
14696
|
function getCachePath2() {
|
|
14504
|
-
return
|
|
14697
|
+
return join25(getConfigDir(), CACHE_FILENAME2);
|
|
14505
14698
|
}
|
|
14506
14699
|
function readCache() {
|
|
14507
14700
|
try {
|
|
14508
14701
|
const path2 = getCachePath2();
|
|
14509
|
-
if (!
|
|
14702
|
+
if (!existsSync14(path2))
|
|
14510
14703
|
return null;
|
|
14511
|
-
const data = JSON.parse(
|
|
14704
|
+
const data = JSON.parse(readFileSync12(path2, "utf-8"));
|
|
14512
14705
|
if (typeof data.lastCheck === "number" && typeof data.latestVersion === "string") {
|
|
14513
14706
|
return data;
|
|
14514
14707
|
}
|
|
@@ -14520,7 +14713,7 @@ function readCache() {
|
|
|
14520
14713
|
function writeCache(cache) {
|
|
14521
14714
|
try {
|
|
14522
14715
|
const dir = getConfigDir();
|
|
14523
|
-
if (!
|
|
14716
|
+
if (!existsSync14(dir)) {
|
|
14524
14717
|
mkdirSync7(dir, { recursive: true, mode: 448 });
|
|
14525
14718
|
}
|
|
14526
14719
|
writeFileSync6(getCachePath2(), JSON.stringify(cache), { mode: 384 });
|
|
@@ -14810,7 +15003,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
|
|
|
14810
15003
|
if (opts.tail !== undefined) {
|
|
14811
15004
|
const n = typeof opts.tail === "string" ? parseInt(opts.tail, 10) || 50 : 50;
|
|
14812
15005
|
try {
|
|
14813
|
-
const content =
|
|
15006
|
+
const content = readFileSync13(logPath, "utf-8");
|
|
14814
15007
|
const lines = content.split(`
|
|
14815
15008
|
`);
|
|
14816
15009
|
console.log(lines.slice(-n).join(`
|