@dosu/cli 0.2.0 → 0.3.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.
Files changed (2) hide show
  1. package/bin/dosu.js +86 -23
  2. package/package.json +1 -1
package/bin/dosu.js CHANGED
@@ -2115,6 +2115,7 @@ function emptyConfig() {
2115
2115
  expires_at: 0
2116
2116
  };
2117
2117
  }
2118
+ var MODE_OSS = "oss";
2118
2119
  var init_config = () => {};
2119
2120
 
2120
2121
  // src/config/constants.ts
@@ -2137,6 +2138,9 @@ import { dirname } from "node:path";
2137
2138
  function mcpURL(deploymentID) {
2138
2139
  return `${getBackendURL()}/v1/mcp/deployments/${deploymentID}`;
2139
2140
  }
2141
+ function mcpBaseURL() {
2142
+ return `${getBackendURL()}/v1/mcp`;
2143
+ }
2140
2144
  function mcpHeaders(apiKey) {
2141
2145
  return { "X-Dosu-API-Key": apiKey };
2142
2146
  }
@@ -2277,6 +2281,11 @@ function createJSONProvider(opts) {
2277
2281
  url: mcpURL(cfg.deployment_id),
2278
2282
  headers: mcpHeaders(cfg.api_key)
2279
2283
  });
2284
+ const defaultBuildOSSServer = (cfg) => ({
2285
+ type: "http",
2286
+ url: mcpBaseURL(),
2287
+ headers: mcpHeaders(cfg.api_key)
2288
+ });
2280
2289
  const buildServer = opts.buildServer ?? defaultBuildServer;
2281
2290
  return {
2282
2291
  name: () => opts.providerName,
@@ -2288,7 +2297,7 @@ function createJSONProvider(opts) {
2288
2297
  globalConfigPath: () => expandHome(opts.globalPath),
2289
2298
  isConfigured: () => isJSONKeyConfigured(expandHome(opts.globalPath), opts.topKey),
2290
2299
  install(cfg, global) {
2291
- if (!cfg.deployment_id)
2300
+ if (cfg.mode !== MODE_OSS && !cfg.deployment_id)
2292
2301
  throw new Error("deployment ID is required");
2293
2302
  let configPath;
2294
2303
  if (global) {
@@ -2298,7 +2307,8 @@ function createJSONProvider(opts) {
2298
2307
  } else {
2299
2308
  throw new Error(`${opts.providerName} does not support local installation`);
2300
2309
  }
2301
- installJSONServer(configPath, opts.topKey, buildServer(cfg));
2310
+ const serverBuilder = cfg.mode === MODE_OSS ? defaultBuildOSSServer : buildServer;
2311
+ installJSONServer(configPath, opts.topKey, serverBuilder(cfg));
2302
2312
  },
2303
2313
  remove(global) {
2304
2314
  let configPath;
@@ -2314,6 +2324,7 @@ function createJSONProvider(opts) {
2314
2324
  };
2315
2325
  }
2316
2326
  var init_base = __esm(() => {
2327
+ init_config();
2317
2328
  init_config_helpers();
2318
2329
  init_detect();
2319
2330
  });
@@ -3626,7 +3637,7 @@ class Client {
3626
3637
  options.body = JSON.stringify(body);
3627
3638
  }
3628
3639
  const controller = new AbortController;
3629
- const timeout = setTimeout(() => controller.abort(), 30000);
3640
+ const timeout = setTimeout(() => controller.abort(), 1e4);
3630
3641
  options.signal = controller.signal;
3631
3642
  try {
3632
3643
  return await fetch(url, options);
@@ -3864,6 +3875,7 @@ async function startCallbackServer() {
3864
3875
  const refreshToken = url.searchParams.get("refresh_token");
3865
3876
  const expiresIn = url.searchParams.get("expires_in");
3866
3877
  const email = url.searchParams.get("email");
3878
+ const mode = url.searchParams.get("mode");
3867
3879
  if (!accessToken) {
3868
3880
  res.writeHead(200, { "Content-Type": "text/html" });
3869
3881
  res.end(CALLBACK_HTML_EXTRACT);
@@ -3879,7 +3891,8 @@ async function startCallbackServer() {
3879
3891
  access_token: accessToken,
3880
3892
  refresh_token: refreshToken && refreshToken !== "null" ? refreshToken : "",
3881
3893
  expires_in: expiresInInt,
3882
- email: email ?? undefined
3894
+ email: email ?? undefined,
3895
+ ...mode === MODE_OSS && { mode: MODE_OSS }
3883
3896
  });
3884
3897
  res.writeHead(200, { "Content-Type": "text/html" });
3885
3898
  res.end(buildSuccessHtml(email ?? undefined));
@@ -3961,6 +3974,9 @@ if (hash) {
3961
3974
  </script>
3962
3975
  </body>
3963
3976
  </html>`;
3977
+ var init_server = __esm(() => {
3978
+ init_config();
3979
+ });
3964
3980
 
3965
3981
  // node_modules/is-docker/index.js
3966
3982
  import fs from "node:fs";
@@ -4507,16 +4523,16 @@ var exports_flow = {};
4507
4523
  __export(exports_flow, {
4508
4524
  startOAuthFlow: () => startOAuthFlow
4509
4525
  });
4510
- async function startOAuthFlow(signal) {
4526
+ async function startOAuthFlow(signal, path2 = "/cli/auth") {
4511
4527
  const { server, tokenPromise } = await startCallbackServer();
4512
4528
  let timeoutId;
4513
4529
  try {
4514
4530
  const callbackURL = `http://localhost:${server.port}/callback`;
4515
- const authURL = buildAuthURL(callbackURL);
4531
+ const authURL = buildAuthURL(callbackURL, path2);
4516
4532
  const open2 = await Promise.resolve().then(() => (init_open(), exports_open));
4517
4533
  await open2.default(authURL);
4518
4534
  const timeout = new Promise((_3, reject) => {
4519
- timeoutId = setTimeout(() => reject(new Error("authentication timeout - please try again")), 300000);
4535
+ timeoutId = setTimeout(() => reject(new Error("authentication timeout - please try again")), 900000);
4520
4536
  });
4521
4537
  const abort = signal ? new Promise((_3, reject) => {
4522
4538
  signal.addEventListener("abort", () => reject(new Error("authentication cancelled")));
@@ -4527,12 +4543,17 @@ async function startOAuthFlow(signal) {
4527
4543
  server.close();
4528
4544
  }
4529
4545
  }
4530
- function buildAuthURL(callbackURL) {
4546
+ function buildAuthURL(callbackURL, path2) {
4531
4547
  const webAppURL = getWebAppURL();
4532
4548
  const params = new URLSearchParams({ callback: callbackURL });
4533
- return `${webAppURL}/cli/auth?${params}`;
4549
+ if (path2 !== "/cli/auth") {
4550
+ params.set("redirect", `${path2}?callback=${encodeURIComponent(callbackURL)}`);
4551
+ }
4552
+ return `${webAppURL}${path2}?${params}`;
4534
4553
  }
4535
- var init_flow = () => {};
4554
+ var init_flow = __esm(() => {
4555
+ init_server();
4556
+ });
4536
4557
 
4537
4558
  // src/setup/flow.ts
4538
4559
  var exports_flow2 = {};
@@ -4545,16 +4566,22 @@ __export(exports_flow2, {
4545
4566
  });
4546
4567
  async function runSetup(opts = {}) {
4547
4568
  Ie("Dosu CLI Setup");
4548
- const cfg = await stepAuthenticate();
4569
+ const cfg = await stepAuthenticate(opts);
4549
4570
  if (!cfg)
4550
4571
  return;
4551
4572
  const apiClient = new Client(cfg);
4552
- let deployment;
4553
4573
  if (opts.deploymentID) {
4554
4574
  const d3 = await stepResolveDeployment(apiClient, opts.deploymentID);
4555
4575
  if (!d3)
4556
4576
  return;
4557
- deployment = d3;
4577
+ cfg.deployment_id = d3.deployment_id;
4578
+ cfg.deployment_name = d3.name;
4579
+ } else if (cfg.mode === MODE_OSS) {
4580
+ const deployments = await fetchDeployments(apiClient);
4581
+ if (deployments.length > 0) {
4582
+ cfg.deployment_id = deployments[0].deployment_id;
4583
+ cfg.deployment_name = deployments[0].name;
4584
+ }
4558
4585
  } else {
4559
4586
  const org = await stepSelectOrg(apiClient);
4560
4587
  if (!org)
@@ -4562,10 +4589,9 @@ async function runSetup(opts = {}) {
4562
4589
  const d3 = await stepSelectDeployment(apiClient, org);
4563
4590
  if (!d3)
4564
4591
  return;
4565
- deployment = d3;
4592
+ cfg.deployment_id = d3.deployment_id;
4593
+ cfg.deployment_name = d3.name;
4566
4594
  }
4567
- cfg.deployment_id = deployment.deployment_id;
4568
- cfg.deployment_name = deployment.name;
4569
4595
  saveConfig(cfg);
4570
4596
  const apiKey = await stepMintAPIKey(apiClient, cfg);
4571
4597
  if (!apiKey)
@@ -4582,10 +4608,14 @@ Run ${info("dosu mcp add <tool>")} to manually configure a tool.`);
4582
4608
  if (!selection)
4583
4609
  return;
4584
4610
  const results = stepConfigureTools(cfg, selection);
4585
- stepShowSummary(results);
4586
- Se("\uD83C\uDF89 Setup complete!");
4611
+ stepShowSummary(results, cfg.mode);
4612
+ if (cfg.mode === MODE_OSS) {
4613
+ Se("Setup complete! Using open-source libraries only.\nRun `dosu setup` again to connect your own repos.");
4614
+ } else {
4615
+ Se("\uD83C\uDF89 Setup complete!");
4616
+ }
4587
4617
  }
4588
- async function stepAuthenticate() {
4618
+ async function stepAuthenticate(opts) {
4589
4619
  const cfg = loadConfig();
4590
4620
  if (cfg.access_token) {
4591
4621
  const s = Y2();
@@ -4595,6 +4625,21 @@ async function stepAuthenticate() {
4595
4625
  const resp = await apiClient.doRequestRaw("GET", "/v1/mcp/deployments");
4596
4626
  if (resp.status === 200) {
4597
4627
  s.stop("Authenticated");
4628
+ if (!opts.deploymentID && cfg.mode === MODE_OSS) {
4629
+ const modeLabel = "open-source libraries only";
4630
+ const action = await ve({
4631
+ message: `Currently configured for ${modeLabel}. What would you like to do?`,
4632
+ options: [
4633
+ { label: "Reconfigure (opens browser)", value: "reconfigure" },
4634
+ { label: "Keep current setup and update tools", value: "keep" }
4635
+ ]
4636
+ });
4637
+ if (pD(action))
4638
+ return null;
4639
+ if (action === "keep")
4640
+ return cfg;
4641
+ return await openBrowserForSetup(cfg, opts);
4642
+ }
4598
4643
  return cfg;
4599
4644
  }
4600
4645
  try {
@@ -4614,15 +4659,21 @@ async function stepAuthenticate() {
4614
4659
  const shouldLogin = await ye({ message: "Open browser to log in?" });
4615
4660
  if (pD(shouldLogin) || !shouldLogin)
4616
4661
  return null;
4662
+ return await openBrowserForSetup(cfg, opts);
4663
+ }
4664
+ async function openBrowserForSetup(cfg, opts) {
4617
4665
  try {
4618
4666
  const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
4619
4667
  const s = Y2();
4620
4668
  s.start("Waiting for authentication...");
4621
- const token = await startOAuthFlow2();
4669
+ const authPath = opts.deploymentID ? "/cli/auth" : "/cli/setup";
4670
+ const token = await startOAuthFlow2(undefined, authPath);
4622
4671
  s.stop("Authenticated");
4623
4672
  cfg.access_token = token.access_token;
4624
4673
  cfg.refresh_token = token.refresh_token;
4625
4674
  cfg.expires_at = Math.floor(Date.now() / 1000) + token.expires_in;
4675
+ if (token.mode === MODE_OSS)
4676
+ cfg.mode = MODE_OSS;
4626
4677
  saveConfig(cfg);
4627
4678
  return cfg;
4628
4679
  } catch (err) {
@@ -4630,6 +4681,13 @@ async function stepAuthenticate() {
4630
4681
  return null;
4631
4682
  }
4632
4683
  }
4684
+ async function fetchDeployments(apiClient) {
4685
+ try {
4686
+ return await apiClient.getDeployments();
4687
+ } catch {
4688
+ return [];
4689
+ }
4690
+ }
4633
4691
  async function stepSelectOrg(apiClient) {
4634
4692
  try {
4635
4693
  const orgs = await apiClient.getOrgs();
@@ -4700,6 +4758,10 @@ ${dim(deployments[0].name)}`);
4700
4758
  }
4701
4759
  }
4702
4760
  async function stepMintAPIKey(apiClient, cfg) {
4761
+ if (!cfg.deployment_id) {
4762
+ M2.error("No deployment available for API key creation");
4763
+ return null;
4764
+ }
4703
4765
  if (cfg.api_key) {
4704
4766
  const valid = await apiClient.validateAPIKey(cfg.api_key, cfg.deployment_id);
4705
4767
  if (valid) {
@@ -4787,7 +4849,7 @@ function stepConfigureTools(cfg, selection) {
4787
4849
  }
4788
4850
  return results;
4789
4851
  }
4790
- function stepShowSummary(results) {
4852
+ function stepShowSummary(results, mode) {
4791
4853
  const installed = results.filter((r) => r.action === "install" && !r.error);
4792
4854
  const removed = results.filter((r) => r.action === "remove" && !r.error);
4793
4855
  const skipped = results.filter((r) => r.action === "skip");
@@ -4809,9 +4871,10 @@ ${lines}`);
4809
4871
  M2.success("All tools already configured. No changes needed.");
4810
4872
  }
4811
4873
  if (installed.length > 0 || skipped.length > 0) {
4874
+ const prompt = mode === MODE_OSS ? `What can I do with the Dosu MCP?` : `Use Dosu to search our team's documentation and answer: what are the main components of our system?`;
4812
4875
  M2.message(`Try it out! Paste this into your agent:
4813
4876
 
4814
- ` + info(`Use Dosu to search our team's documentation and answer: what are the main components of our system?`));
4877
+ ${info(prompt)}`);
4815
4878
  }
4816
4879
  }
4817
4880
  var init_flow2 = __esm(() => {
@@ -5025,7 +5088,7 @@ init_config();
5025
5088
  init_providers();
5026
5089
 
5027
5090
  // src/version/version.ts
5028
- var VERSION = "0.2.0";
5091
+ var VERSION = "0.3.1";
5029
5092
  var COMMIT = "none";
5030
5093
  var DATE = "unknown";
5031
5094
  function getVersionString() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dosu/cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "description": "Dosu CLI - Manage MCP servers for AI tools",
6
6
  "license": "MIT",