@dosu/cli 0.33.1 → 0.34.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 +433 -255
  2. package/package.json +1 -1
package/bin/dosu.js CHANGED
@@ -2097,18 +2097,95 @@ var init_commander = __esm(() => {
2097
2097
  program = new Command;
2098
2098
  });
2099
2099
 
2100
+ // src/config/identity.ts
2101
+ function getAccessTokenUserID(accessToken) {
2102
+ try {
2103
+ const payload = accessToken.split(".")[1];
2104
+ if (!payload)
2105
+ return;
2106
+ const decoded = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
2107
+ return typeof decoded.sub === "string" && decoded.sub.length > 0 ? decoded.sub : undefined;
2108
+ } catch {
2109
+ return;
2110
+ }
2111
+ }
2112
+
2113
+ // src/config/schema.ts
2114
+ var MODE_OSS = "oss", CONFIG_SCHEMA_VERSION = 2;
2115
+
2116
+ // src/config/config-v1-migration.ts
2117
+ function migrateLegacyConfig(value) {
2118
+ if (!isRecord(value))
2119
+ return { schema_version: CONFIG_SCHEMA_VERSION };
2120
+ const accessToken = stringValue(value.access_token) ?? "";
2121
+ const refreshToken = stringValue(value.refresh_token) ?? "";
2122
+ const expiresAt = numberValue(value.expires_at) ?? 0;
2123
+ const hasSession = Boolean(accessToken || refreshToken || expiresAt);
2124
+ const userID = stringValue(value.user_id) ?? getAccessTokenUserID(accessToken);
2125
+ return {
2126
+ schema_version: CONFIG_SCHEMA_VERSION,
2127
+ mode: value.mode === MODE_OSS ? MODE_OSS : undefined,
2128
+ active_account: hasSession ? {
2129
+ user_id: userID,
2130
+ session: {
2131
+ access_token: accessToken,
2132
+ refresh_token: refreshToken,
2133
+ expires_at: expiresAt
2134
+ },
2135
+ target: userID ? legacyTarget(value) : undefined
2136
+ } : undefined
2137
+ };
2138
+ }
2139
+ function legacyTarget(value) {
2140
+ const target = {
2141
+ deployment_id: stringValue(value.deployment_id),
2142
+ deployment_name: stringValue(value.deployment_name),
2143
+ api_key: stringValue(value.api_key),
2144
+ org_id: stringValue(value.org_id),
2145
+ space_id: stringValue(value.space_id)
2146
+ };
2147
+ return Object.values(target).some((field) => field !== undefined) ? target : undefined;
2148
+ }
2149
+ function isRecord(value) {
2150
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2151
+ }
2152
+ function stringValue(value) {
2153
+ return typeof value === "string" ? value : undefined;
2154
+ }
2155
+ function numberValue(value) {
2156
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
2157
+ }
2158
+ var init_config_v1_migration = () => {};
2159
+
2100
2160
  // src/config/config.ts
2101
2161
  import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2102
2162
  import { join } from "node:path";
2163
+ function getConfigUserID(cfg) {
2164
+ return cfg.active_account?.user_id ?? getAccessTokenUserID(cfg.active_account?.session.access_token ?? "");
2165
+ }
2103
2166
  function replaceLoginSession(cfg, session) {
2104
- cfg.access_token = session.access_token;
2105
- cfg.refresh_token = session.refresh_token;
2106
- cfg.expires_at = session.expires_at;
2107
- cfg.deployment_id = undefined;
2108
- cfg.deployment_name = undefined;
2109
- cfg.api_key = undefined;
2110
- cfg.org_id = undefined;
2111
- cfg.space_id = undefined;
2167
+ const previousUserID = getConfigUserID(cfg);
2168
+ const nextUserID = session.user_id ?? getAccessTokenUserID(session.access_token);
2169
+ const preserveTarget = Boolean(previousUserID && nextUserID && previousUserID === nextUserID);
2170
+ cfg.active_account = {
2171
+ user_id: nextUserID,
2172
+ session: sessionWithoutIdentity(session),
2173
+ target: preserveTarget ? cloneTarget(cfg.active_account?.target) : undefined
2174
+ };
2175
+ }
2176
+ function bindAccountIdentity(cfg, userID) {
2177
+ const account = cfg.active_account;
2178
+ if (!account)
2179
+ throw new Error("cannot bind an identity without an authenticated session");
2180
+ if (account.user_id && account.user_id !== userID)
2181
+ account.target = undefined;
2182
+ account.user_id = userID;
2183
+ }
2184
+ function updateTarget(cfg, target) {
2185
+ if (!cfg.active_account?.user_id) {
2186
+ throw new Error("cannot bind a target without a verified account identity");
2187
+ }
2188
+ cfg.active_account.target = { ...cfg.active_account.target, ...target };
2112
2189
  }
2113
2190
  function getConfigDir() {
2114
2191
  const dirName = process.env.DOSU_DEV === "true" ? "dosu-cli-dev" : "dosu-cli";
@@ -2127,43 +2204,113 @@ function getConfigPath() {
2127
2204
  }
2128
2205
  function loadConfig() {
2129
2206
  const path2 = getConfigPath();
2130
- if (!existsSync(path2)) {
2207
+ if (!existsSync(path2))
2131
2208
  return emptyConfig();
2132
- }
2209
+ let raw;
2133
2210
  try {
2134
- const data = readFileSync(path2, "utf-8");
2135
- return JSON.parse(data);
2211
+ raw = JSON.parse(readFileSync(path2, "utf-8"));
2136
2212
  } catch {
2137
2213
  return emptyConfig();
2138
2214
  }
2215
+ if (isConfigV2(raw))
2216
+ return normalizeV2(raw);
2217
+ if (isRecord2(raw) && "schema_version" in raw)
2218
+ return emptyConfig();
2219
+ const migrated = migrateLegacyConfig(raw);
2220
+ try {
2221
+ writeConfig(path2, migrated);
2222
+ } catch {}
2223
+ return migrated;
2139
2224
  }
2140
2225
  function saveConfig(cfg) {
2141
- const path2 = getConfigPath();
2142
- const dir = getConfigDir();
2143
- if (!existsSync(dir)) {
2144
- mkdirSync(dir, { recursive: true, mode: 448 });
2145
- }
2146
- const tmp = `${path2}.${process.pid}.tmp`;
2147
- writeFileSync(tmp, JSON.stringify(cfg, null, 2), { mode: 384 });
2148
- renameSync(tmp, path2);
2226
+ writeConfig(getConfigPath(), cfg);
2149
2227
  }
2150
2228
  function isAuthenticated(cfg) {
2151
- return cfg.access_token !== "";
2229
+ return Boolean(cfg.active_account?.session.access_token);
2152
2230
  }
2153
2231
  function isTokenExpired(cfg) {
2154
- if (cfg.expires_at === 0)
2232
+ const expiresAt = cfg.active_account?.session.expires_at ?? 0;
2233
+ if (expiresAt === 0)
2155
2234
  return false;
2156
- return Math.floor(Date.now() / 1000) > cfg.expires_at - 300;
2235
+ return Math.floor(Date.now() / 1000) > expiresAt - 300;
2236
+ }
2237
+ function clearConfigInPlace(cfg) {
2238
+ cfg.mode = undefined;
2239
+ cfg.active_account = undefined;
2157
2240
  }
2158
2241
  function emptyConfig() {
2242
+ return { schema_version: CONFIG_SCHEMA_VERSION };
2243
+ }
2244
+ function sessionWithoutIdentity(session) {
2245
+ return {
2246
+ access_token: session.access_token,
2247
+ refresh_token: session.refresh_token,
2248
+ expires_at: session.expires_at
2249
+ };
2250
+ }
2251
+ function cloneTarget(target) {
2252
+ return target ? { ...target } : undefined;
2253
+ }
2254
+ function isConfigV2(value) {
2255
+ return isRecord2(value) && value.schema_version === CONFIG_SCHEMA_VERSION;
2256
+ }
2257
+ function normalizeV2(value) {
2258
+ const active = isRecord2(value.active_account) ? value.active_account : undefined;
2259
+ const session = active && isRecord2(active.session) ? active.session : undefined;
2260
+ if (!active || !session) {
2261
+ return {
2262
+ schema_version: CONFIG_SCHEMA_VERSION,
2263
+ mode: value.mode === MODE_OSS ? MODE_OSS : undefined
2264
+ };
2265
+ }
2266
+ const accessToken = stringValue2(session.access_token) ?? "";
2267
+ const userID = stringValue2(active.user_id) ?? getAccessTokenUserID(accessToken);
2159
2268
  return {
2160
- access_token: "",
2161
- refresh_token: "",
2162
- expires_at: 0
2269
+ schema_version: CONFIG_SCHEMA_VERSION,
2270
+ mode: value.mode === MODE_OSS ? MODE_OSS : undefined,
2271
+ active_account: {
2272
+ user_id: userID,
2273
+ session: {
2274
+ access_token: accessToken,
2275
+ refresh_token: stringValue2(session.refresh_token) ?? "",
2276
+ expires_at: numberValue2(session.expires_at) ?? 0
2277
+ },
2278
+ target: userID ? normalizeTarget(active.target) : undefined
2279
+ }
2280
+ };
2281
+ }
2282
+ function normalizeTarget(value) {
2283
+ if (!isRecord2(value))
2284
+ return;
2285
+ const target = {
2286
+ deployment_id: stringValue2(value.deployment_id),
2287
+ deployment_name: stringValue2(value.deployment_name),
2288
+ api_key: stringValue2(value.api_key),
2289
+ org_id: stringValue2(value.org_id),
2290
+ space_id: stringValue2(value.space_id)
2163
2291
  };
2292
+ return Object.values(target).some((field) => field !== undefined) ? target : undefined;
2293
+ }
2294
+ function writeConfig(path2, config) {
2295
+ const dir = getConfigDir();
2296
+ if (!existsSync(dir))
2297
+ mkdirSync(dir, { recursive: true, mode: 448 });
2298
+ const tmp = `${path2}.${process.pid}.tmp`;
2299
+ writeFileSync(tmp, JSON.stringify(config, null, 2), { mode: 384 });
2300
+ renameSync(tmp, path2);
2164
2301
  }
2165
- var MODE_OSS = "oss";
2166
- var init_config = () => {};
2302
+ function isRecord2(value) {
2303
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2304
+ }
2305
+ function stringValue2(value) {
2306
+ return typeof value === "string" ? value : undefined;
2307
+ }
2308
+ function numberValue2(value) {
2309
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
2310
+ }
2311
+ var init_config = __esm(() => {
2312
+ init_config_v1_migration();
2313
+ });
2167
2314
 
2168
2315
  // src/config/constants.ts
2169
2316
  function getWebAppURL() {
@@ -2218,7 +2365,7 @@ class Client {
2218
2365
  const url = this.baseURL + path2;
2219
2366
  const headers = {
2220
2367
  "Content-Type": "application/json",
2221
- "Supabase-Access-Token": this.config.access_token
2368
+ "Supabase-Access-Token": this.config.active_account?.session.access_token ?? ""
2222
2369
  };
2223
2370
  const options = { method, headers };
2224
2371
  if (body !== undefined) {
@@ -2252,13 +2399,13 @@ class Client {
2252
2399
  return this.apiKeyRequest("POST", path2, body);
2253
2400
  }
2254
2401
  async apiKeyRequest(method, path2, body) {
2255
- if (!this.config.api_key) {
2402
+ if (!this.config.active_account?.target?.api_key) {
2256
2403
  throw new Error("no API key available");
2257
2404
  }
2258
2405
  const url = this.baseURL + path2;
2259
2406
  const headers = {
2260
2407
  "Content-Type": "application/json",
2261
- "X-Dosu-API-Key": this.config.api_key
2408
+ "X-Dosu-API-Key": this.config.active_account?.target?.api_key
2262
2409
  };
2263
2410
  const options = { method, headers };
2264
2411
  if (body !== undefined) {
@@ -2275,7 +2422,7 @@ class Client {
2275
2422
  }
2276
2423
  async refreshToken() {
2277
2424
  this.adoptNewerDiskTokens();
2278
- if (!this.config.refresh_token) {
2425
+ if (!this.config.active_account?.session.refresh_token) {
2279
2426
  throw new Error("no refresh token available");
2280
2427
  }
2281
2428
  try {
@@ -2289,15 +2436,21 @@ class Client {
2289
2436
  }
2290
2437
  adoptNewerDiskTokens() {
2291
2438
  const disk = loadConfig();
2292
- if (!disk.refresh_token || disk.refresh_token === this.config.refresh_token) {
2439
+ this.assertSameActiveAccount(disk);
2440
+ const diskSession = disk.active_account?.session;
2441
+ const memorySession = this.config.active_account?.session;
2442
+ if (!diskSession?.refresh_token || !memorySession || diskSession.refresh_token === memorySession.refresh_token) {
2293
2443
  return false;
2294
2444
  }
2295
- this.config.access_token = disk.access_token;
2296
- this.config.refresh_token = disk.refresh_token;
2297
- this.config.expires_at = disk.expires_at;
2445
+ memorySession.access_token = diskSession.access_token;
2446
+ memorySession.refresh_token = diskSession.refresh_token;
2447
+ memorySession.expires_at = diskSession.expires_at;
2298
2448
  return true;
2299
2449
  }
2300
2450
  async refreshTokenOnce() {
2451
+ const session = this.config.active_account?.session;
2452
+ if (!session?.refresh_token)
2453
+ throw new Error("no refresh token available");
2301
2454
  const supabaseURL = getSupabaseURL();
2302
2455
  const endpoint = `${supabaseURL}/auth/v1/token?grant_type=refresh_token`;
2303
2456
  const resp = await fetch(endpoint, {
@@ -2306,17 +2459,25 @@ class Client {
2306
2459
  "Content-Type": "application/json",
2307
2460
  apikey: getSupabaseAnonKey()
2308
2461
  },
2309
- body: JSON.stringify({ refresh_token: this.config.refresh_token })
2462
+ body: JSON.stringify({ refresh_token: session.refresh_token })
2310
2463
  });
2311
2464
  if (resp.status !== 200) {
2312
2465
  throw new Error(`refresh failed with status ${resp.status}`);
2313
2466
  }
2314
2467
  const data = await resp.json();
2315
- this.config.access_token = data.access_token;
2316
- this.config.refresh_token = data.refresh_token;
2317
- this.config.expires_at = Math.floor(Date.now() / 1000) + data.expires_in;
2468
+ this.assertSameActiveAccount(loadConfig());
2469
+ session.access_token = data.access_token;
2470
+ session.refresh_token = data.refresh_token;
2471
+ session.expires_at = Math.floor(Date.now() / 1000) + data.expires_in;
2318
2472
  saveConfig(this.config);
2319
2473
  }
2474
+ assertSameActiveAccount(disk) {
2475
+ const memoryUserID = getConfigUserID(this.config);
2476
+ const diskUserID = getConfigUserID(disk);
2477
+ if (memoryUserID && diskUserID && memoryUserID !== diskUserID) {
2478
+ throw new Error("authenticated account changed while this command was running; retry it");
2479
+ }
2480
+ }
2320
2481
  async getDeployments() {
2321
2482
  const resp = await this.get("/v1/mcp/deployments");
2322
2483
  if (resp.status !== 200) {
@@ -4587,7 +4748,7 @@ var init_dist4 = __esm(() => {
4587
4748
  function getVersionString() {
4588
4749
  return `v${VERSION}`;
4589
4750
  }
4590
- var VERSION = "0.33.1", INSTALL_CHANNEL = "npm";
4751
+ var VERSION = "0.34.0", INSTALL_CHANNEL = "npm";
4591
4752
 
4592
4753
  // src/debug/logger.ts
4593
4754
  import {
@@ -4733,7 +4894,7 @@ function createTypedClient(config) {
4733
4894
  if (!webAppURL) {
4734
4895
  throw new Error("Web app URL not configured");
4735
4896
  }
4736
- if (!config.access_token) {
4897
+ if (!config.active_account?.session.access_token) {
4737
4898
  throw new Error("Not authenticated. Run 'dosu login' first.");
4738
4899
  }
4739
4900
  const httpClient = new Client(config);
@@ -4752,7 +4913,7 @@ function createTypedClient(config) {
4752
4913
  }
4753
4914
  }
4754
4915
  return {
4755
- "Supabase-Access-Token": config.access_token,
4916
+ "Supabase-Access-Token": config.active_account?.session.access_token ?? "",
4756
4917
  "x-dosu-cli-contract": CLI_CONTRACT_HASH
4757
4918
  };
4758
4919
  },
@@ -4769,7 +4930,7 @@ function createTypedClient(config) {
4769
4930
  ...options,
4770
4931
  headers: {
4771
4932
  ...options?.headers,
4772
- "Supabase-Access-Token": config.access_token,
4933
+ "Supabase-Access-Token": config.active_account?.session.access_token ?? "",
4773
4934
  "x-dosu-cli-contract": CLI_CONTRACT_HASH
4774
4935
  }
4775
4936
  });
@@ -7863,12 +8024,12 @@ async function deleteOrphanDeployment(trpc, deploymentID, slug) {
7863
8024
  }
7864
8025
  async function stepConnectGitHubRepo(cfg, detected = detectGitRepo(), opts = {}) {
7865
8026
  logger.info("setup", "Step: connect GitHub repo(s)");
7866
- if (!cfg.org_id || !cfg.space_id) {
8027
+ if (!cfg.active_account?.target?.org_id || !cfg.active_account?.target?.space_id) {
7867
8028
  log.warn("Cannot connect GitHub: your Dosu workspace is missing org/space context. Re-run `dosu setup` from a fresh state.");
7868
8029
  return { advance: false, has_connected_repo: false };
7869
8030
  }
7870
- const orgID = cfg.org_id;
7871
- const spaceID = cfg.space_id;
8031
+ const orgID = cfg.active_account?.target?.org_id;
8032
+ const spaceID = cfg.active_account?.target?.space_id;
7872
8033
  if (detected) {
7873
8034
  log.info(`Connecting GitHub repos (detected local repo: ${detected.slug})`);
7874
8035
  }
@@ -7972,7 +8133,7 @@ ${dim(`deployment ${deployment_id}`)}`);
7972
8133
  advance: true,
7973
8134
  has_connected_repo: true,
7974
8135
  deployment_id: primary.deployment_id,
7975
- space_id: cfg.space_id,
8136
+ space_id: cfg.active_account?.target?.space_id,
7976
8137
  created_data_source_ids: survived.map((c3) => c3.data_source_id),
7977
8138
  created_repository_slugs: survived.map((c3) => c3.slug)
7978
8139
  };
@@ -9105,10 +9266,10 @@ async function buildInsights({
9105
9266
  now = () => new Date,
9106
9267
  onProgress
9107
9268
  }) {
9108
- if (!cfg.space_id) {
9269
+ if (!cfg.active_account?.target?.space_id) {
9109
9270
  throw new Error("space_id missing. Run 'dosu setup' first");
9110
9271
  }
9111
- const spaceId = cfg.space_id;
9272
+ const spaceId = cfg.active_account?.target?.space_id;
9112
9273
  onProgress?.("stats");
9113
9274
  const [currentRaw, combinedRaw] = await Promise.all([
9114
9275
  client.analytics.getUsageStats.query({ spaceId, days: windowDays }),
@@ -9127,7 +9288,7 @@ async function buildInsights({
9127
9288
  return {
9128
9289
  generatedAt: now().toISOString(),
9129
9290
  windowDays,
9130
- spaceName: cfg.deployment_name ?? "your space",
9291
+ spaceName: cfg.active_account?.target?.deployment_name ?? "your space",
9131
9292
  current,
9132
9293
  previous,
9133
9294
  derived,
@@ -10399,13 +10560,13 @@ var init_detect = () => {};
10399
10560
  function createJSONProvider(opts) {
10400
10561
  const defaultBuildServer = (cfg) => ({
10401
10562
  type: "http",
10402
- url: mcpURL(cfg.deployment_id),
10403
- headers: mcpHeaders(cfg.api_key)
10563
+ url: mcpURL(cfg.active_account.target.deployment_id),
10564
+ headers: mcpHeaders(cfg.active_account?.target?.api_key)
10404
10565
  });
10405
10566
  const defaultBuildOSSServer = (cfg) => ({
10406
10567
  type: "http",
10407
10568
  url: mcpBaseURL(),
10408
- headers: mcpHeaders(cfg.api_key)
10569
+ headers: mcpHeaders(cfg.active_account?.target?.api_key)
10409
10570
  });
10410
10571
  const buildServer = opts.buildServer ?? defaultBuildServer;
10411
10572
  return {
@@ -10418,7 +10579,7 @@ function createJSONProvider(opts) {
10418
10579
  globalConfigPath: () => expandHome(opts.globalPath),
10419
10580
  isConfigured: () => isJSONKeyConfigured(expandHome(opts.globalPath), opts.topKey),
10420
10581
  install(cfg, global) {
10421
- if (cfg.mode !== MODE_OSS && !cfg.deployment_id)
10582
+ if (cfg.mode !== MODE_OSS && !cfg.active_account?.target?.deployment_id)
10422
10583
  throw new Error("deployment ID is required");
10423
10584
  let configPath;
10424
10585
  if (global) {
@@ -10460,8 +10621,8 @@ var AntigravityProvider = () => createJSONProvider({
10460
10621
  globalPath: "~/.gemini/antigravity/mcp_config.json",
10461
10622
  topKey: "mcpServers",
10462
10623
  buildServer: (cfg) => ({
10463
- serverUrl: mcpURL(cfg.deployment_id),
10464
- headers: mcpHeaders(cfg.api_key)
10624
+ serverUrl: mcpURL(cfg.active_account.target.deployment_id),
10625
+ headers: mcpHeaders(cfg.active_account.target.api_key)
10465
10626
  })
10466
10627
  });
10467
10628
  var init_antigravity = __esm(() => {
@@ -10518,10 +10679,10 @@ var extensionDir = () => join14(appSupportDir(), "Code", "User", "globalStorage"
10518
10679
  globalPath: join14(extensionDir(), "settings", "cline_mcp_settings.json"),
10519
10680
  topKey: "mcpServers",
10520
10681
  buildServer: (cfg) => ({
10521
- url: mcpURL(cfg.deployment_id),
10682
+ url: mcpURL(cfg.active_account.target.deployment_id),
10522
10683
  type: "streamableHttp",
10523
10684
  disabled: false,
10524
- headers: mcpHeaders(cfg.api_key)
10685
+ headers: mcpHeaders(cfg.active_account.target.api_key)
10525
10686
  })
10526
10687
  });
10527
10688
  var init_cline = __esm(() => {
@@ -10544,10 +10705,10 @@ var ClineCliProvider = () => createJSONProvider({
10544
10705
  globalPath: join15(clineDir(), "data", "settings", "cline_mcp_settings.json"),
10545
10706
  topKey: "mcpServers",
10546
10707
  buildServer: (cfg) => ({
10547
- url: mcpURL(cfg.deployment_id),
10708
+ url: mcpURL(cfg.active_account.target.deployment_id),
10548
10709
  type: "streamableHttp",
10549
10710
  disabled: false,
10550
- headers: mcpHeaders(cfg.api_key)
10711
+ headers: mcpHeaders(cfg.active_account.target.api_key)
10551
10712
  })
10552
10713
  });
10553
10714
  var init_cline_cli = __esm(() => {
@@ -10578,15 +10739,15 @@ function writeTOML(path3, content) {
10578
10739
  function mcpEndpoint(cfg) {
10579
10740
  if (cfg.mode === MODE_OSS)
10580
10741
  return mcpBaseURL();
10581
- if (!cfg.deployment_id)
10742
+ if (!cfg.active_account?.target?.deployment_id)
10582
10743
  throw new Error("deployment ID is required");
10583
- return mcpURL(cfg.deployment_id);
10744
+ return mcpURL(cfg.active_account?.target?.deployment_id);
10584
10745
  }
10585
10746
  function installDosuToTOML(path3, cfg) {
10586
10747
  let content = readTOML(path3);
10587
10748
  content = removeDosuFromTOML(content);
10588
10749
  const url = mcpEndpoint(cfg);
10589
- const headers = mcpHeaders(cfg.api_key);
10750
+ const headers = mcpHeaders(cfg.active_account?.target?.api_key);
10590
10751
  const headerEntries = Object.entries(headers).map(([k, v]) => `${k} = "${v}"`).join(`
10591
10752
  `);
10592
10753
  const section = `
@@ -10634,7 +10795,7 @@ var CodexProvider = () => ({
10634
10795
  return content.includes("[mcp_servers.dosu]");
10635
10796
  },
10636
10797
  install(cfg, global) {
10637
- if (cfg.mode !== MODE_OSS && !cfg.deployment_id)
10798
+ if (cfg.mode !== MODE_OSS && !cfg.active_account?.target?.deployment_id)
10638
10799
  throw new Error("deployment ID is required");
10639
10800
  installDosuToTOML(getConfigPath2(global), cfg);
10640
10801
  },
@@ -10662,9 +10823,9 @@ function globalPath() {
10662
10823
  function mcpEndpoint2(cfg) {
10663
10824
  if (cfg.mode === MODE_OSS)
10664
10825
  return mcpBaseURL();
10665
- if (!cfg.deployment_id)
10826
+ if (!cfg.active_account?.target?.deployment_id)
10666
10827
  throw new Error("deployment ID is required");
10667
- return mcpURL(cfg.deployment_id);
10828
+ return mcpURL(cfg.active_account?.target?.deployment_id);
10668
10829
  }
10669
10830
  var CopilotProvider = () => ({
10670
10831
  name: () => "GitHub Copilot CLI",
@@ -10682,7 +10843,7 @@ var CopilotProvider = () => ({
10682
10843
  type: "http",
10683
10844
  url,
10684
10845
  tools: ["*"],
10685
- headers: mcpHeaders(cfg.api_key)
10846
+ headers: mcpHeaders(cfg.active_account.target.api_key)
10686
10847
  };
10687
10848
  installJSONServer(globalPath(), "mcpServers", server);
10688
10849
  } else {
@@ -10690,7 +10851,7 @@ var CopilotProvider = () => ({
10690
10851
  const server = {
10691
10852
  type: "http",
10692
10853
  url,
10693
- headers: mcpHeaders(cfg.api_key)
10854
+ headers: mcpHeaders(cfg.active_account.target.api_key)
10694
10855
  };
10695
10856
  installJSONServer(configPath, "servers", server);
10696
10857
  }
@@ -10721,8 +10882,8 @@ var CursorProvider = () => createJSONProvider({
10721
10882
  globalPath: "~/.cursor/mcp.json",
10722
10883
  topKey: "mcpServers",
10723
10884
  buildServer: (cfg) => ({
10724
- url: mcpURL(cfg.deployment_id),
10725
- headers: mcpHeaders(cfg.api_key)
10885
+ url: mcpURL(cfg.active_account.target.deployment_id),
10886
+ headers: mcpHeaders(cfg.active_account.target.api_key)
10726
10887
  }),
10727
10888
  localConfigPath: (cwd) => join18(cwd, ".cursor", "mcp.json")
10728
10889
  });
@@ -10767,9 +10928,9 @@ var init_gemini = __esm(() => {
10767
10928
  function mcpEndpoint3(cfg) {
10768
10929
  if (cfg.mode === MODE_OSS)
10769
10930
  return mcpBaseURL();
10770
- if (!cfg.deployment_id)
10931
+ if (!cfg.active_account?.target?.deployment_id)
10771
10932
  throw new Error("deployment ID is required");
10772
- return mcpURL(cfg.deployment_id);
10933
+ return mcpURL(cfg.active_account?.target?.deployment_id);
10773
10934
  }
10774
10935
  function maskSecret(secret) {
10775
10936
  if (secret.length <= 8)
@@ -10783,7 +10944,7 @@ var ManualProvider = () => ({
10783
10944
  supportsLocal: () => false,
10784
10945
  install(cfg, _global, opts = {}) {
10785
10946
  const url = mcpEndpoint3(cfg);
10786
- const apiKey = mcpHeaders(cfg.api_key)["X-Dosu-API-Key"];
10947
+ const apiKey = mcpHeaders(cfg.active_account?.target?.api_key)["X-Dosu-API-Key"];
10787
10948
  const headerValue = opts.showSecret ? apiKey : maskSecret(apiKey);
10788
10949
  console.log("Use these details to configure the Dosu MCP server in your client:");
10789
10950
  console.log();
@@ -10821,9 +10982,9 @@ function resolveGlobalConfigPath() {
10821
10982
  function mcpEndpoint4(cfg) {
10822
10983
  if (cfg.mode === MODE_OSS)
10823
10984
  return mcpBaseURL();
10824
- if (!cfg.deployment_id)
10985
+ if (!cfg.active_account?.target?.deployment_id)
10825
10986
  throw new Error("deployment ID is required");
10826
- return mcpURL(cfg.deployment_id);
10987
+ return mcpURL(cfg.active_account?.target?.deployment_id);
10827
10988
  }
10828
10989
  var MCPorterProvider = () => ({
10829
10990
  name: () => "MCPorter",
@@ -10839,7 +11000,7 @@ var MCPorterProvider = () => ({
10839
11000
  const server = {
10840
11001
  type: "http",
10841
11002
  url: mcpEndpoint4(cfg),
10842
- headers: mcpHeaders(cfg.api_key)
11003
+ headers: mcpHeaders(cfg.active_account.target.api_key)
10843
11004
  };
10844
11005
  installJSONServer(configPath, "mcpServers", server);
10845
11006
  },
@@ -10866,9 +11027,9 @@ var OpenCodeProvider = () => createJSONProvider({
10866
11027
  topKey: "mcp",
10867
11028
  buildServer: (cfg) => ({
10868
11029
  type: "remote",
10869
- url: mcpURL(cfg.deployment_id),
11030
+ url: mcpURL(cfg.active_account.target.deployment_id),
10870
11031
  enabled: true,
10871
- headers: mcpHeaders(cfg.api_key)
11032
+ headers: mcpHeaders(cfg.active_account.target.api_key)
10872
11033
  }),
10873
11034
  localConfigPath: (cwd) => join22(cwd, "opencode.json")
10874
11035
  });
@@ -10930,8 +11091,8 @@ var ZedProvider = () => createJSONProvider({
10930
11091
  buildServer: (cfg) => ({
10931
11092
  source: "custom",
10932
11093
  type: "http",
10933
- url: mcpURL(cfg.deployment_id),
10934
- headers: mcpHeaders(cfg.api_key)
11094
+ url: mcpURL(cfg.active_account.target.deployment_id),
11095
+ headers: mcpHeaders(cfg.active_account.target.api_key)
10935
11096
  }),
10936
11097
  localConfigPath: (cwd) => join25(cwd, ".zed", "settings.json")
10937
11098
  });
@@ -11147,7 +11308,7 @@ var init_agents_md_step = __esm(() => {
11147
11308
 
11148
11309
  // src/setup/analytics.ts
11149
11310
  async function trackCliOnboardingEvent(cfg, onboardingRunID, event, properties = {}) {
11150
- if (!cfg.access_token)
11311
+ if (!cfg.active_account?.session.access_token)
11151
11312
  return;
11152
11313
  try {
11153
11314
  const trpc = createTypedClient(cfg);
@@ -11171,7 +11332,7 @@ async function trackCliOnboardingPreAuthEvent(onboardingRunID, event, properties
11171
11332
  event,
11172
11333
  onboarding_run_id: onboardingRunID,
11173
11334
  properties: {
11174
- ...baseProperties({ access_token: "", refresh_token: "", expires_at: 0 }),
11335
+ ...baseProperties(emptyConfig()),
11175
11336
  ...properties
11176
11337
  }
11177
11338
  }), TRACKING_TIMEOUT_MS);
@@ -11186,9 +11347,9 @@ function baseProperties(cfg) {
11186
11347
  platform: process.platform,
11187
11348
  arch: process.arch,
11188
11349
  mode: cfg.mode ?? "cloud",
11189
- org_id: cfg.org_id,
11190
- deployment_id: cfg.deployment_id,
11191
- space_id: cfg.space_id
11350
+ org_id: cfg.active_account?.target?.org_id,
11351
+ deployment_id: cfg.active_account?.target?.deployment_id,
11352
+ space_id: cfg.active_account?.target?.space_id
11192
11353
  };
11193
11354
  }
11194
11355
  function createAnonymousClient() {
@@ -11227,6 +11388,7 @@ var init_analytics = __esm(() => {
11227
11388
  init_dist();
11228
11389
  init_dist4();
11229
11390
  init_trpc();
11391
+ init_config();
11230
11392
  init_logger();
11231
11393
  });
11232
11394
 
@@ -11798,7 +11960,7 @@ async function runSetup(opts = {}) {
11798
11960
  });
11799
11961
  return;
11800
11962
  }
11801
- } else if (!cfg.deployment_id || opts.deploymentID) {
11963
+ } else if (!cfg.active_account?.target?.deployment_id || opts.deploymentID) {
11802
11964
  const ok = await resolveDeployment(apiClient, cfg, opts);
11803
11965
  if (!ok) {
11804
11966
  await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
@@ -11814,7 +11976,7 @@ async function runSetup(opts = {}) {
11814
11976
  });
11815
11977
  return;
11816
11978
  }
11817
- cfg.api_key = apiKey;
11979
+ updateTarget(cfg, { api_key: apiKey });
11818
11980
  saveConfig(cfg);
11819
11981
  const choices = await stepOneShotConfirm(inGitWorkTree());
11820
11982
  if (!choices) {
@@ -11880,10 +12042,12 @@ async function runSetup(opts = {}) {
11880
12042
  }
11881
12043
  }
11882
12044
  function applyDeployment(cfg, d) {
11883
- cfg.deployment_id = d.deployment_id;
11884
- cfg.deployment_name = d.name;
11885
- cfg.org_id = d.org_id;
11886
- cfg.space_id = d.space_id;
12045
+ updateTarget(cfg, {
12046
+ deployment_id: d.deployment_id,
12047
+ deployment_name: d.name,
12048
+ org_id: d.org_id,
12049
+ space_id: d.space_id
12050
+ });
11887
12051
  }
11888
12052
  function applyModeOverride(cfg, opts) {
11889
12053
  if (!opts.mode)
@@ -11956,7 +12120,7 @@ async function runInstallSkill() {
11956
12120
  async function stepAuthenticate(existingCfg, onboardingRunID) {
11957
12121
  logger.info("setup", "Step: authenticate");
11958
12122
  const cfg = existingCfg ?? loadConfig();
11959
- if (cfg.access_token) {
12123
+ if (cfg.active_account?.session.access_token) {
11960
12124
  const s = spinner();
11961
12125
  s.start("Verifying session...");
11962
12126
  try {
@@ -12084,6 +12248,8 @@ async function resolveCloudSetupContext(cfg) {
12084
12248
  log.error("Could not load your profile.");
12085
12249
  return null;
12086
12250
  }
12251
+ bindAccountIdentity(cfg, profile.user_id);
12252
+ saveConfig(cfg);
12087
12253
  if (profile.finished_onboarding === true) {
12088
12254
  return {
12089
12255
  kind: "setup",
@@ -12119,7 +12285,13 @@ async function resolveOnboardingTargetOrg(trpc) {
12119
12285
  async function resolveCurrentOnboardingTargetOrg(cfg) {
12120
12286
  try {
12121
12287
  const { createTypedClient: createTypedClient2 } = await Promise.resolve().then(() => (init_trpc(), exports_trpc));
12122
- return await resolveOnboardingTargetOrg(createTypedClient2(cfg));
12288
+ const trpc = createTypedClient2(cfg);
12289
+ const profile = await trpc.user.getCliOnboardingContext.query();
12290
+ if (!profile?.user_id)
12291
+ return null;
12292
+ bindAccountIdentity(cfg, profile.user_id);
12293
+ saveConfig(cfg);
12294
+ return await resolveOnboardingTargetOrg(trpc);
12123
12295
  } catch (err) {
12124
12296
  const msg = err instanceof Error ? err.message : String(err);
12125
12297
  logger.error("setup", `Failed to resolve post-onboarding organization: ${msg}`);
@@ -12262,22 +12434,24 @@ ${dim(deployments[0].name)}`);
12262
12434
  }
12263
12435
  }
12264
12436
  async function stepMintAPIKey(apiClient, cfg) {
12265
- if (!cfg.deployment_id) {
12437
+ const target = cfg.active_account?.target;
12438
+ const deploymentID = target?.deployment_id;
12439
+ if (!deploymentID) {
12266
12440
  log.error("No MCP available for API key creation");
12267
12441
  return null;
12268
12442
  }
12269
- if (cfg.api_key) {
12270
- const valid = await apiClient.validateAPIKey(cfg.api_key, cfg.deployment_id);
12443
+ if (target.api_key) {
12444
+ const valid = await apiClient.validateAPIKey(target.api_key, deploymentID);
12271
12445
  logger.debug("setup", `Existing API key valid=${valid}`);
12272
12446
  if (valid) {
12273
12447
  log.success(`API key
12274
12448
  ${dim("using existing")}`);
12275
- return cfg.api_key;
12449
+ return target.api_key;
12276
12450
  }
12277
12451
  log.warn("Existing API key is invalid, creating a new one...");
12278
12452
  }
12279
12453
  try {
12280
- const resp = await apiClient.createAPIKey(cfg.deployment_id, "dosu-cli");
12454
+ const resp = await apiClient.createAPIKey(deploymentID, "dosu-cli");
12281
12455
  logger.info("setup", "API key created");
12282
12456
  log.success(`API key
12283
12457
  ${dim("created")}`);
@@ -12443,13 +12617,13 @@ function createDotsSpinner() {
12443
12617
  };
12444
12618
  }
12445
12619
  function isFullConfig(cfg) {
12446
- return Boolean(cfg.access_token && cfg.api_key && cfg.space_id && cfg.deployment_id);
12620
+ return Boolean(cfg.active_account?.session.access_token && cfg.active_account?.target?.api_key && cfg.active_account?.target?.space_id && cfg.active_account?.target?.deployment_id);
12447
12621
  }
12448
12622
  async function ensureFullConfig() {
12449
12623
  let cfg = loadConfig();
12450
12624
  if (isFullConfig(cfg))
12451
12625
  return cfg;
12452
- const reason = !cfg.access_token ? "Insights needs you to log in first." : "Insights needs a configured Dosu deployment.";
12626
+ const reason = !cfg.active_account?.session.access_token ? "Insights needs you to log in first." : "Insights needs a configured Dosu deployment.";
12453
12627
  log.warn(reason);
12454
12628
  const shouldSetup = await confirm({
12455
12629
  message: "Run setup now?",
@@ -12475,10 +12649,10 @@ function makeAskFn(cfg) {
12475
12649
  method: "POST",
12476
12650
  headers: {
12477
12651
  "Content-Type": "application/json",
12478
- "X-Dosu-API-Key": cfg.api_key
12652
+ "X-Dosu-API-Key": cfg.active_account.target.api_key
12479
12653
  },
12480
12654
  body: JSON.stringify({
12481
- deployment_id: cfg.deployment_id,
12655
+ deployment_id: cfg.active_account.target.deployment_id,
12482
12656
  question
12483
12657
  }),
12484
12658
  signal: controller.signal
@@ -12667,7 +12841,7 @@ async function runTUI() {
12667
12841
  console.log(import_picocolors25.default.magenta(LOGO));
12668
12842
  const cfg = loadConfig();
12669
12843
  while (true) {
12670
- const insightsReady = Boolean(cfg.space_id && cfg.deployment_id && cfg.api_key);
12844
+ const insightsReady = Boolean(cfg.active_account?.target?.space_id && cfg.active_account?.target?.deployment_id && cfg.active_account?.target?.api_key);
12671
12845
  const options = [
12672
12846
  {
12673
12847
  label: "Setup",
@@ -12700,7 +12874,11 @@ async function runTUI() {
12700
12874
  break;
12701
12875
  case "setup":
12702
12876
  await runSetup();
12703
- Object.assign(cfg, loadConfig());
12877
+ {
12878
+ const fresh = loadConfig();
12879
+ cfg.mode = fresh.mode;
12880
+ cfg.active_account = fresh.active_account;
12881
+ }
12704
12882
  break;
12705
12883
  case "insights":
12706
12884
  await executeInsights(cfg);
@@ -12713,7 +12891,7 @@ async function runTUI() {
12713
12891
  outro("Goodbye!");
12714
12892
  }
12715
12893
  async function handleAuthenticate(cfg) {
12716
- if (cfg.access_token) {
12894
+ if (cfg.active_account?.session.access_token) {
12717
12895
  const s = spinner();
12718
12896
  s.start("Verifying session...");
12719
12897
  try {
@@ -12770,13 +12948,7 @@ function handleLogout(cfg) {
12770
12948
  log.warn("You are not logged in.");
12771
12949
  return;
12772
12950
  }
12773
- cfg.access_token = "";
12774
- cfg.refresh_token = "";
12775
- cfg.expires_at = 0;
12776
- cfg.mode = undefined;
12777
- cfg.deployment_id = undefined;
12778
- cfg.deployment_name = undefined;
12779
- cfg.api_key = undefined;
12951
+ clearConfigInPlace(cfg);
12780
12952
  saveConfig(cfg);
12781
12953
  log.success("Credentials cleared.");
12782
12954
  }
@@ -13135,7 +13307,7 @@ async function redeemTicket(ticket, cfg) {
13135
13307
  }
13136
13308
  }
13137
13309
  async function verifyOrMint(cfg, opts) {
13138
- if (cfg.access_token) {
13310
+ if (cfg.active_account?.session.access_token) {
13139
13311
  try {
13140
13312
  const client = new Client(cfg);
13141
13313
  const resp = await client.doRequestRaw("GET", "/v1/mcp/deployments");
@@ -13184,10 +13356,12 @@ async function resolveDeployment2(client, cfg, opts) {
13184
13356
  });
13185
13357
  return { code: 1, cfg };
13186
13358
  }
13187
- cfg.deployment_id = d.deployment_id;
13188
- cfg.deployment_name = d.name;
13189
- cfg.org_id = d.org_id;
13190
- cfg.space_id = d.space_id;
13359
+ updateTarget(cfg, {
13360
+ deployment_id: d.deployment_id,
13361
+ deployment_name: d.name,
13362
+ org_id: d.org_id,
13363
+ space_id: d.space_id
13364
+ });
13191
13365
  cfg.mode = undefined;
13192
13366
  saveConfig(cfg);
13193
13367
  emitStep({
@@ -13205,11 +13379,11 @@ async function resolveDeployment2(client, cfg, opts) {
13205
13379
  return { code: 1, cfg };
13206
13380
  }
13207
13381
  }
13208
- if (cfg.deployment_id) {
13382
+ if (cfg.active_account?.target?.deployment_id) {
13209
13383
  emitStep({
13210
13384
  step: "deployment",
13211
- deployment_id: cfg.deployment_id,
13212
- name: cfg.deployment_name
13385
+ deployment_id: cfg.active_account?.target?.deployment_id,
13386
+ name: cfg.active_account?.target?.deployment_name
13213
13387
  });
13214
13388
  return { code: 0, cfg };
13215
13389
  }
@@ -13234,10 +13408,12 @@ async function resolveDeployment2(client, cfg, opts) {
13234
13408
  }
13235
13409
  if (mcpDeployments.length === 1) {
13236
13410
  const d = mcpDeployments[0];
13237
- cfg.deployment_id = d.deployment_id;
13238
- cfg.deployment_name = d.name;
13239
- cfg.org_id = d.org_id;
13240
- cfg.space_id = d.space_id;
13411
+ updateTarget(cfg, {
13412
+ deployment_id: d.deployment_id,
13413
+ deployment_name: d.name,
13414
+ org_id: d.org_id,
13415
+ space_id: d.space_id
13416
+ });
13241
13417
  cfg.mode = undefined;
13242
13418
  saveConfig(cfg);
13243
13419
  emitStep({
@@ -13275,7 +13451,9 @@ function formatCandidates(deployments) {
13275
13451
  `);
13276
13452
  }
13277
13453
  async function ensureAPIKey(client, cfg) {
13278
- if (!cfg.deployment_id) {
13454
+ const target = cfg.active_account?.target;
13455
+ const deploymentID = target?.deployment_id;
13456
+ if (!deploymentID) {
13279
13457
  emitError({
13280
13458
  step: "api_key",
13281
13459
  reason: "no_deployment",
@@ -13284,15 +13462,15 @@ async function ensureAPIKey(client, cfg) {
13284
13462
  return { code: 1, cfg };
13285
13463
  }
13286
13464
  try {
13287
- if (cfg.api_key) {
13288
- const valid = await client.validateAPIKey(cfg.api_key, cfg.deployment_id);
13465
+ if (target.api_key) {
13466
+ const valid = await client.validateAPIKey(target.api_key, deploymentID);
13289
13467
  if (valid) {
13290
13468
  emitStep({ step: "api_key", reused: true });
13291
13469
  return { code: 0, cfg };
13292
13470
  }
13293
13471
  }
13294
- const resp = await client.createAPIKey(cfg.deployment_id, "dosu-cli");
13295
- cfg.api_key = resp.api_key;
13472
+ const resp = await client.createAPIKey(deploymentID, "dosu-cli");
13473
+ updateTarget(cfg, { api_key: resp.api_key });
13296
13474
  saveConfig(cfg);
13297
13475
  emitStep({ step: "api_key", reused: false });
13298
13476
  return { code: 0, cfg };
@@ -13340,18 +13518,18 @@ init_config();
13340
13518
  var import_picocolors2 = __toESM(require_picocolors(), 1);
13341
13519
  function requireLoginConfig() {
13342
13520
  const cfg = loadConfig();
13343
- if (!cfg.access_token) {
13521
+ if (!cfg.active_account?.session.access_token) {
13344
13522
  console.error(import_picocolors2.default.red("Not logged in. Run 'dosu login' first."));
13345
13523
  process.exit(1);
13346
13524
  }
13347
13525
  return cfg;
13348
13526
  }
13349
13527
  function requireAPIKey(cfg) {
13350
- if (!cfg.api_key) {
13528
+ if (!cfg.active_account?.target?.api_key) {
13351
13529
  console.error(import_picocolors2.default.red("API key not configured. Run 'dosu setup' first."));
13352
13530
  process.exit(1);
13353
13531
  }
13354
- return cfg.api_key;
13532
+ return cfg.active_account?.target?.api_key;
13355
13533
  }
13356
13534
 
13357
13535
  // src/commands/output.ts
@@ -13416,7 +13594,7 @@ function formatDate(dateStr) {
13416
13594
  // src/commands/analytics.ts
13417
13595
  function requireConfig() {
13418
13596
  const cfg = requireLoginConfig();
13419
- if (!cfg.space_id) {
13597
+ if (!cfg.active_account?.target?.space_id) {
13420
13598
  console.error(import_picocolors4.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
13421
13599
  process.exit(1);
13422
13600
  }
@@ -13427,7 +13605,7 @@ function analyticsCommand() {
13427
13605
  const cfg = requireConfig();
13428
13606
  const client = createTypedClient(cfg);
13429
13607
  const stats = await client.analytics.getUsageStats.query({
13430
- spaceId: cfg.space_id,
13608
+ spaceId: cfg.active_account.target.space_id,
13431
13609
  days: Number.parseInt(opts.days ?? "30", 10)
13432
13610
  });
13433
13611
  if (opts.json) {
@@ -13457,11 +13635,11 @@ init_logger();
13457
13635
  var import_picocolors5 = __toESM(require_picocolors(), 1);
13458
13636
  function requireConfig2() {
13459
13637
  const cfg = loadConfig();
13460
- if (!cfg.api_key) {
13638
+ if (!cfg.active_account?.target?.api_key) {
13461
13639
  console.error(import_picocolors5.default.red("Not configured. Run 'dosu setup' first."));
13462
13640
  process.exit(1);
13463
13641
  }
13464
- if (!cfg.deployment_id || !cfg.space_id) {
13642
+ if (!cfg.active_account?.target?.deployment_id || !cfg.active_account?.target?.space_id) {
13465
13643
  console.error(import_picocolors5.default.red("Missing deployment config. Run 'dosu setup' to reconfigure."));
13466
13644
  process.exit(1);
13467
13645
  }
@@ -13483,10 +13661,10 @@ function askCommand() {
13483
13661
  method: "POST",
13484
13662
  headers: {
13485
13663
  "Content-Type": "application/json",
13486
- "X-Dosu-API-Key": cfg.api_key
13664
+ "X-Dosu-API-Key": cfg.active_account.target.api_key
13487
13665
  },
13488
13666
  body: JSON.stringify({
13489
- deployment_id: cfg.deployment_id,
13667
+ deployment_id: cfg.active_account.target.deployment_id,
13490
13668
  question,
13491
13669
  session_id: opts.session ?? undefined
13492
13670
  }),
@@ -13642,7 +13820,7 @@ function checkForReadyTasks() {
13642
13820
  }
13643
13821
  const cfg = loadConfig();
13644
13822
  const backendURL = getBackendURL();
13645
- const apiKey = cfg.api_key;
13823
+ const apiKey = cfg.active_account?.target?.api_key;
13646
13824
  if (backendURL && apiKey) {
13647
13825
  const now = Date.now();
13648
13826
  for (const task of cache.tasks) {
@@ -13683,11 +13861,11 @@ var INDEX_POLL_INTERVAL_MS = 2000;
13683
13861
  var INDEX_POLL_TIMEOUT_MS = 120000;
13684
13862
  function requireConfig3() {
13685
13863
  const cfg = requireLoginConfig();
13686
- if (!cfg.api_key) {
13864
+ if (!cfg.active_account?.target?.api_key) {
13687
13865
  console.error(import_picocolors9.default.red("API key not configured. Run 'dosu setup' first."));
13688
13866
  process.exit(1);
13689
13867
  }
13690
- if (!cfg.org_id) {
13868
+ if (!cfg.active_account?.target?.org_id) {
13691
13869
  console.error(import_picocolors9.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
13692
13870
  process.exit(1);
13693
13871
  }
@@ -13765,7 +13943,10 @@ async function ensureSyncedRepo(cfg, client, detected, explicitDataSourceId, non
13765
13943
  if (explicitDataSourceId) {
13766
13944
  return explicitDataSourceId;
13767
13945
  }
13768
- let sources = await listDataSources(client, cfg.org_id);
13946
+ const orgID = cfg.active_account?.target?.org_id;
13947
+ if (!orgID)
13948
+ throw new Error("missing org config");
13949
+ let sources = await listDataSources(client, orgID);
13769
13950
  let match = findMatch(sources, detected);
13770
13951
  if (!match) {
13771
13952
  if (nonInteractive) {
@@ -13784,7 +13965,7 @@ async function ensureSyncedRepo(cfg, client, detected, explicitDataSourceId, non
13784
13965
  console.error(import_picocolors9.default.red(`Could not connect ${detected.slug}. Run 'dosu setup' and retry.`));
13785
13966
  process.exit(1);
13786
13967
  }
13787
- sources = await listDataSources(client, cfg.org_id);
13968
+ sources = await listDataSources(client, orgID);
13788
13969
  match = findMatch(sources, detected);
13789
13970
  if (!match) {
13790
13971
  console.error(import_picocolors9.default.red(`Could not find ${detected.slug} after connecting. Retry shortly.`));
@@ -13792,7 +13973,7 @@ async function ensureSyncedRepo(cfg, client, detected, explicitDataSourceId, non
13792
13973
  }
13793
13974
  }
13794
13975
  if (match.is_indexed !== true) {
13795
- const indexed = await waitForIndexed(client, cfg.org_id, detected, nonInteractive);
13976
+ const indexed = await waitForIndexed(client, orgID, detected, nonInteractive);
13796
13977
  if (!indexed) {
13797
13978
  if (nonInteractive) {
13798
13979
  console.error(import_picocolors9.default.red(`${detected.slug} is still indexing. Re-run once indexing finishes.`));
@@ -13983,7 +14164,7 @@ function deploymentsCommand() {
13983
14164
  cmd.command("list").description("List all deployments").option("--json", "Output as JSON").action(async (opts) => {
13984
14165
  const cfg = requireConfig4();
13985
14166
  const client = createTypedClient(cfg);
13986
- const deployments = cfg.org_id ? await client.workspaces.listForOrg.query(cfg.org_id) : await client.workspaces.listAll.query({});
14167
+ const deployments = cfg.active_account?.target?.org_id ? await client.workspaces.listForOrg.query(cfg.active_account?.target?.org_id) : await client.workspaces.listAll.query({});
13987
14168
  if (opts.json) {
13988
14169
  printResult(deployments, opts);
13989
14170
  return;
@@ -13998,21 +14179,21 @@ function deploymentsCommand() {
13998
14179
  d.org_id ? d.org_id.slice(0, 8) : "—",
13999
14180
  d.enabled ? import_picocolors10.default.green("active") : import_picocolors10.default.dim("disabled")
14000
14181
  ]), { rawData: deployments });
14001
- if (cfg.deployment_id) {
14182
+ if (cfg.active_account?.target?.deployment_id) {
14002
14183
  console.log(`
14003
- ${import_picocolors10.default.dim(`Current: ${cfg.deployment_name ?? cfg.deployment_id}`)}`);
14184
+ ${import_picocolors10.default.dim(`Current: ${cfg.active_account?.target?.deployment_name ?? cfg.active_account?.target?.deployment_id}`)}`);
14004
14185
  }
14005
14186
  });
14006
14187
  cmd.command("info").description("Show current deployment details").option("--json", "Output as JSON").action(async (opts) => {
14007
14188
  const cfg = requireConfig4();
14008
- if (!cfg.deployment_id) {
14189
+ if (!cfg.active_account?.target?.deployment_id) {
14009
14190
  console.error(import_picocolors10.default.red("No deployment selected. Run 'dosu setup' or 'dosu deployments switch'."));
14010
14191
  process.exit(1);
14011
14192
  }
14012
14193
  const client = createTypedClient(cfg);
14013
- const deployment = await client.workspaces.get.query(cfg.deployment_id);
14194
+ const deployment = await client.workspaces.get.query(cfg.active_account?.target?.deployment_id);
14014
14195
  if (!deployment) {
14015
- console.error(import_picocolors10.default.red(`Deployment not found: ${cfg.deployment_id}`));
14196
+ console.error(import_picocolors10.default.red(`Deployment not found: ${cfg.active_account?.target?.deployment_id}`));
14016
14197
  process.exit(1);
14017
14198
  }
14018
14199
  if (opts.json) {
@@ -14038,10 +14219,12 @@ ${import_picocolors10.default.dim(`Current: ${cfg.deployment_name ?? cfg.deploym
14038
14219
  console.error(import_picocolors10.default.red(`Deployment not found: ${id}`));
14039
14220
  process.exit(1);
14040
14221
  }
14041
- cfg.deployment_id = deployment.deployment_id;
14042
- cfg.deployment_name = deployment.name;
14043
- cfg.org_id = deployment.org_id;
14044
- cfg.space_id = deployment.space_id;
14222
+ updateTarget(cfg, {
14223
+ deployment_id: deployment.deployment_id,
14224
+ deployment_name: deployment.name,
14225
+ org_id: deployment.org_id,
14226
+ space_id: deployment.space_id
14227
+ });
14045
14228
  saveConfig(cfg);
14046
14229
  if (opts.json) {
14047
14230
  printResult({ success: true, deployment_id: deployment.deployment_id, name: deployment.name }, opts);
@@ -14062,7 +14245,7 @@ var import_picocolors11 = __toESM(require_picocolors(), 1);
14062
14245
  import { readFileSync as readFileSync5 } from "node:fs";
14063
14246
  function requireConfig5() {
14064
14247
  const cfg = requireLoginConfig();
14065
- if (!cfg.space_id) {
14248
+ if (!cfg.active_account?.target?.space_id) {
14066
14249
  console.error(import_picocolors11.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
14067
14250
  process.exit(1);
14068
14251
  }
@@ -14164,7 +14347,7 @@ function docsCommand() {
14164
14347
  cmd.command("list").description("List documents").option("--search <query>", "Search documents").option("--tag <id>", "Filter by tag ID").option("--limit <n>", "Maximum results", "20").option("--json", "Output as JSON").action(async (opts) => {
14165
14348
  const cfg = requireConfig5();
14166
14349
  const client = createTypedClient(cfg);
14167
- const ksId = await getKnowledgeStoreId(client, cfg.space_id);
14350
+ const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
14168
14351
  const result = await client.page.listWithTags.query({
14169
14352
  knowledge_store_id: ksId,
14170
14353
  searchTerm: opts.search,
@@ -14216,7 +14399,7 @@ ${page.body}`);
14216
14399
  cmd.command("create").description("Create a new document").requiredOption("--title <title>", "Document title").option("--body <markdown>", "Document body (markdown)").option("--body-file <path>", "Read body from file").option("--json", "Output as JSON").action(async (opts) => {
14217
14400
  const cfg = requireConfig5();
14218
14401
  const client = createTypedClient(cfg);
14219
- const ksId = await getKnowledgeStoreId(client, cfg.space_id);
14402
+ const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
14220
14403
  const body = readBody(opts);
14221
14404
  const result = await client.page.create.mutate({
14222
14405
  knowledge_store_id: ksId,
@@ -14232,7 +14415,7 @@ ${page.body}`);
14232
14415
  cmd.command("update").description("Update a document").argument("<id>", "Page ID").option("--title <title>", "New title").option("--body <markdown>", "New body (markdown)").option("--body-file <path>", "Read body from file").option("--json", "Output as JSON").action(async (id, opts) => {
14233
14416
  const cfg = requireConfig5();
14234
14417
  const client = createTypedClient(cfg);
14235
- const ksId = await getKnowledgeStoreId(client, cfg.space_id);
14418
+ const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
14236
14419
  const body = readBody(opts);
14237
14420
  const result = await client.page.update.mutate({
14238
14421
  id,
@@ -14302,7 +14485,7 @@ ${page.body}`);
14302
14485
  cmd.command("generate").description("Generate a document using AI").requiredOption("--title <title>", "Document title").option("--instructions <text>", "Custom generation instructions").option("--json", "Output as JSON").action(async (opts) => {
14303
14486
  const cfg = requireConfig5();
14304
14487
  const client = createTypedClient(cfg);
14305
- const ksId = await getKnowledgeStoreId(client, cfg.space_id);
14488
+ const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
14306
14489
  const result = await backendPost2("/doc/generate", requireAPIKey(cfg), {
14307
14490
  knowledge_store_id: ksId,
14308
14491
  title: opts.title,
@@ -14326,7 +14509,7 @@ ${page.body}`);
14326
14509
  cmd.command("import").description("Import documents from an external platform").argument("<platform>", "Platform: github, gitlab, confluence, notion, coda").requiredOption("--files <ids>", "Comma-separated file/page IDs to import").option("--json", "Output as JSON").action(async (platform2, opts) => {
14327
14510
  const cfg = requireConfig5();
14328
14511
  const client = createTypedClient(cfg);
14329
- const ksId = await getKnowledgeStoreId(client, cfg.space_id);
14512
+ const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
14330
14513
  const fileIds = opts.files.split(",").map((id) => id.trim());
14331
14514
  const importFn = {
14332
14515
  github: (input) => client.docImports.importGithubFiles.mutate(input),
@@ -14344,7 +14527,7 @@ ${page.body}`);
14344
14527
  try {
14345
14528
  const result = await fn({
14346
14529
  knowledge_store_id: ksId,
14347
- space_id: cfg.space_id,
14530
+ space_id: cfg.active_account.target.space_id,
14348
14531
  [idField]: fileIds
14349
14532
  });
14350
14533
  if (opts.json) {
@@ -14547,7 +14730,7 @@ async function runUserPromptSubmit(input, now = Date.now(), agent = DEFAULT_AGEN
14547
14730
  return;
14548
14731
  }
14549
14732
  const cfg = loadConfig();
14550
- if (!cfg.api_key || !cfg.deployment_id) {
14733
+ if (!cfg.active_account?.target?.api_key || !cfg.active_account?.target?.deployment_id) {
14551
14734
  logger.debug("hooks", "submit skipped reason=not-configured");
14552
14735
  return;
14553
14736
  }
@@ -14556,7 +14739,7 @@ async function runUserPromptSubmit(input, now = Date.now(), agent = DEFAULT_AGEN
14556
14739
  let resp;
14557
14740
  try {
14558
14741
  resp = await tc.requestCreateTicket(cfg, {
14559
- deployment_id: cfg.deployment_id,
14742
+ deployment_id: cfg.active_account?.target?.deployment_id,
14560
14743
  agent,
14561
14744
  session_id: sessionId,
14562
14745
  turn_id: input.turn_id ?? String(now),
@@ -14601,7 +14784,7 @@ async function runPostToolUse(input, now = Date.now()) {
14601
14784
  return;
14602
14785
  }
14603
14786
  const cfg = loadConfig();
14604
- if (!cfg.api_key || !cfg.deployment_id) {
14787
+ if (!cfg.active_account?.target?.api_key || !cfg.active_account?.target?.deployment_id) {
14605
14788
  saveState({ ...state, lastCheckedAt: now });
14606
14789
  return;
14607
14790
  }
@@ -14653,7 +14836,7 @@ async function runStop(input, now = Date.now()) {
14653
14836
  if (state.status !== "pending" || now > state.expiresAt)
14654
14837
  return printContinue();
14655
14838
  const cfg = loadConfig();
14656
- if (!cfg.api_key || !cfg.deployment_id)
14839
+ if (!cfg.active_account?.target?.api_key || !cfg.active_account?.target?.deployment_id)
14657
14840
  return printContinue();
14658
14841
  const tc = await Promise.resolve().then(() => (init_ticket_client(), exports_ticket_client));
14659
14842
  const pollMs = stopPollMs();
@@ -14947,11 +15130,11 @@ async function collectDoctorChecks(opts) {
14947
15130
  } else {
14948
15131
  checks.push({ name: "auth", status: "fail", detail: "not logged in (run 'dosu login')" });
14949
15132
  }
14950
- if (cfg.deployment_id || cfg.mode === MODE_OSS) {
15133
+ if (cfg.active_account?.target?.deployment_id || cfg.mode === MODE_OSS) {
14951
15134
  checks.push({
14952
15135
  name: "deployment",
14953
15136
  status: "ok",
14954
- detail: cfg.deployment_name ?? cfg.deployment_id ?? "oss"
15137
+ detail: cfg.active_account?.target?.deployment_name ?? cfg.active_account?.target?.deployment_id ?? "oss"
14955
15138
  });
14956
15139
  } else {
14957
15140
  checks.push({
@@ -14960,9 +15143,9 @@ async function collectDoctorChecks(opts) {
14960
15143
  detail: "no deployment selected (run 'dosu setup')"
14961
15144
  });
14962
15145
  }
14963
- if (cfg.api_key && cfg.deployment_id) {
15146
+ if (cfg.active_account?.target?.api_key && cfg.active_account?.target?.deployment_id) {
14964
15147
  const { Client: Client2 } = await Promise.resolve().then(() => (init_client(), exports_client));
14965
- const ok = await new Client2(cfg).validateAPIKey(cfg.api_key, cfg.deployment_id);
15148
+ const ok = await new Client2(cfg).validateAPIKey(cfg.active_account?.target?.api_key, cfg.active_account?.target?.deployment_id);
14966
15149
  checks.push({
14967
15150
  name: "backend",
14968
15151
  status: ok ? "ok" : "fail",
@@ -15053,52 +15236,68 @@ init_trpc();
15053
15236
  var import_picocolors15 = __toESM(require_picocolors(), 1);
15054
15237
  function requireConfig6() {
15055
15238
  const cfg = requireLoginConfig();
15056
- if (!cfg.org_id) {
15239
+ if (!cfg.active_account?.target?.org_id) {
15057
15240
  console.error(import_picocolors15.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
15058
15241
  process.exit(1);
15059
15242
  }
15060
15243
  return cfg;
15061
15244
  }
15062
- var NANGO_PLATFORMS = [
15063
- "confluence",
15064
- "notion",
15065
- "coda",
15066
- "gitlab",
15067
- "gitlab-pat",
15068
- "confluence-basic"
15069
- ];
15245
+ var NANGO_PROBES = {
15246
+ gitlab: [
15247
+ { provider: "gitlab", providerConfigKey: "gitlab" },
15248
+ { provider: "gitlab", providerConfigKey: "gitlab-pat" }
15249
+ ],
15250
+ "gitlab-pat": [{ provider: "gitlab", providerConfigKey: "gitlab-pat" }],
15251
+ confluence: [
15252
+ { provider: "confluence", providerConfigKey: "confluence" },
15253
+ { provider: "confluence", providerConfigKey: "confluence-basic" }
15254
+ ],
15255
+ "confluence-basic": [{ provider: "confluence", providerConfigKey: "confluence-basic" }],
15256
+ notion: [{ provider: "notion", providerConfigKey: "notion" }],
15257
+ coda: [{ provider: "coda", providerConfigKey: "coda" }],
15258
+ azure_devops: [
15259
+ { provider: "microsoft-entra-id", providerConfigKey: "microsoft-entra-id" },
15260
+ { provider: "azure_devops", providerConfigKey: "azure-devops" }
15261
+ ]
15262
+ };
15070
15263
  var DISPLAY_PLATFORMS = [
15071
15264
  "github",
15072
15265
  "gitlab",
15266
+ "azure_devops",
15073
15267
  "slack",
15074
15268
  "confluence",
15075
15269
  "notion",
15076
15270
  "coda",
15077
15271
  "teams"
15078
15272
  ];
15273
+ async function probeConnection(client, orgId, platform4) {
15274
+ const probes = NANGO_PROBES[platform4];
15275
+ if (!probes) {
15276
+ return { queryable: false, connected: false, connection: null };
15277
+ }
15278
+ for (const probe of probes) {
15279
+ try {
15280
+ const conn = await client.nango.getConnection.query({
15281
+ provider: probe.provider,
15282
+ providerConfigKey: probe.providerConfigKey,
15283
+ orgId
15284
+ });
15285
+ if (conn != null) {
15286
+ return { queryable: true, connected: true, connection: conn };
15287
+ }
15288
+ } catch {}
15289
+ }
15290
+ return { queryable: true, connected: false, connection: null };
15291
+ }
15079
15292
  function integrationsCommand() {
15080
15293
  const cmd = new Command("integrations").description("Manage integrations");
15081
15294
  cmd.command("list").description("List all integrations and their connection status").option("--json", "Output as JSON").action(async (opts) => {
15082
15295
  const cfg = requireConfig6();
15083
15296
  const client = createTypedClient(cfg);
15084
- const results = [];
15085
- for (const platform4 of DISPLAY_PLATFORMS) {
15086
- const nangoProvider = NANGO_PLATFORMS.find((p2) => p2 === platform4);
15087
- if (nangoProvider) {
15088
- try {
15089
- const conn = await client.nango.getConnection.query({
15090
- provider: nangoProvider,
15091
- providerConfigKey: nangoProvider,
15092
- orgId: cfg.org_id
15093
- });
15094
- results.push({ platform: platform4, connected: conn !== null });
15095
- } catch {
15096
- results.push({ platform: platform4, connected: false });
15097
- }
15098
- } else {
15099
- results.push({ platform: platform4, connected: false });
15100
- }
15101
- }
15297
+ const results = await Promise.all(DISPLAY_PLATFORMS.map(async (platform4) => {
15298
+ const { connected } = await probeConnection(client, cfg.active_account.target.org_id, platform4);
15299
+ return { platform: platform4, connected };
15300
+ }));
15102
15301
  if (opts.json) {
15103
15302
  printResult(results, opts);
15104
15303
  return;
@@ -15111,8 +15310,8 @@ function integrationsCommand() {
15111
15310
  cmd.command("status").description("Check connection status of a specific platform").argument("<platform>", `Platform: ${DISPLAY_PLATFORMS.join(", ")}`).option("--json", "Output as JSON").action(async (platform4, opts) => {
15112
15311
  const cfg = requireConfig6();
15113
15312
  const client = createTypedClient(cfg);
15114
- const nangoProvider = NANGO_PLATFORMS.find((p2) => p2 === platform4);
15115
- if (!nangoProvider) {
15313
+ const { queryable, connected, connection } = await probeConnection(client, cfg.active_account.target.org_id, platform4);
15314
+ if (!queryable) {
15116
15315
  if (opts.json) {
15117
15316
  printResult({ platform: platform4, connected: false, note: "not queryable via nango" }, opts);
15118
15317
  return;
@@ -15120,30 +15319,16 @@ function integrationsCommand() {
15120
15319
  console.log(`${platform4}: ${import_picocolors15.default.dim("not connected (not queryable)")}`);
15121
15320
  return;
15122
15321
  }
15123
- try {
15124
- const conn = await client.nango.getConnection.query({
15125
- provider: nangoProvider,
15126
- providerConfigKey: nangoProvider,
15127
- orgId: cfg.org_id
15128
- });
15129
- const connected = conn !== null;
15130
- if (opts.json) {
15131
- printResult({ platform: platform4, connected, connection: conn }, opts);
15132
- return;
15133
- }
15134
- console.log(`${platform4}: ${connected ? import_picocolors15.default.green("connected") : import_picocolors15.default.dim("not connected")}`);
15135
- } catch {
15136
- if (opts.json) {
15137
- printResult({ platform: platform4, connected: false }, opts);
15138
- return;
15139
- }
15140
- console.log(`${platform4}: ${import_picocolors15.default.dim("not connected")}`);
15322
+ if (opts.json) {
15323
+ printResult({ platform: platform4, connected, connection }, opts);
15324
+ return;
15141
15325
  }
15326
+ console.log(`${platform4}: ${connected ? import_picocolors15.default.green("connected") : import_picocolors15.default.dim("not connected")}`);
15142
15327
  });
15143
15328
  cmd.command("slack-channels").description("List Slack channels").option("--json", "Output as JSON").action(async (opts) => {
15144
15329
  const cfg = requireConfig6();
15145
15330
  const client = createTypedClient(cfg);
15146
- const channels = await client.slackChannel.getAll.query(cfg.org_id);
15331
+ const channels = await client.slackChannel.getAll.query(cfg.active_account.target.org_id);
15147
15332
  if (opts.json) {
15148
15333
  printResult(channels, opts);
15149
15334
  return;
@@ -15190,7 +15375,7 @@ init_trpc();
15190
15375
  var import_picocolors16 = __toESM(require_picocolors(), 1);
15191
15376
  function requireConfig7() {
15192
15377
  const cfg = requireLoginConfig();
15193
- if (!cfg.org_id || !cfg.space_id) {
15378
+ if (!cfg.active_account?.target?.org_id || !cfg.active_account?.target?.space_id) {
15194
15379
  console.error(import_picocolors16.default.red("Missing org/space config. Run 'dosu setup' to reconfigure."));
15195
15380
  process.exit(1);
15196
15381
  }
@@ -15202,7 +15387,7 @@ function knowledgeCommand() {
15202
15387
  const cfg = requireConfig7();
15203
15388
  const client = createTypedClient(cfg);
15204
15389
  const dataSources = await client.dataSource.list.query({
15205
- org_id: cfg.org_id,
15390
+ org_id: cfg.active_account.target.org_id,
15206
15391
  excluded_provider_slugs: []
15207
15392
  });
15208
15393
  const dataSourceIds = dataSources.map((ds) => ds.id).filter((id) => id !== null);
@@ -15238,7 +15423,7 @@ ${results.length - limit} more results not shown.`));
15238
15423
  cmd.command("list").description("Show knowledge store information").option("--json", "Output as JSON").action(async (opts) => {
15239
15424
  const cfg = requireConfig7();
15240
15425
  const client = createTypedClient(cfg);
15241
- const store = await client.knowledgeStore.getBySpaceId.query({ space_id: cfg.space_id });
15426
+ const store = await client.knowledgeStore.getBySpaceId.query({ space_id: cfg.active_account.target.space_id });
15242
15427
  if (opts.json) {
15243
15428
  printResult(store, opts);
15244
15429
  return;
@@ -15260,7 +15445,7 @@ init_trpc();
15260
15445
  var import_picocolors17 = __toESM(require_picocolors(), 1);
15261
15446
  function requireConfig8() {
15262
15447
  const cfg = requireLoginConfig();
15263
- if (!cfg.org_id) {
15448
+ if (!cfg.active_account?.target?.org_id) {
15264
15449
  console.error(import_picocolors17.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
15265
15450
  process.exit(1);
15266
15451
  }
@@ -15290,7 +15475,7 @@ function membersCommand() {
15290
15475
  const client = createTypedClient(cfg);
15291
15476
  const role = opts.role.toUpperCase() === "ADMIN" ? "ADMIN" : "MEMBER";
15292
15477
  await client.invitations.invite.mutate({
15293
- orgId: cfg.org_id,
15478
+ orgId: cfg.active_account.target.org_id,
15294
15479
  email,
15295
15480
  role
15296
15481
  });
@@ -15321,7 +15506,7 @@ function membersCommand() {
15321
15506
  const cfg = requireConfig8();
15322
15507
  const client = createTypedClient(cfg);
15323
15508
  await client.invitations.acceptInvitation.mutate({
15324
- orgId: cfg.org_id,
15509
+ orgId: cfg.active_account.target.org_id,
15325
15510
  email
15326
15511
  });
15327
15512
  if (opts.json) {
@@ -15334,7 +15519,7 @@ function membersCommand() {
15334
15519
  const cfg = requireConfig8();
15335
15520
  const client = createTypedClient(cfg);
15336
15521
  await client.invitations.rejectInvitation.mutate({
15337
- orgId: cfg.org_id,
15522
+ orgId: cfg.active_account.target.org_id,
15338
15523
  email
15339
15524
  });
15340
15525
  if (opts.json) {
@@ -15376,9 +15561,9 @@ function orgCommand() {
15376
15561
  return;
15377
15562
  }
15378
15563
  printTable(["ID", "Name"], orgs.map((o2) => [o2.org_id.slice(0, 8), o2.name]), { rawData: orgs });
15379
- if (cfg.org_id) {
15564
+ if (cfg.active_account?.target?.org_id) {
15380
15565
  console.log(`
15381
- ${import_picocolors18.default.dim(`Current: ${cfg.org_id}`)}`);
15566
+ ${import_picocolors18.default.dim(`Current: ${cfg.active_account?.target?.org_id}`)}`);
15382
15567
  }
15383
15568
  });
15384
15569
  return cmd;
@@ -15492,15 +15677,15 @@ function reviewCommand() {
15492
15677
  const cmd = new Command("review").description("Review workflow (doc changes and draft replies)");
15493
15678
  cmd.command("list").description("List pending review items (doc changes and draft replies)").option("--json", "Output as JSON").action(async (opts) => {
15494
15679
  const cfg = requireConfig10();
15495
- if (!cfg.space_id) {
15680
+ if (!cfg.active_account?.target?.space_id) {
15496
15681
  console.error(import_picocolors19.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
15497
15682
  process.exit(1);
15498
15683
  }
15499
15684
  const client = createTypedClient(cfg);
15500
- const ksId = await getKnowledgeStoreId2(client, cfg.space_id);
15685
+ const ksId = await getKnowledgeStoreId2(client, cfg.active_account?.target?.space_id);
15501
15686
  const result = await client.review.listPending.query({
15502
15687
  knowledgeStoreId: ksId,
15503
- deploymentId: cfg.deployment_id
15688
+ deploymentId: cfg.active_account?.target?.deployment_id
15504
15689
  });
15505
15690
  const { items, truncated, total } = result;
15506
15691
  if (opts.json) {
@@ -15716,7 +15901,7 @@ init_trpc();
15716
15901
  var import_picocolors20 = __toESM(require_picocolors(), 1);
15717
15902
  function requireConfig11() {
15718
15903
  const cfg = requireLoginConfig();
15719
- if (!cfg.org_id) {
15904
+ if (!cfg.active_account?.target?.org_id) {
15720
15905
  console.error(import_picocolors20.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
15721
15906
  process.exit(1);
15722
15907
  }
@@ -15728,7 +15913,7 @@ function sourcesCommand() {
15728
15913
  const cfg = requireConfig11();
15729
15914
  const client = createTypedClient(cfg);
15730
15915
  const dataSources = await client.dataSource.list.query({
15731
- org_id: cfg.org_id,
15916
+ org_id: cfg.active_account.target.org_id,
15732
15917
  excluded_provider_slugs: []
15733
15918
  });
15734
15919
  if (opts.json) {
@@ -15810,7 +15995,7 @@ init_trpc();
15810
15995
  var import_picocolors21 = __toESM(require_picocolors(), 1);
15811
15996
  function requireConfig12() {
15812
15997
  const cfg = requireLoginConfig();
15813
- if (!cfg.space_id) {
15998
+ if (!cfg.active_account?.target?.space_id) {
15814
15999
  console.error(import_picocolors21.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
15815
16000
  process.exit(1);
15816
16001
  }
@@ -15831,7 +16016,7 @@ function suggestCommand() {
15831
16016
  cmd.command("list").description("List pending document suggestions").option("--json", "Output as JSON").action(async (opts) => {
15832
16017
  const cfg = requireConfig12();
15833
16018
  const client = createTypedClient(cfg);
15834
- const ksId = await getKnowledgeStoreId3(client, cfg.space_id);
16019
+ const ksId = await getKnowledgeStoreId3(client, cfg.active_account.target.space_id);
15835
16020
  const suggestions = await client.suggestedDoc.listForKnowledgeStore.query({
15836
16021
  knowledgeStoreId: ksId
15837
16022
  });
@@ -15851,13 +16036,13 @@ function suggestCommand() {
15851
16036
  cmd.command("generate").description("Generate new document suggestions from data sources").option("--json", "Output as JSON").action(async (opts) => {
15852
16037
  const cfg = requireConfig12();
15853
16038
  const client = createTypedClient(cfg);
15854
- const ksId = await getKnowledgeStoreId3(client, cfg.space_id);
15855
- if (!cfg.org_id) {
16039
+ const ksId = await getKnowledgeStoreId3(client, cfg.active_account.target.space_id);
16040
+ if (!cfg.active_account?.target?.org_id) {
15856
16041
  console.error(import_picocolors21.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
15857
16042
  process.exit(1);
15858
16043
  }
15859
16044
  const dataSources = await client.dataSource.list.query({
15860
- org_id: cfg.org_id,
16045
+ org_id: cfg.active_account?.target?.org_id,
15861
16046
  excluded_provider_slugs: []
15862
16047
  });
15863
16048
  const dataSourceIds = dataSources.map((ds) => ds.id).filter((id) => id !== null);
@@ -15890,7 +16075,7 @@ init_trpc();
15890
16075
  var import_picocolors22 = __toESM(require_picocolors(), 1);
15891
16076
  function requireConfig13() {
15892
16077
  const cfg = requireLoginConfig();
15893
- if (!cfg.space_id) {
16078
+ if (!cfg.active_account?.target?.space_id) {
15894
16079
  console.error(import_picocolors22.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
15895
16080
  process.exit(1);
15896
16081
  }
@@ -15914,7 +16099,7 @@ function threadsCommand() {
15914
16099
  read: undefined,
15915
16100
  resolved: undefined,
15916
16101
  search: undefined,
15917
- space_id: cfg.space_id,
16102
+ space_id: cfg.active_account.target.space_id,
15918
16103
  workspaces: undefined,
15919
16104
  limit: Math.min(Number.parseInt(opts.limit ?? "20", 10), 100)
15920
16105
  };
@@ -16009,7 +16194,7 @@ init_trpc();
16009
16194
  var import_picocolors23 = __toESM(require_picocolors(), 1);
16010
16195
  function requireConfig14() {
16011
16196
  const cfg = requireLoginConfig();
16012
- if (!cfg.space_id) {
16197
+ if (!cfg.active_account?.target?.space_id) {
16013
16198
  console.error(import_picocolors23.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
16014
16199
  process.exit(1);
16015
16200
  }
@@ -16030,7 +16215,7 @@ function topicsCommand() {
16030
16215
  cmd.command("list").description("List all topics").option("--json", "Output as JSON").action(async (opts) => {
16031
16216
  const cfg = requireConfig14();
16032
16217
  const client = createTypedClient(cfg);
16033
- const ksId = await getKnowledgeStoreId4(client, cfg.space_id);
16218
+ const ksId = await getKnowledgeStoreId4(client, cfg.active_account.target.space_id);
16034
16219
  const topics = await client.topic.listTopicsByKnowledgeStore.query({
16035
16220
  knowledge_store_id: ksId
16036
16221
  });
@@ -16051,7 +16236,7 @@ function topicsCommand() {
16051
16236
  cmd.command("pages").description("List pages with a specific topic").argument("<topic-id>", "Topic ID").option("--search <query>", "Search within the topic's pages").option("--limit <n>", "Maximum results", "10").option("--json", "Output as JSON").action(async (topicId, opts) => {
16052
16237
  const cfg = requireConfig14();
16053
16238
  const client = createTypedClient(cfg);
16054
- const ksId = await getKnowledgeStoreId4(client, cfg.space_id);
16239
+ const ksId = await getKnowledgeStoreId4(client, cfg.active_account.target.space_id);
16055
16240
  const result = await client.topic.getPagesByTopicId.query({
16056
16241
  knowledge_store_id: ksId,
16057
16242
  topic_id: topicId,
@@ -16339,14 +16524,7 @@ Run 'dosu --help' to see available commands.`;
16339
16524
  console.log("You are not logged in.");
16340
16525
  return;
16341
16526
  }
16342
- cfg.access_token = "";
16343
- cfg.refresh_token = "";
16344
- cfg.expires_at = 0;
16345
- cfg.deployment_id = undefined;
16346
- cfg.deployment_name = undefined;
16347
- cfg.api_key = undefined;
16348
- cfg.org_id = undefined;
16349
- cfg.space_id = undefined;
16527
+ clearConfigInPlace(cfg);
16350
16528
  saveConfig(cfg);
16351
16529
  console.log("Successfully logged out.");
16352
16530
  });
@@ -16366,9 +16544,9 @@ Run 'dosu --help' to see available commands.`;
16366
16544
  if (cfg.mode === MODE_OSS) {
16367
16545
  console.log("Mode: OSS");
16368
16546
  console.log("MCP: Public libraries only");
16369
- } else if (cfg.deployment_id) {
16370
- console.log(`MCP: ${cfg.deployment_name}`);
16371
- console.log(`MCP ID: ${cfg.deployment_id}`);
16547
+ } else if (cfg.active_account?.target?.deployment_id) {
16548
+ console.log(`MCP: ${cfg.active_account?.target?.deployment_name}`);
16549
+ console.log(`MCP ID: ${cfg.active_account?.target?.deployment_id}`);
16372
16550
  } else {
16373
16551
  console.log("MCP: None selected");
16374
16552
  console.log("Run 'dosu deployments list' to see available MCPs, then 'dosu deployments switch <id>' to select one.");
@@ -16389,10 +16567,10 @@ Run 'dosu --help' to see available commands.`;
16389
16567
  if (isTokenExpired(cfg) && !await ensureFreshSession(cfg)) {
16390
16568
  throw new Error("session expired. Run 'dosu login' to re-authenticate");
16391
16569
  }
16392
- if (cfg.mode !== MODE_OSS && !cfg.deployment_id) {
16570
+ if (cfg.mode !== MODE_OSS && !cfg.active_account?.target?.deployment_id) {
16393
16571
  throw new Error("no MCP selected. Run 'dosu' to open the TUI and select an MCP");
16394
16572
  }
16395
- if (!cfg.api_key) {
16573
+ if (!cfg.active_account?.target?.api_key) {
16396
16574
  throw new Error("no API key available. Run 'dosu setup' to create one");
16397
16575
  }
16398
16576
  if (provider.id() === "manual") {