@dosu/cli 0.13.3 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/dosu.js +105 -29
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -4341,7 +4341,7 @@ function getSupabaseAnonKey() {
|
|
|
4341
4341
|
function getVersionString() {
|
|
4342
4342
|
return `v${VERSION}`;
|
|
4343
4343
|
}
|
|
4344
|
-
var VERSION = "0.
|
|
4344
|
+
var VERSION = "0.14.0";
|
|
4345
4345
|
|
|
4346
4346
|
// src/debug/logger.ts
|
|
4347
4347
|
import {
|
|
@@ -9865,7 +9865,7 @@ var exports_flow = {};
|
|
|
9865
9865
|
__export(exports_flow, {
|
|
9866
9866
|
startOAuthFlow: () => startOAuthFlow
|
|
9867
9867
|
});
|
|
9868
|
-
async function startOAuthFlow(signal, path2 = "/cli/auth", params = {}) {
|
|
9868
|
+
async function startOAuthFlow(signal, path2 = "/cli/auth", params = {}, opts = {}) {
|
|
9869
9869
|
const { server, tokenPromise } = await startCallbackServer();
|
|
9870
9870
|
let timeoutId;
|
|
9871
9871
|
try {
|
|
@@ -9873,9 +9873,12 @@ async function startOAuthFlow(signal, path2 = "/cli/auth", params = {}) {
|
|
|
9873
9873
|
logger.debug("auth.flow", `Callback URL: ${callbackURL}`);
|
|
9874
9874
|
const authURL = buildAuthURL(callbackURL, path2, params);
|
|
9875
9875
|
logger.info("auth.flow", `Auth URL: ${authURL}`);
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
|
|
9876
|
+
opts.onAuthURL?.(authURL);
|
|
9877
|
+
if (opts.openBrowser !== false) {
|
|
9878
|
+
const open2 = await Promise.resolve().then(() => (init_open(), exports_open));
|
|
9879
|
+
await open2.default(authURL);
|
|
9880
|
+
logger.info("auth.flow", "Browser open command executed");
|
|
9881
|
+
}
|
|
9879
9882
|
const timeout = new Promise((_3, reject) => {
|
|
9880
9883
|
timeoutId = setTimeout(() => {
|
|
9881
9884
|
logger.warn("auth.flow", "Authentication timed out (8min)");
|
|
@@ -9935,7 +9938,7 @@ async function runSetup(opts = {}) {
|
|
|
9935
9938
|
cfg.mode = undefined;
|
|
9936
9939
|
saveConfig(cfg);
|
|
9937
9940
|
}
|
|
9938
|
-
const authedCfg = await stepAuthenticate(cfg, onboardingRunID);
|
|
9941
|
+
const authedCfg = await stepAuthenticate(cfg, onboardingRunID, opts);
|
|
9939
9942
|
if (!authedCfg)
|
|
9940
9943
|
return;
|
|
9941
9944
|
cfg = authedCfg;
|
|
@@ -9985,7 +9988,8 @@ async function runSetup(opts = {}) {
|
|
|
9985
9988
|
cfg.api_key = apiKey;
|
|
9986
9989
|
saveConfig(cfg);
|
|
9987
9990
|
const choices = await stepOneShotConfirm({
|
|
9988
|
-
includeGitHub: cloudSetupContext?.kind === "onboarding"
|
|
9991
|
+
includeGitHub: cloudSetupContext?.kind === "onboarding",
|
|
9992
|
+
setupOptions: opts
|
|
9989
9993
|
});
|
|
9990
9994
|
if (!choices) {
|
|
9991
9995
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_cancelled", {
|
|
@@ -10003,7 +10007,7 @@ async function runSetup(opts = {}) {
|
|
|
10003
10007
|
let skillCompleted = false;
|
|
10004
10008
|
let docsImported = false;
|
|
10005
10009
|
if (choices.configureMcp) {
|
|
10006
|
-
const configured = await stepConfigureMcpTools(cfg);
|
|
10010
|
+
const configured = await stepConfigureMcpTools(cfg, opts.toolIDs);
|
|
10007
10011
|
if (configured === null) {
|
|
10008
10012
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_cancelled", {
|
|
10009
10013
|
reason: "mcp_selection_cancelled"
|
|
@@ -10126,6 +10130,13 @@ function applyModeOverride(cfg, opts) {
|
|
|
10126
10130
|
saveConfig(cfg);
|
|
10127
10131
|
}
|
|
10128
10132
|
async function stepOneShotConfirm(opts) {
|
|
10133
|
+
if (opts.setupOptions?.yes) {
|
|
10134
|
+
return {
|
|
10135
|
+
configureMcp: !opts.setupOptions.skipMcp,
|
|
10136
|
+
installSkill: !opts.setupOptions.skipSkill,
|
|
10137
|
+
connectGitHub: opts.includeGitHub && !opts.setupOptions.skipGitHub
|
|
10138
|
+
};
|
|
10139
|
+
}
|
|
10129
10140
|
const items = [
|
|
10130
10141
|
{ value: "configureMcp", label: "Install Dosu MCP" },
|
|
10131
10142
|
{ value: "installSkill", label: "Install Dosu skill" }
|
|
@@ -10153,7 +10164,15 @@ async function stepOneShotConfirm(opts) {
|
|
|
10153
10164
|
connectGitHub: chosen.has("connectGitHub")
|
|
10154
10165
|
};
|
|
10155
10166
|
}
|
|
10156
|
-
async function stepConfigureMcpTools(cfg) {
|
|
10167
|
+
async function stepConfigureMcpTools(cfg, requestedToolIDs) {
|
|
10168
|
+
if (requestedToolIDs && requestedToolIDs.length > 0) {
|
|
10169
|
+
const selection2 = selectRequestedTools(requestedToolIDs);
|
|
10170
|
+
if (!selection2)
|
|
10171
|
+
return null;
|
|
10172
|
+
const results2 = stepConfigureTools(cfg, selection2);
|
|
10173
|
+
stepShowSummary(results2);
|
|
10174
|
+
return results2;
|
|
10175
|
+
}
|
|
10157
10176
|
const detected = stepDetectTools();
|
|
10158
10177
|
if (detected.length === 0) {
|
|
10159
10178
|
M2.warn(`No supported AI agents detected on your system.
|
|
@@ -10185,7 +10204,7 @@ async function runInstallSkill() {
|
|
|
10185
10204
|
return false;
|
|
10186
10205
|
}
|
|
10187
10206
|
}
|
|
10188
|
-
async function stepAuthenticate(existingCfg, onboardingRunID) {
|
|
10207
|
+
async function stepAuthenticate(existingCfg, onboardingRunID, opts = {}) {
|
|
10189
10208
|
logger.info("setup", "Step: authenticate");
|
|
10190
10209
|
const cfg = existingCfg ?? loadConfig();
|
|
10191
10210
|
if (cfg.access_token) {
|
|
@@ -10215,26 +10234,36 @@ async function stepAuthenticate(existingCfg, onboardingRunID) {
|
|
|
10215
10234
|
s.stop("Session verification failed");
|
|
10216
10235
|
}
|
|
10217
10236
|
}
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
if (
|
|
10221
|
-
|
|
10222
|
-
|
|
10223
|
-
|
|
10237
|
+
if (!opts.yes && opts.openBrowser !== false) {
|
|
10238
|
+
const shouldLogin = await ye({ message: "Open browser to log in?" });
|
|
10239
|
+
if (pD(shouldLogin) || !shouldLogin) {
|
|
10240
|
+
if (onboardingRunID) {
|
|
10241
|
+
await trackCliOnboardingPreAuthEvent(onboardingRunID, "cli_onboarding_auth_cancelled", {
|
|
10242
|
+
reason: pD(shouldLogin) ? "prompt_cancelled" : "login_declined"
|
|
10243
|
+
});
|
|
10244
|
+
}
|
|
10245
|
+
return null;
|
|
10224
10246
|
}
|
|
10225
|
-
return null;
|
|
10226
10247
|
}
|
|
10227
10248
|
if (onboardingRunID) {
|
|
10228
10249
|
await trackCliOnboardingPreAuthEvent(onboardingRunID, "cli_onboarding_auth_started");
|
|
10229
10250
|
}
|
|
10230
|
-
return await openBrowserForSetup(cfg, onboardingRunID);
|
|
10251
|
+
return await openBrowserForSetup(cfg, onboardingRunID, opts);
|
|
10231
10252
|
}
|
|
10232
|
-
async function openBrowserForSetup(cfg, onboardingRunID) {
|
|
10253
|
+
async function openBrowserForSetup(cfg, onboardingRunID, opts = {}) {
|
|
10233
10254
|
try {
|
|
10234
10255
|
const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
|
|
10235
10256
|
const s = Y2();
|
|
10236
10257
|
s.start("Waiting for authentication...");
|
|
10237
|
-
const token = await startOAuthFlow2(undefined, "/cli/auth", onboardingRunID ? { onboarding_run_id: onboardingRunID } : {}
|
|
10258
|
+
const token = await startOAuthFlow2(undefined, "/cli/auth", onboardingRunID ? { onboarding_run_id: onboardingRunID } : {}, {
|
|
10259
|
+
openBrowser: opts.openBrowser !== false,
|
|
10260
|
+
onAuthURL: opts.openBrowser === false ? (url) => {
|
|
10261
|
+
M2.info(`Open this URL to authenticate:
|
|
10262
|
+
${url}
|
|
10263
|
+
|
|
10264
|
+
Waiting for login to complete...`);
|
|
10265
|
+
} : undefined
|
|
10266
|
+
});
|
|
10238
10267
|
s.stop("Authenticated");
|
|
10239
10268
|
logger.info("setup", "Browser auth completed");
|
|
10240
10269
|
cfg.access_token = token.access_token;
|
|
@@ -10343,10 +10372,10 @@ async function resolveDeployment(apiClient, cfg, opts) {
|
|
|
10343
10372
|
}
|
|
10344
10373
|
return true;
|
|
10345
10374
|
}
|
|
10346
|
-
const org = await stepSelectOrg(apiClient);
|
|
10375
|
+
const org = await stepSelectOrg(apiClient, opts.yes === true);
|
|
10347
10376
|
if (!org)
|
|
10348
10377
|
return false;
|
|
10349
|
-
const d3 = await stepSelectDeployment(apiClient, org);
|
|
10378
|
+
const d3 = await stepSelectDeployment(apiClient, org, opts.yes === true);
|
|
10350
10379
|
if (!d3)
|
|
10351
10380
|
return false;
|
|
10352
10381
|
cfg.mode = undefined;
|
|
@@ -10360,7 +10389,7 @@ async function fetchDeployments(apiClient) {
|
|
|
10360
10389
|
return [];
|
|
10361
10390
|
}
|
|
10362
10391
|
}
|
|
10363
|
-
async function stepSelectOrg(apiClient) {
|
|
10392
|
+
async function stepSelectOrg(apiClient, noPrompt = false) {
|
|
10364
10393
|
try {
|
|
10365
10394
|
const orgs = await apiClient.getOrgs();
|
|
10366
10395
|
if (orgs.length === 0) {
|
|
@@ -10373,6 +10402,10 @@ async function stepSelectOrg(apiClient) {
|
|
|
10373
10402
|
${dim(orgs[0].name)}`);
|
|
10374
10403
|
return orgs[0];
|
|
10375
10404
|
}
|
|
10405
|
+
if (noPrompt) {
|
|
10406
|
+
M2.error("Multiple organizations found. Run `dosu deployments list --json`, choose a deployment, then re-run setup with `--deployment <id>`.");
|
|
10407
|
+
return null;
|
|
10408
|
+
}
|
|
10376
10409
|
const selected = await ve({
|
|
10377
10410
|
message: "Select an organization",
|
|
10378
10411
|
options: orgs.map((o2) => ({ label: o2.name, value: o2.org_id }))
|
|
@@ -10410,7 +10443,7 @@ ${dim(d3.name)}`);
|
|
|
10410
10443
|
return null;
|
|
10411
10444
|
}
|
|
10412
10445
|
}
|
|
10413
|
-
async function stepSelectDeployment(apiClient, org) {
|
|
10446
|
+
async function stepSelectDeployment(apiClient, org, noPrompt = false) {
|
|
10414
10447
|
try {
|
|
10415
10448
|
const allDeployments = await apiClient.getDeployments();
|
|
10416
10449
|
const deployments = allDeployments.filter((d4) => d4.org_id === org.org_id);
|
|
@@ -10424,6 +10457,10 @@ async function stepSelectDeployment(apiClient, org) {
|
|
|
10424
10457
|
${dim(deployments[0].name)}`);
|
|
10425
10458
|
return deployments[0];
|
|
10426
10459
|
}
|
|
10460
|
+
if (noPrompt) {
|
|
10461
|
+
M2.error("Multiple MCPs found. Run `dosu deployments list --json`, choose one, then re-run setup with `--deployment <id>`.");
|
|
10462
|
+
return null;
|
|
10463
|
+
}
|
|
10427
10464
|
const selected = await ve({
|
|
10428
10465
|
message: "Select an MCP",
|
|
10429
10466
|
options: deployments.map((d4) => ({ label: d4.name, value: d4.deployment_id }))
|
|
@@ -10471,6 +10508,24 @@ function isStdioOnly(p2) {
|
|
|
10471
10508
|
function stepDetectTools() {
|
|
10472
10509
|
return allSetupProviders().filter((p2) => p2.isInstalled() && !isStdioOnly(p2));
|
|
10473
10510
|
}
|
|
10511
|
+
function selectRequestedTools(requestedToolIDs) {
|
|
10512
|
+
const normalized = [...new Set(requestedToolIDs.map((id) => id.toLowerCase()))];
|
|
10513
|
+
const providers = allSetupProviders();
|
|
10514
|
+
const selected = [];
|
|
10515
|
+
for (const id of normalized) {
|
|
10516
|
+
const provider = providers.find((p2) => p2.id() === id);
|
|
10517
|
+
if (!provider) {
|
|
10518
|
+
M2.error(`Unknown AI tool '${id}'. Run 'dosu mcp list' to see available tools.`);
|
|
10519
|
+
return null;
|
|
10520
|
+
}
|
|
10521
|
+
if (isStdioOnly(provider)) {
|
|
10522
|
+
M2.error(`${provider.name()} is not supported by setup. Use 'dosu mcp add ${id}'.`);
|
|
10523
|
+
return null;
|
|
10524
|
+
}
|
|
10525
|
+
selected.push(provider);
|
|
10526
|
+
}
|
|
10527
|
+
return { toInstall: selected, toRemove: [], skipped: [] };
|
|
10528
|
+
}
|
|
10474
10529
|
async function stepSelectTools(detected) {
|
|
10475
10530
|
const configuredMap = new Map;
|
|
10476
10531
|
for (const p2 of detected) {
|
|
@@ -12528,19 +12583,27 @@ function createProgram() {
|
|
|
12528
12583
|
const { runTUI: runTUI2 } = await Promise.resolve().then(() => (init_tui(), exports_tui));
|
|
12529
12584
|
await runTUI2();
|
|
12530
12585
|
});
|
|
12531
|
-
program2.command("login").description("Authenticate with Dosu via OAuth").action(async () => {
|
|
12586
|
+
program2.command("login").description("Authenticate with Dosu via OAuth").option("--no-open", "Print the login URL instead of opening a browser").action(async (opts) => {
|
|
12532
12587
|
const cfg = loadConfig();
|
|
12533
12588
|
if (isAuthenticated(cfg) && !isTokenExpired(cfg)) {
|
|
12534
12589
|
console.log("You are already logged in.");
|
|
12535
12590
|
console.log("Run 'dosu logout' first to re-authenticate.");
|
|
12536
12591
|
return;
|
|
12537
12592
|
}
|
|
12538
|
-
console.log("Opening browser for authentication...");
|
|
12593
|
+
console.log(opts.open === false ? "Starting authentication..." : "Opening browser for authentication...");
|
|
12539
12594
|
const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
|
|
12540
12595
|
const { OAuthCallbackError: OAuthCallbackError2 } = await Promise.resolve().then(() => (init_errors(), exports_errors));
|
|
12541
12596
|
let token;
|
|
12542
12597
|
try {
|
|
12543
|
-
token = await startOAuthFlow2(
|
|
12598
|
+
token = await startOAuthFlow2(undefined, "/cli/auth", {}, {
|
|
12599
|
+
openBrowser: opts.open !== false,
|
|
12600
|
+
onAuthURL: opts.open === false ? (url) => {
|
|
12601
|
+
console.log("Open this URL to authenticate:");
|
|
12602
|
+
console.log(url);
|
|
12603
|
+
console.log(`
|
|
12604
|
+
Waiting for login to complete...`);
|
|
12605
|
+
} : undefined
|
|
12606
|
+
});
|
|
12544
12607
|
} catch (err) {
|
|
12545
12608
|
if (err instanceof OAuthCallbackError2) {
|
|
12546
12609
|
console.error(err.userMessage);
|
|
@@ -12670,7 +12733,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
|
|
|
12670
12733
|
program2.addCommand(tagsCommand());
|
|
12671
12734
|
program2.addCommand(threadsCommand());
|
|
12672
12735
|
program2.addCommand(skillCommand());
|
|
12673
|
-
program2.command("setup").description("Set up Dosu MCP for your AI tools").option("--deployment <id>", "Skip to tool configuration for a specific MCP").option("--mode <mode>", "Force OSS or Cloud mode, skipping the interactive prompt (oss|cloud)").action(async (opts) => {
|
|
12736
|
+
program2.command("setup").description("Set up Dosu MCP for your AI tools").option("--deployment <id>", "Skip to tool configuration for a specific MCP").option("--mode <mode>", "Force OSS or Cloud mode, skipping the interactive prompt (oss|cloud)").option("--agent", "Run an agent-assisted setup with safe defaults", false).option("-y, --yes", "Accept setup defaults and skip confirmation prompts", false).option("--no-open", "Print browser login URLs instead of opening them").option("--tool <agent>", "Configure a specific AI tool; may be repeated", collectValues, []).option("--skip-mcp", "Do not configure AI tool MCP entries", false).option("--skip-skill", "Do not install the Dosu agent skill", false).option("--skip-github", "Do not run GitHub repository/doc onboarding", false).action(async (opts) => {
|
|
12674
12737
|
const { runSetup: runSetup2 } = await Promise.resolve().then(() => (init_flow2(), exports_flow2));
|
|
12675
12738
|
let mode;
|
|
12676
12739
|
if (opts.mode !== undefined) {
|
|
@@ -12680,7 +12743,16 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
|
|
|
12680
12743
|
}
|
|
12681
12744
|
mode = normalized;
|
|
12682
12745
|
}
|
|
12683
|
-
await runSetup2({
|
|
12746
|
+
await runSetup2({
|
|
12747
|
+
deploymentID: opts.deployment,
|
|
12748
|
+
mode,
|
|
12749
|
+
yes: opts.agent === true || opts.yes === true,
|
|
12750
|
+
openBrowser: opts.agent === true ? false : opts.open !== false,
|
|
12751
|
+
toolIDs: opts.tool ?? [],
|
|
12752
|
+
skipMcp: opts.skipMcp === true,
|
|
12753
|
+
skipSkill: opts.skipSkill === true,
|
|
12754
|
+
skipGitHub: opts.agent === true || opts.skipGithub === true
|
|
12755
|
+
});
|
|
12684
12756
|
});
|
|
12685
12757
|
program2.command("logs").description("View or manage debug logs").option("-t, --tail [n]", "Show last N lines (default: 50)").option("--clear", "Delete the log file").action((opts) => {
|
|
12686
12758
|
const logPath = logger.getLogPath();
|
|
@@ -12710,6 +12782,10 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
|
|
|
12710
12782
|
});
|
|
12711
12783
|
return program2;
|
|
12712
12784
|
}
|
|
12785
|
+
function collectValues(value, previous) {
|
|
12786
|
+
previous.push(value);
|
|
12787
|
+
return previous;
|
|
12788
|
+
}
|
|
12713
12789
|
async function execute() {
|
|
12714
12790
|
const program2 = createProgram();
|
|
12715
12791
|
await program2.parseAsync(process.argv);
|