@dosu/cli 0.1.7 → 0.3.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 +506 -379
  2. package/package.json +12 -4
package/bin/dosu.js CHANGED
@@ -2115,70 +2115,37 @@ function emptyConfig() {
2115
2115
  expires_at: 0
2116
2116
  };
2117
2117
  }
2118
+ var MODE_OSS = "oss";
2118
2119
  var init_config = () => {};
2119
2120
 
2120
- // src/mcp/detect.ts
2121
- import { existsSync as existsSync2 } from "node:fs";
2122
- import { join as join2 } from "node:path";
2123
- import { homedir, platform } from "node:os";
2124
- function isInstalled(paths) {
2125
- return paths.some((p) => existsSync2(expandHome(p)));
2126
- }
2127
- function expandHome(path) {
2128
- if (!path.startsWith("~"))
2129
- return path;
2130
- return join2(homedir(), path.slice(1));
2131
- }
2132
- function appSupportDir() {
2133
- switch (platform()) {
2134
- case "darwin": {
2135
- return join2(homedir(), "Library", "Application Support");
2136
- }
2137
- case "win32": {
2138
- return process.env.APPDATA ?? "";
2139
- }
2140
- default: {
2141
- const xdg = process.env.XDG_CONFIG_HOME;
2142
- if (xdg)
2143
- return xdg;
2144
- return join2(homedir(), ".config");
2145
- }
2146
- }
2147
- }
2148
- var init_detect = () => {};
2149
-
2150
2121
  // src/config/constants.ts
2151
- function isDev() {
2152
- return process.env.DOSU_DEV === "true";
2153
- }
2154
2122
  function getWebAppURL() {
2155
- if (process.env.DOSU_WEB_APP_URL)
2156
- return process.env.DOSU_WEB_APP_URL;
2157
- return isDev() ? DevWebAppURL : ProdWebAppURL;
2123
+ return "https://app.dosu.dev";
2158
2124
  }
2159
2125
  function getBackendURL() {
2160
- if (process.env.DOSU_BACKEND_URL)
2161
- return process.env.DOSU_BACKEND_URL;
2162
- return isDev() ? DevBackendURL : ProdBackendURL;
2126
+ return "https://api.dosu.dev";
2163
2127
  }
2164
2128
  function getSupabaseURL() {
2165
- if (process.env.SUPABASE_URL)
2166
- return process.env.SUPABASE_URL;
2167
- return isDev() ? DevSupabaseURL : ProdSupabaseURL;
2129
+ return "https://wldmetsoicvieidlsqrb.supabase.co";
2130
+ }
2131
+ function getSupabaseAnonKey() {
2132
+ return "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6IndsbG1ldHNvaWN2aWVpZGxzcXJiIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzQ0NjA1NjUsImV4cCI6MjA1MDAzNjU2NX0.15LIxqSMVRnxsvLrk0GPjL1aSYPfOeaeFMdJXqgc5Xs";
2168
2133
  }
2169
- var DevWebAppURL = "http://localhost:3001", ProdWebAppURL = "https://app.dosu.dev", DevBackendURL = "http://localhost:7001", ProdBackendURL = "https://api.dosu.dev", DevSupabaseURL = "http://localhost:54321", ProdSupabaseURL = "https://wldmetsoicvieidlsqrb.supabase.co";
2170
2134
 
2171
2135
  // src/mcp/config-helpers.ts
2172
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
2136
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
2173
2137
  import { dirname } from "node:path";
2174
2138
  function mcpURL(deploymentID) {
2175
2139
  return `${getBackendURL()}/v1/mcp/deployments/${deploymentID}`;
2176
2140
  }
2141
+ function mcpBaseURL() {
2142
+ return `${getBackendURL()}/v1/mcp`;
2143
+ }
2177
2144
  function mcpHeaders(apiKey) {
2178
2145
  return { "X-Dosu-API-Key": apiKey };
2179
2146
  }
2180
2147
  function loadJSONConfig(path) {
2181
- if (!existsSync3(path))
2148
+ if (!existsSync2(path))
2182
2149
  return {};
2183
2150
  let data = readFileSync2(path, "utf-8").trim();
2184
2151
  if (!data)
@@ -2240,7 +2207,7 @@ function stripJSONComments(data) {
2240
2207
  }
2241
2208
  function saveJSONConfig(path, cfg) {
2242
2209
  const dir = dirname(path);
2243
- if (!existsSync3(dir)) {
2210
+ if (!existsSync2(dir)) {
2244
2211
  mkdirSync2(dir, { recursive: true });
2245
2212
  }
2246
2213
  writeFileSync2(path, JSON.stringify(cfg, null, 2));
@@ -2258,7 +2225,7 @@ function installJSONServer(configPath, topKey, server) {
2258
2225
  if (typeof section !== "object" || section === null) {
2259
2226
  section = {};
2260
2227
  }
2261
- section["dosu"] = server;
2228
+ section.dosu = server;
2262
2229
  jsonCfg[topKey] = section;
2263
2230
  saveJSONConfig(configPath, jsonCfg);
2264
2231
  }
@@ -2271,12 +2238,42 @@ function removeJSONServer(configPath, topKey) {
2271
2238
  }
2272
2239
  const section = jsonCfg[topKey];
2273
2240
  if (typeof section === "object" && section !== null) {
2274
- delete section["dosu"];
2241
+ delete section.dosu;
2275
2242
  }
2276
2243
  saveJSONConfig(configPath, jsonCfg);
2277
2244
  }
2278
2245
  var init_config_helpers = () => {};
2279
2246
 
2247
+ // src/mcp/detect.ts
2248
+ import { existsSync as existsSync3 } from "node:fs";
2249
+ import { homedir, platform } from "node:os";
2250
+ import { join as join2 } from "node:path";
2251
+ function isInstalled(paths) {
2252
+ return paths.some((p) => existsSync3(expandHome(p)));
2253
+ }
2254
+ function expandHome(path) {
2255
+ if (!path.startsWith("~"))
2256
+ return path;
2257
+ return join2(homedir(), path.slice(1));
2258
+ }
2259
+ function appSupportDir() {
2260
+ switch (platform()) {
2261
+ case "darwin": {
2262
+ return join2(homedir(), "Library", "Application Support");
2263
+ }
2264
+ case "win32": {
2265
+ return process.env.APPDATA ?? "";
2266
+ }
2267
+ default: {
2268
+ const xdg = process.env.XDG_CONFIG_HOME;
2269
+ if (xdg)
2270
+ return xdg;
2271
+ return join2(homedir(), ".config");
2272
+ }
2273
+ }
2274
+ }
2275
+ var init_detect = () => {};
2276
+
2280
2277
  // src/mcp/providers/base.ts
2281
2278
  function createJSONProvider(opts) {
2282
2279
  const defaultBuildServer = (cfg) => ({
@@ -2284,6 +2281,11 @@ function createJSONProvider(opts) {
2284
2281
  url: mcpURL(cfg.deployment_id),
2285
2282
  headers: mcpHeaders(cfg.api_key)
2286
2283
  });
2284
+ const defaultBuildOSSServer = (cfg) => ({
2285
+ type: "http",
2286
+ url: mcpBaseURL(),
2287
+ headers: mcpHeaders(cfg.api_key)
2288
+ });
2287
2289
  const buildServer = opts.buildServer ?? defaultBuildServer;
2288
2290
  return {
2289
2291
  name: () => opts.providerName,
@@ -2295,7 +2297,7 @@ function createJSONProvider(opts) {
2295
2297
  globalConfigPath: () => expandHome(opts.globalPath),
2296
2298
  isConfigured: () => isJSONKeyConfigured(expandHome(opts.globalPath), opts.topKey),
2297
2299
  install(cfg, global) {
2298
- if (!cfg.deployment_id)
2300
+ if (cfg.mode !== MODE_OSS && !cfg.deployment_id)
2299
2301
  throw new Error("deployment ID is required");
2300
2302
  let configPath;
2301
2303
  if (global) {
@@ -2305,7 +2307,8 @@ function createJSONProvider(opts) {
2305
2307
  } else {
2306
2308
  throw new Error(`${opts.providerName} does not support local installation`);
2307
2309
  }
2308
- installJSONServer(configPath, opts.topKey, buildServer(cfg));
2310
+ const serverBuilder = cfg.mode === MODE_OSS ? defaultBuildOSSServer : buildServer;
2311
+ installJSONServer(configPath, opts.topKey, serverBuilder(cfg));
2309
2312
  },
2310
2313
  remove(global) {
2311
2314
  let configPath;
@@ -2321,8 +2324,28 @@ function createJSONProvider(opts) {
2321
2324
  };
2322
2325
  }
2323
2326
  var init_base = __esm(() => {
2327
+ init_config();
2328
+ init_config_helpers();
2324
2329
  init_detect();
2330
+ });
2331
+
2332
+ // src/mcp/providers/antigravity.ts
2333
+ var AntigravityProvider = () => createJSONProvider({
2334
+ providerName: "Antigravity",
2335
+ providerID: "antigravity",
2336
+ local: false,
2337
+ priorityValue: 15,
2338
+ paths: ["~/.gemini"],
2339
+ globalPath: "~/.gemini/antigravity/mcp_config.json",
2340
+ topKey: "mcpServers",
2341
+ buildServer: (cfg) => ({
2342
+ serverUrl: mcpURL(cfg.deployment_id),
2343
+ headers: mcpHeaders(cfg.api_key)
2344
+ })
2345
+ });
2346
+ var init_antigravity = __esm(() => {
2325
2347
  init_config_helpers();
2348
+ init_base();
2326
2349
  });
2327
2350
 
2328
2351
  // src/mcp/providers/claude.ts
@@ -2363,71 +2386,65 @@ var init_claude_desktop = __esm(() => {
2363
2386
  init_detect();
2364
2387
  });
2365
2388
 
2366
- // src/mcp/providers/cursor.ts
2389
+ // src/mcp/providers/cline.ts
2367
2390
  import { join as join5 } from "node:path";
2368
- var CursorProvider = () => createJSONProvider({
2369
- providerName: "Cursor",
2370
- providerID: "cursor",
2371
- local: true,
2372
- priorityValue: 5,
2373
- paths: ["~/.cursor"],
2374
- globalPath: "~/.cursor/mcp.json",
2391
+ var extensionDir = () => join5(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
2392
+ providerName: "Cline",
2393
+ providerID: "cline",
2394
+ local: false,
2395
+ priorityValue: 11,
2396
+ paths: [extensionDir()],
2397
+ globalPath: join5(extensionDir(), "settings", "cline_mcp_settings.json"),
2375
2398
  topKey: "mcpServers",
2376
2399
  buildServer: (cfg) => ({
2377
2400
  url: mcpURL(cfg.deployment_id),
2401
+ type: "streamableHttp",
2402
+ disabled: false,
2378
2403
  headers: mcpHeaders(cfg.api_key)
2379
- }),
2380
- localConfigPath: (cwd) => join5(cwd, ".cursor", "mcp.json")
2404
+ })
2381
2405
  });
2382
- var init_cursor = __esm(() => {
2383
- init_base();
2406
+ var init_cline = __esm(() => {
2384
2407
  init_config_helpers();
2385
- });
2386
-
2387
- // src/mcp/providers/vscode.ts
2388
- import { join as join6 } from "node:path";
2389
- var VSCodeProvider = () => createJSONProvider({
2390
- providerName: "VS Code",
2391
- providerID: "vscode",
2392
- local: true,
2393
- priorityValue: 6,
2394
- paths: [join6(appSupportDir(), "Code")],
2395
- globalPath: join6(appSupportDir(), "Code", "User", "mcp.json"),
2396
- topKey: "servers",
2397
- localConfigPath: (cwd) => join6(cwd, ".vscode", "mcp.json")
2398
- });
2399
- var init_vscode = __esm(() => {
2400
- init_base();
2401
2408
  init_detect();
2409
+ init_base();
2402
2410
  });
2403
2411
 
2404
- // src/mcp/providers/gemini.ts
2405
- import { join as join7 } from "node:path";
2406
- var GeminiProvider = () => createJSONProvider({
2407
- providerName: "Gemini CLI",
2408
- providerID: "gemini",
2409
- local: true,
2410
- priorityValue: 7,
2411
- paths: ["~/.gemini"],
2412
- globalPath: "~/.gemini/settings.json",
2412
+ // src/mcp/providers/cline-cli.ts
2413
+ import { join as join6 } from "node:path";
2414
+ function clineDir() {
2415
+ return process.env.CLINE_DIR ?? expandHome("~/.cline");
2416
+ }
2417
+ var ClineCliProvider = () => createJSONProvider({
2418
+ providerName: "Cline CLI",
2419
+ providerID: "cline-cli",
2420
+ local: false,
2421
+ priorityValue: 12,
2422
+ paths: [clineDir()],
2423
+ globalPath: join6(clineDir(), "data", "settings", "cline_mcp_settings.json"),
2413
2424
  topKey: "mcpServers",
2414
- localConfigPath: (cwd) => join7(cwd, ".gemini", "settings.json")
2425
+ buildServer: (cfg) => ({
2426
+ url: mcpURL(cfg.deployment_id),
2427
+ type: "streamableHttp",
2428
+ disabled: false,
2429
+ headers: mcpHeaders(cfg.api_key)
2430
+ })
2415
2431
  });
2416
- var init_gemini = __esm(() => {
2432
+ var init_cline_cli = __esm(() => {
2433
+ init_config_helpers();
2434
+ init_detect();
2417
2435
  init_base();
2418
2436
  });
2419
2437
 
2420
2438
  // src/mcp/providers/codex.ts
2421
- import { join as join8 } from "node:path";
2422
2439
  import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
2423
- import { dirname as dirname2 } from "node:path";
2440
+ import { dirname as dirname2, join as join7 } from "node:path";
2424
2441
  function codexHome() {
2425
2442
  return process.env.CODEX_HOME ?? expandHome("~/.codex");
2426
2443
  }
2427
2444
  function getConfigPath2(global) {
2428
2445
  if (global)
2429
- return join8(codexHome(), "config.toml");
2430
- return join8(process.cwd(), ".codex", "config.toml");
2446
+ return join7(codexHome(), "config.toml");
2447
+ return join7(process.cwd(), ".codex", "config.toml");
2431
2448
  }
2432
2449
  function readTOML(path) {
2433
2450
  if (!existsSync4(path))
@@ -2486,9 +2503,9 @@ var CodexProvider = () => ({
2486
2503
  priority: () => 8,
2487
2504
  detectPaths: () => ["~/.codex"],
2488
2505
  isInstalled: () => isInstalled(["~/.codex"]),
2489
- globalConfigPath: () => join8(codexHome(), "config.toml"),
2506
+ globalConfigPath: () => join7(codexHome(), "config.toml"),
2490
2507
  isConfigured: () => {
2491
- const content = readTOML(join8(codexHome(), "config.toml"));
2508
+ const content = readTOML(join7(codexHome(), "config.toml"));
2492
2509
  return content.includes("[mcp_servers.dosu]");
2493
2510
  },
2494
2511
  install(cfg, global) {
@@ -2504,111 +2521,15 @@ var CodexProvider = () => ({
2504
2521
  }
2505
2522
  });
2506
2523
  var init_codex = __esm(() => {
2507
- init_detect();
2508
2524
  init_config_helpers();
2509
- });
2510
-
2511
- // src/mcp/providers/windsurf.ts
2512
- import { join as join9 } from "node:path";
2513
- import { homedir as homedir2 } from "node:os";
2514
- var WindsurfProvider = () => createJSONProvider({
2515
- providerName: "Windsurf",
2516
- providerID: "windsurf",
2517
- local: false,
2518
- priorityValue: 9,
2519
- paths: [join9(homedir2(), ".codeium", "windsurf")],
2520
- globalPath: join9(homedir2(), ".codeium", "windsurf", "mcp_config.json"),
2521
- topKey: "mcpServers"
2522
- });
2523
- var init_windsurf = __esm(() => {
2524
- init_base();
2525
- });
2526
-
2527
- // src/mcp/providers/zed.ts
2528
- import { join as join10 } from "node:path";
2529
- import { platform as platform2 } from "node:os";
2530
- function zedConfigDir() {
2531
- const os = platform2();
2532
- if (os === "darwin" || os === "win32")
2533
- return join10(appSupportDir(), "Zed");
2534
- return join10(appSupportDir(), "zed");
2535
- }
2536
- var ZedProvider = () => createJSONProvider({
2537
- providerName: "Zed",
2538
- providerID: "zed",
2539
- local: true,
2540
- priorityValue: 10,
2541
- paths: [zedConfigDir()],
2542
- globalPath: join10(zedConfigDir(), "settings.json"),
2543
- topKey: "context_servers",
2544
- buildServer: (cfg) => ({
2545
- source: "custom",
2546
- type: "http",
2547
- url: mcpURL(cfg.deployment_id),
2548
- headers: mcpHeaders(cfg.api_key)
2549
- }),
2550
- localConfigPath: (cwd) => join10(cwd, ".zed", "settings.json")
2551
- });
2552
- var init_zed = __esm(() => {
2553
- init_base();
2554
2525
  init_detect();
2555
- init_config_helpers();
2556
- });
2557
-
2558
- // src/mcp/providers/cline.ts
2559
- import { join as join11 } from "node:path";
2560
- var extensionDir = () => join11(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
2561
- providerName: "Cline",
2562
- providerID: "cline",
2563
- local: false,
2564
- priorityValue: 11,
2565
- paths: [extensionDir()],
2566
- globalPath: join11(extensionDir(), "settings", "cline_mcp_settings.json"),
2567
- topKey: "mcpServers",
2568
- buildServer: (cfg) => ({
2569
- url: mcpURL(cfg.deployment_id),
2570
- type: "streamableHttp",
2571
- disabled: false,
2572
- headers: mcpHeaders(cfg.api_key)
2573
- })
2574
- });
2575
- var init_cline = __esm(() => {
2576
- init_base();
2577
- init_detect();
2578
- init_config_helpers();
2579
- });
2580
-
2581
- // src/mcp/providers/cline-cli.ts
2582
- import { join as join12 } from "node:path";
2583
- function clineDir() {
2584
- return process.env.CLINE_DIR ?? expandHome("~/.cline");
2585
- }
2586
- var ClineCliProvider = () => createJSONProvider({
2587
- providerName: "Cline CLI",
2588
- providerID: "cline-cli",
2589
- local: false,
2590
- priorityValue: 12,
2591
- paths: [clineDir()],
2592
- globalPath: join12(clineDir(), "data", "settings", "cline_mcp_settings.json"),
2593
- topKey: "mcpServers",
2594
- buildServer: (cfg) => ({
2595
- url: mcpURL(cfg.deployment_id),
2596
- type: "streamableHttp",
2597
- disabled: false,
2598
- headers: mcpHeaders(cfg.api_key)
2599
- })
2600
- });
2601
- var init_cline_cli = __esm(() => {
2602
- init_base();
2603
- init_detect();
2604
- init_config_helpers();
2605
2526
  });
2606
2527
 
2607
2528
  // src/mcp/providers/copilot.ts
2608
- import { join as join13 } from "node:path";
2529
+ import { join as join8 } from "node:path";
2609
2530
  function globalPath() {
2610
2531
  if (process.env.XDG_CONFIG_HOME) {
2611
- return join13(process.env.XDG_CONFIG_HOME, "mcp-config.json");
2532
+ return join8(process.env.XDG_CONFIG_HOME, "mcp-config.json");
2612
2533
  }
2613
2534
  return expandHome("~/.copilot/mcp-config.json");
2614
2535
  }
@@ -2634,7 +2555,7 @@ var CopilotProvider = () => ({
2634
2555
  };
2635
2556
  installJSONServer(globalPath(), "mcpServers", server);
2636
2557
  } else {
2637
- const configPath = join13(process.cwd(), ".vscode", "mcp.json");
2558
+ const configPath = join8(process.cwd(), ".vscode", "mcp.json");
2638
2559
  const server = {
2639
2560
  type: "http",
2640
2561
  url,
@@ -2647,61 +2568,79 @@ var CopilotProvider = () => ({
2647
2568
  if (global) {
2648
2569
  removeJSONServer(globalPath(), "mcpServers");
2649
2570
  } else {
2650
- const configPath = join13(process.cwd(), ".vscode", "mcp.json");
2571
+ const configPath = join8(process.cwd(), ".vscode", "mcp.json");
2651
2572
  removeJSONServer(configPath, "servers");
2652
2573
  }
2653
2574
  }
2654
2575
  });
2655
2576
  var init_copilot = __esm(() => {
2656
- init_detect();
2657
2577
  init_config_helpers();
2578
+ init_detect();
2658
2579
  });
2659
2580
 
2660
- // src/mcp/providers/opencode.ts
2661
- import { join as join14 } from "node:path";
2662
- var OpenCodeProvider = () => createJSONProvider({
2663
- providerName: "OpenCode",
2664
- providerID: "opencode",
2581
+ // src/mcp/providers/cursor.ts
2582
+ import { join as join9 } from "node:path";
2583
+ var CursorProvider = () => createJSONProvider({
2584
+ providerName: "Cursor",
2585
+ providerID: "cursor",
2665
2586
  local: true,
2666
- priorityValue: 14,
2667
- paths: ["~/.config/opencode"],
2668
- globalPath: "~/.config/opencode/opencode.json",
2669
- topKey: "mcp",
2587
+ priorityValue: 5,
2588
+ paths: ["~/.cursor"],
2589
+ globalPath: "~/.cursor/mcp.json",
2590
+ topKey: "mcpServers",
2670
2591
  buildServer: (cfg) => ({
2671
- type: "remote",
2672
2592
  url: mcpURL(cfg.deployment_id),
2673
- enabled: true,
2674
2593
  headers: mcpHeaders(cfg.api_key)
2675
2594
  }),
2676
- localConfigPath: (cwd) => join14(cwd, "opencode.json")
2595
+ localConfigPath: (cwd) => join9(cwd, ".cursor", "mcp.json")
2677
2596
  });
2678
- var init_opencode = __esm(() => {
2679
- init_base();
2597
+ var init_cursor = __esm(() => {
2680
2598
  init_config_helpers();
2599
+ init_base();
2681
2600
  });
2682
2601
 
2683
- // src/mcp/providers/antigravity.ts
2684
- var AntigravityProvider = () => createJSONProvider({
2685
- providerName: "Antigravity",
2686
- providerID: "antigravity",
2687
- local: false,
2688
- priorityValue: 15,
2602
+ // src/mcp/providers/gemini.ts
2603
+ import { join as join10 } from "node:path";
2604
+ var GeminiProvider = () => createJSONProvider({
2605
+ providerName: "Gemini CLI",
2606
+ providerID: "gemini",
2607
+ local: true,
2608
+ priorityValue: 7,
2689
2609
  paths: ["~/.gemini"],
2690
- globalPath: "~/.gemini/antigravity/mcp_config.json",
2610
+ globalPath: "~/.gemini/settings.json",
2691
2611
  topKey: "mcpServers",
2692
- buildServer: (cfg) => ({
2693
- serverUrl: mcpURL(cfg.deployment_id),
2694
- headers: mcpHeaders(cfg.api_key)
2695
- })
2612
+ localConfigPath: (cwd) => join10(cwd, ".gemini", "settings.json")
2696
2613
  });
2697
- var init_antigravity = __esm(() => {
2614
+ var init_gemini = __esm(() => {
2698
2615
  init_base();
2616
+ });
2617
+
2618
+ // src/mcp/providers/manual.ts
2619
+ var ManualProvider = () => ({
2620
+ name: () => "Manual Configuration",
2621
+ id: () => "manual",
2622
+ supportsLocal: () => false,
2623
+ install(cfg) {
2624
+ const url = mcpURL(cfg.deployment_id);
2625
+ console.log("Use these details to configure the Dosu MCP server in your client:");
2626
+ console.log();
2627
+ console.log(` Transport: HTTP`);
2628
+ console.log(` Endpoint: ${url}`);
2629
+ console.log(` Header: X-Dosu-API-Key: ${cfg.api_key}`);
2630
+ console.log();
2631
+ },
2632
+ remove() {
2633
+ console.log(`
2634
+ To remove the Dosu MCP server, manually delete the configuration from your client.`);
2635
+ }
2636
+ });
2637
+ var init_manual = __esm(() => {
2699
2638
  init_config_helpers();
2700
2639
  });
2701
2640
 
2702
2641
  // src/mcp/providers/mcporter.ts
2703
- import { join as join15 } from "node:path";
2704
2642
  import { existsSync as existsSync5 } from "node:fs";
2643
+ import { join as join11 } from "node:path";
2705
2644
  function resolveGlobalConfigPath() {
2706
2645
  const jsonPath = expandHome("~/.mcporter/mcporter.json");
2707
2646
  if (existsSync5(jsonPath))
@@ -2723,7 +2662,7 @@ var MCPorterProvider = () => ({
2723
2662
  install(cfg, global) {
2724
2663
  if (!cfg.deployment_id)
2725
2664
  throw new Error("deployment ID is required");
2726
- const configPath = global ? resolveGlobalConfigPath() : join15(process.cwd(), "config", "mcporter.json");
2665
+ const configPath = global ? resolveGlobalConfigPath() : join11(process.cwd(), "config", "mcporter.json");
2727
2666
  const server = {
2728
2667
  type: "http",
2729
2668
  url: mcpURL(cfg.deployment_id),
@@ -2732,36 +2671,100 @@ var MCPorterProvider = () => ({
2732
2671
  installJSONServer(configPath, "mcpServers", server);
2733
2672
  },
2734
2673
  remove(global) {
2735
- const configPath = global ? resolveGlobalConfigPath() : join15(process.cwd(), "config", "mcporter.json");
2674
+ const configPath = global ? resolveGlobalConfigPath() : join11(process.cwd(), "config", "mcporter.json");
2736
2675
  removeJSONServer(configPath, "mcpServers");
2737
2676
  }
2738
2677
  });
2739
2678
  var init_mcporter = __esm(() => {
2679
+ init_config_helpers();
2740
2680
  init_detect();
2681
+ });
2682
+
2683
+ // src/mcp/providers/opencode.ts
2684
+ import { join as join12 } from "node:path";
2685
+ var OpenCodeProvider = () => createJSONProvider({
2686
+ providerName: "OpenCode",
2687
+ providerID: "opencode",
2688
+ local: true,
2689
+ priorityValue: 14,
2690
+ paths: ["~/.config/opencode"],
2691
+ globalPath: "~/.config/opencode/opencode.json",
2692
+ topKey: "mcp",
2693
+ buildServer: (cfg) => ({
2694
+ type: "remote",
2695
+ url: mcpURL(cfg.deployment_id),
2696
+ enabled: true,
2697
+ headers: mcpHeaders(cfg.api_key)
2698
+ }),
2699
+ localConfigPath: (cwd) => join12(cwd, "opencode.json")
2700
+ });
2701
+ var init_opencode = __esm(() => {
2741
2702
  init_config_helpers();
2703
+ init_base();
2742
2704
  });
2743
2705
 
2744
- // src/mcp/providers/manual.ts
2745
- var ManualProvider = () => ({
2746
- name: () => "Manual Configuration",
2747
- id: () => "manual",
2748
- supportsLocal: () => false,
2749
- install(cfg) {
2750
- const url = mcpURL(cfg.deployment_id);
2751
- console.log("Use these details to configure the Dosu MCP server in your client:");
2752
- console.log();
2753
- console.log(` Transport: HTTP`);
2754
- console.log(` Endpoint: ${url}`);
2755
- console.log(` Header: X-Dosu-API-Key: ${cfg.api_key}`);
2756
- console.log();
2757
- },
2758
- remove() {
2759
- console.log(`
2760
- To remove the Dosu MCP server, manually delete the configuration from your client.`);
2761
- }
2706
+ // src/mcp/providers/vscode.ts
2707
+ import { join as join13 } from "node:path";
2708
+ var VSCodeProvider = () => createJSONProvider({
2709
+ providerName: "VS Code",
2710
+ providerID: "vscode",
2711
+ local: true,
2712
+ priorityValue: 6,
2713
+ paths: [join13(appSupportDir(), "Code")],
2714
+ globalPath: join13(appSupportDir(), "Code", "User", "mcp.json"),
2715
+ topKey: "servers",
2716
+ localConfigPath: (cwd) => join13(cwd, ".vscode", "mcp.json")
2762
2717
  });
2763
- var init_manual = __esm(() => {
2718
+ var init_vscode = __esm(() => {
2719
+ init_detect();
2720
+ init_base();
2721
+ });
2722
+
2723
+ // src/mcp/providers/windsurf.ts
2724
+ import { homedir as homedir2 } from "node:os";
2725
+ import { join as join14 } from "node:path";
2726
+ var WindsurfProvider = () => createJSONProvider({
2727
+ providerName: "Windsurf",
2728
+ providerID: "windsurf",
2729
+ local: false,
2730
+ priorityValue: 9,
2731
+ paths: [join14(homedir2(), ".codeium", "windsurf")],
2732
+ globalPath: join14(homedir2(), ".codeium", "windsurf", "mcp_config.json"),
2733
+ topKey: "mcpServers"
2734
+ });
2735
+ var init_windsurf = __esm(() => {
2736
+ init_base();
2737
+ });
2738
+
2739
+ // src/mcp/providers/zed.ts
2740
+ import { platform as platform2 } from "node:os";
2741
+ import { join as join15 } from "node:path";
2742
+ function zedConfigDir() {
2743
+ const os = platform2();
2744
+ if (os === "darwin" || os === "win32")
2745
+ return join15(appSupportDir(), "Zed");
2746
+ return join15(appSupportDir(), "zed");
2747
+ }
2748
+ var ZedProvider = () => createJSONProvider({
2749
+ providerName: "Zed",
2750
+ providerID: "zed",
2751
+ local: true,
2752
+ priorityValue: 10,
2753
+ paths: [zedConfigDir()],
2754
+ globalPath: join15(zedConfigDir(), "settings.json"),
2755
+ topKey: "context_servers",
2756
+ buildServer: (cfg) => ({
2757
+ source: "custom",
2758
+ type: "http",
2759
+ url: mcpURL(cfg.deployment_id),
2760
+ headers: mcpHeaders(cfg.api_key)
2761
+ }),
2762
+ localConfigPath: (cwd) => join15(cwd, ".zed", "settings.json")
2763
+ });
2764
+ var init_zed = __esm(() => {
2764
2765
  init_config_helpers();
2766
+ init_detect();
2767
+ init_base();
2765
2768
  });
2766
2769
 
2767
2770
  // src/mcp/providers.ts
@@ -2805,21 +2808,21 @@ function getProvider(toolID) {
2805
2808
  return provider;
2806
2809
  }
2807
2810
  var init_providers = __esm(() => {
2811
+ init_antigravity();
2808
2812
  init_claude();
2809
2813
  init_claude_desktop();
2810
- init_cursor();
2811
- init_vscode();
2812
- init_gemini();
2813
- init_codex();
2814
- init_windsurf();
2815
- init_zed();
2816
2814
  init_cline();
2817
2815
  init_cline_cli();
2816
+ init_codex();
2818
2817
  init_copilot();
2819
- init_opencode();
2820
- init_antigravity();
2821
- init_mcporter();
2818
+ init_cursor();
2819
+ init_gemini();
2822
2820
  init_manual();
2821
+ init_mcporter();
2822
+ init_opencode();
2823
+ init_vscode();
2824
+ init_windsurf();
2825
+ init_zed();
2823
2826
  });
2824
2827
 
2825
2828
  // node_modules/sisteransi/src/index.js
@@ -3634,7 +3637,7 @@ class Client {
3634
3637
  options.body = JSON.stringify(body);
3635
3638
  }
3636
3639
  const controller = new AbortController;
3637
- const timeout = setTimeout(() => controller.abort(), 30000);
3640
+ const timeout = setTimeout(() => controller.abort(), 1e4);
3638
3641
  options.signal = controller.signal;
3639
3642
  try {
3640
3643
  return await fetch(url, options);
@@ -3662,7 +3665,10 @@ class Client {
3662
3665
  const endpoint = `${supabaseURL}/auth/v1/token?grant_type=refresh_token`;
3663
3666
  const resp = await fetch(endpoint, {
3664
3667
  method: "POST",
3665
- headers: { "Content-Type": "application/json" },
3668
+ headers: {
3669
+ "Content-Type": "application/json",
3670
+ apikey: getSupabaseAnonKey()
3671
+ },
3666
3672
  body: JSON.stringify({ refresh_token: this.config.refresh_token })
3667
3673
  });
3668
3674
  if (resp.status !== 200) {
@@ -3754,6 +3760,104 @@ var init_styles = __esm(() => {
3754
3760
  });
3755
3761
 
3756
3762
  // src/auth/server.ts
3763
+ function buildSuccessHtml(email) {
3764
+ const emailLine = email ? `<p class="email">Signed in as <strong>${email.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")}</strong></p>` : "";
3765
+ return `<!DOCTYPE html>
3766
+ <html lang="en">
3767
+ <head>
3768
+ <meta charset="UTF-8">
3769
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
3770
+ <title>Dosu CLI - Authentication Successful</title>
3771
+ <style>
3772
+ * { margin: 0; padding: 0; box-sizing: border-box; }
3773
+ body {
3774
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
3775
+ background: #fafafa;
3776
+ color: #171717;
3777
+ min-height: 100vh;
3778
+ display: flex;
3779
+ align-items: center;
3780
+ justify-content: center;
3781
+ padding: 20px;
3782
+ }
3783
+ .container {
3784
+ max-width: 420px;
3785
+ width: 100%;
3786
+ text-align: center;
3787
+ }
3788
+ .logo {
3789
+ width: 52px;
3790
+ height: 52px;
3791
+ margin: 0 auto 28px;
3792
+ }
3793
+ h1 {
3794
+ font-size: 24px;
3795
+ font-weight: 600;
3796
+ color: #171717;
3797
+ letter-spacing: -0.02em;
3798
+ margin-bottom: 8px;
3799
+ }
3800
+ .subtitle {
3801
+ font-size: 16px;
3802
+ color: #666;
3803
+ margin-bottom: 8px;
3804
+ }
3805
+ .email {
3806
+ font-size: 14px;
3807
+ color: #999;
3808
+ margin-bottom: 28px;
3809
+ }
3810
+ .card {
3811
+ background: #fff;
3812
+ border: 1px solid #eaeaea;
3813
+ border-radius: 8px;
3814
+ padding: 16px 20px;
3815
+ font-size: 16px;
3816
+ color: #666;
3817
+ line-height: 1.5;
3818
+ cursor: pointer;
3819
+ transition: background 0.15s, border-color 0.15s;
3820
+ }
3821
+ .card:hover {
3822
+ background: #f5f5f5;
3823
+ border-color: #ccc;
3824
+ }
3825
+ .close-hint {
3826
+ margin-top: 20px;
3827
+ font-size: 14px;
3828
+ color: #999;
3829
+ }
3830
+ </style>
3831
+ </head>
3832
+ <body>
3833
+ <div class="container">
3834
+ <div class="logo">
3835
+ <svg width="52" height="54" viewBox="0 0 86 89" fill="none" xmlns="http://www.w3.org/2000/svg">
3836
+ <path d="M5.29236 12.7928L17.7593 6.68188V72.5667L5.29236 84.0618V12.7928Z" fill="#B4BB91"/>
3837
+ <path d="M18.2575 73.1196L59.1329 72.748L51.7011 82.4095L29.0338 86.291L6.23962 85.1554L18.2575 73.1196Z" fill="#778561"/>
3838
+ <path d="M17.4916 3.73633L3.58557 12.7099V83.5792C3.58557 84.7542 4.98563 85.3652 5.84705 84.566L19.6296 71.7801" stroke="black" stroke-width="6.42844" stroke-linecap="round"/>
3839
+ <mask id="path-4-inside-1_355_26707" fill="white">
3840
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M40.704 0.518066H17.0439V76.2221H40.704H42.5805H47.8013C68.7064 76.2221 85.6533 59.2752 85.6533 38.3701C85.6533 17.465 68.7063 0.518066 47.8013 0.518066H42.5805H40.704Z"/>
3841
+ </mask>
3842
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M40.704 0.518066H17.0439V76.2221H40.704H42.5805H47.8013C68.7064 76.2221 85.6533 59.2752 85.6533 38.3701C85.6533 17.465 68.7063 0.518066 47.8013 0.518066H42.5805H40.704Z" fill="#F3F6F1"/>
3843
+ <path d="M17.0439 0.518066V-6.57919H9.94669V0.518066H17.0439ZM17.0439 76.2221H9.94669V83.3194H17.0439V76.2221ZM17.0439 7.61532H40.704V-6.57919H17.0439V7.61532ZM24.1412 76.2221V0.518066H9.94669V76.2221H24.1412ZM40.704 69.1249H17.0439V83.3194H40.704V69.1249ZM42.5805 69.1249H40.704V83.3194H42.5805V69.1249ZM47.8013 69.1249H42.5805V83.3194H47.8013V69.1249ZM78.556 38.3701C78.556 55.3555 64.7867 69.1249 47.8013 69.1249V83.3194C72.6261 83.3194 92.7505 63.1949 92.7505 38.3701H78.556ZM47.8013 7.61532C64.7866 7.61532 78.556 21.3847 78.556 38.3701H92.7505C92.7505 13.5453 72.626 -6.57919 47.8013 -6.57919V7.61532ZM42.5805 7.61532H47.8013V-6.57919H42.5805V7.61532ZM40.704 7.61532H42.5805V-6.57919H40.704V7.61532Z" fill="black" mask="url(#path-4-inside-1_355_26707)"/>
3844
+ <path d="M68.9215 36.0135C68.9215 36.0135 65.7369 49.4738 51.4231 49.4738C37.1093 49.4738 32.5787 37.3596 32.5787 36.0135" stroke="black" stroke-width="7.69161" stroke-linecap="round" stroke-linejoin="round"/>
3845
+ <path d="M0.348633 85.4946C0.348633 85.4946 29.4856 85.8309 34.809 85.698C44.8337 85.4477 51.2872 84.402 57.5269 78.9724C62.8129 74.3727 75.1342 59.6836 75.1342 59.6836" stroke="black" stroke-width="6.16482"/>
3846
+ </svg>
3847
+ </div>
3848
+ <h1>Authentication Successful</h1>
3849
+ <p class="subtitle">You're all set. The CLI is now authenticated.</p>
3850
+ ${emailLine}
3851
+ <div class="card" onclick="window.close()">Close this tab and return to your terminal.</div>
3852
+ <p class="close-hint">This tab will close automatically in <span id="countdown">10</span>s</p>
3853
+ </div>
3854
+ <script>
3855
+ var s=10,el=document.getElementById('countdown');
3856
+ var t=setInterval(function(){if(--s<=0){clearInterval(t);window.close();}el.textContent=s;},1000);
3857
+ </script>
3858
+ </body>
3859
+ </html>`;
3860
+ }
3757
3861
  async function startCallbackServer() {
3758
3862
  let resolveToken;
3759
3863
  const tokenPromise = new Promise((resolve) => {
@@ -3770,6 +3874,8 @@ async function startCallbackServer() {
3770
3874
  const accessToken = url.searchParams.get("access_token");
3771
3875
  const refreshToken = url.searchParams.get("refresh_token");
3772
3876
  const expiresIn = url.searchParams.get("expires_in");
3877
+ const email = url.searchParams.get("email");
3878
+ const mode = url.searchParams.get("mode");
3773
3879
  if (!accessToken) {
3774
3880
  res.writeHead(200, { "Content-Type": "text/html" });
3775
3881
  res.end(CALLBACK_HTML_EXTRACT);
@@ -3778,16 +3884,18 @@ async function startCallbackServer() {
3778
3884
  let expiresInInt = 3600;
3779
3885
  if (expiresIn) {
3780
3886
  const parsed = parseInt(expiresIn, 10);
3781
- if (!isNaN(parsed))
3887
+ if (!Number.isNaN(parsed))
3782
3888
  expiresInInt = parsed;
3783
3889
  }
3784
- resolveToken({
3890
+ resolveToken?.({
3785
3891
  access_token: accessToken,
3786
- refresh_token: refreshToken ?? "",
3787
- expires_in: expiresInInt
3892
+ refresh_token: refreshToken && refreshToken !== "null" ? refreshToken : "",
3893
+ expires_in: expiresInInt,
3894
+ email: email ?? undefined,
3895
+ ...mode === MODE_OSS && { mode: MODE_OSS }
3788
3896
  });
3789
3897
  res.writeHead(200, { "Content-Type": "text/html" });
3790
- res.end(CALLBACK_HTML_SUCCESS);
3898
+ res.end(buildSuccessHtml(email ?? undefined));
3791
3899
  });
3792
3900
  await new Promise((resolve) => {
3793
3901
  httpServer.listen(0, "localhost", () => resolve());
@@ -3853,76 +3961,22 @@ const hash = window.location.hash.substring(1);
3853
3961
  if (hash) {
3854
3962
  const params = new URLSearchParams(hash);
3855
3963
  const token = params.get('access_token');
3856
- const refresh = params.get('refresh_token');
3857
- const expires = params.get('expires_in');
3964
+ const refresh = params.get('refresh_token') || '';
3965
+ const expires = params.get('expires_in') || '';
3966
+ const email = params.get('email');
3858
3967
  if (token) {
3859
3968
  window.location.href = '/callback?access_token=' + encodeURIComponent(token) +
3860
3969
  '&refresh_token=' + encodeURIComponent(refresh) +
3861
- '&expires_in=' + encodeURIComponent(expires);
3970
+ '&expires_in=' + encodeURIComponent(expires) +
3971
+ (email ? '&email=' + encodeURIComponent(email) : '');
3862
3972
  }
3863
3973
  }
3864
3974
  </script>
3865
3975
  </body>
3866
- </html>`, CALLBACK_HTML_SUCCESS = `<!DOCTYPE html>
3867
- <html lang="en">
3868
- <head>
3869
- <meta charset="UTF-8">
3870
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
3871
- <title>Dosu CLI - Authentication Successful</title>
3872
- <style>
3873
- * { margin: 0; padding: 0; box-sizing: border-box; }
3874
- body {
3875
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
3876
- background: #fafafa;
3877
- min-height: 100vh;
3878
- display: flex;
3879
- align-items: center;
3880
- justify-content: center;
3881
- padding: 20px;
3882
- }
3883
- .container {
3884
- background: white;
3885
- border-radius: 12px;
3886
- padding: 48px 40px;
3887
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
3888
- max-width: 480px;
3889
- width: 100%;
3890
- text-align: center;
3891
- border: 1px solid #e5e7eb;
3892
- }
3893
- .checkmark {
3894
- width: 64px;
3895
- height: 64px;
3896
- border-radius: 50%;
3897
- background: #10b981;
3898
- display: flex;
3899
- align-items: center;
3900
- justify-content: center;
3901
- margin: 0 auto 24px;
3902
- }
3903
- .checkmark svg { width: 32px; height: 32px; stroke: white; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; fill: none; }
3904
- h1 { font-size: 24px; font-weight: 600; color: #111827; margin-bottom: 8px; }
3905
- .subtitle { font-size: 15px; color: #6b7280; margin-bottom: 28px; }
3906
- .info { background: #f9fafb; border-radius: 8px; padding: 16px; text-align: left; border: 1px solid #e5e7eb; }
3907
- .info p { font-size: 14px; color: #374151; line-height: 1.5; }
3908
- .info strong { display: block; margin-bottom: 4px; color: #111827; }
3909
- .footer { margin-top: 24px; font-size: 13px; color: #9ca3af; }
3910
- </style>
3911
- </head>
3912
- <body>
3913
- <div class="container">
3914
- <div class="checkmark">
3915
- <svg viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
3916
- </div>
3917
- <h1>Authentication Successful</h1>
3918
- <p class="subtitle">You've successfully authenticated the Dosu CLI</p>
3919
- <div class="info">
3920
- <p><strong>Next step:</strong> Return to your terminal to continue. You can safely close this window.</p>
3921
- </div>
3922
- <div class="footer">Dosu CLI</div>
3923
- </div>
3924
- </body>
3925
3976
  </html>`;
3977
+ var init_server = __esm(() => {
3978
+ init_config();
3979
+ });
3926
3980
 
3927
3981
  // node_modules/is-docker/index.js
3928
3982
  import fs from "node:fs";
@@ -4469,48 +4523,65 @@ var exports_flow = {};
4469
4523
  __export(exports_flow, {
4470
4524
  startOAuthFlow: () => startOAuthFlow
4471
4525
  });
4472
- async function startOAuthFlow(signal) {
4526
+ async function startOAuthFlow(signal, path2 = "/cli/auth") {
4473
4527
  const { server, tokenPromise } = await startCallbackServer();
4528
+ let timeoutId;
4474
4529
  try {
4475
4530
  const callbackURL = `http://localhost:${server.port}/callback`;
4476
- const authURL = buildAuthURL(callbackURL);
4531
+ const authURL = buildAuthURL(callbackURL, path2);
4477
4532
  const open2 = await Promise.resolve().then(() => (init_open(), exports_open));
4478
4533
  await open2.default(authURL);
4479
4534
  const timeout = new Promise((_3, reject) => {
4480
- setTimeout(() => reject(new Error("authentication timeout - please try again")), 300000);
4535
+ timeoutId = setTimeout(() => reject(new Error("authentication timeout - please try again")), 900000);
4481
4536
  });
4482
4537
  const abort = signal ? new Promise((_3, reject) => {
4483
4538
  signal.addEventListener("abort", () => reject(new Error("authentication cancelled")));
4484
4539
  }) : new Promise(() => {});
4485
4540
  return await Promise.race([tokenPromise, timeout, abort]);
4486
4541
  } finally {
4542
+ clearTimeout(timeoutId);
4487
4543
  server.close();
4488
4544
  }
4489
4545
  }
4490
- function buildAuthURL(callbackURL) {
4546
+ function buildAuthURL(callbackURL, path2) {
4491
4547
  const webAppURL = getWebAppURL();
4492
4548
  const params = new URLSearchParams({ callback: callbackURL });
4493
- return `${webAppURL}/cli-login?${params}`;
4549
+ if (path2 !== "/cli/auth") {
4550
+ params.set("redirect", `${path2}?callback=${encodeURIComponent(callbackURL)}`);
4551
+ }
4552
+ return `${webAppURL}${path2}?${params}`;
4494
4553
  }
4495
- var init_flow = () => {};
4554
+ var init_flow = __esm(() => {
4555
+ init_server();
4556
+ });
4496
4557
 
4497
4558
  // src/setup/flow.ts
4498
4559
  var exports_flow2 = {};
4499
4560
  __export(exports_flow2, {
4500
- runSetup: () => runSetup
4561
+ stepShowSummary: () => stepShowSummary,
4562
+ stepDetectTools: () => stepDetectTools,
4563
+ stepConfigureTools: () => stepConfigureTools,
4564
+ runSetup: () => runSetup,
4565
+ isStdioOnly: () => isStdioOnly
4501
4566
  });
4502
4567
  async function runSetup(opts = {}) {
4503
4568
  Ie("Dosu CLI Setup");
4504
- const cfg = await stepAuthenticate();
4569
+ const cfg = await stepAuthenticate(opts);
4505
4570
  if (!cfg)
4506
4571
  return;
4507
4572
  const apiClient = new Client(cfg);
4508
- let deployment;
4509
4573
  if (opts.deploymentID) {
4510
4574
  const d3 = await stepResolveDeployment(apiClient, opts.deploymentID);
4511
4575
  if (!d3)
4512
4576
  return;
4513
- 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
+ }
4514
4585
  } else {
4515
4586
  const org = await stepSelectOrg(apiClient);
4516
4587
  if (!org)
@@ -4518,10 +4589,9 @@ async function runSetup(opts = {}) {
4518
4589
  const d3 = await stepSelectDeployment(apiClient, org);
4519
4590
  if (!d3)
4520
4591
  return;
4521
- deployment = d3;
4592
+ cfg.deployment_id = d3.deployment_id;
4593
+ cfg.deployment_name = d3.name;
4522
4594
  }
4523
- cfg.deployment_id = deployment.deployment_id;
4524
- cfg.deployment_name = deployment.name;
4525
4595
  saveConfig(cfg);
4526
4596
  const apiKey = await stepMintAPIKey(apiClient, cfg);
4527
4597
  if (!apiKey)
@@ -4538,10 +4608,14 @@ Run ${info("dosu mcp add <tool>")} to manually configure a tool.`);
4538
4608
  if (!selection)
4539
4609
  return;
4540
4610
  const results = stepConfigureTools(cfg, selection);
4541
- stepShowSummary(results);
4542
- 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
+ }
4543
4617
  }
4544
- async function stepAuthenticate() {
4618
+ async function stepAuthenticate(opts) {
4545
4619
  const cfg = loadConfig();
4546
4620
  if (cfg.access_token) {
4547
4621
  const s = Y2();
@@ -4551,18 +4625,31 @@ async function stepAuthenticate() {
4551
4625
  const resp = await apiClient.doRequestRaw("GET", "/v1/mcp/deployments");
4552
4626
  if (resp.status === 200) {
4553
4627
  s.stop("Authenticated");
4554
- return cfg;
4555
- }
4556
- if (resp.status === 401 || resp.status === 403 || resp.status === 500) {
4557
- try {
4558
- await apiClient.refreshToken();
4559
- const resp2 = await apiClient.doRequestRaw("GET", "/v1/mcp/deployments");
4560
- if (resp2.status === 200) {
4561
- 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")
4562
4640
  return cfg;
4563
- }
4564
- } catch {}
4641
+ return await openBrowserForSetup(cfg, opts);
4642
+ }
4643
+ return cfg;
4565
4644
  }
4645
+ try {
4646
+ await apiClient.refreshToken();
4647
+ const resp2 = await apiClient.doRequestRaw("GET", "/v1/mcp/deployments");
4648
+ if (resp2.status === 200) {
4649
+ s.stop("Authenticated");
4650
+ return cfg;
4651
+ }
4652
+ } catch {}
4566
4653
  s.stop("Session expired");
4567
4654
  M2.warn("Session expired.");
4568
4655
  } catch {
@@ -4572,22 +4659,35 @@ async function stepAuthenticate() {
4572
4659
  const shouldLogin = await ye({ message: "Open browser to log in?" });
4573
4660
  if (pD(shouldLogin) || !shouldLogin)
4574
4661
  return null;
4662
+ return await openBrowserForSetup(cfg, opts);
4663
+ }
4664
+ async function openBrowserForSetup(cfg, opts) {
4575
4665
  try {
4576
4666
  const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
4577
4667
  const s = Y2();
4578
4668
  s.start("Waiting for authentication...");
4579
- const token = await startOAuthFlow2();
4669
+ const authPath = opts.deploymentID ? "/cli/auth" : "/cli-setup";
4670
+ const token = await startOAuthFlow2(undefined, authPath);
4580
4671
  s.stop("Authenticated");
4581
4672
  cfg.access_token = token.access_token;
4582
4673
  cfg.refresh_token = token.refresh_token;
4583
4674
  cfg.expires_at = Math.floor(Date.now() / 1000) + token.expires_in;
4675
+ if (token.mode === MODE_OSS)
4676
+ cfg.mode = MODE_OSS;
4584
4677
  saveConfig(cfg);
4585
4678
  return cfg;
4586
4679
  } catch (err) {
4587
- M2.error(`Authentication failed: ${err.message}`);
4680
+ M2.error(`Authentication failed: ${err instanceof Error ? err.message : String(err)}`);
4588
4681
  return null;
4589
4682
  }
4590
4683
  }
4684
+ async function fetchDeployments(apiClient) {
4685
+ try {
4686
+ return await apiClient.getDeployments();
4687
+ } catch {
4688
+ return [];
4689
+ }
4690
+ }
4591
4691
  async function stepSelectOrg(apiClient) {
4592
4692
  try {
4593
4693
  const orgs = await apiClient.getOrgs();
@@ -4609,10 +4709,10 @@ ${dim(orgs[0].name)}`);
4609
4709
  return orgs.find((o2) => o2.org_id === selected) ?? null;
4610
4710
  } catch (err) {
4611
4711
  if (err instanceof SessionExpiredError) {
4612
- M2.warn("Session expired. Please run " + info("dosu setup") + " again.");
4712
+ M2.warn(`Session expired. Please run ${info("dosu setup")} again.`);
4613
4713
  return null;
4614
4714
  }
4615
- M2.error(`Organization selection failed: ${err.message}`);
4715
+ M2.error(`Organization selection failed: ${err instanceof Error ? err.message : String(err)}`);
4616
4716
  return null;
4617
4717
  }
4618
4718
  }
@@ -4628,7 +4728,7 @@ async function stepResolveDeployment(apiClient, id) {
4628
4728
  ${dim(d3.name)}`);
4629
4729
  return d3;
4630
4730
  } catch (err) {
4631
- M2.error(`Failed to resolve deployment: ${err.message}`);
4731
+ M2.error(`Failed to resolve deployment: ${err instanceof Error ? err.message : String(err)}`);
4632
4732
  return null;
4633
4733
  }
4634
4734
  }
@@ -4653,11 +4753,15 @@ ${dim(deployments[0].name)}`);
4653
4753
  return null;
4654
4754
  return deployments.find((d3) => d3.deployment_id === selected) ?? null;
4655
4755
  } catch (err) {
4656
- M2.error(`Deployment selection failed: ${err.message}`);
4756
+ M2.error(`Deployment selection failed: ${err instanceof Error ? err.message : String(err)}`);
4657
4757
  return null;
4658
4758
  }
4659
4759
  }
4660
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
+ }
4661
4765
  if (cfg.api_key) {
4662
4766
  const valid = await apiClient.validateAPIKey(cfg.api_key, cfg.deployment_id);
4663
4767
  if (valid) {
@@ -4673,7 +4777,7 @@ ${dim("using existing")}`);
4673
4777
  ${dim("created")}`);
4674
4778
  return resp.api_key;
4675
4779
  } catch (err) {
4676
- M2.error(`API key creation failed: ${err.message}`);
4780
+ M2.error(`API key creation failed: ${err instanceof Error ? err.message : String(err)}`);
4677
4781
  return null;
4678
4782
  }
4679
4783
  }
@@ -4689,7 +4793,7 @@ async function stepSelectTools(detected) {
4689
4793
  configuredMap.set(p2.id(), p2.isConfigured());
4690
4794
  }
4691
4795
  const options = detected.map((p2) => {
4692
- const configured = configuredMap.get(p2.id());
4796
+ const configured = configuredMap.get(p2.id()) ?? false;
4693
4797
  return {
4694
4798
  label: configured ? `${p2.name()} ${dim("(already configured)")}` : p2.name(),
4695
4799
  value: p2.id(),
@@ -4708,7 +4812,7 @@ async function stepSelectTools(detected) {
4708
4812
  const result = { toInstall: [], toRemove: [], skipped: [] };
4709
4813
  for (const provider of detected) {
4710
4814
  const isSelected = selectedSet.has(provider.id());
4711
- const isConfigured = configuredMap.get(provider.id());
4815
+ const isConfigured = configuredMap.get(provider.id()) ?? false;
4712
4816
  if (isSelected && !isConfigured)
4713
4817
  result.toInstall.push(provider);
4714
4818
  else if (isSelected && isConfigured)
@@ -4725,8 +4829,9 @@ function stepConfigureTools(cfg, selection) {
4725
4829
  provider.install(cfg, true);
4726
4830
  results.push({ provider, action: "install" });
4727
4831
  } catch (err) {
4728
- M2.error(`Failed to configure ${provider.name()}: ${err.message}`);
4729
- results.push({ provider, action: "install", error: err });
4832
+ const error = err instanceof Error ? err : new Error(String(err));
4833
+ M2.error(`Failed to configure ${provider.name()}: ${error.message}`);
4834
+ results.push({ provider, action: "install", error });
4730
4835
  }
4731
4836
  }
4732
4837
  for (const provider of selection.toRemove) {
@@ -4734,8 +4839,9 @@ function stepConfigureTools(cfg, selection) {
4734
4839
  provider.remove(true);
4735
4840
  results.push({ provider, action: "remove" });
4736
4841
  } catch (err) {
4737
- M2.error(`Failed to remove ${provider.name()}: ${err.message}`);
4738
- results.push({ provider, action: "remove", error: err });
4842
+ const error = err instanceof Error ? err : new Error(String(err));
4843
+ M2.error(`Failed to remove ${provider.name()}: ${error.message}`);
4844
+ results.push({ provider, action: "remove", error });
4739
4845
  }
4740
4846
  }
4741
4847
  for (const provider of selection.skipped) {
@@ -4743,7 +4849,7 @@ function stepConfigureTools(cfg, selection) {
4743
4849
  }
4744
4850
  return results;
4745
4851
  }
4746
- function stepShowSummary(results) {
4852
+ function stepShowSummary(results, mode) {
4747
4853
  const installed = results.filter((r) => r.action === "install" && !r.error);
4748
4854
  const removed = results.filter((r) => r.action === "remove" && !r.error);
4749
4855
  const skipped = results.filter((r) => r.action === "skip");
@@ -4765,15 +4871,16 @@ ${lines}`);
4765
4871
  M2.success("All tools already configured. No changes needed.");
4766
4872
  }
4767
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?`;
4768
4875
  M2.message(`Try it out! Paste this into your agent:
4769
4876
 
4770
- ` + info(`Use Dosu to search our team's documentation and answer: what are the main components of our system?`));
4877
+ ${info(prompt)}`);
4771
4878
  }
4772
4879
  }
4773
4880
  var init_flow2 = __esm(() => {
4774
4881
  init_dist2();
4775
- init_config();
4776
4882
  init_client();
4883
+ init_config();
4777
4884
  init_providers();
4778
4885
  init_styles();
4779
4886
  });
@@ -4781,7 +4888,8 @@ var init_flow2 = __esm(() => {
4781
4888
  // src/tui/tui.ts
4782
4889
  var exports_tui = {};
4783
4890
  __export(exports_tui, {
4784
- runTUI: () => runTUI
4891
+ runTUI: () => runTUI,
4892
+ handleLogout: () => handleLogout
4785
4893
  });
4786
4894
  async function runTUI() {
4787
4895
  console.log(import_picocolors3.default.magenta(LOGO));
@@ -4795,10 +4903,26 @@ async function runTUI() {
4795
4903
  const action = await ve({
4796
4904
  message: "What would you like to do?",
4797
4905
  options: [
4798
- { label: "Authenticate", value: "setup", hint: isAuthenticated(cfg) ? "Re-authenticate" : undefined },
4799
- { label: "Choose Deployment", value: "deployments", hint: !isAuthenticated(cfg) ? "Login first" : undefined },
4800
- { label: "Add MCP", value: "mcp-add", hint: !hasDeployment ? "Select deployment first" : undefined },
4801
- { label: "Remove MCP", value: "mcp-remove", hint: !hasDeployment ? "Select deployment first" : undefined },
4906
+ {
4907
+ label: "Authenticate",
4908
+ value: "setup",
4909
+ hint: isAuthenticated(cfg) ? "Re-authenticate" : undefined
4910
+ },
4911
+ {
4912
+ label: "Choose Deployment",
4913
+ value: "deployments",
4914
+ hint: !isAuthenticated(cfg) ? "Login first" : undefined
4915
+ },
4916
+ {
4917
+ label: "Add MCP",
4918
+ value: "mcp-add",
4919
+ hint: !hasDeployment ? "Select deployment first" : undefined
4920
+ },
4921
+ {
4922
+ label: "Remove MCP",
4923
+ value: "mcp-remove",
4924
+ hint: !hasDeployment ? "Select deployment first" : undefined
4925
+ },
4802
4926
  { label: "Clear Credentials", value: "logout" },
4803
4927
  { label: "Exit", value: "exit" }
4804
4928
  ]
@@ -4863,7 +4987,7 @@ async function handleDeployments(cfg) {
4863
4987
  M2.success(`Selected: ${deployment.name}`);
4864
4988
  }
4865
4989
  } catch (err) {
4866
- M2.error(`Failed: ${err.message}`);
4990
+ M2.error(`Failed: ${err instanceof Error ? err.message : String(err)}`);
4867
4991
  }
4868
4992
  }
4869
4993
  async function handleMCPAdd(cfg) {
@@ -4886,10 +5010,10 @@ async function handleMCPAdd(cfg) {
4886
5010
  provider.install(cfg, true);
4887
5011
  M2.success(`Added Dosu MCP to ${provider.name()}`);
4888
5012
  } catch (err) {
4889
- M2.error(`Failed: ${err.message}`);
5013
+ M2.error(`Failed: ${err instanceof Error ? err.message : String(err)}`);
4890
5014
  }
4891
5015
  }
4892
- async function handleMCPRemove(cfg) {
5016
+ async function handleMCPRemove(_cfg) {
4893
5017
  const { allProviders: allProviders2 } = await Promise.resolve().then(() => (init_providers(), exports_providers));
4894
5018
  const providers = allProviders2();
4895
5019
  const selected = await ve({
@@ -4908,7 +5032,7 @@ async function handleMCPRemove(cfg) {
4908
5032
  provider.remove(true);
4909
5033
  M2.success(`Removed Dosu MCP from ${provider.name()}`);
4910
5034
  } catch (err) {
4911
- M2.error(`Failed: ${err.message}`);
5035
+ M2.error(`Failed: ${err instanceof Error ? err.message : String(err)}`);
4912
5036
  }
4913
5037
  }
4914
5038
  function handleLogout(cfg) {
@@ -4937,8 +5061,8 @@ var import_picocolors3, LOGO = `
4937
5061
  `;
4938
5062
  var init_tui = __esm(() => {
4939
5063
  init_dist2();
4940
- init_config();
4941
5064
  init_client();
5065
+ init_config();
4942
5066
  init_flow2();
4943
5067
  import_picocolors3 = __toESM(require_picocolors(), 1);
4944
5068
  });
@@ -4959,17 +5083,19 @@ var {
4959
5083
  Help
4960
5084
  } = import__.default;
4961
5085
 
5086
+ // src/cli/cli.ts
5087
+ init_config();
5088
+ init_providers();
5089
+
4962
5090
  // src/version/version.ts
4963
- var VERSION = "0.1.7";
4964
- var COMMIT = "c622ab4d9ae1a89b6fff2802e9cb475137906971";
4965
- var DATE = "";
5091
+ var VERSION = "0.3.0";
5092
+ var COMMIT = "none";
5093
+ var DATE = "unknown";
4966
5094
  function getVersionString() {
4967
5095
  return `dosu ${VERSION} (${COMMIT}, ${DATE})`;
4968
5096
  }
4969
5097
 
4970
5098
  // src/cli/cli.ts
4971
- init_config();
4972
- init_providers();
4973
5099
  function createProgram() {
4974
5100
  const program2 = new Command;
4975
5101
  program2.name("dosu").description("Dosu CLI - Manage MCP servers for AI tools").version(getVersionString(), "-v, --version").action(async () => {
@@ -5096,6 +5222,7 @@ async function execute() {
5096
5222
  }
5097
5223
 
5098
5224
  // src/index.ts
5225
+ process.on("SIGINT", () => process.exit(0));
5099
5226
  execute().catch((err) => {
5100
5227
  console.error(err.message ?? err);
5101
5228
  process.exit(1);