@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.
Files changed (2) hide show
  1. package/bin/dosu.js +105 -29
  2. 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.13.3";
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
- const open2 = await Promise.resolve().then(() => (init_open(), exports_open));
9877
- await open2.default(authURL);
9878
- logger.info("auth.flow", "Browser open command executed");
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
- const shouldLogin = await ye({ message: "Open browser to log in?" });
10219
- if (pD(shouldLogin) || !shouldLogin) {
10220
- if (onboardingRunID) {
10221
- await trackCliOnboardingPreAuthEvent(onboardingRunID, "cli_onboarding_auth_cancelled", {
10222
- reason: pD(shouldLogin) ? "prompt_cancelled" : "login_declined"
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({ deploymentID: opts.deployment, mode });
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dosu/cli",
3
- "version": "0.13.3",
3
+ "version": "0.14.0",
4
4
  "type": "module",
5
5
  "description": "Dosu CLI - Manage MCP servers for AI tools",
6
6
  "license": "MIT",