@dosu/cli 0.18.1 → 0.19.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 +343 -152
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -2151,7 +2151,7 @@ function getSupabaseURL() {
|
|
|
2151
2151
|
return process.env.SUPABASE_URL_OVERRIDE ?? "https://wldmetsoicvieidlsqrb.supabase.co" ?? "";
|
|
2152
2152
|
}
|
|
2153
2153
|
function getSupabaseAnonKey() {
|
|
2154
|
-
return process.env.SUPABASE_ANON_KEY_OVERRIDE ?? "
|
|
2154
|
+
return process.env.SUPABASE_ANON_KEY_OVERRIDE ?? "sb_publishable_NePQHMbqqlFOp1aaHbp5Bg_zyA-kYd6" ?? "";
|
|
2155
2155
|
}
|
|
2156
2156
|
|
|
2157
2157
|
// src/client/client.ts
|
|
@@ -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.19.1";
|
|
4552
4552
|
|
|
4553
4553
|
// src/debug/logger.ts
|
|
4554
4554
|
import {
|
|
@@ -5444,6 +5444,45 @@ var init_dist6 = __esm(() => {
|
|
|
5444
5444
|
J2 = `${import_picocolors7.default.gray(o)} `;
|
|
5445
5445
|
});
|
|
5446
5446
|
|
|
5447
|
+
// src/hooks/prompts.ts
|
|
5448
|
+
var exports_prompts = {};
|
|
5449
|
+
__export(exports_prompts, {
|
|
5450
|
+
buildReadyEnvelope: () => buildReadyEnvelope,
|
|
5451
|
+
STOP_PREFIX: () => STOP_PREFIX,
|
|
5452
|
+
SAVE_NUDGE: () => SAVE_NUDGE,
|
|
5453
|
+
LOOKUP_STARTED_NOTE: () => LOOKUP_STARTED_NOTE
|
|
5454
|
+
});
|
|
5455
|
+
function buildReadyEnvelope(context, saveRecommended = false) {
|
|
5456
|
+
const trimmed = context.trim();
|
|
5457
|
+
const blocks = [];
|
|
5458
|
+
if (trimmed) {
|
|
5459
|
+
blocks.push([
|
|
5460
|
+
"Dosu knowledge context for this task:",
|
|
5461
|
+
"",
|
|
5462
|
+
trimmed,
|
|
5463
|
+
"",
|
|
5464
|
+
"How to use this:",
|
|
5465
|
+
"- Use it quietly to answer faster and with fewer broad searches. Keep working normally.",
|
|
5466
|
+
"- This is the known likely path, not the full boundary. Before finalizing, verify adjacent " + "public/API entrypoints and edge cases that this route map may not cover.",
|
|
5467
|
+
"- Attribution: this context is your team's existing knowledge (docs, past PRs, discussions) " + "surfaced by Dosu — not the live code you're reading. For each main finding it speaks to, " + "add one brief cited note on how the team's knowledge relates: if it agrees, note it in a " + "line and cite the source; if it differs, flag it as worth confirming and reconcile before " + "finalizing; if it adds something the code alone wouldn't tell you (a rationale, a gotcha, " + "a past decision), surface it, cited.",
|
|
5468
|
+
"- Surface this at each main finding the context speaks to — but skip the ones it is " + "genuinely silent on, and never invent agreement or disagreement. Keep each note brief and " + 'next to the finding; do not open with "Dosu told me…", do not add a closing praise ' + "paragraph, and do not reference any ticket or lookup id."
|
|
5469
|
+
].join(`
|
|
5470
|
+
`));
|
|
5471
|
+
}
|
|
5472
|
+
if (saveRecommended) {
|
|
5473
|
+
blocks.push(SAVE_NUDGE);
|
|
5474
|
+
}
|
|
5475
|
+
return blocks.join(`
|
|
5476
|
+
|
|
5477
|
+
`);
|
|
5478
|
+
}
|
|
5479
|
+
var LOOKUP_STARTED_NOTE, STOP_PREFIX, SAVE_NUDGE;
|
|
5480
|
+
var init_prompts = __esm(() => {
|
|
5481
|
+
LOOKUP_STARTED_NOTE = "Dosu started a background knowledge lookup for this request. Keep working normally — " + "do not wait or pause for it. If Dosu context arrives during this session, fold it in " + "quietly to work faster and avoid wrong assumptions. Mention Dosu when its context " + "helps you.";
|
|
5482
|
+
STOP_PREFIX = "Dosu knowledge finished after your last action. Re-check your current conclusion against " + "it, then continue or finish — do not redo work it merely confirms.";
|
|
5483
|
+
SAVE_NUDGE = "Dosu has little or no existing knowledge on this topic. If you uncover something durable — " + "a non-obvious mechanism, a gotcha, or a route through the code — save it with the Dosu " + "`save_topic` tool when you finish, so future sessions start ahead. Only save genuinely " + "reusable knowledge; skip trivial or one-off details.";
|
|
5484
|
+
});
|
|
5485
|
+
|
|
5447
5486
|
// src/hooks/ticket-client.ts
|
|
5448
5487
|
var exports_ticket_client = {};
|
|
5449
5488
|
__export(exports_ticket_client, {
|
|
@@ -5494,45 +5533,6 @@ var init_ticket_client = __esm(() => {
|
|
|
5494
5533
|
};
|
|
5495
5534
|
});
|
|
5496
5535
|
|
|
5497
|
-
// src/hooks/prompts.ts
|
|
5498
|
-
var exports_prompts = {};
|
|
5499
|
-
__export(exports_prompts, {
|
|
5500
|
-
buildReadyEnvelope: () => buildReadyEnvelope,
|
|
5501
|
-
STOP_PREFIX: () => STOP_PREFIX,
|
|
5502
|
-
SAVE_NUDGE: () => SAVE_NUDGE,
|
|
5503
|
-
LOOKUP_STARTED_NOTE: () => LOOKUP_STARTED_NOTE
|
|
5504
|
-
});
|
|
5505
|
-
function buildReadyEnvelope(context, saveRecommended = false) {
|
|
5506
|
-
const trimmed = context.trim();
|
|
5507
|
-
const blocks = [];
|
|
5508
|
-
if (trimmed) {
|
|
5509
|
-
blocks.push([
|
|
5510
|
-
"Dosu knowledge context for this task:",
|
|
5511
|
-
"",
|
|
5512
|
-
trimmed,
|
|
5513
|
-
"",
|
|
5514
|
-
"How to use this:",
|
|
5515
|
-
"- Use it quietly to answer faster and with fewer broad searches. Keep working normally.",
|
|
5516
|
-
"- This is the known likely path, not the full boundary. Before finalizing, verify adjacent " + "public/API entrypoints and edge cases that this route map may not cover.",
|
|
5517
|
-
"- Attribution: this context is your team's existing knowledge (docs, past PRs, discussions) " + "surfaced by Dosu — not the live code you're reading. For each main finding it speaks to, " + "add one brief cited note on how the team's knowledge relates: if it agrees, note it in a " + "line and cite the source; if it differs, flag it as worth confirming and reconcile before " + "finalizing; if it adds something the code alone wouldn't tell you (a rationale, a gotcha, " + "a past decision), surface it, cited.",
|
|
5518
|
-
"- Surface this at each main finding the context speaks to — but skip the ones it is " + "genuinely silent on, and never invent agreement or disagreement. Keep each note brief and " + 'next to the finding; do not open with "Dosu told me…", do not add a closing praise ' + "paragraph, and do not reference any ticket or lookup id."
|
|
5519
|
-
].join(`
|
|
5520
|
-
`));
|
|
5521
|
-
}
|
|
5522
|
-
if (saveRecommended) {
|
|
5523
|
-
blocks.push(SAVE_NUDGE);
|
|
5524
|
-
}
|
|
5525
|
-
return blocks.join(`
|
|
5526
|
-
|
|
5527
|
-
`);
|
|
5528
|
-
}
|
|
5529
|
-
var LOOKUP_STARTED_NOTE, STOP_PREFIX, SAVE_NUDGE;
|
|
5530
|
-
var init_prompts = __esm(() => {
|
|
5531
|
-
LOOKUP_STARTED_NOTE = "Dosu started a background knowledge lookup for this request. Keep working normally — " + "do not wait or pause for it. If Dosu context arrives during this session, fold it in " + "quietly to work faster and avoid wrong assumptions. Mention Dosu when its context " + "helps you.";
|
|
5532
|
-
STOP_PREFIX = "Dosu knowledge finished after your last action. Re-check your current conclusion against " + "it, then continue or finish — do not redo work it merely confirms.";
|
|
5533
|
-
SAVE_NUDGE = "Dosu has little or no existing knowledge on this topic. If you uncover something durable — " + "a non-obvious mechanism, a gotcha, or a route through the code — save it with the Dosu " + "`save_topic` tool when you finish, so future sessions start ahead. Only save genuinely " + "reusable knowledge; skip trivial or one-off details.";
|
|
5534
|
-
});
|
|
5535
|
-
|
|
5536
5536
|
// src/agent/output.ts
|
|
5537
5537
|
var exports_output = {};
|
|
5538
5538
|
__export(exports_output, {
|
|
@@ -6344,6 +6344,135 @@ var init_claude_code = __esm(() => {
|
|
|
6344
6344
|
};
|
|
6345
6345
|
});
|
|
6346
6346
|
|
|
6347
|
+
// src/hooks/codex.ts
|
|
6348
|
+
var exports_codex = {};
|
|
6349
|
+
__export(exports_codex, {
|
|
6350
|
+
removeCodexHooks: () => removeCodexHooks,
|
|
6351
|
+
installCodexHooks: () => installCodexHooks,
|
|
6352
|
+
inspectCodexHooks: () => inspectCodexHooks,
|
|
6353
|
+
codexHooksPath: () => codexHooksPath,
|
|
6354
|
+
codexHookCommand: () => codexHookCommand
|
|
6355
|
+
});
|
|
6356
|
+
import { existsSync as existsSync6, readFileSync as readFileSync7 } from "node:fs";
|
|
6357
|
+
import { join as join5 } from "node:path";
|
|
6358
|
+
function codexHooksPath(dir) {
|
|
6359
|
+
return join5(dir, ".codex", "hooks.json");
|
|
6360
|
+
}
|
|
6361
|
+
function codexHookCommand(subcommand) {
|
|
6362
|
+
return `dosu hooks ${subcommand} --agent codex`;
|
|
6363
|
+
}
|
|
6364
|
+
function dosuGroup2(event) {
|
|
6365
|
+
return {
|
|
6366
|
+
hooks: [
|
|
6367
|
+
{
|
|
6368
|
+
type: "command",
|
|
6369
|
+
command: codexHookCommand(EVENT_SUBCOMMAND2[event]),
|
|
6370
|
+
timeout: EVENT_TIMEOUT_SEC[event],
|
|
6371
|
+
statusMessage: EVENT_STATUS_MESSAGE[event]
|
|
6372
|
+
}
|
|
6373
|
+
]
|
|
6374
|
+
};
|
|
6375
|
+
}
|
|
6376
|
+
function readHooksFileOrThrow(path) {
|
|
6377
|
+
if (!existsSync6(path))
|
|
6378
|
+
return {};
|
|
6379
|
+
const raw = readFileSync7(path, "utf-8").trim();
|
|
6380
|
+
if (!raw)
|
|
6381
|
+
return {};
|
|
6382
|
+
try {
|
|
6383
|
+
return JSON.parse(raw);
|
|
6384
|
+
} catch {
|
|
6385
|
+
throw new Error(`refusing to modify ${path}: file exists but is not valid JSON`);
|
|
6386
|
+
}
|
|
6387
|
+
}
|
|
6388
|
+
function installCodexHooks(configPath, opts = {}) {
|
|
6389
|
+
const config = readHooksFileOrThrow(configPath);
|
|
6390
|
+
const events = DEFAULT_HOOK_EVENTS.filter((e2) => e2 !== "Stop" || opts.stop !== false);
|
|
6391
|
+
const hooks = typeof config.hooks === "object" && config.hooks ? config.hooks : {};
|
|
6392
|
+
for (const event of events) {
|
|
6393
|
+
const groups = Array.isArray(hooks[event]) ? hooks[event] : [];
|
|
6394
|
+
const kept = groups.filter((g2) => !isDosuGroup(g2));
|
|
6395
|
+
kept.push(dosuGroup2(event));
|
|
6396
|
+
hooks[event] = kept;
|
|
6397
|
+
}
|
|
6398
|
+
for (const event of DEFAULT_HOOK_EVENTS) {
|
|
6399
|
+
if (!events.includes(event) && Array.isArray(hooks[event])) {
|
|
6400
|
+
const kept = hooks[event].filter((g2) => !isDosuGroup(g2));
|
|
6401
|
+
if (kept.length > 0)
|
|
6402
|
+
hooks[event] = kept;
|
|
6403
|
+
else
|
|
6404
|
+
delete hooks[event];
|
|
6405
|
+
}
|
|
6406
|
+
}
|
|
6407
|
+
config.hooks = hooks;
|
|
6408
|
+
saveJSONConfig(configPath, config);
|
|
6409
|
+
return { events: [...events] };
|
|
6410
|
+
}
|
|
6411
|
+
function removeCodexHooks(configPath) {
|
|
6412
|
+
if (!existsSync6(configPath))
|
|
6413
|
+
return { removed: false };
|
|
6414
|
+
let config;
|
|
6415
|
+
try {
|
|
6416
|
+
config = readHooksFileOrThrow(configPath);
|
|
6417
|
+
} catch {
|
|
6418
|
+
return { removed: false };
|
|
6419
|
+
}
|
|
6420
|
+
const hooks = config.hooks;
|
|
6421
|
+
if (typeof hooks !== "object" || !hooks)
|
|
6422
|
+
return { removed: false };
|
|
6423
|
+
let removed = false;
|
|
6424
|
+
for (const event of Object.keys(hooks)) {
|
|
6425
|
+
if (!Array.isArray(hooks[event]))
|
|
6426
|
+
continue;
|
|
6427
|
+
const kept = hooks[event].filter((g2) => !isDosuGroup(g2));
|
|
6428
|
+
if (kept.length !== hooks[event].length) {
|
|
6429
|
+
removed = true;
|
|
6430
|
+
if (kept.length > 0)
|
|
6431
|
+
hooks[event] = kept;
|
|
6432
|
+
else
|
|
6433
|
+
delete hooks[event];
|
|
6434
|
+
}
|
|
6435
|
+
}
|
|
6436
|
+
if (removed)
|
|
6437
|
+
saveJSONConfig(configPath, config);
|
|
6438
|
+
return { removed };
|
|
6439
|
+
}
|
|
6440
|
+
function inspectCodexHooks(configPath) {
|
|
6441
|
+
if (!existsSync6(configPath))
|
|
6442
|
+
return { fileExists: false, events: [] };
|
|
6443
|
+
let config;
|
|
6444
|
+
try {
|
|
6445
|
+
config = readHooksFileOrThrow(configPath);
|
|
6446
|
+
} catch {
|
|
6447
|
+
return { fileExists: true, parseError: true, events: [] };
|
|
6448
|
+
}
|
|
6449
|
+
const hooks = config.hooks;
|
|
6450
|
+
if (typeof hooks !== "object" || !hooks)
|
|
6451
|
+
return { fileExists: true, events: [] };
|
|
6452
|
+
const events = Object.keys(hooks).filter((event) => Array.isArray(hooks[event]) && hooks[event].some((g2) => isDosuGroup(g2)));
|
|
6453
|
+
return { fileExists: true, events };
|
|
6454
|
+
}
|
|
6455
|
+
var EVENT_SUBCOMMAND2, EVENT_TIMEOUT_SEC, EVENT_STATUS_MESSAGE;
|
|
6456
|
+
var init_codex = __esm(() => {
|
|
6457
|
+
init_config_helpers();
|
|
6458
|
+
init_claude_code();
|
|
6459
|
+
EVENT_SUBCOMMAND2 = {
|
|
6460
|
+
UserPromptSubmit: "user-prompt-submit",
|
|
6461
|
+
PostToolUse: "post-tool-use",
|
|
6462
|
+
Stop: "stop"
|
|
6463
|
+
};
|
|
6464
|
+
EVENT_TIMEOUT_SEC = {
|
|
6465
|
+
UserPromptSubmit: 10,
|
|
6466
|
+
PostToolUse: 10,
|
|
6467
|
+
Stop: 30
|
|
6468
|
+
};
|
|
6469
|
+
EVENT_STATUS_MESSAGE = {
|
|
6470
|
+
UserPromptSubmit: "Dosu knowledge lookup",
|
|
6471
|
+
PostToolUse: "Dosu knowledge delivery",
|
|
6472
|
+
Stop: "Dosu final knowledge check"
|
|
6473
|
+
};
|
|
6474
|
+
});
|
|
6475
|
+
|
|
6347
6476
|
// src/insights/insights.ts
|
|
6348
6477
|
async function buildInsights({
|
|
6349
6478
|
client,
|
|
@@ -7432,17 +7561,17 @@ var init_insights2 = __esm(() => {
|
|
|
7432
7561
|
});
|
|
7433
7562
|
|
|
7434
7563
|
// src/version/skill-update-check.ts
|
|
7435
|
-
import { existsSync as
|
|
7436
|
-
import { join as
|
|
7564
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "node:fs";
|
|
7565
|
+
import { join as join6 } from "node:path";
|
|
7437
7566
|
function getCachePath() {
|
|
7438
|
-
return
|
|
7567
|
+
return join6(getConfigDir(), CACHE_FILENAME);
|
|
7439
7568
|
}
|
|
7440
7569
|
function readSkillCache() {
|
|
7441
7570
|
try {
|
|
7442
7571
|
const path = getCachePath();
|
|
7443
|
-
if (!
|
|
7572
|
+
if (!existsSync7(path))
|
|
7444
7573
|
return null;
|
|
7445
|
-
const data = JSON.parse(
|
|
7574
|
+
const data = JSON.parse(readFileSync9(path, "utf-8"));
|
|
7446
7575
|
if (typeof data.lastCheck === "number" && typeof data.latestSha === "string" && typeof data.installedSha === "string") {
|
|
7447
7576
|
return data;
|
|
7448
7577
|
}
|
|
@@ -7454,7 +7583,7 @@ function readSkillCache() {
|
|
|
7454
7583
|
function writeSkillCache(cache) {
|
|
7455
7584
|
try {
|
|
7456
7585
|
const dir = getConfigDir();
|
|
7457
|
-
if (!
|
|
7586
|
+
if (!existsSync7(dir)) {
|
|
7458
7587
|
mkdirSync5(dir, { recursive: true, mode: 448 });
|
|
7459
7588
|
}
|
|
7460
7589
|
writeFileSync4(getCachePath(), JSON.stringify(cache), { mode: 384 });
|
|
@@ -7616,21 +7745,21 @@ var init_skill = __esm(() => {
|
|
|
7616
7745
|
var MCP_PROVIDER_SLUG = "dosu_mcp";
|
|
7617
7746
|
|
|
7618
7747
|
// src/mcp/detect.ts
|
|
7619
|
-
import { existsSync as
|
|
7748
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
7620
7749
|
import { homedir, platform } from "node:os";
|
|
7621
|
-
import { join as
|
|
7750
|
+
import { join as join7 } from "node:path";
|
|
7622
7751
|
function isInstalled(paths) {
|
|
7623
|
-
return paths.some((p2) =>
|
|
7752
|
+
return paths.some((p2) => existsSync8(expandHome(p2)));
|
|
7624
7753
|
}
|
|
7625
7754
|
function expandHome(path) {
|
|
7626
7755
|
if (!path.startsWith("~"))
|
|
7627
7756
|
return path;
|
|
7628
|
-
return
|
|
7757
|
+
return join7(homedir(), path.slice(1));
|
|
7629
7758
|
}
|
|
7630
7759
|
function appSupportDir() {
|
|
7631
7760
|
switch (platform()) {
|
|
7632
7761
|
case "darwin": {
|
|
7633
|
-
return
|
|
7762
|
+
return join7(homedir(), "Library", "Application Support");
|
|
7634
7763
|
}
|
|
7635
7764
|
case "win32": {
|
|
7636
7765
|
return process.env.APPDATA ?? "";
|
|
@@ -7639,7 +7768,7 @@ function appSupportDir() {
|
|
|
7639
7768
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
7640
7769
|
if (xdg)
|
|
7641
7770
|
return xdg;
|
|
7642
|
-
return
|
|
7771
|
+
return join7(homedir(), ".config");
|
|
7643
7772
|
}
|
|
7644
7773
|
}
|
|
7645
7774
|
}
|
|
@@ -7720,7 +7849,7 @@ var init_antigravity = __esm(() => {
|
|
|
7720
7849
|
});
|
|
7721
7850
|
|
|
7722
7851
|
// src/mcp/providers/claude.ts
|
|
7723
|
-
import { join as
|
|
7852
|
+
import { join as join8 } from "node:path";
|
|
7724
7853
|
var ClaudeProvider = () => createJSONProvider({
|
|
7725
7854
|
providerName: "Claude Code",
|
|
7726
7855
|
providerID: "claude",
|
|
@@ -7729,22 +7858,22 @@ var ClaudeProvider = () => createJSONProvider({
|
|
|
7729
7858
|
paths: ["~/.claude"],
|
|
7730
7859
|
globalPath: "~/.claude.json",
|
|
7731
7860
|
topKey: "mcpServers",
|
|
7732
|
-
localConfigPath: (cwd) =>
|
|
7861
|
+
localConfigPath: (cwd) => join8(cwd, ".mcp.json")
|
|
7733
7862
|
});
|
|
7734
7863
|
var init_claude = __esm(() => {
|
|
7735
7864
|
init_base();
|
|
7736
7865
|
});
|
|
7737
7866
|
|
|
7738
7867
|
// src/mcp/providers/claude-desktop.ts
|
|
7739
|
-
import { join as
|
|
7868
|
+
import { join as join9 } from "node:path";
|
|
7740
7869
|
var ClaudeDesktopProvider = () => ({
|
|
7741
7870
|
name: () => "Claude Desktop",
|
|
7742
7871
|
id: () => "claude-desktop",
|
|
7743
7872
|
supportsLocal: () => false,
|
|
7744
7873
|
priority: () => 2,
|
|
7745
|
-
detectPaths: () => [
|
|
7746
|
-
isInstalled: () => isInstalled([
|
|
7747
|
-
globalConfigPath: () =>
|
|
7874
|
+
detectPaths: () => [join9(appSupportDir(), "Claude")],
|
|
7875
|
+
isInstalled: () => isInstalled([join9(appSupportDir(), "Claude")]),
|
|
7876
|
+
globalConfigPath: () => join9(appSupportDir(), "Claude", "claude_desktop_config.json"),
|
|
7748
7877
|
isConfigured: () => false,
|
|
7749
7878
|
install() {
|
|
7750
7879
|
throw new Error("this tool only supports local (stdio) servers and cannot be configured for remote MCP");
|
|
@@ -7758,14 +7887,14 @@ var init_claude_desktop = __esm(() => {
|
|
|
7758
7887
|
});
|
|
7759
7888
|
|
|
7760
7889
|
// src/mcp/providers/cline.ts
|
|
7761
|
-
import { join as
|
|
7762
|
-
var extensionDir = () =>
|
|
7890
|
+
import { join as join10 } from "node:path";
|
|
7891
|
+
var extensionDir = () => join10(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
|
|
7763
7892
|
providerName: "Cline",
|
|
7764
7893
|
providerID: "cline",
|
|
7765
7894
|
local: false,
|
|
7766
7895
|
priorityValue: 11,
|
|
7767
7896
|
paths: [extensionDir()],
|
|
7768
|
-
globalPath:
|
|
7897
|
+
globalPath: join10(extensionDir(), "settings", "cline_mcp_settings.json"),
|
|
7769
7898
|
topKey: "mcpServers",
|
|
7770
7899
|
buildServer: (cfg) => ({
|
|
7771
7900
|
url: mcpURL(cfg.deployment_id),
|
|
@@ -7781,7 +7910,7 @@ var init_cline = __esm(() => {
|
|
|
7781
7910
|
});
|
|
7782
7911
|
|
|
7783
7912
|
// src/mcp/providers/cline-cli.ts
|
|
7784
|
-
import { join as
|
|
7913
|
+
import { join as join11 } from "node:path";
|
|
7785
7914
|
function clineDir() {
|
|
7786
7915
|
return process.env.CLINE_DIR ?? expandHome("~/.cline");
|
|
7787
7916
|
}
|
|
@@ -7791,7 +7920,7 @@ var ClineCliProvider = () => createJSONProvider({
|
|
|
7791
7920
|
local: false,
|
|
7792
7921
|
priorityValue: 12,
|
|
7793
7922
|
paths: [clineDir()],
|
|
7794
|
-
globalPath:
|
|
7923
|
+
globalPath: join11(clineDir(), "data", "settings", "cline_mcp_settings.json"),
|
|
7795
7924
|
topKey: "mcpServers",
|
|
7796
7925
|
buildServer: (cfg) => ({
|
|
7797
7926
|
url: mcpURL(cfg.deployment_id),
|
|
@@ -7807,20 +7936,20 @@ var init_cline_cli = __esm(() => {
|
|
|
7807
7936
|
});
|
|
7808
7937
|
|
|
7809
7938
|
// src/mcp/providers/codex.ts
|
|
7810
|
-
import { existsSync as
|
|
7811
|
-
import { join as
|
|
7939
|
+
import { existsSync as existsSync9, readFileSync as readFileSync10 } from "node:fs";
|
|
7940
|
+
import { join as join12 } from "node:path";
|
|
7812
7941
|
function codexHome() {
|
|
7813
7942
|
return process.env.CODEX_HOME ?? expandHome("~/.codex");
|
|
7814
7943
|
}
|
|
7815
7944
|
function getConfigPath2(global) {
|
|
7816
7945
|
if (global)
|
|
7817
|
-
return
|
|
7818
|
-
return
|
|
7946
|
+
return join12(codexHome(), "config.toml");
|
|
7947
|
+
return join12(process.cwd(), ".codex", "config.toml");
|
|
7819
7948
|
}
|
|
7820
7949
|
function readTOML(path) {
|
|
7821
|
-
if (!
|
|
7950
|
+
if (!existsSync9(path))
|
|
7822
7951
|
return "";
|
|
7823
|
-
return
|
|
7952
|
+
return readFileSync10(path, "utf-8");
|
|
7824
7953
|
}
|
|
7825
7954
|
function writeTOML(path, content) {
|
|
7826
7955
|
writeSecureFile(path, content);
|
|
@@ -7878,9 +8007,9 @@ var CodexProvider = () => ({
|
|
|
7878
8007
|
priority: () => 8,
|
|
7879
8008
|
detectPaths: () => ["~/.codex"],
|
|
7880
8009
|
isInstalled: () => isInstalled(["~/.codex"]),
|
|
7881
|
-
globalConfigPath: () =>
|
|
8010
|
+
globalConfigPath: () => join12(codexHome(), "config.toml"),
|
|
7882
8011
|
isConfigured: () => {
|
|
7883
|
-
const content = readTOML(
|
|
8012
|
+
const content = readTOML(join12(codexHome(), "config.toml"));
|
|
7884
8013
|
return content.includes("[mcp_servers.dosu]");
|
|
7885
8014
|
},
|
|
7886
8015
|
install(cfg, global) {
|
|
@@ -7895,17 +8024,17 @@ var CodexProvider = () => ({
|
|
|
7895
8024
|
writeTOML(path, removeDosuFromTOML(content));
|
|
7896
8025
|
}
|
|
7897
8026
|
});
|
|
7898
|
-
var
|
|
8027
|
+
var init_codex2 = __esm(() => {
|
|
7899
8028
|
init_config();
|
|
7900
8029
|
init_config_helpers();
|
|
7901
8030
|
init_detect();
|
|
7902
8031
|
});
|
|
7903
8032
|
|
|
7904
8033
|
// src/mcp/providers/copilot.ts
|
|
7905
|
-
import { join as
|
|
8034
|
+
import { join as join13 } from "node:path";
|
|
7906
8035
|
function globalPath() {
|
|
7907
8036
|
if (process.env.XDG_CONFIG_HOME) {
|
|
7908
|
-
return
|
|
8037
|
+
return join13(process.env.XDG_CONFIG_HOME, "mcp-config.json");
|
|
7909
8038
|
}
|
|
7910
8039
|
return expandHome("~/.copilot/mcp-config.json");
|
|
7911
8040
|
}
|
|
@@ -7936,7 +8065,7 @@ var CopilotProvider = () => ({
|
|
|
7936
8065
|
};
|
|
7937
8066
|
installJSONServer(globalPath(), "mcpServers", server);
|
|
7938
8067
|
} else {
|
|
7939
|
-
const configPath =
|
|
8068
|
+
const configPath = join13(process.cwd(), ".vscode", "mcp.json");
|
|
7940
8069
|
const server = {
|
|
7941
8070
|
type: "http",
|
|
7942
8071
|
url,
|
|
@@ -7949,7 +8078,7 @@ var CopilotProvider = () => ({
|
|
|
7949
8078
|
if (global) {
|
|
7950
8079
|
removeJSONServer(globalPath(), "mcpServers");
|
|
7951
8080
|
} else {
|
|
7952
|
-
const configPath =
|
|
8081
|
+
const configPath = join13(process.cwd(), ".vscode", "mcp.json");
|
|
7953
8082
|
removeJSONServer(configPath, "servers");
|
|
7954
8083
|
}
|
|
7955
8084
|
}
|
|
@@ -7961,7 +8090,7 @@ var init_copilot = __esm(() => {
|
|
|
7961
8090
|
});
|
|
7962
8091
|
|
|
7963
8092
|
// src/mcp/providers/cursor.ts
|
|
7964
|
-
import { join as
|
|
8093
|
+
import { join as join14 } from "node:path";
|
|
7965
8094
|
var CursorProvider = () => createJSONProvider({
|
|
7966
8095
|
providerName: "Cursor",
|
|
7967
8096
|
providerID: "cursor",
|
|
@@ -7974,7 +8103,7 @@ var CursorProvider = () => createJSONProvider({
|
|
|
7974
8103
|
url: mcpURL(cfg.deployment_id),
|
|
7975
8104
|
headers: mcpHeaders(cfg.api_key)
|
|
7976
8105
|
}),
|
|
7977
|
-
localConfigPath: (cwd) =>
|
|
8106
|
+
localConfigPath: (cwd) => join14(cwd, ".cursor", "mcp.json")
|
|
7978
8107
|
});
|
|
7979
8108
|
var init_cursor = __esm(() => {
|
|
7980
8109
|
init_config_helpers();
|
|
@@ -7982,7 +8111,7 @@ var init_cursor = __esm(() => {
|
|
|
7982
8111
|
});
|
|
7983
8112
|
|
|
7984
8113
|
// src/mcp/providers/gemini.ts
|
|
7985
|
-
import { join as
|
|
8114
|
+
import { join as join15 } from "node:path";
|
|
7986
8115
|
var GeminiProvider = () => createJSONProvider({
|
|
7987
8116
|
providerName: "Gemini CLI",
|
|
7988
8117
|
providerID: "gemini",
|
|
@@ -7991,7 +8120,7 @@ var GeminiProvider = () => createJSONProvider({
|
|
|
7991
8120
|
paths: ["~/.gemini"],
|
|
7992
8121
|
globalPath: "~/.gemini/settings.json",
|
|
7993
8122
|
topKey: "mcpServers",
|
|
7994
|
-
localConfigPath: (cwd) =>
|
|
8123
|
+
localConfigPath: (cwd) => join15(cwd, ".gemini", "settings.json")
|
|
7995
8124
|
});
|
|
7996
8125
|
var init_gemini = __esm(() => {
|
|
7997
8126
|
init_base();
|
|
@@ -8041,14 +8170,14 @@ var init_manual = __esm(() => {
|
|
|
8041
8170
|
});
|
|
8042
8171
|
|
|
8043
8172
|
// src/mcp/providers/mcporter.ts
|
|
8044
|
-
import { existsSync as
|
|
8045
|
-
import { join as
|
|
8173
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
8174
|
+
import { join as join16 } from "node:path";
|
|
8046
8175
|
function resolveGlobalConfigPath() {
|
|
8047
8176
|
const jsonPath = expandHome("~/.mcporter/mcporter.json");
|
|
8048
|
-
if (
|
|
8177
|
+
if (existsSync10(jsonPath))
|
|
8049
8178
|
return jsonPath;
|
|
8050
8179
|
const jsoncPath = expandHome("~/.mcporter/mcporter.jsonc");
|
|
8051
|
-
if (
|
|
8180
|
+
if (existsSync10(jsoncPath))
|
|
8052
8181
|
return jsoncPath;
|
|
8053
8182
|
return jsonPath;
|
|
8054
8183
|
}
|
|
@@ -8069,7 +8198,7 @@ var MCPorterProvider = () => ({
|
|
|
8069
8198
|
globalConfigPath: () => resolveGlobalConfigPath(),
|
|
8070
8199
|
isConfigured: () => isJSONKeyConfigured(resolveGlobalConfigPath(), "mcpServers"),
|
|
8071
8200
|
install(cfg, global) {
|
|
8072
|
-
const configPath = global ? resolveGlobalConfigPath() :
|
|
8201
|
+
const configPath = global ? resolveGlobalConfigPath() : join16(process.cwd(), "config", "mcporter.json");
|
|
8073
8202
|
const server = {
|
|
8074
8203
|
type: "http",
|
|
8075
8204
|
url: mcpEndpoint4(cfg),
|
|
@@ -8078,7 +8207,7 @@ var MCPorterProvider = () => ({
|
|
|
8078
8207
|
installJSONServer(configPath, "mcpServers", server);
|
|
8079
8208
|
},
|
|
8080
8209
|
remove(global) {
|
|
8081
|
-
const configPath = global ? resolveGlobalConfigPath() :
|
|
8210
|
+
const configPath = global ? resolveGlobalConfigPath() : join16(process.cwd(), "config", "mcporter.json");
|
|
8082
8211
|
removeJSONServer(configPath, "mcpServers");
|
|
8083
8212
|
}
|
|
8084
8213
|
});
|
|
@@ -8089,7 +8218,7 @@ var init_mcporter = __esm(() => {
|
|
|
8089
8218
|
});
|
|
8090
8219
|
|
|
8091
8220
|
// src/mcp/providers/opencode.ts
|
|
8092
|
-
import { join as
|
|
8221
|
+
import { join as join17 } from "node:path";
|
|
8093
8222
|
var OpenCodeProvider = () => createJSONProvider({
|
|
8094
8223
|
providerName: "OpenCode",
|
|
8095
8224
|
providerID: "opencode",
|
|
@@ -8104,7 +8233,7 @@ var OpenCodeProvider = () => createJSONProvider({
|
|
|
8104
8233
|
enabled: true,
|
|
8105
8234
|
headers: mcpHeaders(cfg.api_key)
|
|
8106
8235
|
}),
|
|
8107
|
-
localConfigPath: (cwd) =>
|
|
8236
|
+
localConfigPath: (cwd) => join17(cwd, "opencode.json")
|
|
8108
8237
|
});
|
|
8109
8238
|
var init_opencode = __esm(() => {
|
|
8110
8239
|
init_config_helpers();
|
|
@@ -8112,16 +8241,16 @@ var init_opencode = __esm(() => {
|
|
|
8112
8241
|
});
|
|
8113
8242
|
|
|
8114
8243
|
// src/mcp/providers/vscode.ts
|
|
8115
|
-
import { join as
|
|
8244
|
+
import { join as join18 } from "node:path";
|
|
8116
8245
|
var VSCodeProvider = () => createJSONProvider({
|
|
8117
8246
|
providerName: "VS Code",
|
|
8118
8247
|
providerID: "vscode",
|
|
8119
8248
|
local: true,
|
|
8120
8249
|
priorityValue: 6,
|
|
8121
|
-
paths: [
|
|
8122
|
-
globalPath:
|
|
8250
|
+
paths: [join18(appSupportDir(), "Code")],
|
|
8251
|
+
globalPath: join18(appSupportDir(), "Code", "User", "mcp.json"),
|
|
8123
8252
|
topKey: "servers",
|
|
8124
|
-
localConfigPath: (cwd) =>
|
|
8253
|
+
localConfigPath: (cwd) => join18(cwd, ".vscode", "mcp.json")
|
|
8125
8254
|
});
|
|
8126
8255
|
var init_vscode = __esm(() => {
|
|
8127
8256
|
init_detect();
|
|
@@ -8130,14 +8259,14 @@ var init_vscode = __esm(() => {
|
|
|
8130
8259
|
|
|
8131
8260
|
// src/mcp/providers/windsurf.ts
|
|
8132
8261
|
import { homedir as homedir2 } from "node:os";
|
|
8133
|
-
import { join as
|
|
8262
|
+
import { join as join19 } from "node:path";
|
|
8134
8263
|
var WindsurfProvider = () => createJSONProvider({
|
|
8135
8264
|
providerName: "Windsurf",
|
|
8136
8265
|
providerID: "windsurf",
|
|
8137
8266
|
local: false,
|
|
8138
8267
|
priorityValue: 9,
|
|
8139
|
-
paths: [
|
|
8140
|
-
globalPath:
|
|
8268
|
+
paths: [join19(homedir2(), ".codeium", "windsurf")],
|
|
8269
|
+
globalPath: join19(homedir2(), ".codeium", "windsurf", "mcp_config.json"),
|
|
8141
8270
|
topKey: "mcpServers"
|
|
8142
8271
|
});
|
|
8143
8272
|
var init_windsurf = __esm(() => {
|
|
@@ -8146,12 +8275,12 @@ var init_windsurf = __esm(() => {
|
|
|
8146
8275
|
|
|
8147
8276
|
// src/mcp/providers/zed.ts
|
|
8148
8277
|
import { platform as platform2 } from "node:os";
|
|
8149
|
-
import { join as
|
|
8278
|
+
import { join as join20 } from "node:path";
|
|
8150
8279
|
function zedConfigDir() {
|
|
8151
8280
|
const os = platform2();
|
|
8152
8281
|
if (os === "darwin" || os === "win32")
|
|
8153
|
-
return
|
|
8154
|
-
return
|
|
8282
|
+
return join20(appSupportDir(), "Zed");
|
|
8283
|
+
return join20(appSupportDir(), "zed");
|
|
8155
8284
|
}
|
|
8156
8285
|
var ZedProvider = () => createJSONProvider({
|
|
8157
8286
|
providerName: "Zed",
|
|
@@ -8159,7 +8288,7 @@ var ZedProvider = () => createJSONProvider({
|
|
|
8159
8288
|
local: true,
|
|
8160
8289
|
priorityValue: 10,
|
|
8161
8290
|
paths: [zedConfigDir()],
|
|
8162
|
-
globalPath:
|
|
8291
|
+
globalPath: join20(zedConfigDir(), "settings.json"),
|
|
8163
8292
|
topKey: "context_servers",
|
|
8164
8293
|
buildServer: (cfg) => ({
|
|
8165
8294
|
source: "custom",
|
|
@@ -8167,7 +8296,7 @@ var ZedProvider = () => createJSONProvider({
|
|
|
8167
8296
|
url: mcpURL(cfg.deployment_id),
|
|
8168
8297
|
headers: mcpHeaders(cfg.api_key)
|
|
8169
8298
|
}),
|
|
8170
|
-
localConfigPath: (cwd) =>
|
|
8299
|
+
localConfigPath: (cwd) => join20(cwd, ".zed", "settings.json")
|
|
8171
8300
|
});
|
|
8172
8301
|
var init_zed = __esm(() => {
|
|
8173
8302
|
init_config_helpers();
|
|
@@ -8211,7 +8340,7 @@ var init_providers = __esm(() => {
|
|
|
8211
8340
|
init_claude_desktop();
|
|
8212
8341
|
init_cline();
|
|
8213
8342
|
init_cline_cli();
|
|
8214
|
-
|
|
8343
|
+
init_codex2();
|
|
8215
8344
|
init_copilot();
|
|
8216
8345
|
init_cursor();
|
|
8217
8346
|
init_gemini();
|
|
@@ -10760,8 +10889,8 @@ __export(exports_flow2, {
|
|
|
10760
10889
|
isStdioOnly: () => isStdioOnly
|
|
10761
10890
|
});
|
|
10762
10891
|
import { randomUUID } from "node:crypto";
|
|
10763
|
-
import { existsSync as
|
|
10764
|
-
import { join as
|
|
10892
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
10893
|
+
import { join as join21 } from "node:path";
|
|
10765
10894
|
async function runSetup(opts = {}) {
|
|
10766
10895
|
const onboardingRunID = randomUUID();
|
|
10767
10896
|
logger.info("setup", `Setup flow started${opts.deploymentID ? ` deployment=${opts.deploymentID}` : ""}${opts.mode ? ` mode=${opts.mode}` : ""}`);
|
|
@@ -10933,7 +11062,7 @@ async function runSetup(opts = {}) {
|
|
|
10933
11062
|
showTryItOutPrompt({
|
|
10934
11063
|
mode: cfg.mode,
|
|
10935
11064
|
docsImported: choices.connectGitHub && githubOnboardingDone,
|
|
10936
|
-
hasAgentsMd:
|
|
11065
|
+
hasAgentsMd: existsSync11(join21(process.cwd(), "AGENTS.md"))
|
|
10937
11066
|
});
|
|
10938
11067
|
}
|
|
10939
11068
|
if (mcpCompleted || skillCompleted || docsImported) {
|
|
@@ -11427,8 +11556,8 @@ var init_flow2 = __esm(() => {
|
|
|
11427
11556
|
});
|
|
11428
11557
|
|
|
11429
11558
|
// src/commands/insights.ts
|
|
11430
|
-
import { existsSync as
|
|
11431
|
-
import { dirname as dirname3, join as
|
|
11559
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync6, readdirSync, unlinkSync, writeFileSync as writeFileSync5 } from "node:fs";
|
|
11560
|
+
import { dirname as dirname3, join as join22 } from "node:path";
|
|
11432
11561
|
function shuffled(arr) {
|
|
11433
11562
|
const copy2 = [...arr];
|
|
11434
11563
|
for (let i = copy2.length - 1;i > 0; i--) {
|
|
@@ -11532,17 +11661,17 @@ function makeAskFn(cfg) {
|
|
|
11532
11661
|
};
|
|
11533
11662
|
}
|
|
11534
11663
|
function insightsDir() {
|
|
11535
|
-
return
|
|
11664
|
+
return join22(getConfigDir(), "insights");
|
|
11536
11665
|
}
|
|
11537
11666
|
function reportPath(timestamp) {
|
|
11538
11667
|
const dir = insightsDir();
|
|
11539
11668
|
if (!timestamp)
|
|
11540
|
-
return
|
|
11669
|
+
return join22(dir, "latest.html");
|
|
11541
11670
|
const iso = timestamp.toISOString().slice(0, 19).replace(/:/g, "-");
|
|
11542
|
-
return
|
|
11671
|
+
return join22(dir, `report-${iso}Z.html`);
|
|
11543
11672
|
}
|
|
11544
11673
|
function pruneOldReports(dir, keepN) {
|
|
11545
|
-
if (!
|
|
11674
|
+
if (!existsSync12(dir))
|
|
11546
11675
|
return;
|
|
11547
11676
|
let entries;
|
|
11548
11677
|
try {
|
|
@@ -11554,7 +11683,7 @@ function pruneOldReports(dir, keepN) {
|
|
|
11554
11683
|
const reports = entries.filter((f) => REPORT_FILE_PATTERN.test(f)).sort().reverse();
|
|
11555
11684
|
for (const f of reports.slice(keepN)) {
|
|
11556
11685
|
try {
|
|
11557
|
-
unlinkSync(
|
|
11686
|
+
unlinkSync(join22(dir, f));
|
|
11558
11687
|
} catch (err) {
|
|
11559
11688
|
logger.debug("insights", `failed to prune ${f}: ${err instanceof Error ? err.message : err}`);
|
|
11560
11689
|
}
|
|
@@ -11627,7 +11756,7 @@ function defaultRunner(cfg) {
|
|
|
11627
11756
|
render: renderHTML,
|
|
11628
11757
|
writeFile: (path2, content) => {
|
|
11629
11758
|
const dir = dirname3(path2);
|
|
11630
|
-
if (!
|
|
11759
|
+
if (!existsSync12(dir))
|
|
11631
11760
|
mkdirSync6(dir, { recursive: true, mode: 448 });
|
|
11632
11761
|
writeFileSync5(path2, content, { mode: 384 });
|
|
11633
11762
|
},
|
|
@@ -12292,7 +12421,7 @@ var init_flow3 = __esm(() => {
|
|
|
12292
12421
|
// src/cli/cli.ts
|
|
12293
12422
|
init_esm();
|
|
12294
12423
|
init_client();
|
|
12295
|
-
import { readFileSync as
|
|
12424
|
+
import { readFileSync as readFileSync12, unlinkSync as unlinkSync2 } from "node:fs";
|
|
12296
12425
|
|
|
12297
12426
|
// src/commands/analytics.ts
|
|
12298
12427
|
init_esm();
|
|
@@ -12977,7 +13106,8 @@ ${page.body}`);
|
|
|
12977
13106
|
init_esm();
|
|
12978
13107
|
init_config();
|
|
12979
13108
|
init_logger();
|
|
12980
|
-
|
|
13109
|
+
init_prompts();
|
|
13110
|
+
import { readFileSync as readFileSync8 } from "node:fs";
|
|
12981
13111
|
import { basename } from "node:path";
|
|
12982
13112
|
|
|
12983
13113
|
// src/hooks/state.ts
|
|
@@ -13016,7 +13146,8 @@ var COOLDOWN_DEFAULT_MS = 3000;
|
|
|
13016
13146
|
var TTL_DEFAULT_MS = 10 * 60 * 1000;
|
|
13017
13147
|
var STOP_WAIT_DEFAULT_MS = 8000;
|
|
13018
13148
|
var STOP_POLL_DEFAULT_MS = 1000;
|
|
13019
|
-
var SUPPORTED_AGENTS = ["claude-code"];
|
|
13149
|
+
var SUPPORTED_AGENTS = ["claude-code", "codex"];
|
|
13150
|
+
var DEFAULT_AGENT = "claude-code";
|
|
13020
13151
|
function cooldownMs() {
|
|
13021
13152
|
const n = Number.parseInt(process.env.DOSU_HOOK_CHECK_COOLDOWN_MS ?? "", 10);
|
|
13022
13153
|
return Number.isFinite(n) && n >= 0 ? n : COOLDOWN_DEFAULT_MS;
|
|
@@ -13049,13 +13180,17 @@ function errMsg(err) {
|
|
|
13049
13180
|
function repoSlug(cwd) {
|
|
13050
13181
|
return cwd ? basename(cwd) : undefined;
|
|
13051
13182
|
}
|
|
13052
|
-
async function runUserPromptSubmit(input, now = Date.now()) {
|
|
13183
|
+
async function runUserPromptSubmit(input, now = Date.now(), agent = DEFAULT_AGENT) {
|
|
13053
13184
|
const sessionId = input.session_id;
|
|
13054
13185
|
if (!sessionId)
|
|
13055
13186
|
return;
|
|
13056
13187
|
const prompt = (input.prompt ?? "").trim();
|
|
13057
13188
|
if (!prompt)
|
|
13058
13189
|
return;
|
|
13190
|
+
if (prompt.startsWith(STOP_PREFIX)) {
|
|
13191
|
+
logger.debug("hooks", "submit skipped reason=own-stop-envelope");
|
|
13192
|
+
return;
|
|
13193
|
+
}
|
|
13059
13194
|
const existing = loadState(sessionId);
|
|
13060
13195
|
if (existing && existing.status === "pending" && now <= existing.expiresAt) {
|
|
13061
13196
|
logger.debug("hooks", `submit sid=${sid8(sessionId)} reuse tid=${existing.ticketId}`);
|
|
@@ -13072,7 +13207,7 @@ async function runUserPromptSubmit(input, now = Date.now()) {
|
|
|
13072
13207
|
try {
|
|
13073
13208
|
resp = await tc.requestCreateTicket(cfg, {
|
|
13074
13209
|
deployment_id: cfg.deployment_id,
|
|
13075
|
-
agent
|
|
13210
|
+
agent,
|
|
13076
13211
|
session_id: sessionId,
|
|
13077
13212
|
turn_id: input.turn_id ?? String(now),
|
|
13078
13213
|
prompt,
|
|
@@ -13219,7 +13354,7 @@ function runStatus(input, opts, now = Date.now()) {
|
|
|
13219
13354
|
console.log(`Status: ${data.status}`);
|
|
13220
13355
|
console.log(`Delivered: ${data.delivered ? "yes" : "no"}`);
|
|
13221
13356
|
}
|
|
13222
|
-
async function runHookEntrypoint(event, raw, now = Date.now()) {
|
|
13357
|
+
async function runHookEntrypoint(event, raw, now = Date.now(), agent = DEFAULT_AGENT) {
|
|
13223
13358
|
let input = {};
|
|
13224
13359
|
try {
|
|
13225
13360
|
input = raw.trim() ? JSON.parse(raw) : {};
|
|
@@ -13228,7 +13363,7 @@ async function runHookEntrypoint(event, raw, now = Date.now()) {
|
|
|
13228
13363
|
}
|
|
13229
13364
|
try {
|
|
13230
13365
|
if (event === "user-prompt-submit")
|
|
13231
|
-
await runUserPromptSubmit(input, now);
|
|
13366
|
+
await runUserPromptSubmit(input, now, agent);
|
|
13232
13367
|
else if (event === "post-tool-use")
|
|
13233
13368
|
await runPostToolUse(input, now);
|
|
13234
13369
|
else
|
|
@@ -13241,7 +13376,7 @@ async function runHookEntrypoint(event, raw, now = Date.now()) {
|
|
|
13241
13376
|
}
|
|
13242
13377
|
function readStdinRaw() {
|
|
13243
13378
|
try {
|
|
13244
|
-
return
|
|
13379
|
+
return readFileSync8(0, "utf8");
|
|
13245
13380
|
} catch {
|
|
13246
13381
|
return "";
|
|
13247
13382
|
}
|
|
@@ -13254,12 +13389,13 @@ async function emitErrorLine(step, reason, agentNextSteps) {
|
|
|
13254
13389
|
emitError2({ step, reason, agent_next_steps: agentNextSteps });
|
|
13255
13390
|
}
|
|
13256
13391
|
async function runInstall(agent, opts) {
|
|
13257
|
-
if (agent
|
|
13392
|
+
if (!SUPPORTED_AGENTS.includes(agent)) {
|
|
13258
13393
|
process.exitCode = 2;
|
|
13394
|
+
const supported = SUPPORTED_AGENTS.join(", ");
|
|
13259
13395
|
if (opts.json) {
|
|
13260
|
-
await emitErrorLine("hooks-install", "unsupported_agent", `
|
|
13396
|
+
await emitErrorLine("hooks-install", "unsupported_agent", `Supported agents: ${supported}.`);
|
|
13261
13397
|
} else {
|
|
13262
|
-
console.error(`Unsupported agent '${agent}'. Supported agents:
|
|
13398
|
+
console.error(`Unsupported agent '${agent}'. Supported agents: ${supported}.`);
|
|
13263
13399
|
}
|
|
13264
13400
|
return;
|
|
13265
13401
|
}
|
|
@@ -13272,13 +13408,28 @@ async function runInstall(agent, opts) {
|
|
|
13272
13408
|
}
|
|
13273
13409
|
return;
|
|
13274
13410
|
}
|
|
13275
|
-
const { installClaudeHooks: installClaudeHooks2, claudeLocalSettingsPath: claudeLocalSettingsPath2 } = await Promise.resolve().then(() => (init_claude_code(), exports_claude_code));
|
|
13276
|
-
const configPath = claudeLocalSettingsPath2(resolveDir(opts.dir));
|
|
13277
13411
|
try {
|
|
13412
|
+
if (agent === "codex") {
|
|
13413
|
+
const { installCodexHooks: installCodexHooks2, codexHooksPath: codexHooksPath2 } = await Promise.resolve().then(() => (init_codex(), exports_codex));
|
|
13414
|
+
const configPath2 = codexHooksPath2(resolveDir(opts.dir));
|
|
13415
|
+
const { events: events2 } = installCodexHooks2(configPath2, { stop: opts.stop });
|
|
13416
|
+
if (opts.json) {
|
|
13417
|
+
const { emitStep: emitStep2 } = await Promise.resolve().then(() => exports_output);
|
|
13418
|
+
emitStep2({ step: "hooks-install", agent, path: configPath2, events: events2 });
|
|
13419
|
+
} else {
|
|
13420
|
+
console.log(`✓ Installed Dosu hooks for Codex (${events2.join(", ")}).`);
|
|
13421
|
+
console.log(` → ${configPath2}`);
|
|
13422
|
+
console.log(" One-time step: open Codex in this project and run /hooks to review and");
|
|
13423
|
+
console.log(" trust the Dosu hooks — Codex skips untrusted hooks by design.");
|
|
13424
|
+
}
|
|
13425
|
+
return;
|
|
13426
|
+
}
|
|
13427
|
+
const { installClaudeHooks: installClaudeHooks2, claudeLocalSettingsPath: claudeLocalSettingsPath2 } = await Promise.resolve().then(() => (init_claude_code(), exports_claude_code));
|
|
13428
|
+
const configPath = claudeLocalSettingsPath2(resolveDir(opts.dir));
|
|
13278
13429
|
const { events } = installClaudeHooks2(configPath, { stop: opts.stop });
|
|
13279
13430
|
if (opts.json) {
|
|
13280
13431
|
const { emitStep: emitStep2 } = await Promise.resolve().then(() => exports_output);
|
|
13281
|
-
emitStep2({ step: "hooks-install", path: configPath, events });
|
|
13432
|
+
emitStep2({ step: "hooks-install", agent, path: configPath, events });
|
|
13282
13433
|
} else {
|
|
13283
13434
|
console.log(`✓ Installed Dosu hooks for Claude Code (${events.join(", ")}).`);
|
|
13284
13435
|
console.log(` → ${configPath}`);
|
|
@@ -13294,18 +13445,27 @@ async function runInstall(agent, opts) {
|
|
|
13294
13445
|
}
|
|
13295
13446
|
}
|
|
13296
13447
|
async function runUninstall(agent, opts) {
|
|
13297
|
-
if (agent
|
|
13448
|
+
if (!SUPPORTED_AGENTS.includes(agent)) {
|
|
13298
13449
|
process.exitCode = 2;
|
|
13450
|
+
const supported = SUPPORTED_AGENTS.join(", ");
|
|
13299
13451
|
if (opts.json) {
|
|
13300
|
-
await emitErrorLine("hooks-uninstall", "unsupported_agent",
|
|
13452
|
+
await emitErrorLine("hooks-uninstall", "unsupported_agent", `Supported agents: ${supported}.`);
|
|
13301
13453
|
} else {
|
|
13302
|
-
console.error(`Unsupported agent '${agent}'. Supported agents:
|
|
13454
|
+
console.error(`Unsupported agent '${agent}'. Supported agents: ${supported}.`);
|
|
13303
13455
|
}
|
|
13304
13456
|
return;
|
|
13305
13457
|
}
|
|
13306
|
-
|
|
13307
|
-
|
|
13308
|
-
|
|
13458
|
+
let configPath;
|
|
13459
|
+
let removed;
|
|
13460
|
+
if (agent === "codex") {
|
|
13461
|
+
const { removeCodexHooks: removeCodexHooks2, codexHooksPath: codexHooksPath2 } = await Promise.resolve().then(() => (init_codex(), exports_codex));
|
|
13462
|
+
configPath = codexHooksPath2(resolveDir(opts.dir));
|
|
13463
|
+
({ removed } = removeCodexHooks2(configPath));
|
|
13464
|
+
} else {
|
|
13465
|
+
const { removeClaudeHooks: removeClaudeHooks2, claudeLocalSettingsPath: claudeLocalSettingsPath2 } = await Promise.resolve().then(() => (init_claude_code(), exports_claude_code));
|
|
13466
|
+
configPath = claudeLocalSettingsPath2(resolveDir(opts.dir));
|
|
13467
|
+
({ removed } = removeClaudeHooks2(configPath));
|
|
13468
|
+
}
|
|
13309
13469
|
if (opts.json) {
|
|
13310
13470
|
const { emitStep: emitStep2 } = await Promise.resolve().then(() => exports_output);
|
|
13311
13471
|
emitStep2({ step: "hooks-uninstall", path: configPath, removed });
|
|
@@ -13318,12 +13478,16 @@ async function runUninstall(agent, opts) {
|
|
|
13318
13478
|
async function collectDoctorChecks(opts) {
|
|
13319
13479
|
const checks = [];
|
|
13320
13480
|
const { claudeLocalSettingsPath: claudeLocalSettingsPath2, inspectClaudeHooks: inspectClaudeHooks2 } = await Promise.resolve().then(() => (init_claude_code(), exports_claude_code));
|
|
13481
|
+
const { codexHooksPath: codexHooksPath2, inspectCodexHooks: inspectCodexHooks2 } = await Promise.resolve().then(() => (init_codex(), exports_codex));
|
|
13321
13482
|
const configPath = claudeLocalSettingsPath2(resolveDir(opts.dir));
|
|
13322
13483
|
const inspection = inspectClaudeHooks2(configPath);
|
|
13484
|
+
const codexPath = codexHooksPath2(resolveDir(opts.dir));
|
|
13485
|
+
const codex = inspectCodexHooks2(codexPath);
|
|
13486
|
+
const codexInstalled = codex.events.includes("UserPromptSubmit") && codex.events.includes("PostToolUse");
|
|
13323
13487
|
if (!inspection.fileExists) {
|
|
13324
13488
|
checks.push({
|
|
13325
13489
|
name: "config",
|
|
13326
|
-
status: "fail",
|
|
13490
|
+
status: codexInstalled ? "warn" : "fail",
|
|
13327
13491
|
detail: `not found: ${configPath} (run 'dosu hooks install claude-code')`
|
|
13328
13492
|
});
|
|
13329
13493
|
} else if (inspection.parseError) {
|
|
@@ -13342,10 +13506,32 @@ async function collectDoctorChecks(opts) {
|
|
|
13342
13506
|
} else {
|
|
13343
13507
|
checks.push({
|
|
13344
13508
|
name: "hooks",
|
|
13345
|
-
status: "fail",
|
|
13509
|
+
status: codexInstalled ? "warn" : "fail",
|
|
13346
13510
|
detail: "UserPromptSubmit + PostToolUse not both installed"
|
|
13347
13511
|
});
|
|
13348
13512
|
}
|
|
13513
|
+
if (codex.fileExists) {
|
|
13514
|
+
if (codex.parseError) {
|
|
13515
|
+
checks.push({ name: "codex-config", status: "fail", detail: `invalid JSON: ${codexPath}` });
|
|
13516
|
+
} else if (codexInstalled) {
|
|
13517
|
+
checks.push({
|
|
13518
|
+
name: "codex-config",
|
|
13519
|
+
status: "ok",
|
|
13520
|
+
detail: `installed: ${codex.events.join(", ")} (${codexPath})`
|
|
13521
|
+
});
|
|
13522
|
+
checks.push({
|
|
13523
|
+
name: "codex-trust",
|
|
13524
|
+
status: "warn",
|
|
13525
|
+
detail: "if hooks aren't firing, run /hooks inside Codex to review + trust them (one-time)"
|
|
13526
|
+
});
|
|
13527
|
+
} else {
|
|
13528
|
+
checks.push({
|
|
13529
|
+
name: "codex-config",
|
|
13530
|
+
status: "fail",
|
|
13531
|
+
detail: "UserPromptSubmit + PostToolUse not both installed"
|
|
13532
|
+
});
|
|
13533
|
+
}
|
|
13534
|
+
}
|
|
13349
13535
|
const cfg = loadConfig();
|
|
13350
13536
|
if (isAuthenticated(cfg)) {
|
|
13351
13537
|
checks.push({ name: "auth", status: "ok", detail: "logged in" });
|
|
@@ -13400,15 +13586,15 @@ async function runDoctor(opts) {
|
|
|
13400
13586
|
}
|
|
13401
13587
|
}
|
|
13402
13588
|
function hooksCommand() {
|
|
13403
|
-
const cmd = new Command("hooks").description("Dosu knowledge-injection hooks for Claude Code");
|
|
13404
|
-
cmd.command("user-prompt-submit").description("Hook entrypoint: create a knowledge ticket on prompt submit").action(async () => {
|
|
13405
|
-
await runHookEntrypoint("user-prompt-submit", readStdinRaw());
|
|
13589
|
+
const cmd = new Command("hooks").description("Dosu knowledge-injection hooks for coding agents (Claude Code, Codex)");
|
|
13590
|
+
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) => {
|
|
13591
|
+
await runHookEntrypoint("user-prompt-submit", readStdinRaw(), Date.now(), opts.agent);
|
|
13406
13592
|
});
|
|
13407
|
-
cmd.command("post-tool-use").description("Hook entrypoint: poll and inject ready knowledge once").action(async () => {
|
|
13408
|
-
await runHookEntrypoint("post-tool-use", readStdinRaw());
|
|
13593
|
+
cmd.command("post-tool-use").description("Hook entrypoint: poll and inject ready knowledge once").option("--agent <agent>", "Calling agent for ticket attribution", DEFAULT_AGENT).action(async (opts) => {
|
|
13594
|
+
await runHookEntrypoint("post-tool-use", readStdinRaw(), Date.now(), opts.agent);
|
|
13409
13595
|
});
|
|
13410
|
-
cmd.command("stop").description("Hook entrypoint: last-chance knowledge delivery when the agent stops").action(async () => {
|
|
13411
|
-
await runHookEntrypoint("stop", readStdinRaw());
|
|
13596
|
+
cmd.command("stop").description("Hook entrypoint: last-chance knowledge delivery when the agent stops").option("--agent <agent>", "Calling agent for ticket attribution", DEFAULT_AGENT).action(async (opts) => {
|
|
13597
|
+
await runHookEntrypoint("stop", readStdinRaw(), Date.now(), opts.agent);
|
|
13412
13598
|
});
|
|
13413
13599
|
cmd.command("status").description("Show the active Dosu knowledge ticket for this session").option("--json", "Output JSON", false).action((opts) => {
|
|
13414
13600
|
let input = {};
|
|
@@ -13426,16 +13612,21 @@ function hooksCommand() {
|
|
|
13426
13612
|
"",
|
|
13427
13613
|
"Examples:",
|
|
13428
13614
|
" $ dosu hooks install claude-code",
|
|
13615
|
+
" $ dosu hooks install codex",
|
|
13429
13616
|
" $ dosu hooks install claude-code --no-stop",
|
|
13430
|
-
" $ dosu hooks install
|
|
13617
|
+
" $ dosu hooks install codex --dir ./my-project",
|
|
13618
|
+
"",
|
|
13619
|
+
"Codex requires a one-time trust step after install: open Codex in the",
|
|
13620
|
+
"project and run /hooks to review and trust the Dosu hooks."
|
|
13431
13621
|
].join(`
|
|
13432
13622
|
`)).action((agent, opts) => runInstall(agent, opts));
|
|
13433
13623
|
cmd.command("uninstall").description("Remove Dosu hooks from a coding agent's local config (Dosu-owned entries only)").addArgument(new Argument("<agent>", "coding agent to clean up").choices(SUPPORTED_AGENTS)).option("--scope <scope>", "Config scope (local only)", "local").option("--dir <path>", "Project root (defaults to current directory)").option("--json", "Emit machine-readable JSON", false).addHelpText("after", [
|
|
13434
13624
|
"",
|
|
13435
13625
|
`Supported agents: ${SUPPORTED_AGENTS.join(", ")}`,
|
|
13436
13626
|
"",
|
|
13437
|
-
"
|
|
13438
|
-
" $ dosu hooks uninstall claude-code"
|
|
13627
|
+
"Examples:",
|
|
13628
|
+
" $ dosu hooks uninstall claude-code",
|
|
13629
|
+
" $ dosu hooks uninstall codex"
|
|
13439
13630
|
].join(`
|
|
13440
13631
|
`)).action((agent, opts) => runUninstall(agent, opts));
|
|
13441
13632
|
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));
|
|
@@ -14271,8 +14462,8 @@ init_skill_update_check();
|
|
|
14271
14462
|
init_config();
|
|
14272
14463
|
init_logger();
|
|
14273
14464
|
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
14274
|
-
import { existsSync as
|
|
14275
|
-
import { join as
|
|
14465
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "node:fs";
|
|
14466
|
+
import { join as join23 } from "node:path";
|
|
14276
14467
|
var CACHE_FILENAME2 = "update-check.json";
|
|
14277
14468
|
var CHECK_INTERVAL_MS2 = 24 * 60 * 60 * 1000;
|
|
14278
14469
|
var FETCH_TIMEOUT_MS2 = 5000;
|
|
@@ -14295,14 +14486,14 @@ function isNewerVersion(latest, current) {
|
|
|
14295
14486
|
return false;
|
|
14296
14487
|
}
|
|
14297
14488
|
function getCachePath2() {
|
|
14298
|
-
return
|
|
14489
|
+
return join23(getConfigDir(), CACHE_FILENAME2);
|
|
14299
14490
|
}
|
|
14300
14491
|
function readCache() {
|
|
14301
14492
|
try {
|
|
14302
14493
|
const path2 = getCachePath2();
|
|
14303
|
-
if (!
|
|
14494
|
+
if (!existsSync13(path2))
|
|
14304
14495
|
return null;
|
|
14305
|
-
const data = JSON.parse(
|
|
14496
|
+
const data = JSON.parse(readFileSync11(path2, "utf-8"));
|
|
14306
14497
|
if (typeof data.lastCheck === "number" && typeof data.latestVersion === "string") {
|
|
14307
14498
|
return data;
|
|
14308
14499
|
}
|
|
@@ -14314,7 +14505,7 @@ function readCache() {
|
|
|
14314
14505
|
function writeCache(cache) {
|
|
14315
14506
|
try {
|
|
14316
14507
|
const dir = getConfigDir();
|
|
14317
|
-
if (!
|
|
14508
|
+
if (!existsSync13(dir)) {
|
|
14318
14509
|
mkdirSync7(dir, { recursive: true, mode: 448 });
|
|
14319
14510
|
}
|
|
14320
14511
|
writeFileSync6(getCachePath2(), JSON.stringify(cache), { mode: 384 });
|
|
@@ -14604,7 +14795,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
|
|
|
14604
14795
|
if (opts.tail !== undefined) {
|
|
14605
14796
|
const n = typeof opts.tail === "string" ? parseInt(opts.tail, 10) || 50 : 50;
|
|
14606
14797
|
try {
|
|
14607
|
-
const content =
|
|
14798
|
+
const content = readFileSync12(logPath, "utf-8");
|
|
14608
14799
|
const lines = content.split(`
|
|
14609
14800
|
`);
|
|
14610
14801
|
console.log(lines.slice(-n).join(`
|