@dosu/cli 0.32.1 → 0.33.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 +247 -115
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -2100,6 +2100,16 @@ var init_commander = __esm(() => {
|
|
|
2100
2100
|
// src/config/config.ts
|
|
2101
2101
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2102
2102
|
import { join } from "node:path";
|
|
2103
|
+
function replaceLoginSession(cfg, session) {
|
|
2104
|
+
cfg.access_token = session.access_token;
|
|
2105
|
+
cfg.refresh_token = session.refresh_token;
|
|
2106
|
+
cfg.expires_at = session.expires_at;
|
|
2107
|
+
cfg.deployment_id = undefined;
|
|
2108
|
+
cfg.deployment_name = undefined;
|
|
2109
|
+
cfg.api_key = undefined;
|
|
2110
|
+
cfg.org_id = undefined;
|
|
2111
|
+
cfg.space_id = undefined;
|
|
2112
|
+
}
|
|
2103
2113
|
function getConfigDir() {
|
|
2104
2114
|
const dirName = process.env.DOSU_DEV === "true" ? "dosu-cli-dev" : "dosu-cli";
|
|
2105
2115
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
@@ -4577,7 +4587,7 @@ var init_dist4 = __esm(() => {
|
|
|
4577
4587
|
function getVersionString() {
|
|
4578
4588
|
return `v${VERSION}`;
|
|
4579
4589
|
}
|
|
4580
|
-
var VERSION = "0.
|
|
4590
|
+
var VERSION = "0.33.1", INSTALL_CHANNEL = "npm";
|
|
4581
4591
|
|
|
4582
4592
|
// src/debug/logger.ts
|
|
4583
4593
|
import {
|
|
@@ -10981,6 +10991,160 @@ var init_providers = __esm(() => {
|
|
|
10981
10991
|
init_zed();
|
|
10982
10992
|
});
|
|
10983
10993
|
|
|
10994
|
+
// src/setup/audit-handoff.ts
|
|
10995
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
10996
|
+
function buildAuditHandoffPrompt(dosuCmd = dosuInvocation()) {
|
|
10997
|
+
return [
|
|
10998
|
+
"Audit this repository to see what docs Dosu can generate for it.",
|
|
10999
|
+
"1. Run the codebase audit from the Dosu skill. It writes findings to .dosu/audit.json.",
|
|
11000
|
+
"2. Show me the findings and which docs you recommend Dosu generate.",
|
|
11001
|
+
`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.`
|
|
11002
|
+
].join(`
|
|
11003
|
+
`);
|
|
11004
|
+
}
|
|
11005
|
+
function binOnPath(bin) {
|
|
11006
|
+
const cmd = process.platform === "win32" ? "where" : "which";
|
|
11007
|
+
try {
|
|
11008
|
+
return spawnSync2(cmd, [bin], { stdio: "ignore" }).status === 0;
|
|
11009
|
+
} catch {
|
|
11010
|
+
return false;
|
|
11011
|
+
}
|
|
11012
|
+
}
|
|
11013
|
+
function claudeCliAvailable() {
|
|
11014
|
+
return binOnPath("claude");
|
|
11015
|
+
}
|
|
11016
|
+
function dosuInvocation() {
|
|
11017
|
+
return binOnPath("dosu") ? "dosu" : "npx -y @dosu/cli";
|
|
11018
|
+
}
|
|
11019
|
+
function printManualAuditNudge() {
|
|
11020
|
+
log.message(`See what docs Dosu can generate for this repo:
|
|
11021
|
+
|
|
11022
|
+
${info("Ask Dosu to audit this repo and show what docs it can generate.")}
|
|
11023
|
+
|
|
11024
|
+
Or run ${info(`${dosuInvocation()} audit`)} after your agent writes the audit.`);
|
|
11025
|
+
}
|
|
11026
|
+
async function offerAuditHandoff() {
|
|
11027
|
+
if (!detectGitRepo())
|
|
11028
|
+
return false;
|
|
11029
|
+
if (!claudeCliAvailable()) {
|
|
11030
|
+
printManualAuditNudge();
|
|
11031
|
+
return false;
|
|
11032
|
+
}
|
|
11033
|
+
const go = await confirm({
|
|
11034
|
+
message: "Kick off the codebase audit in Claude Code now?",
|
|
11035
|
+
initialValue: true
|
|
11036
|
+
});
|
|
11037
|
+
if (isCancel(go) || !go) {
|
|
11038
|
+
printManualAuditNudge();
|
|
11039
|
+
return false;
|
|
11040
|
+
}
|
|
11041
|
+
return true;
|
|
11042
|
+
}
|
|
11043
|
+
function launchAuditAgent() {
|
|
11044
|
+
logger.info("setup", "Handing off to Claude Code for the codebase audit");
|
|
11045
|
+
const result = spawnSync2("claude", ["--model", AUDIT_AGENT_MODEL, buildAuditHandoffPrompt()], {
|
|
11046
|
+
stdio: "inherit",
|
|
11047
|
+
shell: process.platform === "win32"
|
|
11048
|
+
});
|
|
11049
|
+
if (result.error) {
|
|
11050
|
+
logger.warn("setup", `Claude Code launch failed: ${result.error.message}`);
|
|
11051
|
+
printManualAuditNudge();
|
|
11052
|
+
}
|
|
11053
|
+
}
|
|
11054
|
+
var AUDIT_AGENT_MODEL = "haiku";
|
|
11055
|
+
var init_audit_handoff = __esm(() => {
|
|
11056
|
+
init_dist8();
|
|
11057
|
+
init_logger();
|
|
11058
|
+
init_github_step();
|
|
11059
|
+
init_styles();
|
|
11060
|
+
});
|
|
11061
|
+
|
|
11062
|
+
// src/setup/agents-md-step.ts
|
|
11063
|
+
import { execSync as execSync3 } from "node:child_process";
|
|
11064
|
+
import { existsSync as existsSync16, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "node:fs";
|
|
11065
|
+
import { join as join26 } from "node:path";
|
|
11066
|
+
function inGitWorkTree(cwd = process.cwd()) {
|
|
11067
|
+
try {
|
|
11068
|
+
const stdout2 = execSync3("git rev-parse --is-inside-work-tree", {
|
|
11069
|
+
cwd,
|
|
11070
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
11071
|
+
});
|
|
11072
|
+
return stdout2.toString().trim() === "true";
|
|
11073
|
+
} catch {
|
|
11074
|
+
return false;
|
|
11075
|
+
}
|
|
11076
|
+
}
|
|
11077
|
+
function buildDosuAgentsSection(dosuCmd = dosuInvocation()) {
|
|
11078
|
+
return [
|
|
11079
|
+
DOSU_SECTION_START,
|
|
11080
|
+
"## Dosu",
|
|
11081
|
+
"",
|
|
11082
|
+
"Shared team knowledge lives in [Dosu](https://dosu.dev), via the Dosu MCP server.",
|
|
11083
|
+
"",
|
|
11084
|
+
"- Before a task, and for any codebase or docs questions: pull context with `read_knowledge` before digging through source.",
|
|
11085
|
+
"- After a task: save durable learnings with `write_knowledge`.",
|
|
11086
|
+
"",
|
|
11087
|
+
`Missing these tools? Run \`${dosuCmd} setup --help\` — it covers agent-assisted setup.`,
|
|
11088
|
+
DOSU_SECTION_END
|
|
11089
|
+
].join(`
|
|
11090
|
+
`);
|
|
11091
|
+
}
|
|
11092
|
+
function upsertDosuAgentsSection(cwd = process.cwd(), dosuCmd = dosuInvocation()) {
|
|
11093
|
+
const path3 = join26(cwd, "AGENTS.md");
|
|
11094
|
+
const section = buildDosuAgentsSection(dosuCmd);
|
|
11095
|
+
if (!existsSync16(path3)) {
|
|
11096
|
+
writeFileSync7(path3, `${section}
|
|
11097
|
+
`);
|
|
11098
|
+
return { path: path3, action: "created" };
|
|
11099
|
+
}
|
|
11100
|
+
const existing = readFileSync14(path3, "utf-8");
|
|
11101
|
+
const startMatch = existing.match(SECTION_START_RE);
|
|
11102
|
+
const start = startMatch?.index ?? -1;
|
|
11103
|
+
const end = existing.indexOf(DOSU_SECTION_END);
|
|
11104
|
+
let next;
|
|
11105
|
+
if (start !== -1 && end !== -1 && end >= start) {
|
|
11106
|
+
next = existing.slice(0, start) + section + existing.slice(end + DOSU_SECTION_END.length);
|
|
11107
|
+
} else {
|
|
11108
|
+
next = `${existing.trimEnd()}
|
|
11109
|
+
|
|
11110
|
+
${section}
|
|
11111
|
+
`;
|
|
11112
|
+
}
|
|
11113
|
+
if (next === existing)
|
|
11114
|
+
return { path: path3, action: "unchanged" };
|
|
11115
|
+
writeFileSync7(path3, next);
|
|
11116
|
+
return { path: path3, action: "updated" };
|
|
11117
|
+
}
|
|
11118
|
+
function stepUpdateAgentsMd(cwd = process.cwd()) {
|
|
11119
|
+
logger.info("setup", "Step: update AGENTS.md");
|
|
11120
|
+
try {
|
|
11121
|
+
const result = upsertDosuAgentsSection(cwd);
|
|
11122
|
+
logger.info("setup", `AGENTS.md ${result.action} at ${result.path}`);
|
|
11123
|
+
if (result.action === "unchanged") {
|
|
11124
|
+
log.success(`AGENTS.md
|
|
11125
|
+
${dim("Dosu section already up to date")}`);
|
|
11126
|
+
} else {
|
|
11127
|
+
log.success(`AGENTS.md
|
|
11128
|
+
${dim(`Dosu section ${result.action} — ${result.path}`)}`);
|
|
11129
|
+
}
|
|
11130
|
+
return true;
|
|
11131
|
+
} catch (err) {
|
|
11132
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
11133
|
+
logger.error("setup", `AGENTS.md update failed: ${msg}`);
|
|
11134
|
+
log.error(`Could not update AGENTS.md: ${msg}`);
|
|
11135
|
+
return false;
|
|
11136
|
+
}
|
|
11137
|
+
}
|
|
11138
|
+
var DOSU_SECTION_VERSION = 1, DOSU_SECTION_START, DOSU_SECTION_END = "<!-- dosu:mcp:end -->", SECTION_START_RE;
|
|
11139
|
+
var init_agents_md_step = __esm(() => {
|
|
11140
|
+
init_dist8();
|
|
11141
|
+
init_logger();
|
|
11142
|
+
init_audit_handoff();
|
|
11143
|
+
init_styles();
|
|
11144
|
+
DOSU_SECTION_START = `<!-- dosu:mcp:start v${DOSU_SECTION_VERSION} -->`;
|
|
11145
|
+
SECTION_START_RE = /<!-- dosu:mcp:start(?: v(\d+))? -->/;
|
|
11146
|
+
});
|
|
11147
|
+
|
|
10984
11148
|
// src/setup/analytics.ts
|
|
10985
11149
|
async function trackCliOnboardingEvent(cfg, onboardingRunID, event, properties = {}) {
|
|
10986
11150
|
if (!cfg.access_token)
|
|
@@ -11066,74 +11230,6 @@ var init_analytics = __esm(() => {
|
|
|
11066
11230
|
init_logger();
|
|
11067
11231
|
});
|
|
11068
11232
|
|
|
11069
|
-
// src/setup/audit-handoff.ts
|
|
11070
|
-
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
11071
|
-
function buildAuditHandoffPrompt(dosuCmd = dosuInvocation()) {
|
|
11072
|
-
return [
|
|
11073
|
-
"Audit this repository to see what docs Dosu can generate for it.",
|
|
11074
|
-
"1. Run the codebase audit from the Dosu skill. It writes findings to .dosu/audit.json.",
|
|
11075
|
-
"2. Show me the findings and which docs you recommend Dosu generate.",
|
|
11076
|
-
`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.`
|
|
11077
|
-
].join(`
|
|
11078
|
-
`);
|
|
11079
|
-
}
|
|
11080
|
-
function binOnPath(bin) {
|
|
11081
|
-
const cmd = process.platform === "win32" ? "where" : "which";
|
|
11082
|
-
try {
|
|
11083
|
-
return spawnSync2(cmd, [bin], { stdio: "ignore" }).status === 0;
|
|
11084
|
-
} catch {
|
|
11085
|
-
return false;
|
|
11086
|
-
}
|
|
11087
|
-
}
|
|
11088
|
-
function claudeCliAvailable() {
|
|
11089
|
-
return binOnPath("claude");
|
|
11090
|
-
}
|
|
11091
|
-
function dosuInvocation() {
|
|
11092
|
-
return binOnPath("dosu") ? "dosu" : "npx -y @dosu/cli";
|
|
11093
|
-
}
|
|
11094
|
-
function printManualAuditNudge() {
|
|
11095
|
-
log.message(`See what docs Dosu can generate for this repo:
|
|
11096
|
-
|
|
11097
|
-
${info("Ask Dosu to audit this repo and show what docs it can generate.")}
|
|
11098
|
-
|
|
11099
|
-
Or run ${info(`${dosuInvocation()} audit`)} after your agent writes the audit.`);
|
|
11100
|
-
}
|
|
11101
|
-
async function offerAuditHandoff() {
|
|
11102
|
-
if (!detectGitRepo())
|
|
11103
|
-
return false;
|
|
11104
|
-
if (!claudeCliAvailable()) {
|
|
11105
|
-
printManualAuditNudge();
|
|
11106
|
-
return false;
|
|
11107
|
-
}
|
|
11108
|
-
const go = await confirm({
|
|
11109
|
-
message: "Kick off the codebase audit in Claude Code now?",
|
|
11110
|
-
initialValue: true
|
|
11111
|
-
});
|
|
11112
|
-
if (isCancel(go) || !go) {
|
|
11113
|
-
printManualAuditNudge();
|
|
11114
|
-
return false;
|
|
11115
|
-
}
|
|
11116
|
-
return true;
|
|
11117
|
-
}
|
|
11118
|
-
function launchAuditAgent() {
|
|
11119
|
-
logger.info("setup", "Handing off to Claude Code for the codebase audit");
|
|
11120
|
-
const result = spawnSync2("claude", ["--model", AUDIT_AGENT_MODEL, buildAuditHandoffPrompt()], {
|
|
11121
|
-
stdio: "inherit",
|
|
11122
|
-
shell: process.platform === "win32"
|
|
11123
|
-
});
|
|
11124
|
-
if (result.error) {
|
|
11125
|
-
logger.warn("setup", `Claude Code launch failed: ${result.error.message}`);
|
|
11126
|
-
printManualAuditNudge();
|
|
11127
|
-
}
|
|
11128
|
-
}
|
|
11129
|
-
var AUDIT_AGENT_MODEL = "haiku";
|
|
11130
|
-
var init_audit_handoff = __esm(() => {
|
|
11131
|
-
init_dist8();
|
|
11132
|
-
init_logger();
|
|
11133
|
-
init_github_step();
|
|
11134
|
-
init_styles();
|
|
11135
|
-
});
|
|
11136
|
-
|
|
11137
11233
|
// src/auth/errors.ts
|
|
11138
11234
|
var exports_errors = {};
|
|
11139
11235
|
__export(exports_errors, {
|
|
@@ -11662,7 +11758,7 @@ async function runSetup(opts = {}) {
|
|
|
11662
11758
|
authTab?.close();
|
|
11663
11759
|
};
|
|
11664
11760
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_auth_completed");
|
|
11665
|
-
|
|
11761
|
+
let apiClient = new Client(cfg);
|
|
11666
11762
|
let cloudSetupContext = null;
|
|
11667
11763
|
if (cfg.mode !== MODE_OSS) {
|
|
11668
11764
|
const s = spinner();
|
|
@@ -11693,7 +11789,9 @@ async function runSetup(opts = {}) {
|
|
|
11693
11789
|
});
|
|
11694
11790
|
return;
|
|
11695
11791
|
}
|
|
11696
|
-
|
|
11792
|
+
apiClient = new Client(cfg);
|
|
11793
|
+
const targetOrg = await resolveCurrentOnboardingTargetOrg(cfg);
|
|
11794
|
+
const ok = await bindOnboardingDeployment(apiClient, cfg, targetOrg);
|
|
11697
11795
|
if (!ok) {
|
|
11698
11796
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
|
|
11699
11797
|
reason: "onboarding_deployment_failed"
|
|
@@ -11718,7 +11816,7 @@ async function runSetup(opts = {}) {
|
|
|
11718
11816
|
}
|
|
11719
11817
|
cfg.api_key = apiKey;
|
|
11720
11818
|
saveConfig(cfg);
|
|
11721
|
-
const choices = await stepOneShotConfirm();
|
|
11819
|
+
const choices = await stepOneShotConfirm(inGitWorkTree());
|
|
11722
11820
|
if (!choices) {
|
|
11723
11821
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_cancelled", {
|
|
11724
11822
|
reason: "options_cancelled"
|
|
@@ -11727,7 +11825,8 @@ async function runSetup(opts = {}) {
|
|
|
11727
11825
|
}
|
|
11728
11826
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_options_selected", {
|
|
11729
11827
|
configure_mcp: choices.configureMcp,
|
|
11730
|
-
install_skill: choices.installSkill
|
|
11828
|
+
install_skill: choices.installSkill,
|
|
11829
|
+
update_agents_md: choices.updateAgentsMd
|
|
11731
11830
|
});
|
|
11732
11831
|
let mcpConfiguredThisRun = false;
|
|
11733
11832
|
let mcpCompleted = false;
|
|
@@ -11756,14 +11855,19 @@ async function runSetup(opts = {}) {
|
|
|
11756
11855
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_skill_installed");
|
|
11757
11856
|
}
|
|
11758
11857
|
}
|
|
11858
|
+
let agentsMdCompleted = false;
|
|
11859
|
+
if (choices.updateAgentsMd) {
|
|
11860
|
+
agentsMdCompleted = stepUpdateAgentsMd();
|
|
11861
|
+
}
|
|
11759
11862
|
let handoffToAudit = false;
|
|
11760
11863
|
if (mcpConfiguredThisRun && cfg.mode !== MODE_OSS) {
|
|
11761
11864
|
handoffToAudit = await offerAuditHandoff();
|
|
11762
11865
|
}
|
|
11763
|
-
if (mcpCompleted || skillCompleted) {
|
|
11866
|
+
if (mcpCompleted || skillCompleted || agentsMdCompleted) {
|
|
11764
11867
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_completed", {
|
|
11765
11868
|
completed_mcp: mcpCompleted,
|
|
11766
|
-
completed_skill: skillCompleted
|
|
11869
|
+
completed_skill: skillCompleted,
|
|
11870
|
+
completed_agents_md: agentsMdCompleted
|
|
11767
11871
|
});
|
|
11768
11872
|
}
|
|
11769
11873
|
if (cfg.mode === MODE_OSS) {
|
|
@@ -11792,11 +11896,14 @@ function applyModeOverride(cfg, opts) {
|
|
|
11792
11896
|
}
|
|
11793
11897
|
saveConfig(cfg);
|
|
11794
11898
|
}
|
|
11795
|
-
async function stepOneShotConfirm() {
|
|
11899
|
+
async function stepOneShotConfirm(offerAgentsMd) {
|
|
11796
11900
|
const items = [
|
|
11797
11901
|
{ value: "configureMcp", label: "Install Dosu MCP" },
|
|
11798
11902
|
{ value: "installSkill", label: "Install Dosu skill" }
|
|
11799
11903
|
];
|
|
11904
|
+
if (offerAgentsMd) {
|
|
11905
|
+
items.push({ value: "updateAgentsMd", label: "Add Dosu instructions to AGENTS.md" });
|
|
11906
|
+
}
|
|
11800
11907
|
const selected = await multiselect({
|
|
11801
11908
|
message: "Dosu will set these up — press Enter to accept, space to toggle",
|
|
11802
11909
|
options: items.map((it) => ({ value: it.value, label: it.label })),
|
|
@@ -11810,7 +11917,8 @@ async function stepOneShotConfirm() {
|
|
|
11810
11917
|
const chosen = new Set(selected);
|
|
11811
11918
|
return {
|
|
11812
11919
|
configureMcp: chosen.has("configureMcp"),
|
|
11813
|
-
installSkill: chosen.has("installSkill")
|
|
11920
|
+
installSkill: chosen.has("installSkill"),
|
|
11921
|
+
updateAgentsMd: chosen.has("updateAgentsMd")
|
|
11814
11922
|
};
|
|
11815
11923
|
}
|
|
11816
11924
|
async function stepConfigureMcpTools(cfg) {
|
|
@@ -11899,9 +12007,11 @@ async function openBrowserForSetup(cfg, onboardingRunID) {
|
|
|
11899
12007
|
const token = result.token;
|
|
11900
12008
|
s.stop("Authenticated");
|
|
11901
12009
|
logger.info("setup", "Browser auth completed");
|
|
11902
|
-
cfg
|
|
11903
|
-
|
|
11904
|
-
|
|
12010
|
+
replaceLoginSession(cfg, {
|
|
12011
|
+
access_token: token.access_token,
|
|
12012
|
+
refresh_token: token.refresh_token,
|
|
12013
|
+
expires_at: Math.floor(Date.now() / 1000) + token.expires_in
|
|
12014
|
+
});
|
|
11905
12015
|
saveConfig(cfg);
|
|
11906
12016
|
return { cfg, authTab: result.server };
|
|
11907
12017
|
} catch (err) {
|
|
@@ -11946,9 +12056,11 @@ async function stepWebOnboarding(cfg, onboardingRunID, authTab) {
|
|
|
11946
12056
|
s.stop("Could not open a browser");
|
|
11947
12057
|
return false;
|
|
11948
12058
|
}
|
|
11949
|
-
cfg
|
|
11950
|
-
|
|
11951
|
-
|
|
12059
|
+
replaceLoginSession(cfg, {
|
|
12060
|
+
access_token: result.token.access_token,
|
|
12061
|
+
refresh_token: result.token.refresh_token,
|
|
12062
|
+
expires_at: Math.floor(Date.now() / 1000) + result.token.expires_in
|
|
12063
|
+
});
|
|
11952
12064
|
saveConfig(cfg);
|
|
11953
12065
|
s.stop("Onboarding finished in the browser");
|
|
11954
12066
|
logger.info("setup", "Web onboarding handoff completed");
|
|
@@ -12004,6 +12116,17 @@ async function resolveOnboardingTargetOrg(trpc) {
|
|
|
12004
12116
|
}
|
|
12005
12117
|
return accessibleOrgs[0] ?? null;
|
|
12006
12118
|
}
|
|
12119
|
+
async function resolveCurrentOnboardingTargetOrg(cfg) {
|
|
12120
|
+
try {
|
|
12121
|
+
const { createTypedClient: createTypedClient2 } = await Promise.resolve().then(() => (init_trpc(), exports_trpc));
|
|
12122
|
+
return await resolveOnboardingTargetOrg(createTypedClient2(cfg));
|
|
12123
|
+
} catch (err) {
|
|
12124
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
12125
|
+
logger.error("setup", `Failed to resolve post-onboarding organization: ${msg}`);
|
|
12126
|
+
log.error(`Could not determine your onboarding organization: ${msg}`);
|
|
12127
|
+
return null;
|
|
12128
|
+
}
|
|
12129
|
+
}
|
|
12007
12130
|
async function bindOnboardingDeployment(apiClient, cfg, targetOrg) {
|
|
12008
12131
|
if (!targetOrg) {
|
|
12009
12132
|
log.error("Could not determine your onboarding organization.");
|
|
@@ -12263,14 +12386,15 @@ var init_flow2 = __esm(() => {
|
|
|
12263
12386
|
init_config();
|
|
12264
12387
|
init_logger();
|
|
12265
12388
|
init_providers();
|
|
12389
|
+
init_agents_md_step();
|
|
12266
12390
|
init_analytics();
|
|
12267
12391
|
init_audit_handoff();
|
|
12268
12392
|
init_styles();
|
|
12269
12393
|
});
|
|
12270
12394
|
|
|
12271
12395
|
// src/commands/insights.ts
|
|
12272
|
-
import { existsSync as
|
|
12273
|
-
import { dirname as dirname5, join as
|
|
12396
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync8, readdirSync, unlinkSync, writeFileSync as writeFileSync8 } from "node:fs";
|
|
12397
|
+
import { dirname as dirname5, join as join27 } from "node:path";
|
|
12274
12398
|
function shuffled(arr) {
|
|
12275
12399
|
const copy2 = [...arr];
|
|
12276
12400
|
for (let i2 = copy2.length - 1;i2 > 0; i2--) {
|
|
@@ -12374,17 +12498,17 @@ function makeAskFn(cfg) {
|
|
|
12374
12498
|
};
|
|
12375
12499
|
}
|
|
12376
12500
|
function insightsDir() {
|
|
12377
|
-
return
|
|
12501
|
+
return join27(getConfigDir(), "insights");
|
|
12378
12502
|
}
|
|
12379
12503
|
function reportPath(timestamp) {
|
|
12380
12504
|
const dir = insightsDir();
|
|
12381
12505
|
if (!timestamp)
|
|
12382
|
-
return
|
|
12506
|
+
return join27(dir, "latest.html");
|
|
12383
12507
|
const iso = timestamp.toISOString().slice(0, 19).replace(/:/g, "-");
|
|
12384
|
-
return
|
|
12508
|
+
return join27(dir, `report-${iso}Z.html`);
|
|
12385
12509
|
}
|
|
12386
12510
|
function pruneOldReports(dir, keepN) {
|
|
12387
|
-
if (!
|
|
12511
|
+
if (!existsSync17(dir))
|
|
12388
12512
|
return;
|
|
12389
12513
|
let entries;
|
|
12390
12514
|
try {
|
|
@@ -12396,7 +12520,7 @@ function pruneOldReports(dir, keepN) {
|
|
|
12396
12520
|
const reports = entries.filter((f2) => REPORT_FILE_PATTERN.test(f2)).sort().reverse();
|
|
12397
12521
|
for (const f2 of reports.slice(keepN)) {
|
|
12398
12522
|
try {
|
|
12399
|
-
unlinkSync(
|
|
12523
|
+
unlinkSync(join27(dir, f2));
|
|
12400
12524
|
} catch (err) {
|
|
12401
12525
|
logger.debug("insights", `failed to prune ${f2}: ${err instanceof Error ? err.message : err}`);
|
|
12402
12526
|
}
|
|
@@ -12469,9 +12593,9 @@ function defaultRunner(cfg) {
|
|
|
12469
12593
|
render: renderHTML,
|
|
12470
12594
|
writeFile: (path3, content) => {
|
|
12471
12595
|
const dir = dirname5(path3);
|
|
12472
|
-
if (!
|
|
12596
|
+
if (!existsSync17(dir))
|
|
12473
12597
|
mkdirSync8(dir, { recursive: true, mode: 448 });
|
|
12474
|
-
|
|
12598
|
+
writeFileSync8(path3, content, { mode: 384 });
|
|
12475
12599
|
},
|
|
12476
12600
|
prune: pruneOldReports,
|
|
12477
12601
|
openInBrowser: async (path3) => {
|
|
@@ -12626,9 +12750,11 @@ async function handleAuthenticate(cfg) {
|
|
|
12626
12750
|
}
|
|
12627
12751
|
const token = result.token;
|
|
12628
12752
|
s.stop("Authenticated");
|
|
12629
|
-
cfg
|
|
12630
|
-
|
|
12631
|
-
|
|
12753
|
+
replaceLoginSession(cfg, {
|
|
12754
|
+
access_token: token.access_token,
|
|
12755
|
+
refresh_token: token.refresh_token,
|
|
12756
|
+
expires_at: Math.floor(Date.now() / 1000) + token.expires_in
|
|
12757
|
+
});
|
|
12632
12758
|
saveConfig(cfg);
|
|
12633
12759
|
} catch (err) {
|
|
12634
12760
|
const { OAuthCallbackError: OAuthCallbackError2 } = await Promise.resolve().then(() => (init_errors(), exports_errors));
|
|
@@ -12795,9 +12921,11 @@ async function runLoginCheck(opts) {
|
|
|
12795
12921
|
}
|
|
12796
12922
|
if (result.status === "authenticated") {
|
|
12797
12923
|
const cfg = loadConfig();
|
|
12798
|
-
cfg
|
|
12799
|
-
|
|
12800
|
-
|
|
12924
|
+
replaceLoginSession(cfg, {
|
|
12925
|
+
access_token: result.access_token ?? "",
|
|
12926
|
+
refresh_token: result.refresh_token ?? "",
|
|
12927
|
+
expires_at: Math.floor(Date.now() / 1000) + (result.expires_in ?? 3600)
|
|
12928
|
+
});
|
|
12801
12929
|
saveConfig(cfg);
|
|
12802
12930
|
logger.info("auth.ticket", "Ticket redeemed via dosu login --check");
|
|
12803
12931
|
if (opts.json) {
|
|
@@ -12988,9 +13116,11 @@ async function redeemTicket(ticket, cfg) {
|
|
|
12988
13116
|
});
|
|
12989
13117
|
return { code: 0, cfg, exit: true };
|
|
12990
13118
|
}
|
|
12991
|
-
cfg
|
|
12992
|
-
|
|
12993
|
-
|
|
13119
|
+
replaceLoginSession(cfg, {
|
|
13120
|
+
access_token: result.access_token ?? "",
|
|
13121
|
+
refresh_token: result.refresh_token ?? "",
|
|
13122
|
+
expires_at: Math.floor(Date.now() / 1000) + (result.expires_in ?? 3600)
|
|
13123
|
+
});
|
|
12994
13124
|
saveConfig(cfg);
|
|
12995
13125
|
logger.info("agent.flow", "Ticket redeemed; session saved");
|
|
12996
13126
|
emitStep({ step: "auth", email: result.email });
|
|
@@ -13198,7 +13328,7 @@ var init_flow3 = __esm(() => {
|
|
|
13198
13328
|
// src/cli/cli.ts
|
|
13199
13329
|
init_commander();
|
|
13200
13330
|
init_client();
|
|
13201
|
-
import { readFileSync as
|
|
13331
|
+
import { readFileSync as readFileSync17, unlinkSync as unlinkSync2 } from "node:fs";
|
|
13202
13332
|
|
|
13203
13333
|
// src/commands/analytics.ts
|
|
13204
13334
|
init_commander();
|
|
@@ -15260,7 +15390,7 @@ init_dist();
|
|
|
15260
15390
|
init_commander();
|
|
15261
15391
|
init_trpc();
|
|
15262
15392
|
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
15263
|
-
import { readFileSync as
|
|
15393
|
+
import { readFileSync as readFileSync15 } from "node:fs";
|
|
15264
15394
|
function requireConfig10() {
|
|
15265
15395
|
return requireLoginConfig();
|
|
15266
15396
|
}
|
|
@@ -15436,7 +15566,7 @@ function reviewCommand() {
|
|
|
15436
15566
|
let body = opts.body;
|
|
15437
15567
|
if (opts.bodyFile) {
|
|
15438
15568
|
try {
|
|
15439
|
-
body =
|
|
15569
|
+
body = readFileSync15(opts.bodyFile, "utf-8");
|
|
15440
15570
|
} catch (err) {
|
|
15441
15571
|
console.error(import_picocolors19.default.red(`Failed to read --body-file: ${err.message}`));
|
|
15442
15572
|
process.exit(1);
|
|
@@ -15956,8 +16086,8 @@ init_skill_update_check();
|
|
|
15956
16086
|
init_config();
|
|
15957
16087
|
init_logger();
|
|
15958
16088
|
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
15959
|
-
import { existsSync as
|
|
15960
|
-
import { join as
|
|
16089
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync9, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "node:fs";
|
|
16090
|
+
import { join as join28 } from "node:path";
|
|
15961
16091
|
var CACHE_FILENAME3 = "update-check.json";
|
|
15962
16092
|
var CHECK_INTERVAL_MS3 = 24 * 60 * 60 * 1000;
|
|
15963
16093
|
var FETCH_TIMEOUT_MS3 = 5000;
|
|
@@ -15980,14 +16110,14 @@ function isNewerVersion(latest, current) {
|
|
|
15980
16110
|
return false;
|
|
15981
16111
|
}
|
|
15982
16112
|
function getCachePath3() {
|
|
15983
|
-
return
|
|
16113
|
+
return join28(getConfigDir(), CACHE_FILENAME3);
|
|
15984
16114
|
}
|
|
15985
16115
|
function readCache() {
|
|
15986
16116
|
try {
|
|
15987
16117
|
const path3 = getCachePath3();
|
|
15988
|
-
if (!
|
|
16118
|
+
if (!existsSync18(path3))
|
|
15989
16119
|
return null;
|
|
15990
|
-
const data = JSON.parse(
|
|
16120
|
+
const data = JSON.parse(readFileSync16(path3, "utf-8"));
|
|
15991
16121
|
if (typeof data.lastCheck === "number" && typeof data.latestVersion === "string") {
|
|
15992
16122
|
return data;
|
|
15993
16123
|
}
|
|
@@ -15999,10 +16129,10 @@ function readCache() {
|
|
|
15999
16129
|
function writeCache(cache) {
|
|
16000
16130
|
try {
|
|
16001
16131
|
const dir = getConfigDir();
|
|
16002
|
-
if (!
|
|
16132
|
+
if (!existsSync18(dir)) {
|
|
16003
16133
|
mkdirSync9(dir, { recursive: true, mode: 448 });
|
|
16004
16134
|
}
|
|
16005
|
-
|
|
16135
|
+
writeFileSync9(getCachePath3(), JSON.stringify(cache), { mode: 384 });
|
|
16006
16136
|
} catch {}
|
|
16007
16137
|
}
|
|
16008
16138
|
async function fetchLatestVersion() {
|
|
@@ -16194,9 +16324,11 @@ Run 'dosu --help' to see available commands.`;
|
|
|
16194
16324
|
token = result.token;
|
|
16195
16325
|
}
|
|
16196
16326
|
}
|
|
16197
|
-
cfg
|
|
16198
|
-
|
|
16199
|
-
|
|
16327
|
+
replaceLoginSession(cfg, {
|
|
16328
|
+
access_token: token.access_token,
|
|
16329
|
+
refresh_token: token.refresh_token,
|
|
16330
|
+
expires_at: Math.floor(Date.now() / 1000) + token.expires_in
|
|
16331
|
+
});
|
|
16200
16332
|
saveConfig(cfg);
|
|
16201
16333
|
console.log("Successfully authenticated!");
|
|
16202
16334
|
console.log(`Credentials saved to ${getConfigPath()}`);
|
|
@@ -16366,7 +16498,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
|
|
|
16366
16498
|
if (opts.tail !== undefined) {
|
|
16367
16499
|
const n2 = typeof opts.tail === "string" ? parseInt(opts.tail, 10) || 50 : 50;
|
|
16368
16500
|
try {
|
|
16369
|
-
const content =
|
|
16501
|
+
const content = readFileSync17(logPath, "utf-8");
|
|
16370
16502
|
const lines = content.split(`
|
|
16371
16503
|
`);
|
|
16372
16504
|
console.log(lines.slice(-n2).join(`
|