@dosu/cli 0.1.7 → 0.2.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 +424 -360
  2. package/package.json +12 -4
package/bin/dosu.js CHANGED
@@ -2117,59 +2117,22 @@ function emptyConfig() {
2117
2117
  }
2118
2118
  var init_config = () => {};
2119
2119
 
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
2120
  // src/config/constants.ts
2151
- function isDev() {
2152
- return process.env.DOSU_DEV === "true";
2153
- }
2154
2121
  function getWebAppURL() {
2155
- if (process.env.DOSU_WEB_APP_URL)
2156
- return process.env.DOSU_WEB_APP_URL;
2157
- return isDev() ? DevWebAppURL : ProdWebAppURL;
2122
+ return "https://app.dosu.dev";
2158
2123
  }
2159
2124
  function getBackendURL() {
2160
- if (process.env.DOSU_BACKEND_URL)
2161
- return process.env.DOSU_BACKEND_URL;
2162
- return isDev() ? DevBackendURL : ProdBackendURL;
2125
+ return "https://api.dosu.dev";
2163
2126
  }
2164
2127
  function getSupabaseURL() {
2165
- if (process.env.SUPABASE_URL)
2166
- return process.env.SUPABASE_URL;
2167
- return isDev() ? DevSupabaseURL : ProdSupabaseURL;
2128
+ return "https://wldmetsoicvieidlsqrb.supabase.co";
2129
+ }
2130
+ function getSupabaseAnonKey() {
2131
+ return "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6IndsbG1ldHNvaWN2aWVpZGxzcXJiIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzQ0NjA1NjUsImV4cCI6MjA1MDAzNjU2NX0.15LIxqSMVRnxsvLrk0GPjL1aSYPfOeaeFMdJXqgc5Xs";
2168
2132
  }
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
2133
 
2171
2134
  // src/mcp/config-helpers.ts
2172
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
2135
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
2173
2136
  import { dirname } from "node:path";
2174
2137
  function mcpURL(deploymentID) {
2175
2138
  return `${getBackendURL()}/v1/mcp/deployments/${deploymentID}`;
@@ -2178,7 +2141,7 @@ function mcpHeaders(apiKey) {
2178
2141
  return { "X-Dosu-API-Key": apiKey };
2179
2142
  }
2180
2143
  function loadJSONConfig(path) {
2181
- if (!existsSync3(path))
2144
+ if (!existsSync2(path))
2182
2145
  return {};
2183
2146
  let data = readFileSync2(path, "utf-8").trim();
2184
2147
  if (!data)
@@ -2240,7 +2203,7 @@ function stripJSONComments(data) {
2240
2203
  }
2241
2204
  function saveJSONConfig(path, cfg) {
2242
2205
  const dir = dirname(path);
2243
- if (!existsSync3(dir)) {
2206
+ if (!existsSync2(dir)) {
2244
2207
  mkdirSync2(dir, { recursive: true });
2245
2208
  }
2246
2209
  writeFileSync2(path, JSON.stringify(cfg, null, 2));
@@ -2258,7 +2221,7 @@ function installJSONServer(configPath, topKey, server) {
2258
2221
  if (typeof section !== "object" || section === null) {
2259
2222
  section = {};
2260
2223
  }
2261
- section["dosu"] = server;
2224
+ section.dosu = server;
2262
2225
  jsonCfg[topKey] = section;
2263
2226
  saveJSONConfig(configPath, jsonCfg);
2264
2227
  }
@@ -2271,12 +2234,42 @@ function removeJSONServer(configPath, topKey) {
2271
2234
  }
2272
2235
  const section = jsonCfg[topKey];
2273
2236
  if (typeof section === "object" && section !== null) {
2274
- delete section["dosu"];
2237
+ delete section.dosu;
2275
2238
  }
2276
2239
  saveJSONConfig(configPath, jsonCfg);
2277
2240
  }
2278
2241
  var init_config_helpers = () => {};
2279
2242
 
2243
+ // src/mcp/detect.ts
2244
+ import { existsSync as existsSync3 } from "node:fs";
2245
+ import { homedir, platform } from "node:os";
2246
+ import { join as join2 } from "node:path";
2247
+ function isInstalled(paths) {
2248
+ return paths.some((p) => existsSync3(expandHome(p)));
2249
+ }
2250
+ function expandHome(path) {
2251
+ if (!path.startsWith("~"))
2252
+ return path;
2253
+ return join2(homedir(), path.slice(1));
2254
+ }
2255
+ function appSupportDir() {
2256
+ switch (platform()) {
2257
+ case "darwin": {
2258
+ return join2(homedir(), "Library", "Application Support");
2259
+ }
2260
+ case "win32": {
2261
+ return process.env.APPDATA ?? "";
2262
+ }
2263
+ default: {
2264
+ const xdg = process.env.XDG_CONFIG_HOME;
2265
+ if (xdg)
2266
+ return xdg;
2267
+ return join2(homedir(), ".config");
2268
+ }
2269
+ }
2270
+ }
2271
+ var init_detect = () => {};
2272
+
2280
2273
  // src/mcp/providers/base.ts
2281
2274
  function createJSONProvider(opts) {
2282
2275
  const defaultBuildServer = (cfg) => ({
@@ -2321,8 +2314,27 @@ function createJSONProvider(opts) {
2321
2314
  };
2322
2315
  }
2323
2316
  var init_base = __esm(() => {
2317
+ init_config_helpers();
2324
2318
  init_detect();
2319
+ });
2320
+
2321
+ // src/mcp/providers/antigravity.ts
2322
+ var AntigravityProvider = () => createJSONProvider({
2323
+ providerName: "Antigravity",
2324
+ providerID: "antigravity",
2325
+ local: false,
2326
+ priorityValue: 15,
2327
+ paths: ["~/.gemini"],
2328
+ globalPath: "~/.gemini/antigravity/mcp_config.json",
2329
+ topKey: "mcpServers",
2330
+ buildServer: (cfg) => ({
2331
+ serverUrl: mcpURL(cfg.deployment_id),
2332
+ headers: mcpHeaders(cfg.api_key)
2333
+ })
2334
+ });
2335
+ var init_antigravity = __esm(() => {
2325
2336
  init_config_helpers();
2337
+ init_base();
2326
2338
  });
2327
2339
 
2328
2340
  // src/mcp/providers/claude.ts
@@ -2363,71 +2375,65 @@ var init_claude_desktop = __esm(() => {
2363
2375
  init_detect();
2364
2376
  });
2365
2377
 
2366
- // src/mcp/providers/cursor.ts
2378
+ // src/mcp/providers/cline.ts
2367
2379
  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",
2380
+ var extensionDir = () => join5(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
2381
+ providerName: "Cline",
2382
+ providerID: "cline",
2383
+ local: false,
2384
+ priorityValue: 11,
2385
+ paths: [extensionDir()],
2386
+ globalPath: join5(extensionDir(), "settings", "cline_mcp_settings.json"),
2375
2387
  topKey: "mcpServers",
2376
2388
  buildServer: (cfg) => ({
2377
2389
  url: mcpURL(cfg.deployment_id),
2390
+ type: "streamableHttp",
2391
+ disabled: false,
2378
2392
  headers: mcpHeaders(cfg.api_key)
2379
- }),
2380
- localConfigPath: (cwd) => join5(cwd, ".cursor", "mcp.json")
2393
+ })
2381
2394
  });
2382
- var init_cursor = __esm(() => {
2383
- init_base();
2395
+ var init_cline = __esm(() => {
2384
2396
  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
2397
  init_detect();
2398
+ init_base();
2402
2399
  });
2403
2400
 
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",
2401
+ // src/mcp/providers/cline-cli.ts
2402
+ import { join as join6 } from "node:path";
2403
+ function clineDir() {
2404
+ return process.env.CLINE_DIR ?? expandHome("~/.cline");
2405
+ }
2406
+ var ClineCliProvider = () => createJSONProvider({
2407
+ providerName: "Cline CLI",
2408
+ providerID: "cline-cli",
2409
+ local: false,
2410
+ priorityValue: 12,
2411
+ paths: [clineDir()],
2412
+ globalPath: join6(clineDir(), "data", "settings", "cline_mcp_settings.json"),
2413
2413
  topKey: "mcpServers",
2414
- localConfigPath: (cwd) => join7(cwd, ".gemini", "settings.json")
2414
+ buildServer: (cfg) => ({
2415
+ url: mcpURL(cfg.deployment_id),
2416
+ type: "streamableHttp",
2417
+ disabled: false,
2418
+ headers: mcpHeaders(cfg.api_key)
2419
+ })
2415
2420
  });
2416
- var init_gemini = __esm(() => {
2421
+ var init_cline_cli = __esm(() => {
2422
+ init_config_helpers();
2423
+ init_detect();
2417
2424
  init_base();
2418
2425
  });
2419
2426
 
2420
2427
  // src/mcp/providers/codex.ts
2421
- import { join as join8 } from "node:path";
2422
2428
  import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
2423
- import { dirname as dirname2 } from "node:path";
2429
+ import { dirname as dirname2, join as join7 } from "node:path";
2424
2430
  function codexHome() {
2425
2431
  return process.env.CODEX_HOME ?? expandHome("~/.codex");
2426
2432
  }
2427
2433
  function getConfigPath2(global) {
2428
2434
  if (global)
2429
- return join8(codexHome(), "config.toml");
2430
- return join8(process.cwd(), ".codex", "config.toml");
2435
+ return join7(codexHome(), "config.toml");
2436
+ return join7(process.cwd(), ".codex", "config.toml");
2431
2437
  }
2432
2438
  function readTOML(path) {
2433
2439
  if (!existsSync4(path))
@@ -2486,9 +2492,9 @@ var CodexProvider = () => ({
2486
2492
  priority: () => 8,
2487
2493
  detectPaths: () => ["~/.codex"],
2488
2494
  isInstalled: () => isInstalled(["~/.codex"]),
2489
- globalConfigPath: () => join8(codexHome(), "config.toml"),
2495
+ globalConfigPath: () => join7(codexHome(), "config.toml"),
2490
2496
  isConfigured: () => {
2491
- const content = readTOML(join8(codexHome(), "config.toml"));
2497
+ const content = readTOML(join7(codexHome(), "config.toml"));
2492
2498
  return content.includes("[mcp_servers.dosu]");
2493
2499
  },
2494
2500
  install(cfg, global) {
@@ -2504,111 +2510,15 @@ var CodexProvider = () => ({
2504
2510
  }
2505
2511
  });
2506
2512
  var init_codex = __esm(() => {
2507
- init_detect();
2508
2513
  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
2514
  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
2515
  });
2606
2516
 
2607
2517
  // src/mcp/providers/copilot.ts
2608
- import { join as join13 } from "node:path";
2518
+ import { join as join8 } from "node:path";
2609
2519
  function globalPath() {
2610
2520
  if (process.env.XDG_CONFIG_HOME) {
2611
- return join13(process.env.XDG_CONFIG_HOME, "mcp-config.json");
2521
+ return join8(process.env.XDG_CONFIG_HOME, "mcp-config.json");
2612
2522
  }
2613
2523
  return expandHome("~/.copilot/mcp-config.json");
2614
2524
  }
@@ -2634,7 +2544,7 @@ var CopilotProvider = () => ({
2634
2544
  };
2635
2545
  installJSONServer(globalPath(), "mcpServers", server);
2636
2546
  } else {
2637
- const configPath = join13(process.cwd(), ".vscode", "mcp.json");
2547
+ const configPath = join8(process.cwd(), ".vscode", "mcp.json");
2638
2548
  const server = {
2639
2549
  type: "http",
2640
2550
  url,
@@ -2647,61 +2557,79 @@ var CopilotProvider = () => ({
2647
2557
  if (global) {
2648
2558
  removeJSONServer(globalPath(), "mcpServers");
2649
2559
  } else {
2650
- const configPath = join13(process.cwd(), ".vscode", "mcp.json");
2560
+ const configPath = join8(process.cwd(), ".vscode", "mcp.json");
2651
2561
  removeJSONServer(configPath, "servers");
2652
2562
  }
2653
2563
  }
2654
2564
  });
2655
2565
  var init_copilot = __esm(() => {
2656
- init_detect();
2657
2566
  init_config_helpers();
2567
+ init_detect();
2658
2568
  });
2659
2569
 
2660
- // src/mcp/providers/opencode.ts
2661
- import { join as join14 } from "node:path";
2662
- var OpenCodeProvider = () => createJSONProvider({
2663
- providerName: "OpenCode",
2664
- providerID: "opencode",
2570
+ // src/mcp/providers/cursor.ts
2571
+ import { join as join9 } from "node:path";
2572
+ var CursorProvider = () => createJSONProvider({
2573
+ providerName: "Cursor",
2574
+ providerID: "cursor",
2665
2575
  local: true,
2666
- priorityValue: 14,
2667
- paths: ["~/.config/opencode"],
2668
- globalPath: "~/.config/opencode/opencode.json",
2669
- topKey: "mcp",
2576
+ priorityValue: 5,
2577
+ paths: ["~/.cursor"],
2578
+ globalPath: "~/.cursor/mcp.json",
2579
+ topKey: "mcpServers",
2670
2580
  buildServer: (cfg) => ({
2671
- type: "remote",
2672
2581
  url: mcpURL(cfg.deployment_id),
2673
- enabled: true,
2674
2582
  headers: mcpHeaders(cfg.api_key)
2675
2583
  }),
2676
- localConfigPath: (cwd) => join14(cwd, "opencode.json")
2584
+ localConfigPath: (cwd) => join9(cwd, ".cursor", "mcp.json")
2677
2585
  });
2678
- var init_opencode = __esm(() => {
2679
- init_base();
2586
+ var init_cursor = __esm(() => {
2680
2587
  init_config_helpers();
2588
+ init_base();
2681
2589
  });
2682
2590
 
2683
- // src/mcp/providers/antigravity.ts
2684
- var AntigravityProvider = () => createJSONProvider({
2685
- providerName: "Antigravity",
2686
- providerID: "antigravity",
2687
- local: false,
2688
- priorityValue: 15,
2591
+ // src/mcp/providers/gemini.ts
2592
+ import { join as join10 } from "node:path";
2593
+ var GeminiProvider = () => createJSONProvider({
2594
+ providerName: "Gemini CLI",
2595
+ providerID: "gemini",
2596
+ local: true,
2597
+ priorityValue: 7,
2689
2598
  paths: ["~/.gemini"],
2690
- globalPath: "~/.gemini/antigravity/mcp_config.json",
2599
+ globalPath: "~/.gemini/settings.json",
2691
2600
  topKey: "mcpServers",
2692
- buildServer: (cfg) => ({
2693
- serverUrl: mcpURL(cfg.deployment_id),
2694
- headers: mcpHeaders(cfg.api_key)
2695
- })
2601
+ localConfigPath: (cwd) => join10(cwd, ".gemini", "settings.json")
2696
2602
  });
2697
- var init_antigravity = __esm(() => {
2603
+ var init_gemini = __esm(() => {
2698
2604
  init_base();
2605
+ });
2606
+
2607
+ // src/mcp/providers/manual.ts
2608
+ var ManualProvider = () => ({
2609
+ name: () => "Manual Configuration",
2610
+ id: () => "manual",
2611
+ supportsLocal: () => false,
2612
+ install(cfg) {
2613
+ const url = mcpURL(cfg.deployment_id);
2614
+ console.log("Use these details to configure the Dosu MCP server in your client:");
2615
+ console.log();
2616
+ console.log(` Transport: HTTP`);
2617
+ console.log(` Endpoint: ${url}`);
2618
+ console.log(` Header: X-Dosu-API-Key: ${cfg.api_key}`);
2619
+ console.log();
2620
+ },
2621
+ remove() {
2622
+ console.log(`
2623
+ To remove the Dosu MCP server, manually delete the configuration from your client.`);
2624
+ }
2625
+ });
2626
+ var init_manual = __esm(() => {
2699
2627
  init_config_helpers();
2700
2628
  });
2701
2629
 
2702
2630
  // src/mcp/providers/mcporter.ts
2703
- import { join as join15 } from "node:path";
2704
2631
  import { existsSync as existsSync5 } from "node:fs";
2632
+ import { join as join11 } from "node:path";
2705
2633
  function resolveGlobalConfigPath() {
2706
2634
  const jsonPath = expandHome("~/.mcporter/mcporter.json");
2707
2635
  if (existsSync5(jsonPath))
@@ -2723,7 +2651,7 @@ var MCPorterProvider = () => ({
2723
2651
  install(cfg, global) {
2724
2652
  if (!cfg.deployment_id)
2725
2653
  throw new Error("deployment ID is required");
2726
- const configPath = global ? resolveGlobalConfigPath() : join15(process.cwd(), "config", "mcporter.json");
2654
+ const configPath = global ? resolveGlobalConfigPath() : join11(process.cwd(), "config", "mcporter.json");
2727
2655
  const server = {
2728
2656
  type: "http",
2729
2657
  url: mcpURL(cfg.deployment_id),
@@ -2732,36 +2660,100 @@ var MCPorterProvider = () => ({
2732
2660
  installJSONServer(configPath, "mcpServers", server);
2733
2661
  },
2734
2662
  remove(global) {
2735
- const configPath = global ? resolveGlobalConfigPath() : join15(process.cwd(), "config", "mcporter.json");
2663
+ const configPath = global ? resolveGlobalConfigPath() : join11(process.cwd(), "config", "mcporter.json");
2736
2664
  removeJSONServer(configPath, "mcpServers");
2737
2665
  }
2738
2666
  });
2739
2667
  var init_mcporter = __esm(() => {
2668
+ init_config_helpers();
2740
2669
  init_detect();
2670
+ });
2671
+
2672
+ // src/mcp/providers/opencode.ts
2673
+ import { join as join12 } from "node:path";
2674
+ var OpenCodeProvider = () => createJSONProvider({
2675
+ providerName: "OpenCode",
2676
+ providerID: "opencode",
2677
+ local: true,
2678
+ priorityValue: 14,
2679
+ paths: ["~/.config/opencode"],
2680
+ globalPath: "~/.config/opencode/opencode.json",
2681
+ topKey: "mcp",
2682
+ buildServer: (cfg) => ({
2683
+ type: "remote",
2684
+ url: mcpURL(cfg.deployment_id),
2685
+ enabled: true,
2686
+ headers: mcpHeaders(cfg.api_key)
2687
+ }),
2688
+ localConfigPath: (cwd) => join12(cwd, "opencode.json")
2689
+ });
2690
+ var init_opencode = __esm(() => {
2741
2691
  init_config_helpers();
2692
+ init_base();
2742
2693
  });
2743
2694
 
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
- }
2695
+ // src/mcp/providers/vscode.ts
2696
+ import { join as join13 } from "node:path";
2697
+ var VSCodeProvider = () => createJSONProvider({
2698
+ providerName: "VS Code",
2699
+ providerID: "vscode",
2700
+ local: true,
2701
+ priorityValue: 6,
2702
+ paths: [join13(appSupportDir(), "Code")],
2703
+ globalPath: join13(appSupportDir(), "Code", "User", "mcp.json"),
2704
+ topKey: "servers",
2705
+ localConfigPath: (cwd) => join13(cwd, ".vscode", "mcp.json")
2762
2706
  });
2763
- var init_manual = __esm(() => {
2707
+ var init_vscode = __esm(() => {
2708
+ init_detect();
2709
+ init_base();
2710
+ });
2711
+
2712
+ // src/mcp/providers/windsurf.ts
2713
+ import { homedir as homedir2 } from "node:os";
2714
+ import { join as join14 } from "node:path";
2715
+ var WindsurfProvider = () => createJSONProvider({
2716
+ providerName: "Windsurf",
2717
+ providerID: "windsurf",
2718
+ local: false,
2719
+ priorityValue: 9,
2720
+ paths: [join14(homedir2(), ".codeium", "windsurf")],
2721
+ globalPath: join14(homedir2(), ".codeium", "windsurf", "mcp_config.json"),
2722
+ topKey: "mcpServers"
2723
+ });
2724
+ var init_windsurf = __esm(() => {
2725
+ init_base();
2726
+ });
2727
+
2728
+ // src/mcp/providers/zed.ts
2729
+ import { platform as platform2 } from "node:os";
2730
+ import { join as join15 } from "node:path";
2731
+ function zedConfigDir() {
2732
+ const os = platform2();
2733
+ if (os === "darwin" || os === "win32")
2734
+ return join15(appSupportDir(), "Zed");
2735
+ return join15(appSupportDir(), "zed");
2736
+ }
2737
+ var ZedProvider = () => createJSONProvider({
2738
+ providerName: "Zed",
2739
+ providerID: "zed",
2740
+ local: true,
2741
+ priorityValue: 10,
2742
+ paths: [zedConfigDir()],
2743
+ globalPath: join15(zedConfigDir(), "settings.json"),
2744
+ topKey: "context_servers",
2745
+ buildServer: (cfg) => ({
2746
+ source: "custom",
2747
+ type: "http",
2748
+ url: mcpURL(cfg.deployment_id),
2749
+ headers: mcpHeaders(cfg.api_key)
2750
+ }),
2751
+ localConfigPath: (cwd) => join15(cwd, ".zed", "settings.json")
2752
+ });
2753
+ var init_zed = __esm(() => {
2764
2754
  init_config_helpers();
2755
+ init_detect();
2756
+ init_base();
2765
2757
  });
2766
2758
 
2767
2759
  // src/mcp/providers.ts
@@ -2805,21 +2797,21 @@ function getProvider(toolID) {
2805
2797
  return provider;
2806
2798
  }
2807
2799
  var init_providers = __esm(() => {
2800
+ init_antigravity();
2808
2801
  init_claude();
2809
2802
  init_claude_desktop();
2810
- init_cursor();
2811
- init_vscode();
2812
- init_gemini();
2813
- init_codex();
2814
- init_windsurf();
2815
- init_zed();
2816
2803
  init_cline();
2817
2804
  init_cline_cli();
2805
+ init_codex();
2818
2806
  init_copilot();
2819
- init_opencode();
2820
- init_antigravity();
2821
- init_mcporter();
2807
+ init_cursor();
2808
+ init_gemini();
2822
2809
  init_manual();
2810
+ init_mcporter();
2811
+ init_opencode();
2812
+ init_vscode();
2813
+ init_windsurf();
2814
+ init_zed();
2823
2815
  });
2824
2816
 
2825
2817
  // node_modules/sisteransi/src/index.js
@@ -3662,7 +3654,10 @@ class Client {
3662
3654
  const endpoint = `${supabaseURL}/auth/v1/token?grant_type=refresh_token`;
3663
3655
  const resp = await fetch(endpoint, {
3664
3656
  method: "POST",
3665
- headers: { "Content-Type": "application/json" },
3657
+ headers: {
3658
+ "Content-Type": "application/json",
3659
+ apikey: getSupabaseAnonKey()
3660
+ },
3666
3661
  body: JSON.stringify({ refresh_token: this.config.refresh_token })
3667
3662
  });
3668
3663
  if (resp.status !== 200) {
@@ -3754,6 +3749,104 @@ var init_styles = __esm(() => {
3754
3749
  });
3755
3750
 
3756
3751
  // src/auth/server.ts
3752
+ function buildSuccessHtml(email) {
3753
+ const emailLine = email ? `<p class="email">Signed in as <strong>${email.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")}</strong></p>` : "";
3754
+ return `<!DOCTYPE html>
3755
+ <html lang="en">
3756
+ <head>
3757
+ <meta charset="UTF-8">
3758
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
3759
+ <title>Dosu CLI - Authentication Successful</title>
3760
+ <style>
3761
+ * { margin: 0; padding: 0; box-sizing: border-box; }
3762
+ body {
3763
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
3764
+ background: #fafafa;
3765
+ color: #171717;
3766
+ min-height: 100vh;
3767
+ display: flex;
3768
+ align-items: center;
3769
+ justify-content: center;
3770
+ padding: 20px;
3771
+ }
3772
+ .container {
3773
+ max-width: 420px;
3774
+ width: 100%;
3775
+ text-align: center;
3776
+ }
3777
+ .logo {
3778
+ width: 52px;
3779
+ height: 52px;
3780
+ margin: 0 auto 28px;
3781
+ }
3782
+ h1 {
3783
+ font-size: 24px;
3784
+ font-weight: 600;
3785
+ color: #171717;
3786
+ letter-spacing: -0.02em;
3787
+ margin-bottom: 8px;
3788
+ }
3789
+ .subtitle {
3790
+ font-size: 16px;
3791
+ color: #666;
3792
+ margin-bottom: 8px;
3793
+ }
3794
+ .email {
3795
+ font-size: 14px;
3796
+ color: #999;
3797
+ margin-bottom: 28px;
3798
+ }
3799
+ .card {
3800
+ background: #fff;
3801
+ border: 1px solid #eaeaea;
3802
+ border-radius: 8px;
3803
+ padding: 16px 20px;
3804
+ font-size: 16px;
3805
+ color: #666;
3806
+ line-height: 1.5;
3807
+ cursor: pointer;
3808
+ transition: background 0.15s, border-color 0.15s;
3809
+ }
3810
+ .card:hover {
3811
+ background: #f5f5f5;
3812
+ border-color: #ccc;
3813
+ }
3814
+ .close-hint {
3815
+ margin-top: 20px;
3816
+ font-size: 14px;
3817
+ color: #999;
3818
+ }
3819
+ </style>
3820
+ </head>
3821
+ <body>
3822
+ <div class="container">
3823
+ <div class="logo">
3824
+ <svg width="52" height="54" viewBox="0 0 86 89" fill="none" xmlns="http://www.w3.org/2000/svg">
3825
+ <path d="M5.29236 12.7928L17.7593 6.68188V72.5667L5.29236 84.0618V12.7928Z" fill="#B4BB91"/>
3826
+ <path d="M18.2575 73.1196L59.1329 72.748L51.7011 82.4095L29.0338 86.291L6.23962 85.1554L18.2575 73.1196Z" fill="#778561"/>
3827
+ <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"/>
3828
+ <mask id="path-4-inside-1_355_26707" fill="white">
3829
+ <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"/>
3830
+ </mask>
3831
+ <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"/>
3832
+ <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)"/>
3833
+ <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"/>
3834
+ <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"/>
3835
+ </svg>
3836
+ </div>
3837
+ <h1>Authentication Successful</h1>
3838
+ <p class="subtitle">You're all set. The CLI is now authenticated.</p>
3839
+ ${emailLine}
3840
+ <div class="card" onclick="window.close()">Close this tab and return to your terminal.</div>
3841
+ <p class="close-hint">This tab will close automatically in <span id="countdown">10</span>s</p>
3842
+ </div>
3843
+ <script>
3844
+ var s=10,el=document.getElementById('countdown');
3845
+ var t=setInterval(function(){if(--s<=0){clearInterval(t);window.close();}el.textContent=s;},1000);
3846
+ </script>
3847
+ </body>
3848
+ </html>`;
3849
+ }
3757
3850
  async function startCallbackServer() {
3758
3851
  let resolveToken;
3759
3852
  const tokenPromise = new Promise((resolve) => {
@@ -3770,6 +3863,7 @@ async function startCallbackServer() {
3770
3863
  const accessToken = url.searchParams.get("access_token");
3771
3864
  const refreshToken = url.searchParams.get("refresh_token");
3772
3865
  const expiresIn = url.searchParams.get("expires_in");
3866
+ const email = url.searchParams.get("email");
3773
3867
  if (!accessToken) {
3774
3868
  res.writeHead(200, { "Content-Type": "text/html" });
3775
3869
  res.end(CALLBACK_HTML_EXTRACT);
@@ -3778,16 +3872,17 @@ async function startCallbackServer() {
3778
3872
  let expiresInInt = 3600;
3779
3873
  if (expiresIn) {
3780
3874
  const parsed = parseInt(expiresIn, 10);
3781
- if (!isNaN(parsed))
3875
+ if (!Number.isNaN(parsed))
3782
3876
  expiresInInt = parsed;
3783
3877
  }
3784
- resolveToken({
3878
+ resolveToken?.({
3785
3879
  access_token: accessToken,
3786
- refresh_token: refreshToken ?? "",
3787
- expires_in: expiresInInt
3880
+ refresh_token: refreshToken && refreshToken !== "null" ? refreshToken : "",
3881
+ expires_in: expiresInInt,
3882
+ email: email ?? undefined
3788
3883
  });
3789
3884
  res.writeHead(200, { "Content-Type": "text/html" });
3790
- res.end(CALLBACK_HTML_SUCCESS);
3885
+ res.end(buildSuccessHtml(email ?? undefined));
3791
3886
  });
3792
3887
  await new Promise((resolve) => {
3793
3888
  httpServer.listen(0, "localhost", () => resolve());
@@ -3853,75 +3948,18 @@ const hash = window.location.hash.substring(1);
3853
3948
  if (hash) {
3854
3949
  const params = new URLSearchParams(hash);
3855
3950
  const token = params.get('access_token');
3856
- const refresh = params.get('refresh_token');
3857
- const expires = params.get('expires_in');
3951
+ const refresh = params.get('refresh_token') || '';
3952
+ const expires = params.get('expires_in') || '';
3953
+ const email = params.get('email');
3858
3954
  if (token) {
3859
3955
  window.location.href = '/callback?access_token=' + encodeURIComponent(token) +
3860
3956
  '&refresh_token=' + encodeURIComponent(refresh) +
3861
- '&expires_in=' + encodeURIComponent(expires);
3957
+ '&expires_in=' + encodeURIComponent(expires) +
3958
+ (email ? '&email=' + encodeURIComponent(email) : '');
3862
3959
  }
3863
3960
  }
3864
3961
  </script>
3865
3962
  </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
3963
  </html>`;
3926
3964
 
3927
3965
  // node_modules/is-docker/index.js
@@ -4471,33 +4509,39 @@ __export(exports_flow, {
4471
4509
  });
4472
4510
  async function startOAuthFlow(signal) {
4473
4511
  const { server, tokenPromise } = await startCallbackServer();
4512
+ let timeoutId;
4474
4513
  try {
4475
4514
  const callbackURL = `http://localhost:${server.port}/callback`;
4476
4515
  const authURL = buildAuthURL(callbackURL);
4477
4516
  const open2 = await Promise.resolve().then(() => (init_open(), exports_open));
4478
4517
  await open2.default(authURL);
4479
4518
  const timeout = new Promise((_3, reject) => {
4480
- setTimeout(() => reject(new Error("authentication timeout - please try again")), 300000);
4519
+ timeoutId = setTimeout(() => reject(new Error("authentication timeout - please try again")), 300000);
4481
4520
  });
4482
4521
  const abort = signal ? new Promise((_3, reject) => {
4483
4522
  signal.addEventListener("abort", () => reject(new Error("authentication cancelled")));
4484
4523
  }) : new Promise(() => {});
4485
4524
  return await Promise.race([tokenPromise, timeout, abort]);
4486
4525
  } finally {
4526
+ clearTimeout(timeoutId);
4487
4527
  server.close();
4488
4528
  }
4489
4529
  }
4490
4530
  function buildAuthURL(callbackURL) {
4491
4531
  const webAppURL = getWebAppURL();
4492
4532
  const params = new URLSearchParams({ callback: callbackURL });
4493
- return `${webAppURL}/cli-login?${params}`;
4533
+ return `${webAppURL}/cli/auth?${params}`;
4494
4534
  }
4495
4535
  var init_flow = () => {};
4496
4536
 
4497
4537
  // src/setup/flow.ts
4498
4538
  var exports_flow2 = {};
4499
4539
  __export(exports_flow2, {
4500
- runSetup: () => runSetup
4540
+ stepShowSummary: () => stepShowSummary,
4541
+ stepDetectTools: () => stepDetectTools,
4542
+ stepConfigureTools: () => stepConfigureTools,
4543
+ runSetup: () => runSetup,
4544
+ isStdioOnly: () => isStdioOnly
4501
4545
  });
4502
4546
  async function runSetup(opts = {}) {
4503
4547
  Ie("Dosu CLI Setup");
@@ -4553,16 +4597,14 @@ async function stepAuthenticate() {
4553
4597
  s.stop("Authenticated");
4554
4598
  return cfg;
4555
4599
  }
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");
4562
- return cfg;
4563
- }
4564
- } catch {}
4565
- }
4600
+ try {
4601
+ await apiClient.refreshToken();
4602
+ const resp2 = await apiClient.doRequestRaw("GET", "/v1/mcp/deployments");
4603
+ if (resp2.status === 200) {
4604
+ s.stop("Authenticated");
4605
+ return cfg;
4606
+ }
4607
+ } catch {}
4566
4608
  s.stop("Session expired");
4567
4609
  M2.warn("Session expired.");
4568
4610
  } catch {
@@ -4584,7 +4626,7 @@ async function stepAuthenticate() {
4584
4626
  saveConfig(cfg);
4585
4627
  return cfg;
4586
4628
  } catch (err) {
4587
- M2.error(`Authentication failed: ${err.message}`);
4629
+ M2.error(`Authentication failed: ${err instanceof Error ? err.message : String(err)}`);
4588
4630
  return null;
4589
4631
  }
4590
4632
  }
@@ -4609,10 +4651,10 @@ ${dim(orgs[0].name)}`);
4609
4651
  return orgs.find((o2) => o2.org_id === selected) ?? null;
4610
4652
  } catch (err) {
4611
4653
  if (err instanceof SessionExpiredError) {
4612
- M2.warn("Session expired. Please run " + info("dosu setup") + " again.");
4654
+ M2.warn(`Session expired. Please run ${info("dosu setup")} again.`);
4613
4655
  return null;
4614
4656
  }
4615
- M2.error(`Organization selection failed: ${err.message}`);
4657
+ M2.error(`Organization selection failed: ${err instanceof Error ? err.message : String(err)}`);
4616
4658
  return null;
4617
4659
  }
4618
4660
  }
@@ -4628,7 +4670,7 @@ async function stepResolveDeployment(apiClient, id) {
4628
4670
  ${dim(d3.name)}`);
4629
4671
  return d3;
4630
4672
  } catch (err) {
4631
- M2.error(`Failed to resolve deployment: ${err.message}`);
4673
+ M2.error(`Failed to resolve deployment: ${err instanceof Error ? err.message : String(err)}`);
4632
4674
  return null;
4633
4675
  }
4634
4676
  }
@@ -4653,7 +4695,7 @@ ${dim(deployments[0].name)}`);
4653
4695
  return null;
4654
4696
  return deployments.find((d3) => d3.deployment_id === selected) ?? null;
4655
4697
  } catch (err) {
4656
- M2.error(`Deployment selection failed: ${err.message}`);
4698
+ M2.error(`Deployment selection failed: ${err instanceof Error ? err.message : String(err)}`);
4657
4699
  return null;
4658
4700
  }
4659
4701
  }
@@ -4673,7 +4715,7 @@ ${dim("using existing")}`);
4673
4715
  ${dim("created")}`);
4674
4716
  return resp.api_key;
4675
4717
  } catch (err) {
4676
- M2.error(`API key creation failed: ${err.message}`);
4718
+ M2.error(`API key creation failed: ${err instanceof Error ? err.message : String(err)}`);
4677
4719
  return null;
4678
4720
  }
4679
4721
  }
@@ -4689,7 +4731,7 @@ async function stepSelectTools(detected) {
4689
4731
  configuredMap.set(p2.id(), p2.isConfigured());
4690
4732
  }
4691
4733
  const options = detected.map((p2) => {
4692
- const configured = configuredMap.get(p2.id());
4734
+ const configured = configuredMap.get(p2.id()) ?? false;
4693
4735
  return {
4694
4736
  label: configured ? `${p2.name()} ${dim("(already configured)")}` : p2.name(),
4695
4737
  value: p2.id(),
@@ -4708,7 +4750,7 @@ async function stepSelectTools(detected) {
4708
4750
  const result = { toInstall: [], toRemove: [], skipped: [] };
4709
4751
  for (const provider of detected) {
4710
4752
  const isSelected = selectedSet.has(provider.id());
4711
- const isConfigured = configuredMap.get(provider.id());
4753
+ const isConfigured = configuredMap.get(provider.id()) ?? false;
4712
4754
  if (isSelected && !isConfigured)
4713
4755
  result.toInstall.push(provider);
4714
4756
  else if (isSelected && isConfigured)
@@ -4725,8 +4767,9 @@ function stepConfigureTools(cfg, selection) {
4725
4767
  provider.install(cfg, true);
4726
4768
  results.push({ provider, action: "install" });
4727
4769
  } catch (err) {
4728
- M2.error(`Failed to configure ${provider.name()}: ${err.message}`);
4729
- results.push({ provider, action: "install", error: err });
4770
+ const error = err instanceof Error ? err : new Error(String(err));
4771
+ M2.error(`Failed to configure ${provider.name()}: ${error.message}`);
4772
+ results.push({ provider, action: "install", error });
4730
4773
  }
4731
4774
  }
4732
4775
  for (const provider of selection.toRemove) {
@@ -4734,8 +4777,9 @@ function stepConfigureTools(cfg, selection) {
4734
4777
  provider.remove(true);
4735
4778
  results.push({ provider, action: "remove" });
4736
4779
  } catch (err) {
4737
- M2.error(`Failed to remove ${provider.name()}: ${err.message}`);
4738
- results.push({ provider, action: "remove", error: err });
4780
+ const error = err instanceof Error ? err : new Error(String(err));
4781
+ M2.error(`Failed to remove ${provider.name()}: ${error.message}`);
4782
+ results.push({ provider, action: "remove", error });
4739
4783
  }
4740
4784
  }
4741
4785
  for (const provider of selection.skipped) {
@@ -4772,8 +4816,8 @@ ${lines}`);
4772
4816
  }
4773
4817
  var init_flow2 = __esm(() => {
4774
4818
  init_dist2();
4775
- init_config();
4776
4819
  init_client();
4820
+ init_config();
4777
4821
  init_providers();
4778
4822
  init_styles();
4779
4823
  });
@@ -4781,7 +4825,8 @@ var init_flow2 = __esm(() => {
4781
4825
  // src/tui/tui.ts
4782
4826
  var exports_tui = {};
4783
4827
  __export(exports_tui, {
4784
- runTUI: () => runTUI
4828
+ runTUI: () => runTUI,
4829
+ handleLogout: () => handleLogout
4785
4830
  });
4786
4831
  async function runTUI() {
4787
4832
  console.log(import_picocolors3.default.magenta(LOGO));
@@ -4795,10 +4840,26 @@ async function runTUI() {
4795
4840
  const action = await ve({
4796
4841
  message: "What would you like to do?",
4797
4842
  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 },
4843
+ {
4844
+ label: "Authenticate",
4845
+ value: "setup",
4846
+ hint: isAuthenticated(cfg) ? "Re-authenticate" : undefined
4847
+ },
4848
+ {
4849
+ label: "Choose Deployment",
4850
+ value: "deployments",
4851
+ hint: !isAuthenticated(cfg) ? "Login first" : undefined
4852
+ },
4853
+ {
4854
+ label: "Add MCP",
4855
+ value: "mcp-add",
4856
+ hint: !hasDeployment ? "Select deployment first" : undefined
4857
+ },
4858
+ {
4859
+ label: "Remove MCP",
4860
+ value: "mcp-remove",
4861
+ hint: !hasDeployment ? "Select deployment first" : undefined
4862
+ },
4802
4863
  { label: "Clear Credentials", value: "logout" },
4803
4864
  { label: "Exit", value: "exit" }
4804
4865
  ]
@@ -4863,7 +4924,7 @@ async function handleDeployments(cfg) {
4863
4924
  M2.success(`Selected: ${deployment.name}`);
4864
4925
  }
4865
4926
  } catch (err) {
4866
- M2.error(`Failed: ${err.message}`);
4927
+ M2.error(`Failed: ${err instanceof Error ? err.message : String(err)}`);
4867
4928
  }
4868
4929
  }
4869
4930
  async function handleMCPAdd(cfg) {
@@ -4886,10 +4947,10 @@ async function handleMCPAdd(cfg) {
4886
4947
  provider.install(cfg, true);
4887
4948
  M2.success(`Added Dosu MCP to ${provider.name()}`);
4888
4949
  } catch (err) {
4889
- M2.error(`Failed: ${err.message}`);
4950
+ M2.error(`Failed: ${err instanceof Error ? err.message : String(err)}`);
4890
4951
  }
4891
4952
  }
4892
- async function handleMCPRemove(cfg) {
4953
+ async function handleMCPRemove(_cfg) {
4893
4954
  const { allProviders: allProviders2 } = await Promise.resolve().then(() => (init_providers(), exports_providers));
4894
4955
  const providers = allProviders2();
4895
4956
  const selected = await ve({
@@ -4908,7 +4969,7 @@ async function handleMCPRemove(cfg) {
4908
4969
  provider.remove(true);
4909
4970
  M2.success(`Removed Dosu MCP from ${provider.name()}`);
4910
4971
  } catch (err) {
4911
- M2.error(`Failed: ${err.message}`);
4972
+ M2.error(`Failed: ${err instanceof Error ? err.message : String(err)}`);
4912
4973
  }
4913
4974
  }
4914
4975
  function handleLogout(cfg) {
@@ -4937,8 +4998,8 @@ var import_picocolors3, LOGO = `
4937
4998
  `;
4938
4999
  var init_tui = __esm(() => {
4939
5000
  init_dist2();
4940
- init_config();
4941
5001
  init_client();
5002
+ init_config();
4942
5003
  init_flow2();
4943
5004
  import_picocolors3 = __toESM(require_picocolors(), 1);
4944
5005
  });
@@ -4959,17 +5020,19 @@ var {
4959
5020
  Help
4960
5021
  } = import__.default;
4961
5022
 
5023
+ // src/cli/cli.ts
5024
+ init_config();
5025
+ init_providers();
5026
+
4962
5027
  // src/version/version.ts
4963
- var VERSION = "0.1.7";
4964
- var COMMIT = "c622ab4d9ae1a89b6fff2802e9cb475137906971";
4965
- var DATE = "";
5028
+ var VERSION = "0.2.0";
5029
+ var COMMIT = "none";
5030
+ var DATE = "unknown";
4966
5031
  function getVersionString() {
4967
5032
  return `dosu ${VERSION} (${COMMIT}, ${DATE})`;
4968
5033
  }
4969
5034
 
4970
5035
  // src/cli/cli.ts
4971
- init_config();
4972
- init_providers();
4973
5036
  function createProgram() {
4974
5037
  const program2 = new Command;
4975
5038
  program2.name("dosu").description("Dosu CLI - Manage MCP servers for AI tools").version(getVersionString(), "-v, --version").action(async () => {
@@ -5096,6 +5159,7 @@ async function execute() {
5096
5159
  }
5097
5160
 
5098
5161
  // src/index.ts
5162
+ process.on("SIGINT", () => process.exit(0));
5099
5163
  execute().catch((err) => {
5100
5164
  console.error(err.message ?? err);
5101
5165
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dosu/cli",
3
- "version": "0.1.7",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "description": "Dosu CLI - Manage MCP servers for AI tools",
6
6
  "license": "MIT",
@@ -19,20 +19,28 @@
19
19
  "scripts": {
20
20
  "dev": "bun run src/index.ts",
21
21
  "dev:local": "DOSU_DEV=true bun run src/index.ts",
22
- "build": "bun build --compile src/index.ts --outfile bin/dosu",
23
- "build:npm": "bun run scripts/build-npm.ts",
24
- "build:all": "bun run scripts/build-all.ts",
22
+ "build": "bun --env-file=.env.production build --compile --env=DOSU_* --env=SUPABASE_* src/index.ts --outfile bin/dosu",
23
+ "build:npm": "bun --env-file=.env.production run scripts/build-npm.ts",
24
+ "build:all": "bun --env-file=.env.production run scripts/build-all.ts",
25
25
  "test": "bunx vitest run",
26
26
  "test:watch": "bunx vitest",
27
27
  "typecheck": "bunx tsc --noEmit",
28
+ "lint": "bunx biome lint .",
29
+ "format": "bunx biome format .",
30
+ "check": "bunx biome check .",
28
31
  "prepack": "bun run build:npm"
29
32
  },
30
33
  "engines": {
31
34
  "node": ">=18"
32
35
  },
33
36
  "devDependencies": {
37
+ "@biomejs/biome": "^2.4.9",
38
+ "@semantic-release/changelog": "^6.0.3",
39
+ "@semantic-release/exec": "^7.1.0",
40
+ "@semantic-release/git": "^10.0.1",
34
41
  "@types/bun": "^1.3.11",
35
42
  "@vitest/coverage-v8": "^3.2.0",
43
+ "semantic-release": "^25.0.3",
36
44
  "typescript": "^5.8.3",
37
45
  "vitest": "^3.1.1"
38
46
  },