@dosu/cli 0.49.3 → 0.50.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 (3) hide show
  1. package/README.md +3 -3
  2. package/bin/dosu.js +929 -377
  3. package/package.json +1 -1
package/bin/dosu.js CHANGED
@@ -5000,7 +5000,7 @@ function isNpxInvocation(channel = INSTALL_CHANNEL, env = process.env) {
5000
5000
  function getVersionString() {
5001
5001
  return `v${VERSION}`;
5002
5002
  }
5003
- var VERSION = "0.49.3", INSTALL_CHANNEL = "npm";
5003
+ var VERSION = "0.50.0", INSTALL_CHANNEL = "npm";
5004
5004
 
5005
5005
  // src/debug/logger.ts
5006
5006
  import {
@@ -5134,7 +5134,7 @@ var init_logger = __esm(() => {
5134
5134
  });
5135
5135
 
5136
5136
  // src/client/contract.ts
5137
- var CLI_CONTRACT_HASH = "de4d34216f45";
5137
+ var CLI_CONTRACT_HASH = "ac90a31489e1";
5138
5138
 
5139
5139
  // src/client/trpc.ts
5140
5140
  var exports_trpc = {};
@@ -6864,7 +6864,7 @@ var init_dist8 = __esm(() => {
6864
6864
 
6865
6865
  // src/setup/styles.ts
6866
6866
  function dim(msg) {
6867
- return import_picocolors7.default.dim(msg);
6867
+ return import_picocolors9.default.dim(msg);
6868
6868
  }
6869
6869
  function formatSetupSummary(title, items, marker = IconAdd) {
6870
6870
  const lines = items.map((item) => {
@@ -6881,11 +6881,11 @@ function browserFallbackHint(url) {
6881
6881
  ${url}`);
6882
6882
  }
6883
6883
  function info(msg) {
6884
- return import_picocolors7.default.cyan(msg);
6884
+ return import_picocolors9.default.cyan(msg);
6885
6885
  }
6886
- var import_picocolors7, IconAdd = "+", IconRemove = "-";
6886
+ var import_picocolors9, IconAdd = "+", IconRemove = "-";
6887
6887
  var init_styles = __esm(() => {
6888
- import_picocolors7 = __toESM(require_picocolors(), 1);
6888
+ import_picocolors9 = __toESM(require_picocolors(), 1);
6889
6889
  });
6890
6890
 
6891
6891
  // node_modules/is-docker/index.js
@@ -8715,8 +8715,8 @@ async function fetchLatestSha() {
8715
8715
  }
8716
8716
  function displayNotice() {
8717
8717
  const msg = `
8718
- ${import_picocolors12.default.yellow(" Dosu skill update available")}
8719
- ` + `${import_picocolors12.default.dim(' Run "dosu skill update" to upgrade')}
8718
+ ${import_picocolors14.default.yellow(" Dosu skill update available")}
8719
+ ` + `${import_picocolors14.default.dim(' Run "dosu skill update" to upgrade')}
8720
8720
  `;
8721
8721
  console.error(msg);
8722
8722
  }
@@ -8746,11 +8746,11 @@ function checkForSkillUpdates() {
8746
8746
  logger.error("skill-update-check", `Skill update check failed: ${err}`);
8747
8747
  }
8748
8748
  }
8749
- var import_picocolors12, CACHE_FILENAME2 = "skill-update-check.json", CHECK_INTERVAL_MS2, FETCH_TIMEOUT_MS2 = 5000, GITHUB_API_URL = "https://api.github.com/repos/dosu-ai/dosu-skill/commits/HEAD";
8749
+ var import_picocolors14, CACHE_FILENAME2 = "skill-update-check.json", CHECK_INTERVAL_MS2, FETCH_TIMEOUT_MS2 = 5000, GITHUB_API_URL = "https://api.github.com/repos/dosu-ai/dosu-skill/commits/HEAD";
8750
8750
  var init_skill_update_check = __esm(() => {
8751
8751
  init_config();
8752
8752
  init_logger();
8753
- import_picocolors12 = __toESM(require_picocolors(), 1);
8753
+ import_picocolors14 = __toESM(require_picocolors(), 1);
8754
8754
  CHECK_INTERVAL_MS2 = 24 * 60 * 60 * 1000;
8755
8755
  });
8756
8756
 
@@ -8857,10 +8857,10 @@ function skillCommand() {
8857
8857
  console.log(`Installing skills from ${SKILL_REPO}...`);
8858
8858
  const result = await installSkill();
8859
8859
  if (result.success) {
8860
- console.log(import_picocolors13.default.green(`
8860
+ console.log(import_picocolors15.default.green(`
8861
8861
  ✓ Skills installed successfully.`));
8862
8862
  } else {
8863
- console.error(import_picocolors13.default.red(`
8863
+ console.error(import_picocolors15.default.red(`
8864
8864
  Failed to install skill. Make sure npx is available.`));
8865
8865
  process.exit(1);
8866
8866
  }
@@ -8878,10 +8878,10 @@ Failed to install skill. Make sure npx is available.`));
8878
8878
  stdio: "inherit"
8879
8879
  });
8880
8880
  clearInstalledSha();
8881
- console.log(import_picocolors13.default.green(`
8881
+ console.log(import_picocolors15.default.green(`
8882
8882
  ✓ Skills removed.`));
8883
8883
  } catch {
8884
- console.error(import_picocolors13.default.red(`
8884
+ console.error(import_picocolors15.default.red(`
8885
8885
  Failed to remove skills.`));
8886
8886
  process.exit(1);
8887
8887
  }
@@ -8890,21 +8890,21 @@ Failed to remove skills.`));
8890
8890
  console.log(`Updating skills from ${SKILL_REPO}...`);
8891
8891
  const result = await installSkill();
8892
8892
  if (!result.success) {
8893
- console.error(import_picocolors13.default.red(`
8893
+ console.error(import_picocolors15.default.red(`
8894
8894
  Failed to update skill.`));
8895
8895
  process.exit(1);
8896
8896
  }
8897
- console.log(import_picocolors13.default.green(`
8897
+ console.log(import_picocolors15.default.green(`
8898
8898
  ✓ Skills updated.`));
8899
8899
  });
8900
8900
  return cmd;
8901
8901
  }
8902
- var import_picocolors13, SKILL_REPO = "dosu-ai/dosu-skill", SKILL_NAME = "dosu", SAFE_SKILL_NAME, SUPPORTED_SKILL_AGENTS, SKILL_AGENT_BY_PROVIDER;
8902
+ var import_picocolors15, SKILL_REPO = "dosu-ai/dosu-skill", SKILL_NAME = "dosu", SAFE_SKILL_NAME, SUPPORTED_SKILL_AGENTS, SKILL_AGENT_BY_PROVIDER;
8903
8903
  var init_skill = __esm(() => {
8904
8904
  init_commander();
8905
8905
  init_logger();
8906
8906
  init_skill_update_check();
8907
- import_picocolors13 = __toESM(require_picocolors(), 1);
8907
+ import_picocolors15 = __toESM(require_picocolors(), 1);
8908
8908
  SAFE_SKILL_NAME = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
8909
8909
  SUPPORTED_SKILL_AGENTS = [
8910
8910
  "claude-code",
@@ -8935,7 +8935,7 @@ var init_skill = __esm(() => {
8935
8935
  });
8936
8936
 
8937
8937
  // src/mcp/constants.ts
8938
- var MCP_PROVIDER_SLUG = "dosu_mcp";
8938
+ var MCP_PROVIDER_SLUG2 = "dosu_mcp";
8939
8939
 
8940
8940
  // node_modules/signal-exit/dist/cjs/signals.js
8941
8941
  var require_signals = __commonJS((exports) => {
@@ -10593,7 +10593,7 @@ var init_settings = __esm(() => {
10593
10593
  });
10594
10594
 
10595
10595
  // src/telemetry/debug-id.ts
10596
- var BUNDLE_DEBUG_ID_PLACEHOLDER = "d08d0e8f-b86e-9699-6475-6e2164756e21";
10596
+ var BUNDLE_DEBUG_ID_PLACEHOLDER = "9d873764-f667-b08c-6475-6e2164756e21";
10597
10597
 
10598
10598
  // src/telemetry/telemetry.ts
10599
10599
  import { randomUUID as randomUUID3 } from "node:crypto";
@@ -11133,8 +11133,8 @@ function safeUuid(generate) {
11133
11133
  }
11134
11134
  }
11135
11135
  function eventId(generate) {
11136
- const uuid = safeUuid(generate);
11137
- return uuid?.replaceAll("-", "");
11136
+ const uuid2 = safeUuid(generate);
11137
+ return uuid2?.replaceAll("-", "");
11138
11138
  }
11139
11139
  function createCommandTelemetry(settings2, dependencies = {}) {
11140
11140
  const env = dependencies.env ?? process.env;
@@ -12728,7 +12728,7 @@ async function stepSelectDeployment(apiClient, org) {
12728
12728
  ${dim(deployments[0].name)}`);
12729
12729
  return deployments[0];
12730
12730
  }
12731
- const mcpDeployments = deployments.filter((d2) => d2.provider_slug === MCP_PROVIDER_SLUG);
12731
+ const mcpDeployments = deployments.filter((d2) => d2.provider_slug === MCP_PROVIDER_SLUG2);
12732
12732
  if (mcpDeployments.length === 1) {
12733
12733
  logger.info("setup", `Selected deployment: ${mcpDeployments[0].name} (auto, single MCP)`);
12734
12734
  log.success(`Using MCP
@@ -12908,7 +12908,7 @@ function createDotsSpinner() {
12908
12908
  let current = "";
12909
12909
  const isTTY = Boolean(process.stdout.isTTY) && process.env.CI !== "true";
12910
12910
  const draw = () => {
12911
- process.stdout.write(`\r\x1B[2K${import_picocolors14.default.cyan(SPINNER_FRAMES[frameIdx])} ${current}`);
12911
+ process.stdout.write(`\r\x1B[2K${import_picocolors16.default.cyan(SPINNER_FRAMES[frameIdx])} ${current}`);
12912
12912
  frameIdx = (frameIdx + 1) % SPINNER_FRAMES.length;
12913
12913
  };
12914
12914
  return {
@@ -12930,7 +12930,7 @@ function createDotsSpinner() {
12930
12930
  clearInterval(timer);
12931
12931
  timer = undefined;
12932
12932
  }
12933
- const symbol3 = code === 0 ? import_picocolors14.default.green("✓") : import_picocolors14.default.red("✗");
12933
+ const symbol3 = code === 0 ? import_picocolors16.default.green("✓") : import_picocolors16.default.red("✗");
12934
12934
  if (isTTY) {
12935
12935
  process.stdout.write(`\r\x1B[2K${symbol3} ${msg}
12936
12936
  `);
@@ -13071,18 +13071,18 @@ async function runInsights(cfg, runner) {
13071
13071
  runner.writeFile(latestPath, html);
13072
13072
  runner.prune(insightsDir(), KEEP_REPORTS);
13073
13073
  console.log("");
13074
- console.log(import_picocolors14.default.bold(`\uD83D\uDCCA Dosu Insights · ${report.spaceName}`));
13074
+ console.log(import_picocolors16.default.bold(`\uD83D\uDCCA Dosu Insights · ${report.spaceName}`));
13075
13075
  if (report.cheers[0]) {
13076
- console.log(import_picocolors14.default.green(` ${report.cheers[0]}`));
13076
+ console.log(import_picocolors16.default.green(` ${report.cheers[0]}`));
13077
13077
  }
13078
13078
  console.log("");
13079
- console.log(` Snapshot: ${import_picocolors14.default.cyan(`file://${snapshotPath}`)}`);
13080
- console.log(` Latest: ${import_picocolors14.default.cyan(`file://${latestPath}`)}`);
13081
- console.log(import_picocolors14.default.dim(" Opening in your browser..."));
13079
+ console.log(` Snapshot: ${import_picocolors16.default.cyan(`file://${snapshotPath}`)}`);
13080
+ console.log(` Latest: ${import_picocolors16.default.cyan(`file://${latestPath}`)}`);
13081
+ console.log(import_picocolors16.default.dim(" Opening in your browser..."));
13082
13082
  try {
13083
13083
  await runner.openInBrowser(snapshotPath);
13084
13084
  } catch {
13085
- console.log(import_picocolors14.default.dim(" (couldn't auto-open. Copy the link above.)"));
13085
+ console.log(import_picocolors16.default.dim(" (couldn't auto-open. Copy the link above.)"));
13086
13086
  }
13087
13087
  return snapshotPath;
13088
13088
  }
@@ -13109,7 +13109,7 @@ async function executeInsights(cfg) {
13109
13109
  try {
13110
13110
  await runInsights(cfg, defaultRunner(cfg));
13111
13111
  } catch (err) {
13112
- console.error(import_picocolors14.default.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
13112
+ console.error(import_picocolors16.default.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
13113
13113
  }
13114
13114
  }
13115
13115
  function insightsCommand() {
@@ -13120,12 +13120,12 @@ function insightsCommand() {
13120
13120
  try {
13121
13121
  await runInsights(cfg, defaultRunner(cfg));
13122
13122
  } catch (err) {
13123
- console.error(import_picocolors14.default.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
13123
+ console.error(import_picocolors16.default.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
13124
13124
  process.exit(1);
13125
13125
  }
13126
13126
  });
13127
13127
  }
13128
- var import_picocolors14, ASK_TIMEOUT_MS = 90000, KEEP_REPORTS = 20, REPORT_FILE_PATTERN, HINT_INTERVAL_MS = 6000, NARRATIVE_HINTS, SPINNER_FRAMES, SPINNER_INTERVAL_MS = 80;
13128
+ var import_picocolors16, ASK_TIMEOUT_MS = 90000, KEEP_REPORTS = 20, REPORT_FILE_PATTERN, HINT_INTERVAL_MS = 6000, NARRATIVE_HINTS, SPINNER_FRAMES, SPINNER_INTERVAL_MS = 80;
13129
13129
  var init_insights3 = __esm(() => {
13130
13130
  init_dist8();
13131
13131
  init_commander();
@@ -13134,7 +13134,7 @@ var init_insights3 = __esm(() => {
13134
13134
  init_logger();
13135
13135
  init_insights2();
13136
13136
  init_flow2();
13137
- import_picocolors14 = __toESM(require_picocolors(), 1);
13137
+ import_picocolors16 = __toESM(require_picocolors(), 1);
13138
13138
  REPORT_FILE_PATTERN = /^report-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z\.html$/;
13139
13139
  NARRATIVE_HINTS = [
13140
13140
  "Reading your reactions and confidence levels",
@@ -13163,7 +13163,7 @@ __export(exports_tui, {
13163
13163
  handleLogout: () => handleLogout
13164
13164
  });
13165
13165
  async function runTUI() {
13166
- console.log(import_picocolors26.default.magenta(LOGO));
13166
+ console.log(import_picocolors29.default.magenta(LOGO));
13167
13167
  const cfg = loadConfig();
13168
13168
  while (true) {
13169
13169
  const insightsReady = Boolean(cfg.active_account?.target?.space_id && cfg.active_account?.target?.deployment_id && cfg.active_account?.target?.api_key);
@@ -13277,7 +13277,7 @@ function handleLogout(cfg) {
13277
13277
  saveConfig(cfg);
13278
13278
  log.success("Credentials cleared.");
13279
13279
  }
13280
- var import_picocolors26, LOGO = `
13280
+ var import_picocolors29, LOGO = `
13281
13281
  /$$$$$$$
13282
13282
  | $$__ $$
13283
13283
  | $$ \\ $$ /$$$$$$ /$$$$$$$ /$$ /$$
@@ -13294,7 +13294,7 @@ var init_tui = __esm(() => {
13294
13294
  init_config();
13295
13295
  init_flow2();
13296
13296
  init_styles();
13297
- import_picocolors26 = __toESM(require_picocolors(), 1);
13297
+ import_picocolors29 = __toESM(require_picocolors(), 1);
13298
13298
  });
13299
13299
 
13300
13300
  // src/auth/ticket.ts
@@ -13813,7 +13813,7 @@ async function resolveDeployment2(client, cfg, opts) {
13813
13813
  });
13814
13814
  return { code: 1, cfg };
13815
13815
  }
13816
- const mcpDeployments = allDeployments.filter((d) => d.provider_slug === MCP_PROVIDER_SLUG);
13816
+ const mcpDeployments = allDeployments.filter((d) => d.provider_slug === MCP_PROVIDER_SLUG2);
13817
13817
  if (mcpDeployments.length === 0) {
13818
13818
  emitError({
13819
13819
  step: "deployment",
@@ -13934,10 +13934,80 @@ import {
13934
13934
  unlinkSync as unlinkSync5
13935
13935
  } from "node:fs";
13936
13936
 
13937
- // src/commands/analytics.ts
13937
+ // src/commands/agents.ts
13938
13938
  init_commander();
13939
13939
  init_trpc();
13940
- var import_picocolors4 = __toESM(require_picocolors(), 1);
13940
+ var import_picocolors5 = __toESM(require_picocolors(), 1);
13941
+
13942
+ // src/commands/arguments.ts
13943
+ init_commander();
13944
+ function positiveInteger(value) {
13945
+ const parsed = Number(value);
13946
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) {
13947
+ throw new InvalidArgumentError("must be a positive integer");
13948
+ }
13949
+ return parsed;
13950
+ }
13951
+ function positiveIntegerAtMost(maximum) {
13952
+ return (value) => {
13953
+ const parsed = positiveInteger(value);
13954
+ if (parsed > maximum) {
13955
+ throw new InvalidArgumentError(`must be at most ${maximum}`);
13956
+ }
13957
+ return parsed;
13958
+ };
13959
+ }
13960
+ function messageLimit(value) {
13961
+ const parsed = Number(value);
13962
+ if (!Number.isSafeInteger(parsed) || parsed !== -1 && parsed <= 0) {
13963
+ throw new InvalidArgumentError("must be -1 or a positive integer");
13964
+ }
13965
+ return parsed;
13966
+ }
13967
+ function uuid(value) {
13968
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value)) {
13969
+ throw new InvalidArgumentError("must be a UUID");
13970
+ }
13971
+ return value;
13972
+ }
13973
+ function uuidV4(value) {
13974
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value)) {
13975
+ throw new InvalidArgumentError("must be a UUID v4");
13976
+ }
13977
+ return value;
13978
+ }
13979
+ function jsonValue(value) {
13980
+ try {
13981
+ return JSON.parse(value);
13982
+ } catch {
13983
+ throw new InvalidArgumentError("must be valid JSON");
13984
+ }
13985
+ }
13986
+ function jsonStringArray(value) {
13987
+ const parsed = jsonValue(value);
13988
+ if (!Array.isArray(parsed) || !parsed.every((item) => typeof item === "string")) {
13989
+ throw new InvalidArgumentError("must be a JSON array of strings");
13990
+ }
13991
+ return parsed;
13992
+ }
13993
+ function onOrOff(value) {
13994
+ if (value === "on")
13995
+ return true;
13996
+ if (value === "off")
13997
+ return false;
13998
+ throw new InvalidArgumentError("must be 'on' or 'off'");
13999
+ }
14000
+ function boundedText(maximum) {
14001
+ return (value) => {
14002
+ const trimmed = value.trim();
14003
+ if (!trimmed)
14004
+ throw new InvalidArgumentError("must not be empty");
14005
+ if (trimmed.length > maximum) {
14006
+ throw new InvalidArgumentError(`must be at most ${maximum} characters`);
14007
+ }
14008
+ return trimmed;
14009
+ };
14010
+ }
13941
14011
 
13942
14012
  // src/commands/auth.ts
13943
14013
  init_config();
@@ -13950,6 +14020,15 @@ function requireLoginConfig() {
13950
14020
  }
13951
14021
  return cfg;
13952
14022
  }
14023
+ function requireOrgConfig() {
14024
+ const cfg = requireLoginConfig();
14025
+ const orgId = cfg.active_account?.target?.org_id;
14026
+ if (!orgId) {
14027
+ console.error(import_picocolors2.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
14028
+ process.exit(1);
14029
+ }
14030
+ return { cfg, orgId };
14031
+ }
13953
14032
  function requireAPIKey(cfg) {
13954
14033
  if (!cfg.active_account?.target?.api_key) {
13955
14034
  console.error(import_picocolors2.default.red("API key not configured. Run 'dosu setup' first."));
@@ -13958,6 +14037,10 @@ function requireAPIKey(cfg) {
13958
14037
  return cfg.active_account?.target?.api_key;
13959
14038
  }
13960
14039
 
14040
+ // src/commands/confirmation.ts
14041
+ init_dist8();
14042
+ var import_picocolors4 = __toESM(require_picocolors(), 1);
14043
+
13961
14044
  // src/commands/output.ts
13962
14045
  var import_picocolors3 = __toESM(require_picocolors(), 1);
13963
14046
  var stripAnsi = (str) => str.replace(/\x1b\[[0-9;]*m/g, "");
@@ -13977,14 +14060,14 @@ function printTable(headers, rows, opts = {}) {
13977
14060
  console.log(import_picocolors3.default.dim("No results found."));
13978
14061
  return;
13979
14062
  }
13980
- const widths = headers.map((h, i) => Math.max(h.length, ...rows.map((r) => stripAnsi(r[i] ?? "").length)));
13981
- const headerLine = headers.map((h, i) => h.padEnd(widths[i])).join(" ");
14063
+ const widths = headers.map((h2, i2) => Math.max(h2.length, ...rows.map((r2) => stripAnsi(r2[i2] ?? "").length)));
14064
+ const headerLine = headers.map((h2, i2) => h2.padEnd(widths[i2])).join(" ");
13982
14065
  console.log(import_picocolors3.default.bold(headerLine));
13983
14066
  console.log(import_picocolors3.default.dim("─".repeat(headerLine.length)));
13984
14067
  for (const row of rows) {
13985
- console.log(row.map((cell, i) => {
14068
+ console.log(row.map((cell, i2) => {
13986
14069
  const s = cell ?? "";
13987
- const pad = Math.max(0, widths[i] - stripAnsi(s).length);
14070
+ const pad = Math.max(0, widths[i2] - stripAnsi(s).length);
13988
14071
  return s + " ".repeat(pad);
13989
14072
  }).join(" "));
13990
14073
  }
@@ -14017,22 +14100,203 @@ function formatDate(dateStr) {
14017
14100
  });
14018
14101
  }
14019
14102
 
14103
+ // src/commands/confirmation.ts
14104
+ async function confirmAction({
14105
+ confirmed,
14106
+ json,
14107
+ message,
14108
+ preview
14109
+ }) {
14110
+ if (confirmed)
14111
+ return true;
14112
+ if (!json && process.stdin?.isTTY) {
14113
+ const answer = await confirm({ message, initialValue: false });
14114
+ if (isCancel(answer)) {
14115
+ console.log(import_picocolors4.default.dim("Cancelled."));
14116
+ return false;
14117
+ }
14118
+ if (answer === true)
14119
+ return true;
14120
+ }
14121
+ if (json) {
14122
+ printResult({ ...preview, applied: false, confirmRequired: true }, { json: true });
14123
+ } else {
14124
+ console.log(import_picocolors4.default.dim("Aborted. Re-run with --confirm to apply."));
14125
+ }
14126
+ return false;
14127
+ }
14128
+
14129
+ // src/commands/agents.ts
14130
+ function validateConfigPath(path2) {
14131
+ if (path2.length > 200) {
14132
+ throw new InvalidArgumentError("must be at most 200 characters");
14133
+ }
14134
+ const parts = path2.split(".");
14135
+ if (parts.some((part) => !part || part.trim() !== part || ["__proto__", "constructor", "prototype"].includes(part))) {
14136
+ throw new InvalidArgumentError("must be a dot-separated config leaf path");
14137
+ }
14138
+ return path2;
14139
+ }
14140
+ function agentsCommand() {
14141
+ const cmd = new Command("agents").description("Manage Dosu agents");
14142
+ cmd.command("list").description("List configurable agents in the selected organization").option("--json", "Output as JSON").action(async (opts) => {
14143
+ const { cfg, orgId } = requireOrgConfig();
14144
+ const agents = await createTypedClient(cfg).agents.list.query({ org_id: orgId });
14145
+ if (opts.json)
14146
+ return printResult(agents, opts);
14147
+ printTable(["ID", "Name", "Provider", "Library", "Status"], agents.map((agent) => [
14148
+ agent.deployment_id.slice(0, 8),
14149
+ agent.name,
14150
+ agent.provider_slug,
14151
+ agent.space_id.slice(0, 8),
14152
+ agent.enabled ? "active" : "disabled"
14153
+ ]), { rawData: agents });
14154
+ });
14155
+ cmd.command("info").description("Show an agent").argument("<agent-id>", "Agent ID", uuidV4).option("--json", "Output as JSON").action(async (agentId, opts) => {
14156
+ const { cfg } = requireOrgConfig();
14157
+ const agent = await createTypedClient(cfg).agents.get.query(agentId);
14158
+ if (opts.json)
14159
+ return printResult(agent, opts);
14160
+ printInfo([
14161
+ ["ID", agent.deployment_id],
14162
+ ["Name", agent.name],
14163
+ ["Provider", agent.provider_slug],
14164
+ ["Library", agent.space_id],
14165
+ ["Status", agent.enabled ? "active" : "disabled"],
14166
+ ["Guidelines", agent.response_guidelines ?? undefined],
14167
+ ["Updated", formatDate(agent.updated_at)]
14168
+ ], { rawData: agent });
14169
+ });
14170
+ cmd.command("create").description("Create a safe Mention-only agent from an existing data source").requiredOption("--library <id>", "Library ID", uuidV4).requiredOption("--source <id>", "Data source ID", uuidV4).option("--name <name>", "Agent name", boundedText(80)).option("--guidelines <text>", "Response guidelines").option("--json", "Output as JSON").action(async (opts) => {
14171
+ if (opts.guidelines && opts.guidelines.length > 20000) {
14172
+ throw new InvalidArgumentError("--guidelines must be at most 20000 characters");
14173
+ }
14174
+ const { cfg, orgId } = requireOrgConfig();
14175
+ const agent = await createTypedClient(cfg).agents.create.mutate({
14176
+ data_source_id: opts.source,
14177
+ name: opts.name,
14178
+ org_id: orgId,
14179
+ response_guidelines: opts.guidelines,
14180
+ space_id: opts.library
14181
+ });
14182
+ if (opts.json)
14183
+ return printResult(agent, opts);
14184
+ console.log(import_picocolors5.default.green(`Created agent '${agent.name}' (${agent.deployment_id}).`));
14185
+ });
14186
+ cmd.command("update").description("Update an agent (requires confirmation)").argument("<agent-id>", "Agent ID", uuidV4).option("--name <name>", "New name", boundedText(80)).addOption(new Option("--enabled <on|off>", "Enable or disable the agent").argParser(onOrOff)).addOption(new Option("--guidelines <text>", "Replace response guidelines").conflicts("clearGuidelines")).addOption(new Option("--clear-guidelines", "Clear response guidelines").conflicts("guidelines")).option("--confirm", "Apply without the interactive prompt").option("--json", "Output as JSON").action(async (agentId, opts) => {
14187
+ if (opts.name === undefined && opts.enabled === undefined && opts.guidelines === undefined && !opts.clearGuidelines) {
14188
+ throw new InvalidArgumentError("specify --name, --enabled, --guidelines, or --clear-guidelines");
14189
+ }
14190
+ if (opts.guidelines && opts.guidelines.length > 20000) {
14191
+ throw new InvalidArgumentError("--guidelines must be at most 20000 characters");
14192
+ }
14193
+ const responseGuidelines = opts.clearGuidelines ? null : opts.guidelines;
14194
+ if (!await confirmAction({
14195
+ confirmed: opts.confirm,
14196
+ json: opts.json,
14197
+ message: "Update this agent?",
14198
+ preview: {
14199
+ action: "update_agent",
14200
+ id: agentId,
14201
+ name: opts.name,
14202
+ enabled: opts.enabled,
14203
+ response_guidelines: responseGuidelines
14204
+ }
14205
+ }))
14206
+ return;
14207
+ const { cfg } = requireOrgConfig();
14208
+ const agent = await createTypedClient(cfg).agents.update.mutate({
14209
+ deployment_id: agentId,
14210
+ enabled: opts.enabled,
14211
+ name: opts.name,
14212
+ response_guidelines: responseGuidelines
14213
+ });
14214
+ if (opts.json)
14215
+ return printResult(agent, opts);
14216
+ console.log(import_picocolors5.default.green(`Updated agent '${agent.name}'.`));
14217
+ });
14218
+ cmd.command("delete").description("Delete an agent (requires confirmation)").argument("<agent-id>", "Agent ID", uuidV4).option("--confirm", "Apply without the interactive prompt").option("--json", "Output as JSON").action(async (agentId, opts) => {
14219
+ if (!await confirmAction({
14220
+ confirmed: opts.confirm,
14221
+ json: opts.json,
14222
+ message: "Delete this agent?",
14223
+ preview: { action: "delete_agent", id: agentId }
14224
+ }))
14225
+ return;
14226
+ const { cfg } = requireOrgConfig();
14227
+ const result = await createTypedClient(cfg).agents.delete.mutate(agentId);
14228
+ if (opts.json)
14229
+ return printResult(result, opts);
14230
+ console.log(import_picocolors5.default.green(`Deleted agent ${agentId}.`));
14231
+ });
14232
+ cmd.command("move").description("Move an agent to another library (requires confirmation)").argument("<agent-id>", "Agent ID", uuidV4).requiredOption("--library <id>", "Destination library ID", uuidV4).option("--confirm", "Apply without the interactive prompt").option("--json", "Output as JSON").action(async (agentId, opts) => {
14233
+ if (!await confirmAction({
14234
+ confirmed: opts.confirm,
14235
+ json: opts.json,
14236
+ message: "Move this agent to another library?",
14237
+ preview: { action: "move_agent", id: agentId, library_id: opts.library }
14238
+ }))
14239
+ return;
14240
+ const { cfg } = requireOrgConfig();
14241
+ const result = await createTypedClient(cfg).agents.move.mutate({
14242
+ deployment_id: agentId,
14243
+ space_id: opts.library
14244
+ });
14245
+ if (opts.json)
14246
+ return printResult(result, opts);
14247
+ console.log(import_picocolors5.default.green(`Moved agent '${result.name}' to library ${result.space_id}.`));
14248
+ });
14249
+ const config = cmd.command("config").description("Read or patch agent configuration");
14250
+ config.command("get").description("Show agent configuration").argument("<agent-id>", "Agent ID", uuidV4).option("--json", "Output as JSON").action(async (agentId, opts) => {
14251
+ const { cfg } = requireOrgConfig();
14252
+ const result = await createTypedClient(cfg).agents.getConfig.query(agentId);
14253
+ if (opts.json)
14254
+ return printResult(result, opts);
14255
+ printResult(result.config, opts);
14256
+ });
14257
+ config.command("set").description("Set one existing config leaf (requires confirmation)").argument("<agent-id>", "Agent ID", uuidV4).argument("<path>", "Dot-separated config leaf path", validateConfigPath).requiredOption("--value <json>", "New value as JSON", jsonValue).option("--confirm", "Apply without the interactive prompt").option("--json", "Output as JSON").action(async (agentId, path2, opts) => {
14258
+ if (!await confirmAction({
14259
+ confirmed: opts.confirm,
14260
+ json: opts.json,
14261
+ message: `Set agent config '${path2}'?`,
14262
+ preview: { action: "set_agent_config", id: agentId, path: path2, value: opts.value }
14263
+ }))
14264
+ return;
14265
+ const { cfg } = requireOrgConfig();
14266
+ const client = createTypedClient(cfg);
14267
+ const current = await client.agents.getConfig.query(agentId);
14268
+ const result = await client.agents.setConfig.mutate({
14269
+ deployment_id: agentId,
14270
+ expected_updated_at: current.updated_at,
14271
+ path: path2,
14272
+ value: opts.value
14273
+ });
14274
+ if (opts.json)
14275
+ return printResult(result, opts);
14276
+ console.log(import_picocolors5.default.green(`Updated agent config '${path2}'.`));
14277
+ });
14278
+ return cmd;
14279
+ }
14280
+
14020
14281
  // src/commands/analytics.ts
14282
+ init_commander();
14283
+ init_trpc();
14284
+ var import_picocolors6 = __toESM(require_picocolors(), 1);
14021
14285
  function requireConfig() {
14022
14286
  const cfg = requireLoginConfig();
14023
14287
  if (!cfg.active_account?.target?.space_id) {
14024
- console.error(import_picocolors4.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
14288
+ console.error(import_picocolors6.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
14025
14289
  process.exit(1);
14026
14290
  }
14027
14291
  return cfg;
14028
14292
  }
14029
14293
  function analyticsCommand() {
14030
- const cmd = new Command("analytics").description("View usage statistics").option("--days <n>", "Number of days to analyze (default: 30)", "30").option("--json", "Output as JSON").action(async (opts) => {
14294
+ const cmd = new Command("analytics").description("View usage statistics").addOption(new Option("--days <n>", "Number of days to analyze (default: 30)").argParser(positiveInteger).default(30)).option("--json", "Output as JSON").action(async (opts) => {
14031
14295
  const cfg = requireConfig();
14032
14296
  const client = createTypedClient(cfg);
14033
14297
  const stats = await client.analytics.getUsageStats.query({
14034
14298
  spaceId: cfg.active_account.target.space_id,
14035
- days: Number.parseInt(opts.days ?? "30", 10)
14299
+ days: opts.days
14036
14300
  });
14037
14301
  if (opts.json) {
14038
14302
  printResult(stats, opts);
@@ -14058,16 +14322,16 @@ function analyticsCommand() {
14058
14322
  init_commander();
14059
14323
  init_config();
14060
14324
  init_logger();
14061
- var import_picocolors5 = __toESM(require_picocolors(), 1);
14325
+ var import_picocolors7 = __toESM(require_picocolors(), 1);
14062
14326
  var DEFAULT_TIMEOUT_SECONDS = 600;
14063
14327
  function requireConfig2() {
14064
14328
  const cfg = loadConfig();
14065
14329
  if (!cfg.active_account?.target?.api_key) {
14066
- console.error(import_picocolors5.default.red("Not configured. Run 'dosu setup' first."));
14330
+ console.error(import_picocolors7.default.red("Not configured. Run 'dosu setup' first."));
14067
14331
  process.exit(1);
14068
14332
  }
14069
14333
  if (!cfg.active_account?.target?.deployment_id || !cfg.active_account?.target?.space_id) {
14070
- console.error(import_picocolors5.default.red("Missing deployment config. Run 'dosu setup' to reconfigure."));
14334
+ console.error(import_picocolors7.default.red("Missing deployment config. Run 'dosu setup' to reconfigure."));
14071
14335
  process.exit(1);
14072
14336
  }
14073
14337
  return cfg;
@@ -14077,14 +14341,14 @@ function askCommand() {
14077
14341
  const cfg = requireConfig2();
14078
14342
  const backendURL = getBackendURL();
14079
14343
  if (!backendURL) {
14080
- console.error(import_picocolors5.default.red("Backend URL not configured."));
14344
+ console.error(import_picocolors7.default.red("Backend URL not configured."));
14081
14345
  process.exit(1);
14082
14346
  }
14083
14347
  let timeoutSeconds = DEFAULT_TIMEOUT_SECONDS;
14084
14348
  if (opts.timeout !== undefined) {
14085
14349
  timeoutSeconds = Number(opts.timeout);
14086
14350
  if (!Number.isFinite(timeoutSeconds) || timeoutSeconds <= 0) {
14087
- console.error(import_picocolors5.default.red("--timeout must be a positive number of seconds."));
14351
+ console.error(import_picocolors7.default.red("--timeout must be a positive number of seconds."));
14088
14352
  process.exit(1);
14089
14353
  }
14090
14354
  }
@@ -14112,7 +14376,7 @@ function askCommand() {
14112
14376
  const raw = errBody.detail ?? detail;
14113
14377
  detail = typeof raw === "string" ? raw : JSON.stringify(raw, null, 2);
14114
14378
  } catch {}
14115
- console.error(import_picocolors5.default.red(`Error: ${detail}`));
14379
+ console.error(import_picocolors7.default.red(`Error: ${detail}`));
14116
14380
  process.exit(1);
14117
14381
  }
14118
14382
  const body = await resp.json();
@@ -14127,18 +14391,18 @@ function askCommand() {
14127
14391
  }
14128
14392
  if (body.session_id) {
14129
14393
  console.log(`
14130
- ${import_picocolors5.default.dim(`Session: ${body.session_id}`)}`);
14394
+ ${import_picocolors7.default.dim(`Session: ${body.session_id}`)}`);
14131
14395
  }
14132
14396
  if (body.observations && body.observations.length > 0) {
14133
14397
  console.log(`
14134
- ${import_picocolors5.default.bold("Key observations:")}`);
14398
+ ${import_picocolors7.default.bold("Key observations:")}`);
14135
14399
  for (const obs of body.observations) {
14136
- console.log(` ${import_picocolors5.default.dim("•")} ${obs}`);
14400
+ console.log(` ${import_picocolors7.default.dim("•")} ${obs}`);
14137
14401
  }
14138
14402
  }
14139
14403
  } catch (err) {
14140
14404
  if (err instanceof Error && err.name === "AbortError") {
14141
- console.error(import_picocolors5.default.red("Request timed out."));
14405
+ console.error(import_picocolors7.default.red("Request timed out."));
14142
14406
  process.exit(1);
14143
14407
  }
14144
14408
  throw err;
@@ -14154,7 +14418,7 @@ init_dist8();
14154
14418
  init_commander();
14155
14419
  init_trpc();
14156
14420
  init_logger();
14157
- var import_picocolors9 = __toESM(require_picocolors(), 1);
14421
+ var import_picocolors11 = __toESM(require_picocolors(), 1);
14158
14422
  import { existsSync as existsSync5, readFileSync as readFileSync5, rmSync, writeFileSync as writeFileSync5 } from "node:fs";
14159
14423
  import { dirname, join as join5 } from "node:path";
14160
14424
 
@@ -14258,7 +14522,7 @@ var DEFAULT_DEPLOYMENT_CONFIG_GITHUB = {
14258
14522
 
14259
14523
  // src/setup/github-repo-prompt.ts
14260
14524
  init_dist7();
14261
- var import_picocolors6 = __toESM(require_picocolors(), 1);
14525
+ var import_picocolors8 = __toESM(require_picocolors(), 1);
14262
14526
 
14263
14527
  // src/setup/prompt-symbols.ts
14264
14528
  var unicode2 = supportsUnicode();
@@ -14376,33 +14640,33 @@ class GitHubRepoPrompt extends V {
14376
14640
  this.selected = this.selected.length === repoValues.length ? [] : repoValues;
14377
14641
  }
14378
14642
  renderPrompt() {
14379
- const symbolByState = this.state === "submit" ? import_picocolors6.default.green(SUBMIT_SYMBOL) : this.state === "cancel" ? import_picocolors6.default.red(CANCEL_SYMBOL2) : import_picocolors6.default.cyan(ACTIVE_SYMBOL);
14380
- const header = `${import_picocolors6.default.gray(BAR)}
14643
+ const symbolByState = this.state === "submit" ? import_picocolors8.default.green(SUBMIT_SYMBOL) : this.state === "cancel" ? import_picocolors8.default.red(CANCEL_SYMBOL2) : import_picocolors8.default.cyan(ACTIVE_SYMBOL);
14644
+ const header = `${import_picocolors8.default.gray(BAR)}
14381
14645
  ${symbolByState} ${this.message}
14382
14646
  `;
14383
14647
  if (this.state === "submit") {
14384
- return `${header}${import_picocolors6.default.gray(BAR)} ${import_picocolors6.default.dim(this.submitLabel())}`;
14648
+ return `${header}${import_picocolors8.default.gray(BAR)} ${import_picocolors8.default.dim(this.submitLabel())}`;
14385
14649
  }
14386
14650
  if (this.state === "cancel") {
14387
- return `${header}${import_picocolors6.default.gray(BAR)}`;
14651
+ return `${header}${import_picocolors8.default.gray(BAR)}`;
14388
14652
  }
14389
14653
  const body = visibleOptions(this.cursor, this.options, this.maxItems).map((option) => {
14390
14654
  if (option.kind === "ellipsis") {
14391
- return `${import_picocolors6.default.gray(BAR)} ${import_picocolors6.default.dim(ELLIPSIS)}`;
14655
+ return `${import_picocolors8.default.gray(BAR)} ${import_picocolors8.default.dim(ELLIPSIS)}`;
14392
14656
  }
14393
14657
  const current = this.options[option.index];
14394
14658
  if (current.kind === "separator") {
14395
- return `${import_picocolors6.default.gray(BAR)} ${import_picocolors6.default.dim(SEPARATOR_LINE)}`;
14659
+ return `${import_picocolors8.default.gray(BAR)} ${import_picocolors8.default.dim(SEPARATOR_LINE)}`;
14396
14660
  }
14397
14661
  const isActive = option.index === this.cursor;
14398
- const marker = current.kind === "action" ? isActive ? import_picocolors6.default.cyan(ACTION_ARROW) : import_picocolors6.default.dim(ACTION_ARROW) : this.selected.includes(current.value) ? isActive ? import_picocolors6.default.cyan(CHECKBOX_ON) : CHECKBOX_ON : isActive ? import_picocolors6.default.cyan(CHECKBOX_OFF) : CHECKBOX_OFF;
14399
- const label = isActive ? import_picocolors6.default.cyan(current.label) : current.label;
14400
- const hint = current.hint ? ` ${import_picocolors6.default.dim(`(${current.hint})`)}` : "";
14401
- return `${import_picocolors6.default.gray(BAR)} ${marker} ${label}${hint}`;
14662
+ const marker = current.kind === "action" ? isActive ? import_picocolors8.default.cyan(ACTION_ARROW) : import_picocolors8.default.dim(ACTION_ARROW) : this.selected.includes(current.value) ? isActive ? import_picocolors8.default.cyan(CHECKBOX_ON) : CHECKBOX_ON : isActive ? import_picocolors8.default.cyan(CHECKBOX_OFF) : CHECKBOX_OFF;
14663
+ const label = isActive ? import_picocolors8.default.cyan(current.label) : current.label;
14664
+ const hint = current.hint ? ` ${import_picocolors8.default.dim(`(${current.hint})`)}` : "";
14665
+ return `${import_picocolors8.default.gray(BAR)} ${marker} ${label}${hint}`;
14402
14666
  });
14403
14667
  return `${header}${body.join(`
14404
14668
  `)}
14405
- ${import_picocolors6.default.cyan(FOOTER)}`;
14669
+ ${import_picocolors8.default.cyan(FOOTER)}`;
14406
14670
  }
14407
14671
  submitLabel() {
14408
14672
  if (typeof this.value === "string") {
@@ -14666,6 +14930,26 @@ var REPO_REFRESH_POLL_TIMEOUT_MS = 1e4;
14666
14930
  var REPO_MULTISELECT_MAX_ITEMS = 10;
14667
14931
  var DATA_SOURCE_VERIFY_POLL_INTERVAL_MS = 1000;
14668
14932
  var DATA_SOURCE_VERIFY_POLL_TIMEOUT_MS = 1e4;
14933
+ function parseAvailableRepos(value) {
14934
+ if (!Array.isArray(value))
14935
+ throw new Error("githubRepository.listForOrg returned a non-array");
14936
+ return value.map((repository, index) => {
14937
+ if (repository === null || typeof repository !== "object" || !("repository_id" in repository) || typeof repository.repository_id !== "number" || !("name" in repository) || typeof repository.name !== "string" || !("slug" in repository) || typeof repository.slug !== "string" || !("is_deployed" in repository) || typeof repository.is_deployed !== "boolean" || "created_at" in repository && repository.created_at !== undefined && typeof repository.created_at !== "string") {
14938
+ throw new Error(`githubRepository.listForOrg returned an invalid repository at index ${index}`);
14939
+ }
14940
+ return repository;
14941
+ });
14942
+ }
14943
+ function parseDeploymentIds(value) {
14944
+ if (!Array.isArray(value))
14945
+ throw new Error("workspaces.listForSpace returned a non-array");
14946
+ return value.map((deployment, index) => {
14947
+ if (deployment === null || typeof deployment !== "object" || !("deployment_id" in deployment) || typeof deployment.deployment_id !== "string") {
14948
+ throw new Error(`workspaces.listForSpace returned an invalid deployment at index ${index}`);
14949
+ }
14950
+ return deployment.deployment_id;
14951
+ });
14952
+ }
14669
14953
  function detectGitRepo(cwd = process.cwd()) {
14670
14954
  let url;
14671
14955
  try {
@@ -14689,9 +14973,9 @@ function detectGitRepo(cwd = process.cwd()) {
14689
14973
  }
14690
14974
  async function fetchListForOrg(trpc, orgID) {
14691
14975
  try {
14692
- const repos = await trpc.githubRepository.listForOrg.query({
14976
+ const repos = parseAvailableRepos(await trpc.githubRepository.listForOrg.query({
14693
14977
  org_id: orgID
14694
- });
14978
+ }));
14695
14979
  return sortReposByRecency(repos);
14696
14980
  } catch (err) {
14697
14981
  const msg = err instanceof Error ? err.message : String(err);
@@ -14831,9 +15115,9 @@ async function createDeploymentForRepo(trpc, orgID, spaceID, repo) {
14831
15115
  space_id: spaceID,
14832
15116
  data_source_ids: [dataSourceID]
14833
15117
  });
14834
- const spaceDeployments = await trpc.workspaces.listForSpace.query(spaceID);
14835
- await Promise.all(spaceDeployments.map((d) => trpc.deploymentDataSource.create.mutate({
14836
- deployment_id: d.deployment_id,
15118
+ const spaceDeploymentIds = parseDeploymentIds(await trpc.workspaces.listForSpace.query(spaceID));
15119
+ await Promise.all(spaceDeploymentIds.map((deploymentID) => trpc.deploymentDataSource.create.mutate({
15120
+ deployment_id: deploymentID,
14837
15121
  data_source_id: dataSourceID
14838
15122
  })));
14839
15123
  return {
@@ -15009,7 +15293,7 @@ ${dim(`deployment ${deployment_id}`)}`);
15009
15293
  // src/version/pending-tasks-check.ts
15010
15294
  init_config();
15011
15295
  init_logger();
15012
- var import_picocolors8 = __toESM(require_picocolors(), 1);
15296
+ var import_picocolors10 = __toESM(require_picocolors(), 1);
15013
15297
  import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
15014
15298
  import { join as join4 } from "node:path";
15015
15299
  var CACHE_FILENAME = "pending-tasks.json";
@@ -15074,11 +15358,11 @@ async function fetchTaskRun(backendURL, apiKey, taskId) {
15074
15358
  function displayTask(task) {
15075
15359
  if (task.prUrl) {
15076
15360
  console.error(`
15077
- ${import_picocolors8.default.green(`✓ Dosu PR ready (${task.repo}): ${task.prUrl}`)}
15361
+ ${import_picocolors10.default.green(`✓ Dosu PR ready (${task.repo}): ${task.prUrl}`)}
15078
15362
  `);
15079
15363
  } else {
15080
15364
  console.error(`
15081
- ${import_picocolors8.default.yellow(`✗ Dosu doc generation failed (${task.repo}): ${task.error}`)}
15365
+ ${import_picocolors10.default.yellow(`✗ Dosu doc generation failed (${task.repo}): ${task.error}`)}
15082
15366
  `);
15083
15367
  }
15084
15368
  }
@@ -15144,11 +15428,11 @@ var INDEX_POLL_TIMEOUT_MS = 120000;
15144
15428
  function requireConfig3() {
15145
15429
  const cfg = requireLoginConfig();
15146
15430
  if (!cfg.active_account?.target?.api_key) {
15147
- console.error(import_picocolors9.default.red("API key not configured. Run 'dosu setup' first."));
15431
+ console.error(import_picocolors11.default.red("API key not configured. Run 'dosu setup' first."));
15148
15432
  process.exit(1);
15149
15433
  }
15150
15434
  if (!cfg.active_account?.target?.org_id) {
15151
- console.error(import_picocolors9.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
15435
+ console.error(import_picocolors11.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
15152
15436
  process.exit(1);
15153
15437
  }
15154
15438
  return cfg;
@@ -15156,7 +15440,7 @@ function requireConfig3() {
15156
15440
  function requireBackendURL() {
15157
15441
  const backendURL = getBackendURL();
15158
15442
  if (!backendURL) {
15159
- console.error(import_picocolors9.default.red("Backend URL not configured."));
15443
+ console.error(import_picocolors11.default.red("Backend URL not configured."));
15160
15444
  process.exit(1);
15161
15445
  }
15162
15446
  return backendURL;
@@ -15232,25 +15516,25 @@ async function ensureSyncedRepo(cfg, client, detected, explicitDataSourceId, non
15232
15516
  let match = findMatch(sources, detected);
15233
15517
  if (!match) {
15234
15518
  if (nonInteractive) {
15235
- console.error(import_picocolors9.default.red(`${detected.slug} isn't connected to Dosu. Run 'dosu setup' to connect it first.`));
15519
+ console.error(import_picocolors11.default.red(`${detected.slug} isn't connected to Dosu. Run 'dosu setup' to connect it first.`));
15236
15520
  process.exit(1);
15237
15521
  }
15238
15522
  const connect = await confirm({
15239
15523
  message: `${detected.slug} isn't connected to Dosu. Connect and sync it now?`
15240
15524
  });
15241
15525
  if (isCancel(connect) || !connect) {
15242
- console.error(import_picocolors9.default.red(`Repo not connected. Run 'dosu setup' to connect ${detected.slug}, then retry.`));
15526
+ console.error(import_picocolors11.default.red(`Repo not connected. Run 'dosu setup' to connect ${detected.slug}, then retry.`));
15243
15527
  process.exit(1);
15244
15528
  }
15245
15529
  const result = await stepConnectGitHubRepo(cfg, detected);
15246
15530
  if (!result.has_connected_repo) {
15247
- console.error(import_picocolors9.default.red(`Could not connect ${detected.slug}. Run 'dosu setup' and retry.`));
15531
+ console.error(import_picocolors11.default.red(`Could not connect ${detected.slug}. Run 'dosu setup' and retry.`));
15248
15532
  process.exit(1);
15249
15533
  }
15250
15534
  sources = await listDataSources(client, orgID);
15251
15535
  match = findMatch(sources, detected);
15252
15536
  if (!match) {
15253
- console.error(import_picocolors9.default.red(`Could not find ${detected.slug} after connecting. Retry shortly.`));
15537
+ console.error(import_picocolors11.default.red(`Could not find ${detected.slug} after connecting. Retry shortly.`));
15254
15538
  process.exit(1);
15255
15539
  }
15256
15540
  }
@@ -15258,7 +15542,7 @@ async function ensureSyncedRepo(cfg, client, detected, explicitDataSourceId, non
15258
15542
  const indexed = await waitForIndexed(client, orgID, detected, nonInteractive);
15259
15543
  if (!indexed) {
15260
15544
  if (nonInteractive) {
15261
- console.error(import_picocolors9.default.red(`${detected.slug} is still indexing. Re-run once indexing finishes.`));
15545
+ console.error(import_picocolors11.default.red(`${detected.slug} is still indexing. Re-run once indexing finishes.`));
15262
15546
  process.exit(1);
15263
15547
  }
15264
15548
  log.info(`${detected.slug} is still indexing. Re-run 'dosu audit' in a few minutes once it's ready.`);
@@ -15267,14 +15551,14 @@ async function ensureSyncedRepo(cfg, client, detected, explicitDataSourceId, non
15267
15551
  match = indexed;
15268
15552
  }
15269
15553
  if (!match.data_source_id) {
15270
- console.error(import_picocolors9.default.red("Matched data source has no id. Run 'dosu setup' and retry."));
15554
+ console.error(import_picocolors11.default.red("Matched data source has no id. Run 'dosu setup' and retry."));
15271
15555
  process.exit(1);
15272
15556
  }
15273
15557
  return match.data_source_id;
15274
15558
  }
15275
15559
  function loadFindings(findingsPath) {
15276
15560
  const fail = () => {
15277
- console.error(import_picocolors9.default.red("Run the Dosu audit in your coding agent first (it writes .dosu/audit.json)."));
15561
+ console.error(import_picocolors11.default.red("Run the Dosu audit in your coding agent first (it writes .dosu/audit.json)."));
15278
15562
  process.exit(1);
15279
15563
  };
15280
15564
  if (!existsSync5(findingsPath)) {
@@ -15337,13 +15621,13 @@ function auditCommand() {
15337
15621
  return;
15338
15622
  }
15339
15623
  for (const t2 of tasks) {
15340
- console.log(`${t2.id} ${import_picocolors9.default.dim(`(${t2.doc_type})`)} ${t2.label} — ${t2.description}`);
15624
+ console.log(`${t2.id} ${import_picocolors11.default.dim(`(${t2.doc_type})`)} ${t2.label} — ${t2.description}`);
15341
15625
  }
15342
15626
  return;
15343
15627
  }
15344
15628
  const detected = detectGitRepo();
15345
15629
  if (!detected) {
15346
- console.error(import_picocolors9.default.red("Not a GitHub repo. Run 'dosu audit' from a GitHub repository."));
15630
+ console.error(import_picocolors11.default.red("Not a GitHub repo. Run 'dosu audit' from a GitHub repository."));
15347
15631
  process.exit(1);
15348
15632
  }
15349
15633
  const nonInteractive = Boolean(opts.tasks);
@@ -15352,7 +15636,7 @@ function auditCommand() {
15352
15636
  const findingsPath = opts.findings ?? join5(process.cwd(), ".dosu", "audit.json");
15353
15637
  const findings = loadFindings(findingsPath);
15354
15638
  if (!opts.dataSourceId && findings.repo?.slug && findings.repo.slug !== detected.slug) {
15355
- console.error(import_picocolors9.default.red(`Audit was run on ${findings.repo.slug}, but the current repo is ${detected.slug}. ` + `Run 'dosu audit' from ${findings.repo.slug} so the PR targets the audited repo.`));
15639
+ console.error(import_picocolors11.default.red(`Audit was run on ${findings.repo.slug}, but the current repo is ${detected.slug}. ` + `Run 'dosu audit' from ${findings.repo.slug} so the PR targets the audited repo.`));
15356
15640
  process.exit(1);
15357
15641
  }
15358
15642
  const capsResp = await backendGet("/v1/cli/tasks", apiKey);
@@ -15381,7 +15665,7 @@ function auditCommand() {
15381
15665
  message: "Which docs should Dosu generate?",
15382
15666
  options: actionable.map((item) => ({
15383
15667
  value: item.task,
15384
- label: `${item.file} ${import_picocolors9.default.dim(`(${item.type})`)}`,
15668
+ label: `${item.file} ${import_picocolors11.default.dim(`(${item.type})`)}`,
15385
15669
  hint: `${item.status} — ${item.rationale}`
15386
15670
  })),
15387
15671
  initialValues: actionable.filter(isPreselected).map((item) => item.task),
@@ -15435,47 +15719,57 @@ function auditCommand() {
15435
15719
 
15436
15720
  // src/commands/deployments.ts
15437
15721
  init_commander();
15722
+ init_client();
15438
15723
  init_trpc();
15439
15724
  init_config();
15440
- var import_picocolors10 = __toESM(require_picocolors(), 1);
15725
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
15726
+ var MCP_PROVIDER_SLUG = "dosu_mcp";
15441
15727
  function requireConfig4() {
15442
15728
  return requireLoginConfig();
15443
15729
  }
15730
+ async function listAccessibleDeployments(client, activeOrgId) {
15731
+ if (activeOrgId)
15732
+ return client.workspaces.listForOrg.query(activeOrgId);
15733
+ const orgs = await client.organization.getOrganizations.query({});
15734
+ const deployments = await Promise.all(orgs.map((org) => client.workspaces.listForOrg.query(org.org_id)));
15735
+ return deployments.flat();
15736
+ }
15444
15737
  function deploymentsCommand() {
15445
15738
  const cmd = new Command("deployments").description("Manage deployments");
15446
15739
  cmd.command("list").description("List all deployments").option("--json", "Output as JSON").action(async (opts) => {
15447
15740
  const cfg = requireConfig4();
15448
15741
  const client = createTypedClient(cfg);
15449
- const deployments = cfg.active_account?.target?.org_id ? await client.workspaces.listForOrg.query(cfg.active_account?.target?.org_id) : await client.workspaces.listAll.query({});
15742
+ const allDeployments = await listAccessibleDeployments(client, cfg.active_account?.target?.org_id);
15743
+ const deployments = allDeployments.filter((deployment) => deployment.provider_slug === MCP_PROVIDER_SLUG);
15450
15744
  if (opts.json) {
15451
15745
  printResult(deployments, opts);
15452
15746
  return;
15453
15747
  }
15454
15748
  if (!deployments || deployments.length === 0) {
15455
- console.log(import_picocolors10.default.dim("No deployments found."));
15749
+ console.log(import_picocolors12.default.dim("No deployments found."));
15456
15750
  return;
15457
15751
  }
15458
15752
  printTable(["ID", "Name", "Org", "Status"], deployments.map((d) => [
15459
15753
  d.deployment_id.slice(0, 8),
15460
15754
  d.name ?? "(unnamed)",
15461
15755
  d.org_id ? d.org_id.slice(0, 8) : "—",
15462
- d.enabled ? import_picocolors10.default.green("active") : import_picocolors10.default.dim("disabled")
15756
+ d.enabled ? import_picocolors12.default.green("active") : import_picocolors12.default.dim("disabled")
15463
15757
  ]), { rawData: deployments });
15464
15758
  if (cfg.active_account?.target?.deployment_id) {
15465
15759
  console.log(`
15466
- ${import_picocolors10.default.dim(`Current: ${cfg.active_account?.target?.deployment_name ?? cfg.active_account?.target?.deployment_id}`)}`);
15760
+ ${import_picocolors12.default.dim(`Current: ${cfg.active_account?.target?.deployment_name ?? cfg.active_account?.target?.deployment_id}`)}`);
15467
15761
  }
15468
15762
  });
15469
15763
  cmd.command("info").description("Show current deployment details").option("--json", "Output as JSON").action(async (opts) => {
15470
15764
  const cfg = requireConfig4();
15471
15765
  if (!cfg.active_account?.target?.deployment_id) {
15472
- console.error(import_picocolors10.default.red("No deployment selected. Run 'dosu setup' or 'dosu deployments switch'."));
15766
+ console.error(import_picocolors12.default.red("No deployment selected. Run 'dosu setup' or 'dosu deployments switch'."));
15473
15767
  process.exit(1);
15474
15768
  }
15475
15769
  const client = createTypedClient(cfg);
15476
15770
  const deployment = await client.workspaces.get.query(cfg.active_account?.target?.deployment_id);
15477
15771
  if (!deployment) {
15478
- console.error(import_picocolors10.default.red(`Deployment not found: ${cfg.active_account?.target?.deployment_id}`));
15772
+ console.error(import_picocolors12.default.red(`Deployment not found: ${cfg.active_account?.target?.deployment_id}`));
15479
15773
  process.exit(1);
15480
15774
  }
15481
15775
  if (opts.json) {
@@ -15498,21 +15792,27 @@ ${import_picocolors10.default.dim(`Current: ${cfg.active_account?.target?.deploy
15498
15792
  const client = createTypedClient(cfg);
15499
15793
  const deployment = await client.workspaces.get.query(id);
15500
15794
  if (!deployment) {
15501
- console.error(import_picocolors10.default.red(`Deployment not found: ${id}`));
15795
+ console.error(import_picocolors12.default.red(`Deployment not found: ${id}`));
15502
15796
  process.exit(1);
15503
15797
  }
15798
+ if (deployment.provider_slug !== MCP_PROVIDER_SLUG) {
15799
+ console.error(import_picocolors12.default.red(`Not a Dosu MCP deployment: ${id}`));
15800
+ process.exit(1);
15801
+ }
15802
+ const apiKey = await new Client(cfg).createAPIKey(deployment.deployment_id, "dosu-cli");
15504
15803
  updateTarget(cfg, {
15505
15804
  deployment_id: deployment.deployment_id,
15506
15805
  deployment_name: deployment.name,
15507
15806
  org_id: deployment.org_id,
15508
- space_id: deployment.space_id
15807
+ space_id: deployment.space_id,
15808
+ api_key: apiKey.api_key
15509
15809
  });
15510
15810
  saveConfig(cfg);
15511
15811
  if (opts.json) {
15512
15812
  printResult({ success: true, deployment_id: deployment.deployment_id, name: deployment.name }, opts);
15513
15813
  return;
15514
15814
  }
15515
- console.log(import_picocolors10.default.green(`Switched to deployment: ${deployment.name}`));
15815
+ console.log(import_picocolors12.default.green(`Switched to deployment: ${deployment.name}`));
15516
15816
  });
15517
15817
  return cmd;
15518
15818
  }
@@ -15521,14 +15821,51 @@ ${import_picocolors10.default.dim(`Current: ${cfg.active_account?.target?.deploy
15521
15821
  init_dist8();
15522
15822
  init_dist();
15523
15823
  init_commander();
15824
+ init_client();
15524
15825
  init_trpc();
15525
15826
  init_logger();
15526
- var import_picocolors11 = __toESM(require_picocolors(), 1);
15827
+ var import_picocolors13 = __toESM(require_picocolors(), 1);
15527
15828
  import { readFileSync as readFileSync6 } from "node:fs";
15829
+
15830
+ // src/commands/doc-import.ts
15831
+ var IMPORT_PLATFORMS = [
15832
+ "github",
15833
+ "gitlab",
15834
+ "azure_devops",
15835
+ "confluence",
15836
+ "notion",
15837
+ "coda"
15838
+ ];
15839
+ async function importDocuments(client, platform2, context, ids) {
15840
+ const baseInput = {
15841
+ knowledge_store_id: context.knowledgeStoreId,
15842
+ space_id: context.spaceId
15843
+ };
15844
+ switch (platform2) {
15845
+ case "github":
15846
+ return client.docImports.importGithubFiles.mutate({ ...baseInput, file_ids: ids });
15847
+ case "gitlab":
15848
+ return client.docImports.importGitlabFiles.mutate({ ...baseInput, file_ids: ids });
15849
+ case "azure_devops":
15850
+ return client.docImports.importAzureDevopsFiles.mutate({ ...baseInput, file_ids: ids });
15851
+ case "confluence":
15852
+ return client.docImports.importConfluencePages.mutate({ ...baseInput, page_ids: ids });
15853
+ case "notion":
15854
+ return client.docImports.importNotionPages.mutate({ ...baseInput, page_ids: ids });
15855
+ case "coda":
15856
+ return client.docImports.importCodaPages.mutate({ ...baseInput, page_ids: ids });
15857
+ default: {
15858
+ const unsupported = platform2;
15859
+ throw new Error(`Unsupported import platform: ${unsupported}`);
15860
+ }
15861
+ }
15862
+ }
15863
+
15864
+ // src/commands/docs.ts
15528
15865
  function requireConfig5() {
15529
15866
  const cfg = requireLoginConfig();
15530
15867
  if (!cfg.active_account?.target?.space_id) {
15531
- console.error(import_picocolors11.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
15868
+ console.error(import_picocolors13.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
15532
15869
  process.exit(1);
15533
15870
  }
15534
15871
  return cfg;
@@ -15538,7 +15875,7 @@ async function getKnowledgeStoreId(client, spaceId) {
15538
15875
  space_id: spaceId
15539
15876
  });
15540
15877
  if (!store) {
15541
- console.error(import_picocolors11.default.red("No knowledge store found for this deployment."));
15878
+ console.error(import_picocolors13.default.red("No knowledge store found for this deployment."));
15542
15879
  process.exit(1);
15543
15880
  }
15544
15881
  return store.id;
@@ -15606,7 +15943,7 @@ function isConcurrentImportError(err, msg) {
15606
15943
  async function backendPost2(path3, apiKey, body) {
15607
15944
  const backendURL = getBackendURL();
15608
15945
  if (!backendURL) {
15609
- console.error(import_picocolors11.default.red("Backend URL not configured."));
15946
+ console.error(import_picocolors13.default.red("Backend URL not configured."));
15610
15947
  process.exit(1);
15611
15948
  }
15612
15949
  const resp = await fetch(`${backendURL}${path3}`, {
@@ -15614,6 +15951,9 @@ async function backendPost2(path3, apiKey, body) {
15614
15951
  headers: { "Content-Type": "application/json", "X-Dosu-API-Key": apiKey },
15615
15952
  body: JSON.stringify(body)
15616
15953
  });
15954
+ return parseBackendResponse2(resp);
15955
+ }
15956
+ async function parseBackendResponse2(resp) {
15617
15957
  if (!resp.ok) {
15618
15958
  let detail = `Request failed with status ${resp.status}`;
15619
15959
  try {
@@ -15626,15 +15966,15 @@ async function backendPost2(path3, apiKey, body) {
15626
15966
  }
15627
15967
  function docsCommand() {
15628
15968
  const cmd = new Command("docs").description("Document management");
15629
- 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) => {
15969
+ cmd.command("list").description("List documents").option("--search <query>", "Search documents").option("--topic <id>", "Filter by topic ID").addOption(new Option("--limit <n>", "Maximum results").argParser(positiveInteger).default(20)).option("--json", "Output as JSON").action(async (opts) => {
15630
15970
  const cfg = requireConfig5();
15631
15971
  const client = createTypedClient(cfg);
15632
15972
  const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
15633
15973
  const result = await client.page.listWithTags.query({
15634
15974
  knowledge_store_id: ksId,
15635
15975
  searchTerm: opts.search,
15636
- topic_id: opts.tag,
15637
- limit: Number.parseInt(opts.limit ?? "20", 10)
15976
+ topic_id: opts.topic,
15977
+ limit: opts.limit
15638
15978
  });
15639
15979
  const pages = result.data;
15640
15980
  if (opts.json) {
@@ -15642,7 +15982,7 @@ function docsCommand() {
15642
15982
  return;
15643
15983
  }
15644
15984
  if (!pages || pages.length === 0) {
15645
- console.log(import_picocolors11.default.dim("No documents found."));
15985
+ console.log(import_picocolors13.default.dim("No documents found."));
15646
15986
  return;
15647
15987
  }
15648
15988
  printTable(["ID", "Title", "Status", "Created"], pages.map((p2) => [
@@ -15652,22 +15992,22 @@ function docsCommand() {
15652
15992
  formatDate(p2.created_at)
15653
15993
  ]), { rawData: pages });
15654
15994
  });
15655
- cmd.command("get").description("Get a document").argument("<id>", "Page ID").option("--version <v>", "Specific version number").option("--json", "Output as JSON").action(async (id, opts) => {
15995
+ cmd.command("get").description("Get a document").argument("<id>", "Page ID").addOption(new Option("--revision <n>", "Specific revision number").argParser(positiveInteger)).option("--json", "Output as JSON").action(async (id, opts) => {
15656
15996
  const cfg = requireConfig5();
15657
15997
  const client = createTypedClient(cfg);
15658
15998
  const page = await client.page.get.query({
15659
15999
  page_id: id,
15660
- version: opts.version ? Number.parseInt(opts.version, 10) : undefined
16000
+ version: opts.revision
15661
16001
  });
15662
16002
  if (opts.json) {
15663
16003
  printResult(page, opts);
15664
16004
  return;
15665
16005
  }
15666
16006
  if (!page) {
15667
- console.log(import_picocolors11.default.dim("Document not found."));
16007
+ console.log(import_picocolors13.default.dim("Document not found."));
15668
16008
  return;
15669
16009
  }
15670
- console.log(import_picocolors11.default.bold(page.title ?? "(untitled)"));
16010
+ console.log(import_picocolors13.default.bold(page.title ?? "(untitled)"));
15671
16011
  printInfo([
15672
16012
  ["ID", page.id],
15673
16013
  ["Status", page.published ? "published" : "draft"],
@@ -15678,7 +16018,7 @@ function docsCommand() {
15678
16018
  ${page.body}`);
15679
16019
  }
15680
16020
  });
15681
- 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) => {
16021
+ cmd.command("create").description("Create a new document").requiredOption("--title <title>", "Document title").option("--body <markdown>", "Document body (markdown)").addOption(new Option("--body-file <path>", "Read body from file").conflicts("body")).option("--json", "Output as JSON").action(async (opts) => {
15682
16022
  const cfg = requireConfig5();
15683
16023
  const client = createTypedClient(cfg);
15684
16024
  const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
@@ -15692,24 +16032,27 @@ ${page.body}`);
15692
16032
  printResult(result, opts);
15693
16033
  return;
15694
16034
  }
15695
- console.log(import_picocolors11.default.green(`Document "${opts.title}" created.`));
16035
+ console.log(import_picocolors13.default.green(`Document "${opts.title}" created.`));
15696
16036
  });
15697
- 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) => {
16037
+ cmd.command("update").description("Update a document").argument("<id>", "Page ID").option("--title <title>", "New title").option("--body <markdown>", "New body (markdown)").addOption(new Option("--body-file <path>", "Read body from file").conflicts("body")).option("--json", "Output as JSON").action(async (id, opts) => {
16038
+ if (opts.title === undefined && opts.body === undefined && opts.bodyFile === undefined) {
16039
+ throw new Error("Specify at least one of --title, --body, or --body-file.");
16040
+ }
15698
16041
  const cfg = requireConfig5();
15699
16042
  const client = createTypedClient(cfg);
15700
16043
  const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
15701
16044
  const body = readBody(opts);
15702
- const result = await client.page.update.mutate({
16045
+ await client.page.update.mutate({
15703
16046
  id,
15704
16047
  knowledge_store_id: ksId,
15705
16048
  title: opts.title,
15706
16049
  body
15707
16050
  });
15708
16051
  if (opts.json) {
15709
- printResult(result, opts);
16052
+ printResult({ success: true, id }, opts);
15710
16053
  return;
15711
16054
  }
15712
- console.log(import_picocolors11.default.green("Document updated."));
16055
+ console.log(import_picocolors13.default.green("Document updated."));
15713
16056
  });
15714
16057
  for (const archived of [true, false]) {
15715
16058
  const name = archived ? "archive" : "unarchive";
@@ -15721,7 +16064,7 @@ ${page.body}`);
15721
16064
  printResult({ success: true, id, archived }, opts);
15722
16065
  return;
15723
16066
  }
15724
- console.log(import_picocolors11.default.green(`Document ${name}d.`));
16067
+ console.log(import_picocolors13.default.green(`Document ${name}d.`));
15725
16068
  });
15726
16069
  }
15727
16070
  cmd.command("delete").description("Delete a document").argument("<id>", "Page ID").option("--json", "Output as JSON").action(async (id, opts) => {
@@ -15732,7 +16075,7 @@ ${page.body}`);
15732
16075
  printResult({ success: true, id }, opts);
15733
16076
  return;
15734
16077
  }
15735
- console.log(import_picocolors11.default.green("Document deleted."));
16078
+ console.log(import_picocolors13.default.green("Document deleted."));
15736
16079
  });
15737
16080
  cmd.command("versions").description("List document versions").argument("<id>", "Page ID").option("--json", "Output as JSON").action(async (id, opts) => {
15738
16081
  const cfg = requireConfig5();
@@ -15743,7 +16086,7 @@ ${page.body}`);
15743
16086
  return;
15744
16087
  }
15745
16088
  if (!versions || versions.length === 0) {
15746
- console.log(import_picocolors11.default.dim("No versions found."));
16089
+ console.log(import_picocolors13.default.dim("No versions found."));
15747
16090
  return;
15748
16091
  }
15749
16092
  printTable(["Version", "Created"], versions.map((v) => [
@@ -15751,18 +16094,18 @@ ${page.body}`);
15751
16094
  formatDate(v.created_at)
15752
16095
  ]), { rawData: versions });
15753
16096
  });
15754
- cmd.command("restore").description("Restore a document version").argument("<id>", "Page ID").requiredOption("--version <n>", "Version number to restore").option("--json", "Output as JSON").action(async (id, opts) => {
16097
+ cmd.command("restore").description("Restore a document version").argument("<id>", "Page ID").addOption(new Option("--revision <n>", "Revision number to restore").argParser(positiveInteger).makeOptionMandatory()).option("--json", "Output as JSON").action(async (id, opts) => {
15755
16098
  const cfg = requireConfig5();
15756
16099
  const client = createTypedClient(cfg);
15757
16100
  await client.page.restoreVersion.mutate({
15758
16101
  page_id: id,
15759
- version_to_restore: Number.parseInt(opts.version, 10)
16102
+ version_to_restore: opts.revision
15760
16103
  });
15761
16104
  if (opts.json) {
15762
- printResult({ success: true, id, version: opts.version }, opts);
16105
+ printResult({ success: true, id, revision: opts.revision }, opts);
15763
16106
  return;
15764
16107
  }
15765
- console.log(import_picocolors11.default.green(`Document restored to version ${opts.version}.`));
16108
+ console.log(import_picocolors13.default.green(`Document restored to version ${opts.revision}.`));
15766
16109
  });
15767
16110
  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) => {
15768
16111
  const cfg = requireConfig5();
@@ -15777,7 +16120,7 @@ ${page.body}`);
15777
16120
  printResult(result, opts);
15778
16121
  return;
15779
16122
  }
15780
- console.log(import_picocolors11.default.green("Document generation started."));
16123
+ console.log(import_picocolors13.default.green("Document generation started."));
15781
16124
  });
15782
16125
  cmd.command("auto-tag").description("Auto-tag a document using AI").argument("<id>", "Page ID").option("--json", "Output as JSON").action(async (id, opts) => {
15783
16126
  const cfg = requireConfig5();
@@ -15786,38 +16129,26 @@ ${page.body}`);
15786
16129
  printResult(result, opts);
15787
16130
  return;
15788
16131
  }
15789
- console.log(import_picocolors11.default.green("Auto-tagging started."));
16132
+ console.log(import_picocolors13.default.green("Auto-tagging started."));
15790
16133
  });
15791
- cmd.command("import").description("Import documents from an external platform").argument("<platform>", "Platform: github, gitlab, azure_devops, confluence, notion, coda").requiredOption("--files <ids>", "Comma-separated file/page IDs to import").option("--json", "Output as JSON").action(async (platform2, opts) => {
16134
+ cmd.command("import").description("Import documents from an external platform").addArgument(new Argument("<platform>", "Import platform").choices([...IMPORT_PLATFORMS])).requiredOption("--files <ids>", "Comma-separated file/page IDs to import").option("--json", "Output as JSON").action(async (platform2, opts) => {
15792
16135
  const cfg = requireConfig5();
15793
16136
  const client = createTypedClient(cfg);
15794
16137
  const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
15795
- const fileIds = opts.files.split(",").map((id) => id.trim());
15796
- const importFn = {
15797
- github: (input) => client.docImports.importGithubFiles.mutate(input),
15798
- gitlab: (input) => client.docImports.importGitlabFiles.mutate(input),
15799
- azure_devops: (input) => client.docImports.importAzureDevopsFiles.mutate(input),
15800
- confluence: (input) => client.docImports.importConfluencePages.mutate(input),
15801
- notion: (input) => client.docImports.importNotionPages.mutate(input),
15802
- coda: (input) => client.docImports.importCodaPages.mutate(input)
15803
- };
15804
- const fn = importFn[platform2.toLowerCase()];
15805
- if (!fn) {
15806
- console.error(import_picocolors11.default.red(`Unknown platform: ${platform2}. Use: github, gitlab, azure_devops, confluence, notion, coda`));
15807
- process.exit(1);
16138
+ const fileIds = opts.files.split(",").map((id) => id.trim()).filter(Boolean);
16139
+ if (fileIds.length === 0) {
16140
+ throw new Error("--files must contain at least one file or page ID.");
15808
16141
  }
15809
- const idField = ["confluence", "notion", "coda"].includes(platform2.toLowerCase()) ? "page_ids" : "file_ids";
15810
16142
  try {
15811
- const result = await fn({
15812
- knowledge_store_id: ksId,
15813
- space_id: cfg.active_account.target.space_id,
15814
- [idField]: fileIds
15815
- });
16143
+ const result = await importDocuments(client, platform2, {
16144
+ knowledgeStoreId: ksId,
16145
+ spaceId: cfg.active_account.target.space_id
16146
+ }, fileIds);
15816
16147
  if (opts.json) {
15817
16148
  printResult(result, opts);
15818
16149
  return;
15819
16150
  }
15820
- console.log(import_picocolors11.default.green(`Import started.${result.task_id ? ` Task ID: ${result.task_id}` : ""}`));
16151
+ console.log(import_picocolors13.default.green(`Import started.${result.task_id ? ` Task ID: ${result.task_id}` : ""}`));
15821
16152
  } catch (err) {
15822
16153
  const msg = err instanceof Error ? err.message : String(err);
15823
16154
  logger.warn("docs-import", `Import failed: ${msg}`);
@@ -15828,7 +16159,7 @@ ${page.body}`);
15828
16159
  console.error(JSON.stringify({ error }));
15829
16160
  } else if (isConcurrentImport) {
15830
16161
  log.error("An import is already in progress for this organization.");
15831
- log.info(`Check status with: ${import_picocolors11.default.cyan("dosu docs import-status <task-id>")}`);
16162
+ log.info(`Check status with: ${import_picocolors13.default.cyan("dosu docs import-status <task-id>")}`);
15832
16163
  log.info("Only one import can run per organization at a time.");
15833
16164
  } else {
15834
16165
  log.error(detail);
@@ -15836,16 +16167,16 @@ ${page.body}`);
15836
16167
  process.exit(1);
15837
16168
  }
15838
16169
  });
15839
- cmd.command("import-status").description("Check import task status").argument("<task-id>", "Import task ID").option("--json", "Output as JSON").action(async (taskId, opts) => {
16170
+ cmd.command("import-status").description("Check import task status").addArgument(new Argument("<task-id>", "Import task ID").argParser(uuid)).option("--json", "Output as JSON").action(async (taskId, opts) => {
15840
16171
  const cfg = requireConfig5();
15841
- const client = createTypedClient(cfg);
15842
- const status = await client.docImports.getImportStatus.query(taskId);
16172
+ const response = await new Client(cfg).get(`/doc-imports/status/${encodeURIComponent(taskId)}`);
16173
+ const status = response.status === 404 ? null : await parseBackendResponse2(response);
15843
16174
  if (opts.json) {
15844
16175
  printResult(status, opts);
15845
16176
  return;
15846
16177
  }
15847
16178
  if (!status) {
15848
- console.log(import_picocolors11.default.dim("Import task not found."));
16179
+ console.log(import_picocolors13.default.dim("Import task not found."));
15849
16180
  return;
15850
16181
  }
15851
16182
  console.log(`Status: ${JSON.stringify(status)}`);
@@ -15874,7 +16205,7 @@ ${page.body}`);
15874
16205
  path: `/sync-back/azure_devops/${id}/publish`,
15875
16206
  buildBody: () => {
15876
16207
  if (!opts.dataSourceId) {
15877
- console.error(import_picocolors11.default.red("--data-source-id <id> is required when publishing to azure_devops"));
16208
+ console.error(import_picocolors13.default.red("--data-source-id <id> is required when publishing to azure_devops"));
15878
16209
  process.exit(1);
15879
16210
  }
15880
16211
  return {
@@ -15907,7 +16238,7 @@ ${page.body}`);
15907
16238
  };
15908
16239
  const config = publishMap[platform2];
15909
16240
  if (!config) {
15910
- console.error(import_picocolors11.default.red(`Unknown platform: ${platform2}`));
16241
+ console.error(import_picocolors13.default.red(`Unknown platform: ${platform2}`));
15911
16242
  process.exit(1);
15912
16243
  }
15913
16244
  logger.debug("docs", `Publishing to ${platform2}`);
@@ -15916,7 +16247,7 @@ ${page.body}`);
15916
16247
  printResult(result, opts);
15917
16248
  return;
15918
16249
  }
15919
- console.log(import_picocolors11.default.green(`Document published to ${platform2}.`));
16250
+ console.log(import_picocolors13.default.green(`Document published to ${platform2}.`));
15920
16251
  });
15921
16252
  cmd.command("sync-back").description("Sync document back to its source (Notion/Confluence)").argument("<id>", "Page ID").option("--json", "Output as JSON").action(async (id, opts) => {
15922
16253
  const cfg = requireConfig5();
@@ -15926,7 +16257,7 @@ ${page.body}`);
15926
16257
  printResult(result, opts);
15927
16258
  return;
15928
16259
  }
15929
- console.log(import_picocolors11.default.green("Sync-back initiated."));
16260
+ console.log(import_picocolors13.default.green("Sync-back initiated."));
15930
16261
  });
15931
16262
  return cmd;
15932
16263
  }
@@ -15937,26 +16268,34 @@ init_insights3();
15937
16268
  // src/commands/integrations.ts
15938
16269
  init_commander();
15939
16270
  init_trpc();
15940
- var import_picocolors15 = __toESM(require_picocolors(), 1);
16271
+ var import_picocolors17 = __toESM(require_picocolors(), 1);
15941
16272
  function requireConfig6() {
15942
16273
  const cfg = requireLoginConfig();
15943
16274
  if (!cfg.active_account?.target?.org_id) {
15944
- console.error(import_picocolors15.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
16275
+ console.error(import_picocolors17.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
15945
16276
  process.exit(1);
15946
16277
  }
15947
16278
  return cfg;
15948
16279
  }
16280
+ var DISPLAY_PLATFORMS = [
16281
+ "github",
16282
+ "gitlab",
16283
+ "azure_devops",
16284
+ "slack",
16285
+ "confluence",
16286
+ "notion",
16287
+ "coda",
16288
+ "teams"
16289
+ ];
15949
16290
  var NANGO_PROBES = {
15950
16291
  gitlab: [
15951
16292
  { provider: "gitlab", providerConfigKey: "gitlab" },
15952
16293
  { provider: "gitlab", providerConfigKey: "gitlab-pat" }
15953
16294
  ],
15954
- "gitlab-pat": [{ provider: "gitlab", providerConfigKey: "gitlab-pat" }],
15955
16295
  confluence: [
15956
16296
  { provider: "confluence", providerConfigKey: "confluence" },
15957
16297
  { provider: "confluence", providerConfigKey: "confluence-basic" }
15958
16298
  ],
15959
- "confluence-basic": [{ provider: "confluence", providerConfigKey: "confluence-basic" }],
15960
16299
  notion: [{ provider: "notion", providerConfigKey: "notion" }],
15961
16300
  coda: [{ provider: "coda", providerConfigKey: "coda" }],
15962
16301
  azure_devops: [
@@ -15964,32 +16303,20 @@ var NANGO_PROBES = {
15964
16303
  { provider: "azure_devops", providerConfigKey: "azure-devops" }
15965
16304
  ]
15966
16305
  };
15967
- var DISPLAY_PLATFORMS = [
15968
- "github",
15969
- "gitlab",
15970
- "azure_devops",
15971
- "slack",
15972
- "confluence",
15973
- "notion",
15974
- "coda",
15975
- "teams"
15976
- ];
15977
16306
  async function probeConnection(client, orgId, platform4) {
15978
16307
  const probes = NANGO_PROBES[platform4];
15979
16308
  if (!probes) {
15980
- return { queryable: false, connected: false, connection: null };
16309
+ return { queryable: false, connected: null, connection: null };
15981
16310
  }
15982
16311
  for (const probe of probes) {
15983
- try {
15984
- const conn = await client.nango.getConnection.query({
15985
- provider: probe.provider,
15986
- providerConfigKey: probe.providerConfigKey,
15987
- orgId
15988
- });
15989
- if (conn != null) {
15990
- return { queryable: true, connected: true, connection: conn };
15991
- }
15992
- } catch {}
16312
+ const conn = await client.nango.getConnection.query({
16313
+ provider: probe.provider,
16314
+ providerConfigKey: probe.providerConfigKey,
16315
+ orgId
16316
+ });
16317
+ if (conn != null) {
16318
+ return { queryable: true, connected: true, connection: conn };
16319
+ }
15993
16320
  }
15994
16321
  return { queryable: true, connected: false, connection: null };
15995
16322
  }
@@ -16008,26 +16335,26 @@ function integrationsCommand() {
16008
16335
  }
16009
16336
  printTable(["Platform", "Status"], results.map((r2) => [
16010
16337
  r2.platform,
16011
- r2.connected ? import_picocolors15.default.green("connected") : import_picocolors15.default.dim("not connected")
16338
+ r2.connected === null ? import_picocolors17.default.dim("status unavailable") : r2.connected ? import_picocolors17.default.green("connected") : import_picocolors17.default.dim("not connected")
16012
16339
  ]), { rawData: results });
16013
16340
  });
16014
- 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) => {
16341
+ cmd.command("status").description("Check connection status of a specific platform").addArgument(new Argument("<platform>", "Integration platform").choices([...DISPLAY_PLATFORMS])).option("--json", "Output as JSON").action(async (platform4, opts) => {
16015
16342
  const cfg = requireConfig6();
16016
16343
  const client = createTypedClient(cfg);
16017
16344
  const { queryable, connected, connection } = await probeConnection(client, cfg.active_account.target.org_id, platform4);
16018
16345
  if (!queryable) {
16019
16346
  if (opts.json) {
16020
- printResult({ platform: platform4, connected: false, note: "not queryable via nango" }, opts);
16347
+ printResult({ platform: platform4, connected: null, note: "connection status unavailable via CLI" }, opts);
16021
16348
  return;
16022
16349
  }
16023
- console.log(`${platform4}: ${import_picocolors15.default.dim("not connected (not queryable)")}`);
16350
+ console.log(`${platform4}: ${import_picocolors17.default.dim("connection status unavailable via CLI")}`);
16024
16351
  return;
16025
16352
  }
16026
16353
  if (opts.json) {
16027
16354
  printResult({ platform: platform4, connected, connection }, opts);
16028
16355
  return;
16029
16356
  }
16030
- console.log(`${platform4}: ${connected ? import_picocolors15.default.green("connected") : import_picocolors15.default.dim("not connected")}`);
16357
+ console.log(`${platform4}: ${connected ? import_picocolors17.default.green("connected") : import_picocolors17.default.dim("not connected")}`);
16031
16358
  });
16032
16359
  cmd.command("slack-channels").description("List Slack channels").option("--json", "Output as JSON").action(async (opts) => {
16033
16360
  const cfg = requireConfig6();
@@ -16038,7 +16365,7 @@ function integrationsCommand() {
16038
16365
  return;
16039
16366
  }
16040
16367
  if (!channels || channels.length === 0) {
16041
- console.log(import_picocolors15.default.dim("No Slack channels found."));
16368
+ console.log(import_picocolors17.default.dim("No Slack channels found."));
16042
16369
  return;
16043
16370
  }
16044
16371
  printTable(["ID", "Name"], channels.map((c3) => [
@@ -16054,18 +16381,18 @@ function integrationsCommand() {
16054
16381
  printResult({ success: true, channelId }, opts);
16055
16382
  return;
16056
16383
  }
16057
- console.log(import_picocolors15.default.green(`Joined Slack channel ${channelId}.`));
16384
+ console.log(import_picocolors17.default.green(`Joined Slack channel ${channelId}.`));
16058
16385
  });
16059
- cmd.command("github-collaborators").description("List GitHub repository collaborators").option("--json", "Output as JSON").action(async (opts) => {
16386
+ cmd.command("github-collaborators").description("List GitHub repository collaborators").addArgument(new Argument("<repository-id>", "Numeric GitHub repository ID").argParser(positiveInteger)).option("--json", "Output as JSON").action(async (repositoryId, opts) => {
16060
16387
  const cfg = requireConfig6();
16061
16388
  const client = createTypedClient(cfg);
16062
- const collaborators = await client.githubRepository.getCollaborators.query(0);
16389
+ const collaborators = await client.githubRepository.getCollaborators.query(repositoryId);
16063
16390
  if (opts.json) {
16064
16391
  printResult(collaborators, opts);
16065
16392
  return;
16066
16393
  }
16067
16394
  if (!collaborators || collaborators.length === 0) {
16068
- console.log(import_picocolors15.default.dim("No collaborators found."));
16395
+ console.log(import_picocolors17.default.dim("No collaborators found."));
16069
16396
  return;
16070
16397
  }
16071
16398
  printTable(["Username", "Name", "Email"], collaborators.map((c3) => [c3.user_name ?? "—", c3.full_name ?? "—", c3.email ?? "—"]), { rawData: collaborators });
@@ -16076,18 +16403,18 @@ function integrationsCommand() {
16076
16403
  // src/commands/knowledge.ts
16077
16404
  init_commander();
16078
16405
  init_trpc();
16079
- var import_picocolors16 = __toESM(require_picocolors(), 1);
16406
+ var import_picocolors18 = __toESM(require_picocolors(), 1);
16080
16407
  function requireConfig7() {
16081
16408
  const cfg = requireLoginConfig();
16082
16409
  if (!cfg.active_account?.target?.org_id || !cfg.active_account?.target?.space_id) {
16083
- console.error(import_picocolors16.default.red("Missing org/space config. Run 'dosu setup' to reconfigure."));
16410
+ console.error(import_picocolors18.default.red("Missing org/space config. Run 'dosu setup' to reconfigure."));
16084
16411
  process.exit(1);
16085
16412
  }
16086
16413
  return cfg;
16087
16414
  }
16088
16415
  function knowledgeCommand() {
16089
16416
  const cmd = new Command("knowledge").description("Search and browse your knowledge base");
16090
- cmd.command("search").description("Search the knowledge base").argument("<query>", "Search query").option("--json", "Output as JSON").option("--limit <n>", "Maximum results", "10").action(async (query, opts) => {
16417
+ cmd.command("search").description("Search the knowledge base").argument("<query>", "Search query").option("--json", "Output as JSON").addOption(new Option("--limit <n>", "Maximum results").argParser(positiveInteger).default(10)).action(async (query, opts) => {
16091
16418
  const cfg = requireConfig7();
16092
16419
  const client = createTypedClient(cfg);
16093
16420
  const dataSources = await client.dataSource.list.query({
@@ -16096,7 +16423,7 @@ function knowledgeCommand() {
16096
16423
  });
16097
16424
  const dataSourceIds = dataSources.map((ds) => ds.id).filter((id) => id !== null);
16098
16425
  if (dataSourceIds.length === 0) {
16099
- console.log(import_picocolors16.default.dim("No data sources connected. Add data sources in the Dosu dashboard."));
16426
+ console.log(import_picocolors18.default.dim("No data sources connected. Add data sources in the Dosu dashboard."));
16100
16427
  return;
16101
16428
  }
16102
16429
  const data = await client.search.getMentions.query({
@@ -16110,18 +16437,17 @@ function knowledgeCommand() {
16110
16437
  return;
16111
16438
  }
16112
16439
  if (!results || results.length === 0) {
16113
- console.log(import_picocolors16.default.dim("No results found."));
16440
+ console.log(import_picocolors18.default.dim("No results found."));
16114
16441
  return;
16115
16442
  }
16116
- const limit = Number.parseInt(opts.limit ?? "10", 10);
16117
- const limited = results.slice(0, limit);
16443
+ const limited = results.slice(0, opts.limit);
16118
16444
  printTable(["Title", "Type"], limited.map((r2) => [
16119
16445
  truncate(r2.title ?? "(untitled)", 60),
16120
16446
  r2.entity_type ?? "—"
16121
16447
  ]), { json: false, rawData: limited });
16122
- if (results.length > limit) {
16123
- console.log(import_picocolors16.default.dim(`
16124
- ${results.length - limit} more results not shown.`));
16448
+ if (results.length > opts.limit) {
16449
+ console.log(import_picocolors18.default.dim(`
16450
+ ${results.length - opts.limit} more results not shown.`));
16125
16451
  }
16126
16452
  });
16127
16453
  cmd.command("list").description("Show knowledge store information").option("--json", "Output as JSON").action(async (opts) => {
@@ -16133,51 +16459,297 @@ ${results.length - limit} more results not shown.`));
16133
16459
  return;
16134
16460
  }
16135
16461
  if (!store) {
16136
- console.log(import_picocolors16.default.dim("No knowledge store found for this deployment."));
16462
+ console.log(import_picocolors18.default.dim("No knowledge store found for this deployment."));
16137
16463
  return;
16138
16464
  }
16139
- console.log(import_picocolors16.default.bold("Knowledge Store"));
16465
+ console.log(import_picocolors18.default.bold("Knowledge Store"));
16140
16466
  console.log(` ID: ${store.id}`);
16141
16467
  console.log(` Space ID: ${store.space_id}`);
16142
16468
  });
16143
16469
  return cmd;
16144
16470
  }
16145
16471
 
16472
+ // src/commands/libraries.ts
16473
+ init_commander();
16474
+ init_trpc();
16475
+ var import_picocolors19 = __toESM(require_picocolors(), 1);
16476
+ var LIBRARY_VISIBILITIES = ["public", "internal", "private"];
16477
+ var CONFIG_SETTINGS = {
16478
+ commit_to_trigger_pr: true,
16479
+ default_accept_review: true,
16480
+ default_save_publish: true,
16481
+ review_timeout_days: true
16482
+ };
16483
+ var CONFIG_SETTING_NAMES = Object.keys(CONFIG_SETTINGS);
16484
+ function validatedDocumentationValue(setting, value) {
16485
+ if (setting === "review_timeout_days") {
16486
+ if (typeof value !== "number" || ![7, 14, 30, 90].includes(value)) {
16487
+ throw new InvalidArgumentError("value must be one of 7, 14, 30, or 90");
16488
+ }
16489
+ return value;
16490
+ }
16491
+ if (typeof value !== "boolean") {
16492
+ throw new InvalidArgumentError("value must be true or false");
16493
+ }
16494
+ return value;
16495
+ }
16496
+ function printLibrary(library, opts) {
16497
+ printInfo([
16498
+ ["ID", library.id],
16499
+ ["Name", library.name],
16500
+ ["Visibility", library.visibility],
16501
+ ["Created", formatDate(library.created_at)],
16502
+ ["Updated", formatDate(library.updated_at)]
16503
+ ], { json: opts.json, rawData: library });
16504
+ }
16505
+ function librariesCommand() {
16506
+ const cmd = new Command("libraries").description("Manage Dosu libraries");
16507
+ cmd.command("list").description("List libraries in the selected organization").option("--json", "Output as JSON").action(async (opts) => {
16508
+ const { cfg, orgId } = requireOrgConfig();
16509
+ const libraries = await createTypedClient(cfg).libraries.list.query(orgId);
16510
+ if (opts.json)
16511
+ return printResult(libraries, opts);
16512
+ printTable(["ID", "Name", "Visibility", "Updated"], libraries.map((library) => [
16513
+ library.id.slice(0, 8),
16514
+ library.name,
16515
+ library.visibility,
16516
+ formatDate(library.updated_at)
16517
+ ]), { rawData: libraries });
16518
+ });
16519
+ cmd.command("info").description("Show a library").argument("<library-id>", "Library ID", uuidV4).option("--json", "Output as JSON").action(async (libraryId, opts) => {
16520
+ const { cfg } = requireOrgConfig();
16521
+ printLibrary(await createTypedClient(cfg).libraries.info.query(libraryId), opts);
16522
+ });
16523
+ cmd.command("create").description("Create a library").requiredOption("--name <name>", "Library name", boundedText(50)).addOption(new Option("--visibility <visibility>", "Library visibility").choices([
16524
+ ...LIBRARY_VISIBILITIES
16525
+ ])).option("--json", "Output as JSON").action(async (opts) => {
16526
+ const { cfg, orgId } = requireOrgConfig();
16527
+ const library = await createTypedClient(cfg).libraries.create.mutate({
16528
+ name: opts.name,
16529
+ org_id: orgId,
16530
+ visibility: opts.visibility
16531
+ });
16532
+ if (opts.json)
16533
+ return printResult(library, opts);
16534
+ console.log(import_picocolors19.default.green(`Created library '${library.name}' (${library.id}).`));
16535
+ });
16536
+ cmd.command("update").description("Update a library (requires confirmation)").argument("<library-id>", "Library ID", uuidV4).option("--name <name>", "New name", boundedText(50)).addOption(new Option("--visibility <visibility>", "New visibility").choices([...LIBRARY_VISIBILITIES])).option("--confirm", "Apply without the interactive prompt").option("--json", "Output as JSON").action(async (libraryId, opts) => {
16537
+ if (opts.name === undefined && opts.visibility === undefined) {
16538
+ throw new InvalidArgumentError("specify --name or --visibility");
16539
+ }
16540
+ if (!await confirmAction({
16541
+ confirmed: opts.confirm,
16542
+ json: opts.json,
16543
+ message: "Update this library?",
16544
+ preview: {
16545
+ action: "update_library",
16546
+ id: libraryId,
16547
+ name: opts.name,
16548
+ visibility: opts.visibility
16549
+ }
16550
+ }))
16551
+ return;
16552
+ const { cfg } = requireOrgConfig();
16553
+ const library = await createTypedClient(cfg).libraries.update.mutate({
16554
+ id: libraryId,
16555
+ name: opts.name,
16556
+ visibility: opts.visibility
16557
+ });
16558
+ if (opts.json)
16559
+ return printResult(library, opts);
16560
+ console.log(import_picocolors19.default.green(`Updated library '${library.name}'.`));
16561
+ });
16562
+ cmd.command("delete").description("Delete a library (requires confirmation)").argument("<library-id>", "Library ID", uuidV4).option("--confirm", "Apply without the interactive prompt").option("--json", "Output as JSON").action(async (libraryId, opts) => {
16563
+ if (!await confirmAction({
16564
+ confirmed: opts.confirm,
16565
+ json: opts.json,
16566
+ message: "Delete this library and its child data?",
16567
+ preview: { action: "delete_library", id: libraryId }
16568
+ }))
16569
+ return;
16570
+ const { cfg } = requireOrgConfig();
16571
+ const result = await createTypedClient(cfg).libraries.delete.mutate(libraryId);
16572
+ if (opts.json)
16573
+ return printResult(result, opts);
16574
+ console.log(import_picocolors19.default.green(`Deleted library ${libraryId}.`));
16575
+ });
16576
+ const config = cmd.command("config").description("Manage library documentation settings");
16577
+ config.command("get").description("Show documentation settings").argument("<library-id>", "Library ID", uuidV4).option("--json", "Output as JSON").action(async (libraryId, opts) => {
16578
+ const { cfg } = requireOrgConfig();
16579
+ const result = await createTypedClient(cfg).libraries.configGet.query(libraryId);
16580
+ if (opts.json)
16581
+ return printResult(result, opts);
16582
+ printResult(result.config, opts);
16583
+ });
16584
+ config.command("set").description("Set one documentation setting (requires confirmation)").argument("<library-id>", "Library ID", uuidV4).addArgument(new Argument("<setting>", "Documentation setting").choices(CONFIG_SETTING_NAMES)).requiredOption("--value <json>", "New value as JSON", jsonValue).option("--confirm", "Apply without the interactive prompt").option("--json", "Output as JSON").action(async (libraryId, setting, opts) => {
16585
+ const value = validatedDocumentationValue(setting, opts.value);
16586
+ if (!await confirmAction({
16587
+ confirmed: opts.confirm,
16588
+ json: opts.json,
16589
+ message: `Set documentation.${setting}?`,
16590
+ preview: { action: "set_library_config", id: libraryId, setting, value }
16591
+ }))
16592
+ return;
16593
+ const { cfg } = requireOrgConfig();
16594
+ const client = createTypedClient(cfg);
16595
+ const current = await client.libraries.configGet.query(libraryId);
16596
+ const result = await client.libraries.configSet.mutate({
16597
+ expected_updated_at: current.updated_at,
16598
+ setting,
16599
+ space_id: libraryId,
16600
+ value
16601
+ });
16602
+ if (opts.json)
16603
+ return printResult(result, opts);
16604
+ console.log(import_picocolors19.default.green(`Updated documentation.${setting}.`));
16605
+ });
16606
+ const sources = cmd.command("sources").description("Manage sources attached to a library");
16607
+ sources.command("list").description("List attached sources").argument("<library-id>", "Library ID", uuidV4).option("--json", "Output as JSON").action(async (libraryId, opts) => {
16608
+ const { cfg } = requireOrgConfig();
16609
+ const rows = await createTypedClient(cfg).libraries.sourcesList.query(libraryId);
16610
+ if (opts.json)
16611
+ return printResult(rows, opts);
16612
+ printTable(["ID", "Name", "Provider", "Status"], rows.map((row) => [
16613
+ row.data_source_id.slice(0, 8),
16614
+ row.name,
16615
+ row.provider_slug,
16616
+ row.status
16617
+ ]), { rawData: rows });
16618
+ });
16619
+ for (const action of ["attach", "detach"]) {
16620
+ sources.command(action).description(`${action === "attach" ? "Attach" : "Detach"} sources (requires confirmation)`).argument("<library-id>", "Library ID", uuidV4).argument("<source-ids...>", "One or more data source IDs").option("--confirm", "Apply without the interactive prompt").option("--json", "Output as JSON").action(async (libraryId, sourceIds, opts) => {
16621
+ const uniqueIds = [...new Set(sourceIds.map(uuidV4))];
16622
+ if (!await confirmAction({
16623
+ confirmed: opts.confirm,
16624
+ json: opts.json,
16625
+ message: `${action === "attach" ? "Attach" : "Detach"} ${uniqueIds.length} source(s)?`,
16626
+ preview: {
16627
+ action: `${action}_library_sources`,
16628
+ id: libraryId,
16629
+ source_ids: uniqueIds
16630
+ }
16631
+ }))
16632
+ return;
16633
+ const { cfg } = requireOrgConfig();
16634
+ const client = createTypedClient(cfg);
16635
+ const count = await (action === "attach" ? client.libraries.sourcesAttach.mutate({
16636
+ space_id: libraryId,
16637
+ data_source_ids: uniqueIds
16638
+ }) : client.libraries.sourcesDetach.mutate({
16639
+ space_id: libraryId,
16640
+ data_source_ids: uniqueIds
16641
+ }));
16642
+ const result = { action, library_id: libraryId, source_ids: uniqueIds, changed: count };
16643
+ if (opts.json)
16644
+ return printResult(result, opts);
16645
+ console.log(import_picocolors19.default.green(`${action === "attach" ? "Attached" : "Detached"} ${count} source(s).`));
16646
+ });
16647
+ }
16648
+ const sourceConfig = sources.command("config").description("Manage per-library source settings");
16649
+ sourceConfig.command("get").description("Show source settings").argument("<library-id>", "Library ID", uuidV4).argument("<source-id>", "Data source ID", uuidV4).option("--json", "Output as JSON").action(async (libraryId, sourceId, opts) => {
16650
+ const { cfg } = requireOrgConfig();
16651
+ const result = await createTypedClient(cfg).libraries.sourceConfigGet.query({
16652
+ data_source_id: sourceId,
16653
+ space_id: libraryId
16654
+ });
16655
+ printResult(result, opts);
16656
+ });
16657
+ sourceConfig.command("update").description("Update source settings (requires confirmation)").argument("<library-id>", "Library ID", uuidV4).argument("<source-id>", "Data source ID", uuidV4).addOption(new Option("--issues <on|off>", "Read GitHub issues").argParser(onOrOff)).addOption(new Option("--pull-requests <on|off>", "Read GitHub pull requests").argParser(onOrOff)).addOption(new Option("--discussions <on|off>", "Read GitHub discussions").argParser(onOrOff)).addOption(new Option("--wiki <on|off>", "Read the GitHub wiki").argParser(onOrOff)).addOption(new Option("--include-patterns <json>", "Replace included file patterns").argParser(jsonStringArray)).addOption(new Option("--exclude-patterns <json>", "Replace excluded file patterns").argParser(jsonStringArray)).option("--confirm", "Apply without the interactive prompt").option("--json", "Output as JSON").action(async (libraryId, sourceId, opts) => {
16658
+ const updates = {
16659
+ discussions_enabled: opts.discussions,
16660
+ excluded_file_patterns: opts.excludePatterns,
16661
+ included_file_patterns: opts.includePatterns,
16662
+ issues_enabled: opts.issues,
16663
+ pull_requests_enabled: opts.pullRequests,
16664
+ wiki_enabled: opts.wiki
16665
+ };
16666
+ if (Object.values(updates).every((value) => value === undefined)) {
16667
+ throw new InvalidArgumentError("specify at least one source setting");
16668
+ }
16669
+ if (!await confirmAction({
16670
+ confirmed: opts.confirm,
16671
+ json: opts.json,
16672
+ message: "Update this source's library settings?",
16673
+ preview: {
16674
+ action: "update_library_source_config",
16675
+ id: libraryId,
16676
+ source_id: sourceId,
16677
+ ...updates
16678
+ }
16679
+ }))
16680
+ return;
16681
+ const { cfg } = requireOrgConfig();
16682
+ const result = await createTypedClient(cfg).libraries.sourceConfigUpdate.mutate({
16683
+ data_source_id: sourceId,
16684
+ space_id: libraryId,
16685
+ ...updates
16686
+ });
16687
+ if (opts.json)
16688
+ return printResult(result, opts);
16689
+ console.log(import_picocolors19.default.green("Updated source settings."));
16690
+ });
16691
+ const monitors = cmd.command("monitors").description("Manage source-oriented Monitor settings");
16692
+ monitors.command("list").description("List Monitor settings by source").argument("<library-id>", "Library ID", uuidV4).option("--json", "Output as JSON").action(async (libraryId, opts) => {
16693
+ const { cfg } = requireOrgConfig();
16694
+ const rows = await createTypedClient(cfg).libraries.monitorsList.query(libraryId);
16695
+ if (opts.json)
16696
+ return printResult(rows, opts);
16697
+ printTable(["Source ID", "Name", "Provider", "Monitor", "Setup"], rows.map((row) => [
16698
+ row.data_source_id.slice(0, 8),
16699
+ row.source_name,
16700
+ row.provider_slug,
16701
+ row.enabled ? "on" : "off",
16702
+ row.setup_required ? "web required" : "ready"
16703
+ ]), { rawData: rows });
16704
+ });
16705
+ monitors.command("update").description("Update Monitor settings by source (requires confirmation)").argument("<library-id>", "Library ID", uuidV4).argument("<source-id>", "Data source ID", uuidV4).addOption(new Option("--enabled <on|off>", "Turn Monitor on or off").argParser(onOrOff)).addOption(new Option("--paths <json>", "Replace monitored paths").argParser(jsonStringArray)).addOption(new Option("--up-to-date-behavior <behavior>", "Behavior when docs are current").choices([
16706
+ "emoji",
16707
+ "comment",
16708
+ "silent"
16709
+ ])).option("--confirm", "Apply without the interactive prompt").option("--json", "Output as JSON").action(async (libraryId, sourceId, opts) => {
16710
+ if (opts.enabled === undefined && opts.paths === undefined && opts.upToDateBehavior === undefined) {
16711
+ throw new InvalidArgumentError("specify at least one Monitor setting");
16712
+ }
16713
+ if (!await confirmAction({
16714
+ confirmed: opts.confirm,
16715
+ json: opts.json,
16716
+ message: "Update Monitor for this source?",
16717
+ preview: { action: "update_library_monitor", id: libraryId, source_id: sourceId }
16718
+ }))
16719
+ return;
16720
+ const { cfg } = requireOrgConfig();
16721
+ const result = await createTypedClient(cfg).libraries.monitorsUpdate.mutate({
16722
+ data_source_id: sourceId,
16723
+ enabled: opts.enabled,
16724
+ monitored_paths: opts.paths,
16725
+ no_update_behavior: opts.upToDateBehavior,
16726
+ space_id: libraryId
16727
+ });
16728
+ if (opts.json)
16729
+ return printResult(result, opts);
16730
+ console.log(import_picocolors19.default.green("Updated Monitor settings."));
16731
+ });
16732
+ return cmd;
16733
+ }
16734
+
16146
16735
  // src/commands/members.ts
16147
16736
  init_commander();
16148
16737
  init_trpc();
16149
- var import_picocolors17 = __toESM(require_picocolors(), 1);
16738
+ var import_picocolors20 = __toESM(require_picocolors(), 1);
16150
16739
  function requireConfig8() {
16151
16740
  const cfg = requireLoginConfig();
16152
16741
  if (!cfg.active_account?.target?.org_id) {
16153
- console.error(import_picocolors17.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
16742
+ console.error(import_picocolors20.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
16154
16743
  process.exit(1);
16155
16744
  }
16156
16745
  return cfg;
16157
16746
  }
16158
16747
  function membersCommand() {
16159
- const cmd = new Command("members").description("Manage team members");
16160
- cmd.command("list").description("List team members and invitations").option("--json", "Output as JSON").action(async (opts) => {
16161
- const cfg = requireConfig8();
16162
- const client = createTypedClient(cfg);
16163
- const data = await client.invitations.getInvitations.query();
16164
- if (opts.json) {
16165
- printResult(data, opts);
16166
- return;
16167
- }
16168
- if (!data.items || data.items.length === 0) {
16169
- console.log(import_picocolors17.default.dim("No members or invitations found."));
16170
- return;
16171
- }
16172
- printTable(["Email", "Org"], data.items.map((m3) => [
16173
- m3.email ?? "—",
16174
- m3.org?.name ?? "—"
16175
- ]), { rawData: data });
16176
- });
16177
- cmd.command("invite").description("Invite a member to the organization").argument("<email>", "Email address to invite").option("--role <role>", "Role: admin or member", "member").option("--json", "Output as JSON").action(async (email, opts) => {
16748
+ const cmd = new Command("members").description("Invite organization members");
16749
+ cmd.command("invite").description("Invite a member to the organization").argument("<email>", "Email address to invite").addOption(new Option("--role <role>", "Organization role").choices(["admin", "member"]).default("member")).option("--json", "Output as JSON").action(async (email, opts) => {
16178
16750
  const cfg = requireConfig8();
16179
16751
  const client = createTypedClient(cfg);
16180
- const role = opts.role.toUpperCase() === "ADMIN" ? "ADMIN" : "MEMBER";
16752
+ const role = opts.role === "admin" ? "ADMIN" : "MEMBER";
16181
16753
  await client.invitations.invite.mutate({
16182
16754
  orgId: cfg.active_account.target.org_id,
16183
16755
  email,
@@ -16187,50 +16759,7 @@ function membersCommand() {
16187
16759
  printResult({ success: true, email, role }, opts);
16188
16760
  return;
16189
16761
  }
16190
- console.log(import_picocolors17.default.green(`Invitation sent to ${email} as ${role}.`));
16191
- });
16192
- cmd.command("requests").description("List pending access requests").option("--json", "Output as JSON").action(async (opts) => {
16193
- const cfg = requireConfig8();
16194
- const client = createTypedClient(cfg);
16195
- const data = await client.invitations.getInvitations.query();
16196
- if (opts.json) {
16197
- printResult(data, opts);
16198
- return;
16199
- }
16200
- if (!data.items || data.items.length === 0) {
16201
- console.log(import_picocolors17.default.dim("No pending access requests."));
16202
- return;
16203
- }
16204
- printTable(["Email", "Org"], data.items.map((r2) => [
16205
- r2.email ?? "—",
16206
- r2.org?.name ?? "—"
16207
- ]), { rawData: data });
16208
- });
16209
- cmd.command("approve").description("Approve an access request").argument("<email>", "Email of requester").option("--json", "Output as JSON").action(async (email, opts) => {
16210
- const cfg = requireConfig8();
16211
- const client = createTypedClient(cfg);
16212
- await client.invitations.acceptInvitation.mutate({
16213
- orgId: cfg.active_account.target.org_id,
16214
- email
16215
- });
16216
- if (opts.json) {
16217
- printResult({ success: true, email, action: "approved" }, opts);
16218
- return;
16219
- }
16220
- console.log(import_picocolors17.default.green(`Access request from ${email} approved.`));
16221
- });
16222
- cmd.command("deny").description("Deny an access request").argument("<email>", "Email of requester").option("--json", "Output as JSON").action(async (email, opts) => {
16223
- const cfg = requireConfig8();
16224
- const client = createTypedClient(cfg);
16225
- await client.invitations.rejectInvitation.mutate({
16226
- orgId: cfg.active_account.target.org_id,
16227
- email
16228
- });
16229
- if (opts.json) {
16230
- printResult({ success: true, email, action: "denied" }, opts);
16231
- return;
16232
- }
16233
- console.log(import_picocolors17.default.green(`Access request from ${email} denied.`));
16762
+ console.log(import_picocolors20.default.green(`Invitation sent to ${email} as ${role}.`));
16234
16763
  });
16235
16764
  return cmd;
16236
16765
  }
@@ -16238,7 +16767,7 @@ function membersCommand() {
16238
16767
  // src/commands/org.ts
16239
16768
  init_commander();
16240
16769
  init_trpc();
16241
- var import_picocolors18 = __toESM(require_picocolors(), 1);
16770
+ var import_picocolors21 = __toESM(require_picocolors(), 1);
16242
16771
  function requireConfig9() {
16243
16772
  return requireLoginConfig();
16244
16773
  }
@@ -16253,7 +16782,7 @@ function orgCommand() {
16253
16782
  return;
16254
16783
  }
16255
16784
  if (!orgs || orgs.length === 0) {
16256
- console.log(import_picocolors18.default.dim("No organizations found."));
16785
+ console.log(import_picocolors21.default.dim("No organizations found."));
16257
16786
  return;
16258
16787
  }
16259
16788
  if (orgs.length === 1) {
@@ -16267,18 +16796,17 @@ function orgCommand() {
16267
16796
  printTable(["ID", "Name"], orgs.map((o2) => [o2.org_id.slice(0, 8), o2.name]), { rawData: orgs });
16268
16797
  if (cfg.active_account?.target?.org_id) {
16269
16798
  console.log(`
16270
- ${import_picocolors18.default.dim(`Current: ${cfg.active_account?.target?.org_id}`)}`);
16799
+ ${import_picocolors21.default.dim(`Current: ${cfg.active_account?.target?.org_id}`)}`);
16271
16800
  }
16272
16801
  });
16273
16802
  return cmd;
16274
16803
  }
16275
16804
 
16276
16805
  // src/commands/review.ts
16277
- init_dist8();
16278
16806
  init_dist();
16279
16807
  init_commander();
16280
16808
  init_trpc();
16281
- var import_picocolors19 = __toESM(require_picocolors(), 1);
16809
+ var import_picocolors22 = __toESM(require_picocolors(), 1);
16282
16810
  import { readFileSync as readFileSync13 } from "node:fs";
16283
16811
  function requireConfig10() {
16284
16812
  return requireLoginConfig();
@@ -16304,7 +16832,7 @@ async function requireChange(client, id) {
16304
16832
  return await client.review.getChange.query({ id });
16305
16833
  } catch (err) {
16306
16834
  if (isNotFound(err) || isInvalidId(err)) {
16307
- console.error(import_picocolors19.default.red(`No review item found for '${id}'. Run 'dosu review list' to see pending items.`));
16835
+ console.error(import_picocolors22.default.red(`No review item found for '${id}'. Run 'dosu review list' to see pending items.`));
16308
16836
  process.exit(1);
16309
16837
  }
16310
16838
  throw err;
@@ -16313,7 +16841,7 @@ async function requireChange(client, id) {
16313
16841
  async function requireDraft(client, id) {
16314
16842
  const draft = await client.messages.getMessage.query(bareMessageId(id));
16315
16843
  if (!draft) {
16316
- console.error(import_picocolors19.default.red(`No review item found for '${id}'. Run 'dosu review list' to see pending items.`));
16844
+ console.error(import_picocolors22.default.red(`No review item found for '${id}'. Run 'dosu review list' to see pending items.`));
16317
16845
  process.exit(1);
16318
16846
  }
16319
16847
  return draft;
@@ -16336,12 +16864,12 @@ function colorizeDiff(diff) {
16336
16864
  return diff.split(`
16337
16865
  `).map((line) => {
16338
16866
  if (line.startsWith("+"))
16339
- return import_picocolors19.default.green(line);
16867
+ return import_picocolors22.default.green(line);
16340
16868
  if (line.startsWith("-"))
16341
- return import_picocolors19.default.red(line);
16869
+ return import_picocolors22.default.red(line);
16342
16870
  if (line.startsWith("@@"))
16343
- return import_picocolors19.default.cyan(line);
16344
- return import_picocolors19.default.dim(line);
16871
+ return import_picocolors22.default.cyan(line);
16872
+ return import_picocolors22.default.dim(line);
16345
16873
  }).join(`
16346
16874
  `);
16347
16875
  }
@@ -16355,7 +16883,7 @@ function printChangePreview(change) {
16355
16883
  ]
16356
16884
  ]);
16357
16885
  if (!change.hasChanges) {
16358
- console.log(import_picocolors19.default.dim("No content changes."));
16886
+ console.log(import_picocolors22.default.dim("No content changes."));
16359
16887
  return;
16360
16888
  }
16361
16889
  console.log();
@@ -16372,7 +16900,7 @@ function printDraftPreview(draft) {
16372
16900
  async function getKnowledgeStoreId2(client, spaceId) {
16373
16901
  const store = await client.knowledgeStore.getBySpaceId.query({ space_id: spaceId });
16374
16902
  if (!store) {
16375
- console.error(import_picocolors19.default.red("No knowledge store found for this deployment."));
16903
+ console.error(import_picocolors22.default.red("No knowledge store found for this deployment."));
16376
16904
  process.exit(1);
16377
16905
  }
16378
16906
  return store.id;
@@ -16382,7 +16910,7 @@ function reviewCommand() {
16382
16910
  cmd.command("list").description("List pending review items (doc changes and draft replies)").option("--json", "Output as JSON").action(async (opts) => {
16383
16911
  const cfg = requireConfig10();
16384
16912
  if (!cfg.active_account?.target?.space_id) {
16385
- console.error(import_picocolors19.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
16913
+ console.error(import_picocolors22.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
16386
16914
  process.exit(1);
16387
16915
  }
16388
16916
  const client = createTypedClient(cfg);
@@ -16397,7 +16925,7 @@ function reviewCommand() {
16397
16925
  return;
16398
16926
  }
16399
16927
  if (!items || items.length === 0) {
16400
- console.log(import_picocolors19.default.dim("No pending review items."));
16928
+ console.log(import_picocolors22.default.dim("No pending review items."));
16401
16929
  return;
16402
16930
  }
16403
16931
  printTable(["ID", "Kind", "Title", "Source", "Status", "Created"], items.map((i2) => i2.kind === "draft_message" ? [
@@ -16416,7 +16944,7 @@ function reviewCommand() {
16416
16944
  formatDate(i2.createdAt)
16417
16945
  ]), { rawData: items });
16418
16946
  if (truncated) {
16419
- console.log(import_picocolors19.default.dim(`Showing ${items.length} of ${total}+ pending items (list truncated).`));
16947
+ console.log(import_picocolors22.default.dim(`Showing ${items.length} of ${total}+ pending items (list truncated).`));
16420
16948
  }
16421
16949
  });
16422
16950
  cmd.command("diff").description("Show a pending review item (doc-change diff or draft reply body)").argument("<id>", "Review item ID (from `dosu review list`)").option("--json", "Output as JSON").action(async (id, opts) => {
@@ -16428,8 +16956,8 @@ function reviewCommand() {
16428
16956
  printResult({ id, kind: "draft_message", title: draft.title, body: draft.body }, opts);
16429
16957
  return;
16430
16958
  }
16431
- console.log(import_picocolors19.default.bold(draft.title ?? "(untitled)"));
16432
- console.log(import_picocolors19.default.dim("Draft reply"));
16959
+ console.log(import_picocolors22.default.bold(draft.title ?? "(untitled)"));
16960
+ console.log(import_picocolors22.default.dim("Draft reply"));
16433
16961
  console.log("");
16434
16962
  console.log(draft.body ?? "");
16435
16963
  return;
@@ -16440,16 +16968,16 @@ function reviewCommand() {
16440
16968
  return;
16441
16969
  }
16442
16970
  const versions = change.publishedVersion != null ? `v${change.publishedVersion} → v${change.version}` : `v${change.version}`;
16443
- console.log(import_picocolors19.default.bold(change.title));
16444
- console.log(import_picocolors19.default.dim(`${change.source} · ${versions}`));
16971
+ console.log(import_picocolors22.default.bold(change.title));
16972
+ console.log(import_picocolors22.default.dim(`${change.source} · ${versions}`));
16445
16973
  console.log("");
16446
16974
  console.log(change.diff);
16447
16975
  });
16448
- cmd.command("edit").description("Edit a pending review item in place (doc body/title, or draft reply body)").argument("<id>", "Review item ID (from `dosu review list`)").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) => {
16976
+ cmd.command("edit").description("Edit a pending doc or Dosu App draft in place").argument("<id>", "Review item ID (from `dosu review list`)").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) => {
16449
16977
  const cfg = requireConfig10();
16450
16978
  const client = createTypedClient(cfg);
16451
16979
  if (opts.body !== undefined && opts.bodyFile !== undefined) {
16452
- console.error(import_picocolors19.default.red("Pass only one of --body or --body-file."));
16980
+ console.error(import_picocolors22.default.red("Pass only one of --body or --body-file."));
16453
16981
  process.exit(1);
16454
16982
  }
16455
16983
  let body = opts.body;
@@ -16457,17 +16985,21 @@ function reviewCommand() {
16457
16985
  try {
16458
16986
  body = readFileSync13(opts.bodyFile, "utf-8");
16459
16987
  } catch (err) {
16460
- console.error(import_picocolors19.default.red(`Failed to read --body-file: ${err.message}`));
16988
+ console.error(import_picocolors22.default.red(`Failed to read --body-file: ${err.message}`));
16461
16989
  process.exit(1);
16462
16990
  }
16463
16991
  }
16464
16992
  if (body === undefined && opts.title === undefined) {
16465
- console.error(import_picocolors19.default.red("Nothing to edit. Pass --title and/or --body/--body-file."));
16993
+ console.error(import_picocolors22.default.red("Nothing to edit. Pass --title and/or --body/--body-file."));
16466
16994
  process.exit(1);
16467
16995
  }
16468
16996
  if (isDraftId(id)) {
16469
16997
  if (opts.title !== undefined) {
16470
- console.error(import_picocolors19.default.red("Draft replies support --body only (no --title)."));
16998
+ console.error(import_picocolors22.default.red("Draft replies support --body only (no --title)."));
16999
+ process.exit(1);
17000
+ }
17001
+ if (body === undefined) {
17002
+ console.error(import_picocolors22.default.red("Draft replies require --body or --body-file."));
16471
17003
  process.exit(1);
16472
17004
  }
16473
17005
  await requireDraft(client, id);
@@ -16484,7 +17016,7 @@ function reviewCommand() {
16484
17016
  });
16485
17017
  } catch (err) {
16486
17018
  if (isNotFound(err)) {
16487
- console.error(import_picocolors19.default.red(`No pending review item found for '${id}'. Run 'dosu review list' to see editable items.`));
17019
+ console.error(import_picocolors22.default.red(`No pending review item found for '${id}'. Run 'dosu review list' to see editable items.`));
16488
17020
  process.exit(1);
16489
17021
  }
16490
17022
  throw err;
@@ -16494,7 +17026,7 @@ function reviewCommand() {
16494
17026
  printResult({ success: true, id }, opts);
16495
17027
  return;
16496
17028
  }
16497
- console.log(import_picocolors19.default.green(`Review edited: ${truncateId(id)}`));
17029
+ console.log(import_picocolors22.default.green(`Review edited: ${truncateId(id)}`));
16498
17030
  });
16499
17031
  cmd.command("context").description("Get review context for a thread").argument("<thread-id>", "Thread ID").option("--json", "Output as JSON").action(async (threadId, opts) => {
16500
17032
  const cfg = requireConfig10();
@@ -16534,32 +17066,19 @@ function reviewCommand() {
16534
17066
  else
16535
17067
  printDraftPreview(draft);
16536
17068
  }
16537
- let proceed = opts.confirm === true;
16538
- if (!proceed && !opts.json && process.stdin?.isTTY) {
16539
- const answer = await confirm({
16540
- message: `${verb} this ${noun}?`,
16541
- initialValue: false
16542
- });
16543
- if (isCancel(answer)) {
16544
- console.log(import_picocolors19.default.dim("Cancelled."));
16545
- return;
16546
- }
16547
- proceed = answer === true;
16548
- }
16549
- if (!proceed) {
16550
- if (opts.json) {
16551
- const preview = change ?? {
16552
- id,
16553
- kind: "draft_message",
16554
- title: draft?.title,
16555
- body: draft?.body
16556
- };
16557
- printResult({ ...preview, applied: false, confirmRequired: true }, opts);
16558
- } else {
16559
- console.log(import_picocolors19.default.dim("Aborted. Re-run with --confirm to apply."));
16560
- }
17069
+ const preview = change ?? {
17070
+ id,
17071
+ kind: "draft_message",
17072
+ title: draft?.title,
17073
+ body: draft?.body
17074
+ };
17075
+ if (!await confirmAction({
17076
+ confirmed: opts.confirm,
17077
+ json: opts.json,
17078
+ message: `${verb} this ${noun}?`,
17079
+ preview
17080
+ }))
16561
17081
  return;
16562
- }
16563
17082
  if (change) {
16564
17083
  await client.page.updatePublicationStatus.mutate({ page_version_id: id, action });
16565
17084
  } else if (action === "accept") {
@@ -16571,15 +17090,15 @@ function reviewCommand() {
16571
17090
  printResult({ success: true, id, action }, opts);
16572
17091
  return;
16573
17092
  }
16574
- console.log(import_picocolors19.default.green(`Review ${name}: ${truncateId(id)}`));
17093
+ console.log(import_picocolors22.default.green(`Review ${name}: ${truncateId(id)}`));
16575
17094
  });
16576
17095
  }
16577
- cmd.command("revert").description("Revert a doc change to pending review (not supported for draft replies)").argument("<id>", "Review item ID (from `dosu review list`)").option("--json", "Output as JSON").action(async (id, opts) => {
17096
+ cmd.command("revert").description("Reopen a previously accepted or declined doc change for review").argument("<id>", "Page version ID (not a pending item from `dosu review list`)").option("--json", "Output as JSON").action(async (id, opts) => {
16578
17097
  const cfg = requireConfig10();
16579
17098
  const client = createTypedClient(cfg);
16580
17099
  if (isDraftId(id)) {
16581
17100
  await requireDraft(client, id);
16582
- console.error(import_picocolors19.default.red("Revert is not supported for draft replies. A rejected draft is regenerated on the next agent run."));
17101
+ console.error(import_picocolors22.default.red("Revert is not supported for draft replies. A rejected draft is regenerated on the next agent run."));
16583
17102
  process.exit(1);
16584
17103
  }
16585
17104
  await requireChange(client, id);
@@ -16591,7 +17110,7 @@ function reviewCommand() {
16591
17110
  printResult({ success: true, id, action: "revert_to_pending" }, opts);
16592
17111
  return;
16593
17112
  }
16594
- console.log(import_picocolors19.default.green(`Review revert: ${truncateId(id)}`));
17113
+ console.log(import_picocolors22.default.green(`Review revert: ${truncateId(id)}`));
16595
17114
  });
16596
17115
  return cmd;
16597
17116
  }
@@ -16602,11 +17121,11 @@ init_skill();
16602
17121
  // src/commands/sources.ts
16603
17122
  init_commander();
16604
17123
  init_trpc();
16605
- var import_picocolors20 = __toESM(require_picocolors(), 1);
17124
+ var import_picocolors23 = __toESM(require_picocolors(), 1);
16606
17125
  function requireConfig11() {
16607
17126
  const cfg = requireLoginConfig();
16608
17127
  if (!cfg.active_account?.target?.org_id) {
16609
- console.error(import_picocolors20.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
17128
+ console.error(import_picocolors23.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
16610
17129
  process.exit(1);
16611
17130
  }
16612
17131
  return cfg;
@@ -16626,7 +17145,7 @@ function sourcesCommand() {
16626
17145
  }
16627
17146
  const list = dataSources ?? [];
16628
17147
  if (list.length === 0) {
16629
- console.log(import_picocolors20.default.dim("No data sources connected."));
17148
+ console.log(import_picocolors23.default.dim("No data sources connected."));
16630
17149
  return;
16631
17150
  }
16632
17151
  printTable(["ID", "Name", "Provider", "Created"], list.map((ds) => [
@@ -16645,7 +17164,7 @@ function sourcesCommand() {
16645
17164
  return;
16646
17165
  }
16647
17166
  if (!ds) {
16648
- console.log(import_picocolors20.default.dim("Data source not found."));
17167
+ console.log(import_picocolors23.default.dim("Data source not found."));
16649
17168
  return;
16650
17169
  }
16651
17170
  printInfo([
@@ -16664,9 +17183,12 @@ function sourcesCommand() {
16664
17183
  printResult({ success: true, id }, opts);
16665
17184
  return;
16666
17185
  }
16667
- console.log(import_picocolors20.default.green(`Data source sync triggered for ${id.slice(0, 8)}.`));
17186
+ console.log(import_picocolors23.default.green(`Data source sync triggered for ${id.slice(0, 8)}.`));
16668
17187
  });
16669
17188
  cmd.command("update").description("Update a data source").argument("<id>", "Data source ID").option("--name <name>", "New name").option("--description <desc>", "New description").option("--json", "Output as JSON").action(async (id, opts) => {
17189
+ if (opts.name === undefined && opts.description === undefined) {
17190
+ throw new Error("Specify at least one of --name or --description.");
17191
+ }
16670
17192
  const cfg = requireConfig11();
16671
17193
  const client = createTypedClient(cfg);
16672
17194
  const result = await client.dataSource.update.mutate({
@@ -16678,7 +17200,7 @@ function sourcesCommand() {
16678
17200
  printResult(result, opts);
16679
17201
  return;
16680
17202
  }
16681
- console.log(import_picocolors20.default.green("Data source updated."));
17203
+ console.log(import_picocolors23.default.green("Data source updated."));
16682
17204
  });
16683
17205
  cmd.command("delete").description("Delete a data source").argument("<id>", "Data source ID").option("--json", "Output as JSON").action(async (id, opts) => {
16684
17206
  const cfg = requireConfig11();
@@ -16688,19 +17210,48 @@ function sourcesCommand() {
16688
17210
  printResult({ success: true, id }, opts);
16689
17211
  return;
16690
17212
  }
16691
- console.log(import_picocolors20.default.green("Data source deleted."));
17213
+ console.log(import_picocolors23.default.green("Data source deleted."));
16692
17214
  });
16693
17215
  return cmd;
16694
17216
  }
16695
17217
 
16696
17218
  // src/commands/suggest.ts
16697
17219
  init_commander();
17220
+ var import_picocolors24 = __toESM(require_picocolors(), 1);
17221
+
17222
+ // src/client/supabase.ts
17223
+ async function listSpaceDataSourceIds(config, spaceId) {
17224
+ const accessToken = config.active_account?.session.access_token;
17225
+ if (!accessToken)
17226
+ throw new Error("Not logged in. Run 'dosu login' first.");
17227
+ const endpoint = new URL("/rest/v1/space_data_source", getSupabaseURL());
17228
+ endpoint.searchParams.set("select", "data_source_id");
17229
+ endpoint.searchParams.set("space_id", `eq.${spaceId}`);
17230
+ const response = await fetch(endpoint, {
17231
+ headers: {
17232
+ apikey: getSupabaseAnonKey(),
17233
+ Authorization: `Bearer ${accessToken}`
17234
+ }
17235
+ });
17236
+ if (!response.ok) {
17237
+ throw new Error(`Failed to list this deployment's data sources (status ${response.status}).`);
17238
+ }
17239
+ const rows = await response.json();
17240
+ if (!Array.isArray(rows) || rows.some((row) => !isDataSourceLink(row))) {
17241
+ throw new Error("Supabase returned an invalid space_data_source response.");
17242
+ }
17243
+ return rows.map((row) => row.data_source_id);
17244
+ }
17245
+ function isDataSourceLink(value) {
17246
+ return value !== null && typeof value === "object" && "data_source_id" in value && typeof value.data_source_id === "string";
17247
+ }
17248
+
17249
+ // src/commands/suggest.ts
16698
17250
  init_trpc();
16699
- var import_picocolors21 = __toESM(require_picocolors(), 1);
16700
17251
  function requireConfig12() {
16701
17252
  const cfg = requireLoginConfig();
16702
17253
  if (!cfg.active_account?.target?.space_id) {
16703
- console.error(import_picocolors21.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
17254
+ console.error(import_picocolors24.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
16704
17255
  process.exit(1);
16705
17256
  }
16706
17257
  return cfg;
@@ -16710,7 +17261,7 @@ async function getKnowledgeStoreId3(client, spaceId) {
16710
17261
  space_id: spaceId
16711
17262
  });
16712
17263
  if (!store) {
16713
- console.error(import_picocolors21.default.red("No knowledge store found for this deployment."));
17264
+ console.error(import_picocolors24.default.red("No knowledge store found for this deployment."));
16714
17265
  process.exit(1);
16715
17266
  }
16716
17267
  return store.id;
@@ -16729,7 +17280,7 @@ function suggestCommand() {
16729
17280
  return;
16730
17281
  }
16731
17282
  if (!suggestions || suggestions.length === 0) {
16732
- console.log(import_picocolors21.default.dim("No pending suggestions."));
17283
+ console.log(import_picocolors24.default.dim("No pending suggestions."));
16733
17284
  return;
16734
17285
  }
16735
17286
  printTable(["ID", "Title"], suggestions.map((s) => [
@@ -16741,15 +17292,10 @@ function suggestCommand() {
16741
17292
  const cfg = requireConfig12();
16742
17293
  const client = createTypedClient(cfg);
16743
17294
  const ksId = await getKnowledgeStoreId3(client, cfg.active_account.target.space_id);
16744
- if (!cfg.active_account?.target?.org_id) {
16745
- console.error(import_picocolors21.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
16746
- process.exit(1);
17295
+ const dataSourceIds = await listSpaceDataSourceIds(cfg, cfg.active_account.target.space_id);
17296
+ if (dataSourceIds.length === 0) {
17297
+ throw new Error("No data sources are connected to the active deployment.");
16747
17298
  }
16748
- const dataSources = await client.dataSource.list.query({
16749
- org_id: cfg.active_account?.target?.org_id,
16750
- excluded_provider_slugs: []
16751
- });
16752
- const dataSourceIds = dataSources.map((ds) => ds.id).filter((id) => id !== null);
16753
17299
  const result = await client.suggestedDoc.generate.mutate({
16754
17300
  knowledgeStoreId: ksId,
16755
17301
  dataSourceIds
@@ -16758,7 +17304,7 @@ function suggestCommand() {
16758
17304
  printResult(result, opts);
16759
17305
  return;
16760
17306
  }
16761
- console.log(import_picocolors21.default.green("Document suggestions are being generated."));
17307
+ console.log(import_picocolors24.default.green("Document suggestions are being generated."));
16762
17308
  });
16763
17309
  cmd.command("reject").description("Reject a suggestion").argument("<id>", "Suggestion ID").option("--json", "Output as JSON").action(async (id, opts) => {
16764
17310
  const cfg = requireConfig12();
@@ -16768,7 +17314,7 @@ function suggestCommand() {
16768
17314
  printResult({ success: true, id }, opts);
16769
17315
  return;
16770
17316
  }
16771
- console.log(import_picocolors21.default.green("Suggestion rejected."));
17317
+ console.log(import_picocolors24.default.green("Suggestion rejected."));
16772
17318
  });
16773
17319
  return cmd;
16774
17320
  }
@@ -16841,18 +17387,22 @@ function telemetryCommand() {
16841
17387
  // src/commands/threads.ts
16842
17388
  init_commander();
16843
17389
  init_trpc();
16844
- var import_picocolors22 = __toESM(require_picocolors(), 1);
17390
+ var import_picocolors25 = __toESM(require_picocolors(), 1);
16845
17391
  function requireConfig13() {
16846
17392
  const cfg = requireLoginConfig();
16847
17393
  if (!cfg.active_account?.target?.space_id) {
16848
- console.error(import_picocolors22.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
17394
+ console.error(import_picocolors25.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
16849
17395
  process.exit(1);
16850
17396
  }
16851
17397
  return cfg;
16852
17398
  }
16853
17399
  function threadsCommand() {
16854
17400
  const cmd = new Command("threads").description("List and manage conversation threads");
16855
- cmd.command("list").description("List threads").option("--status <status>", "Filter by status: pending, resolved, archived").option("--search <query>", "Search threads").option("--limit <n>", "Maximum results (default: 20)", "20").option("--json", "Output as JSON").action(async (opts) => {
17401
+ cmd.command("list").description("List threads").addOption(new Option("--status <status>", "Filter by status").choices([
17402
+ "pending",
17403
+ "resolved",
17404
+ "archived"
17405
+ ])).option("--search <query>", "Search threads").addOption(new Option("--limit <n>", "Maximum results (default: 20; max: 100)").argParser(positiveIntegerAtMost(100)).default(20)).option("--json", "Output as JSON").action(async (opts) => {
16856
17406
  const cfg = requireConfig13();
16857
17407
  const client = createTypedClient(cfg);
16858
17408
  const input = {
@@ -16870,7 +17420,7 @@ function threadsCommand() {
16870
17420
  search: undefined,
16871
17421
  space_id: cfg.active_account.target.space_id,
16872
17422
  workspaces: undefined,
16873
- limit: Math.min(Number.parseInt(opts.limit ?? "20", 10), 100)
17423
+ limit: opts.limit
16874
17424
  };
16875
17425
  if (opts.search)
16876
17426
  input.search = opts.search;
@@ -16892,7 +17442,7 @@ function threadsCommand() {
16892
17442
  return;
16893
17443
  }
16894
17444
  if (!threads || threads.length === 0) {
16895
- console.log(import_picocolors22.default.dim("No threads found."));
17445
+ console.log(import_picocolors25.default.dim("No threads found."));
16896
17446
  return;
16897
17447
  }
16898
17448
  printTable(["ID", "Title", "Status", "Created"], threads.map((t2) => [
@@ -16902,14 +17452,14 @@ function threadsCommand() {
16902
17452
  formatDate(t2.created_at)
16903
17453
  ]), { rawData: threads });
16904
17454
  });
16905
- cmd.command("get").description("View a thread and its messages").argument("<id>", "Thread ID").option("--limit <n>", "Number of messages to show (default: 20)", "20").option("--json", "Output as JSON").action(async (id, opts) => {
17455
+ cmd.command("get").description("View a thread and its messages").argument("<id>", "Thread ID").addOption(new Option("--limit <n>", "Number of messages to show (default: 20; -1 for all)").argParser(messageLimit).default(20)).option("--json", "Output as JSON").action(async (id, opts) => {
16906
17456
  const cfg = requireConfig13();
16907
17457
  const client = createTypedClient(cfg);
16908
17458
  const [thread, messagesData] = await Promise.all([
16909
17459
  client.thread.get.query(id),
16910
17460
  client.messages.list.query({
16911
17461
  thread_id: id,
16912
- limit: Number.parseInt(opts.limit ?? "20", 10)
17462
+ limit: opts.limit
16913
17463
  })
16914
17464
  ]);
16915
17465
  if (opts.json) {
@@ -16917,10 +17467,10 @@ function threadsCommand() {
16917
17467
  return;
16918
17468
  }
16919
17469
  if (!thread) {
16920
- console.log(import_picocolors22.default.dim("Thread not found."));
17470
+ console.log(import_picocolors25.default.dim("Thread not found."));
16921
17471
  return;
16922
17472
  }
16923
- console.log(import_picocolors22.default.bold(thread.generated_title ?? "(untitled thread)"));
17473
+ console.log(import_picocolors25.default.bold(thread.generated_title ?? "(untitled thread)"));
16924
17474
  printInfo([
16925
17475
  ["ID", thread.id],
16926
17476
  ["Created", formatDate(thread.created_at)],
@@ -16931,13 +17481,13 @@ function threadsCommand() {
16931
17481
  if (messages && messages.length > 0) {
16932
17482
  const allMessages = messages.flatMap((group) => group.messages);
16933
17483
  console.log(`
16934
- ${import_picocolors22.default.bold("Messages")} (${allMessages.length})`);
16935
- console.log(import_picocolors22.default.dim("─".repeat(60)));
17484
+ ${import_picocolors25.default.bold("Messages")} (${allMessages.length})`);
17485
+ console.log(import_picocolors25.default.dim("─".repeat(60)));
16936
17486
  for (const msg of allMessages) {
16937
17487
  const role = msg.author_role ?? "unknown";
16938
17488
  const date = formatDate(msg.created_at);
16939
17489
  console.log(`
16940
- ${import_picocolors22.default.bold(role)} ${import_picocolors22.default.dim(date)}`);
17490
+ ${import_picocolors25.default.bold(role)} ${import_picocolors25.default.dim(date)}`);
16941
17491
  if (msg.body) {
16942
17492
  console.log(truncate(msg.body, 500));
16943
17493
  }
@@ -16952,7 +17502,7 @@ ${import_picocolors22.default.bold(role)} ${import_picocolors22.default.dim(date
16952
17502
  printResult({ success: true, id }, opts);
16953
17503
  return;
16954
17504
  }
16955
- console.log(import_picocolors22.default.green(`Thread ${id.slice(0, 8)} archived.`));
17505
+ console.log(import_picocolors25.default.green(`Thread ${id.slice(0, 8)} archived.`));
16956
17506
  });
16957
17507
  return cmd;
16958
17508
  }
@@ -16960,11 +17510,11 @@ ${import_picocolors22.default.bold(role)} ${import_picocolors22.default.dim(date
16960
17510
  // src/commands/topics.ts
16961
17511
  init_commander();
16962
17512
  init_trpc();
16963
- var import_picocolors23 = __toESM(require_picocolors(), 1);
17513
+ var import_picocolors26 = __toESM(require_picocolors(), 1);
16964
17514
  function requireConfig14() {
16965
17515
  const cfg = requireLoginConfig();
16966
17516
  if (!cfg.active_account?.target?.space_id) {
16967
- console.error(import_picocolors23.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
17517
+ console.error(import_picocolors26.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
16968
17518
  process.exit(1);
16969
17519
  }
16970
17520
  return cfg;
@@ -16974,13 +17524,13 @@ async function getKnowledgeStoreId4(client, spaceId) {
16974
17524
  space_id: spaceId
16975
17525
  });
16976
17526
  if (!store) {
16977
- console.error(import_picocolors23.default.red("No knowledge store found for this deployment."));
17527
+ console.error(import_picocolors26.default.red("No knowledge store found for this deployment."));
16978
17528
  process.exit(1);
16979
17529
  }
16980
17530
  return store.id;
16981
17531
  }
16982
17532
  function topicsCommand() {
16983
- const cmd = new Command("topics").alias("tags").description("Browse Topics in your knowledge base");
17533
+ const cmd = new Command("topics").description("Browse Topics in your knowledge base");
16984
17534
  cmd.command("list").description("List all topics").option("--json", "Output as JSON").action(async (opts) => {
16985
17535
  const cfg = requireConfig14();
16986
17536
  const client = createTypedClient(cfg);
@@ -16993,7 +17543,7 @@ function topicsCommand() {
16993
17543
  return;
16994
17544
  }
16995
17545
  if (!topics || topics.length === 0) {
16996
- console.log(import_picocolors23.default.dim("No topics found."));
17546
+ console.log(import_picocolors26.default.dim("No topics found."));
16997
17547
  return;
16998
17548
  }
16999
17549
  printTable(["ID", "Name", "Description"], topics.map((t2) => [
@@ -17002,7 +17552,7 @@ function topicsCommand() {
17002
17552
  t2.description ?? "—"
17003
17553
  ]), { rawData: topics });
17004
17554
  });
17005
- 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) => {
17555
+ cmd.command("pages").description("List pages with a specific topic").argument("<topic-id>", "Topic ID").option("--search <query>", "Search within the topic's pages").addOption(new Option("--limit <n>", "Maximum results").argParser(positiveInteger).default(10)).option("--json", "Output as JSON").action(async (topicId, opts) => {
17006
17556
  const cfg = requireConfig14();
17007
17557
  const client = createTypedClient(cfg);
17008
17558
  const ksId = await getKnowledgeStoreId4(client, cfg.active_account.target.space_id);
@@ -17010,7 +17560,7 @@ function topicsCommand() {
17010
17560
  knowledge_store_id: ksId,
17011
17561
  topic_id: topicId,
17012
17562
  searchTerm: opts.search,
17013
- limit: Number.parseInt(opts.limit ?? "10", 10)
17563
+ limit: opts.limit
17014
17564
  });
17015
17565
  const pages = result.data;
17016
17566
  if (opts.json) {
@@ -17018,7 +17568,7 @@ function topicsCommand() {
17018
17568
  return;
17019
17569
  }
17020
17570
  if (!pages || pages.length === 0) {
17021
- console.log(import_picocolors23.default.dim("No pages found with this topic."));
17571
+ console.log(import_picocolors26.default.dim("No pages found with this topic."));
17022
17572
  return;
17023
17573
  }
17024
17574
  printTable(["ID", "Title"], pages.map((p2) => [
@@ -17032,7 +17582,7 @@ function topicsCommand() {
17032
17582
  // src/commands/upgrade.ts
17033
17583
  init_commander();
17034
17584
  init_skill();
17035
- var import_picocolors24 = __toESM(require_picocolors(), 1);
17585
+ var import_picocolors27 = __toESM(require_picocolors(), 1);
17036
17586
  import { spawnSync as spawnSync2 } from "node:child_process";
17037
17587
  import { realpathSync } from "node:fs";
17038
17588
  import { homedir as homedir6 } from "node:os";
@@ -17201,7 +17751,7 @@ Could not update Dosu automatically.`);
17201
17751
  ${plan.manualCommand}`);
17202
17752
  return result.status && result.status > 0 ? result.status : 1;
17203
17753
  }
17204
- console.log(import_picocolors24.default.green(`
17754
+ console.log(import_picocolors27.default.green(`
17205
17755
  ✓ Update command completed.`));
17206
17756
  console.log('Run "dosu --version" to verify.');
17207
17757
  return 0;
@@ -17214,7 +17764,7 @@ async function completeUpgrade(channel = INSTALL_CHANNEL, options = {}) {
17214
17764
  try {
17215
17765
  const result = await installSkill();
17216
17766
  if (result.success) {
17217
- console.log(import_picocolors24.default.green("✓ Skills updated."));
17767
+ console.log(import_picocolors27.default.green("✓ Skills updated."));
17218
17768
  } else {
17219
17769
  console.error('Skills could not be refreshed. Run "dosu skill update" to retry.');
17220
17770
  }
@@ -17243,7 +17793,7 @@ init_skill_update_check();
17243
17793
  // src/version/update-check.ts
17244
17794
  init_config();
17245
17795
  init_logger();
17246
- var import_picocolors25 = __toESM(require_picocolors(), 1);
17796
+ var import_picocolors28 = __toESM(require_picocolors(), 1);
17247
17797
  import { existsSync as existsSync17, mkdirSync as mkdirSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "node:fs";
17248
17798
  import { join as join28 } from "node:path";
17249
17799
  var CACHE_FILENAME3 = "update-check.json";
@@ -17336,7 +17886,7 @@ function buildUpdateNotice(current, latest, channel, interactive, npx = false) {
17336
17886
  `└${horizontal}┘`
17337
17887
  ];
17338
17888
  return `
17339
- ${frameLines.map((line) => import_picocolors25.default.yellow(line)).join(`
17889
+ ${frameLines.map((line) => import_picocolors28.default.yellow(line)).join(`
17340
17890
  `)}
17341
17891
  `;
17342
17892
  }
@@ -17751,6 +18301,7 @@ Start ${provider.name()} in this project directory to use the Dosu MCP.`);
17751
18301
  console.log(`
17752
18302
  Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
17753
18303
  });
18304
+ program2.addCommand(agentsCommand());
17754
18305
  program2.addCommand(analyticsCommand());
17755
18306
  program2.addCommand(askCommand());
17756
18307
  program2.addCommand(auditCommand());
@@ -17759,6 +18310,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
17759
18310
  program2.addCommand(insightsCommand());
17760
18311
  program2.addCommand(integrationsCommand());
17761
18312
  program2.addCommand(knowledgeCommand());
18313
+ program2.addCommand(librariesCommand());
17762
18314
  program2.addCommand(membersCommand());
17763
18315
  program2.addCommand(orgCommand());
17764
18316
  program2.addCommand(reviewCommand());
@@ -17884,4 +18436,4 @@ execute().catch((err) => {
17884
18436
  process.exit(1);
17885
18437
  });
17886
18438
 
17887
- //# debugId=d08d0e8f-b86e-9699-6475-6e2164756e21
18439
+ //# debugId=9d873764-f667-b08c-6475-6e2164756e21