@dosu/cli 0.49.2 → 0.49.4

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 +239 -184
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -120,10 +120,10 @@ Once authenticated against a deployment, you can drive the Dosu platform without
120
120
  | `dosu review` | Document review workflow |
121
121
  | `dosu sources` | Manage connected data sources (list, sync, update) |
122
122
  | `dosu integrations` | List and inspect platform integrations (Slack, GitHub, …) |
123
- | `dosu tags` | List knowledge base tags and tagged pages |
124
- | `dosu members` | Manage team members and access requests |
123
+ | `dosu topics` | List knowledge base topics and their pages |
124
+ | `dosu members` | Invite organization members |
125
125
  | `dosu org` | Show organization information |
126
- | `dosu deployments` | List / show / switch deployments |
126
+ | `dosu deployments` | List / show / switch Dosu MCP deployments |
127
127
  | `dosu analytics` | View usage statistics |
128
128
  | `dosu insights` | Open a visual report of your Dosu space activity |
129
129
  | `dosu skill` | Install / update / remove the Dosu agent skill |
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.2", INSTALL_CHANNEL = "npm";
5003
+ var VERSION = "0.49.4", INSTALL_CHANNEL = "npm";
5004
5004
 
5005
5005
  // src/debug/logger.ts
5006
5006
  import {
@@ -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 = "20790a5a-a63f-06a4-6475-6e2164756e21";
10596
+ var BUNDLE_DEBUG_ID_PLACEHOLDER = "0e1efd83-4f86-ddb7-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
@@ -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",
@@ -13939,6 +13939,38 @@ init_commander();
13939
13939
  init_trpc();
13940
13940
  var import_picocolors4 = __toESM(require_picocolors(), 1);
13941
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
+
13942
13974
  // src/commands/auth.ts
13943
13975
  init_config();
13944
13976
  var import_picocolors2 = __toESM(require_picocolors(), 1);
@@ -14027,12 +14059,12 @@ function requireConfig() {
14027
14059
  return cfg;
14028
14060
  }
14029
14061
  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) => {
14062
+ 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
14063
  const cfg = requireConfig();
14032
14064
  const client = createTypedClient(cfg);
14033
14065
  const stats = await client.analytics.getUsageStats.query({
14034
14066
  spaceId: cfg.active_account.target.space_id,
14035
- days: Number.parseInt(opts.days ?? "30", 10)
14067
+ days: opts.days
14036
14068
  });
14037
14069
  if (opts.json) {
14038
14070
  printResult(stats, opts);
@@ -14186,8 +14218,7 @@ var DEFAULT_DEPLOYMENT_CONFIG_GITHUB = {
14186
14218
  multiple_labels_per_group: false,
14187
14219
  include: [],
14188
14220
  exclude: [],
14189
- separator: null,
14190
- custom_instructions: null
14221
+ separator: null
14191
14222
  },
14192
14223
  voting: {
14193
14224
  enabled: false
@@ -14213,8 +14244,7 @@ var DEFAULT_DEPLOYMENT_CONFIG_GITHUB = {
14213
14244
  multiple_labels_per_group: false,
14214
14245
  include: [],
14215
14246
  exclude: [],
14216
- separator: null,
14217
- custom_instructions: null
14247
+ separator: null
14218
14248
  },
14219
14249
  lgtm_label: {
14220
14250
  enabled: false,
@@ -14233,10 +14263,6 @@ var DEFAULT_DEPLOYMENT_CONFIG_GITHUB = {
14233
14263
  color: "FFA500",
14234
14264
  description: "This PR is set to be merged"
14235
14265
  },
14236
- stale_doc_check: {
14237
- enabled: true,
14238
- monitored_paths: []
14239
- },
14240
14266
  diff_review_policies: []
14241
14267
  },
14242
14268
  discussions: {
@@ -14256,14 +14282,6 @@ var DEFAULT_DEPLOYMENT_CONFIG_GITHUB = {
14256
14282
  included_categories: ["Q&A", "Questions"],
14257
14283
  quality_checklist: null
14258
14284
  },
14259
- stale_bot: {
14260
- enabled: false,
14261
- days_before_stale: 90,
14262
- days_before_close: 7,
14263
- max_issues_close_per_day: 25,
14264
- excluded_label_ids: [],
14265
- tag_maintainer_response: false
14266
- },
14267
14285
  changelogs: {
14268
14286
  visibility: false,
14269
14287
  enabled: false
@@ -14680,6 +14698,26 @@ var REPO_REFRESH_POLL_TIMEOUT_MS = 1e4;
14680
14698
  var REPO_MULTISELECT_MAX_ITEMS = 10;
14681
14699
  var DATA_SOURCE_VERIFY_POLL_INTERVAL_MS = 1000;
14682
14700
  var DATA_SOURCE_VERIFY_POLL_TIMEOUT_MS = 1e4;
14701
+ function parseAvailableRepos(value) {
14702
+ if (!Array.isArray(value))
14703
+ throw new Error("githubRepository.listForOrg returned a non-array");
14704
+ return value.map((repository, index) => {
14705
+ 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") {
14706
+ throw new Error(`githubRepository.listForOrg returned an invalid repository at index ${index}`);
14707
+ }
14708
+ return repository;
14709
+ });
14710
+ }
14711
+ function parseDeploymentIds(value) {
14712
+ if (!Array.isArray(value))
14713
+ throw new Error("workspaces.listForSpace returned a non-array");
14714
+ return value.map((deployment, index) => {
14715
+ if (deployment === null || typeof deployment !== "object" || !("deployment_id" in deployment) || typeof deployment.deployment_id !== "string") {
14716
+ throw new Error(`workspaces.listForSpace returned an invalid deployment at index ${index}`);
14717
+ }
14718
+ return deployment.deployment_id;
14719
+ });
14720
+ }
14683
14721
  function detectGitRepo(cwd = process.cwd()) {
14684
14722
  let url;
14685
14723
  try {
@@ -14703,9 +14741,9 @@ function detectGitRepo(cwd = process.cwd()) {
14703
14741
  }
14704
14742
  async function fetchListForOrg(trpc, orgID) {
14705
14743
  try {
14706
- const repos = await trpc.githubRepository.listForOrg.query({
14744
+ const repos = parseAvailableRepos(await trpc.githubRepository.listForOrg.query({
14707
14745
  org_id: orgID
14708
- });
14746
+ }));
14709
14747
  return sortReposByRecency(repos);
14710
14748
  } catch (err) {
14711
14749
  const msg = err instanceof Error ? err.message : String(err);
@@ -14845,9 +14883,9 @@ async function createDeploymentForRepo(trpc, orgID, spaceID, repo) {
14845
14883
  space_id: spaceID,
14846
14884
  data_source_ids: [dataSourceID]
14847
14885
  });
14848
- const spaceDeployments = await trpc.workspaces.listForSpace.query(spaceID);
14849
- await Promise.all(spaceDeployments.map((d) => trpc.deploymentDataSource.create.mutate({
14850
- deployment_id: d.deployment_id,
14886
+ const spaceDeploymentIds = parseDeploymentIds(await trpc.workspaces.listForSpace.query(spaceID));
14887
+ await Promise.all(spaceDeploymentIds.map((deploymentID) => trpc.deploymentDataSource.create.mutate({
14888
+ deployment_id: deploymentID,
14851
14889
  data_source_id: dataSourceID
14852
14890
  })));
14853
14891
  return {
@@ -15449,18 +15487,28 @@ function auditCommand() {
15449
15487
 
15450
15488
  // src/commands/deployments.ts
15451
15489
  init_commander();
15490
+ init_client();
15452
15491
  init_trpc();
15453
15492
  init_config();
15454
15493
  var import_picocolors10 = __toESM(require_picocolors(), 1);
15494
+ var MCP_PROVIDER_SLUG = "dosu_mcp";
15455
15495
  function requireConfig4() {
15456
15496
  return requireLoginConfig();
15457
15497
  }
15498
+ async function listAccessibleDeployments(client, activeOrgId) {
15499
+ if (activeOrgId)
15500
+ return client.workspaces.listForOrg.query(activeOrgId);
15501
+ const orgs = await client.organization.getOrganizations.query({});
15502
+ const deployments = await Promise.all(orgs.map((org) => client.workspaces.listForOrg.query(org.org_id)));
15503
+ return deployments.flat();
15504
+ }
15458
15505
  function deploymentsCommand() {
15459
15506
  const cmd = new Command("deployments").description("Manage deployments");
15460
15507
  cmd.command("list").description("List all deployments").option("--json", "Output as JSON").action(async (opts) => {
15461
15508
  const cfg = requireConfig4();
15462
15509
  const client = createTypedClient(cfg);
15463
- const deployments = cfg.active_account?.target?.org_id ? await client.workspaces.listForOrg.query(cfg.active_account?.target?.org_id) : await client.workspaces.listAll.query({});
15510
+ const allDeployments = await listAccessibleDeployments(client, cfg.active_account?.target?.org_id);
15511
+ const deployments = allDeployments.filter((deployment) => deployment.provider_slug === MCP_PROVIDER_SLUG);
15464
15512
  if (opts.json) {
15465
15513
  printResult(deployments, opts);
15466
15514
  return;
@@ -15515,11 +15563,17 @@ ${import_picocolors10.default.dim(`Current: ${cfg.active_account?.target?.deploy
15515
15563
  console.error(import_picocolors10.default.red(`Deployment not found: ${id}`));
15516
15564
  process.exit(1);
15517
15565
  }
15566
+ if (deployment.provider_slug !== MCP_PROVIDER_SLUG) {
15567
+ console.error(import_picocolors10.default.red(`Not a Dosu MCP deployment: ${id}`));
15568
+ process.exit(1);
15569
+ }
15570
+ const apiKey = await new Client(cfg).createAPIKey(deployment.deployment_id, "dosu-cli");
15518
15571
  updateTarget(cfg, {
15519
15572
  deployment_id: deployment.deployment_id,
15520
15573
  deployment_name: deployment.name,
15521
15574
  org_id: deployment.org_id,
15522
- space_id: deployment.space_id
15575
+ space_id: deployment.space_id,
15576
+ api_key: apiKey.api_key
15523
15577
  });
15524
15578
  saveConfig(cfg);
15525
15579
  if (opts.json) {
@@ -15535,10 +15589,47 @@ ${import_picocolors10.default.dim(`Current: ${cfg.active_account?.target?.deploy
15535
15589
  init_dist8();
15536
15590
  init_dist();
15537
15591
  init_commander();
15592
+ init_client();
15538
15593
  init_trpc();
15539
15594
  init_logger();
15540
15595
  var import_picocolors11 = __toESM(require_picocolors(), 1);
15541
15596
  import { readFileSync as readFileSync6 } from "node:fs";
15597
+
15598
+ // src/commands/doc-import.ts
15599
+ var IMPORT_PLATFORMS = [
15600
+ "github",
15601
+ "gitlab",
15602
+ "azure_devops",
15603
+ "confluence",
15604
+ "notion",
15605
+ "coda"
15606
+ ];
15607
+ async function importDocuments(client, platform2, context, ids) {
15608
+ const baseInput = {
15609
+ knowledge_store_id: context.knowledgeStoreId,
15610
+ space_id: context.spaceId
15611
+ };
15612
+ switch (platform2) {
15613
+ case "github":
15614
+ return client.docImports.importGithubFiles.mutate({ ...baseInput, file_ids: ids });
15615
+ case "gitlab":
15616
+ return client.docImports.importGitlabFiles.mutate({ ...baseInput, file_ids: ids });
15617
+ case "azure_devops":
15618
+ return client.docImports.importAzureDevopsFiles.mutate({ ...baseInput, file_ids: ids });
15619
+ case "confluence":
15620
+ return client.docImports.importConfluencePages.mutate({ ...baseInput, page_ids: ids });
15621
+ case "notion":
15622
+ return client.docImports.importNotionPages.mutate({ ...baseInput, page_ids: ids });
15623
+ case "coda":
15624
+ return client.docImports.importCodaPages.mutate({ ...baseInput, page_ids: ids });
15625
+ default: {
15626
+ const unsupported = platform2;
15627
+ throw new Error(`Unsupported import platform: ${unsupported}`);
15628
+ }
15629
+ }
15630
+ }
15631
+
15632
+ // src/commands/docs.ts
15542
15633
  function requireConfig5() {
15543
15634
  const cfg = requireLoginConfig();
15544
15635
  if (!cfg.active_account?.target?.space_id) {
@@ -15628,6 +15719,9 @@ async function backendPost2(path3, apiKey, body) {
15628
15719
  headers: { "Content-Type": "application/json", "X-Dosu-API-Key": apiKey },
15629
15720
  body: JSON.stringify(body)
15630
15721
  });
15722
+ return parseBackendResponse2(resp);
15723
+ }
15724
+ async function parseBackendResponse2(resp) {
15631
15725
  if (!resp.ok) {
15632
15726
  let detail = `Request failed with status ${resp.status}`;
15633
15727
  try {
@@ -15640,15 +15734,15 @@ async function backendPost2(path3, apiKey, body) {
15640
15734
  }
15641
15735
  function docsCommand() {
15642
15736
  const cmd = new Command("docs").description("Document management");
15643
- 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) => {
15737
+ 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) => {
15644
15738
  const cfg = requireConfig5();
15645
15739
  const client = createTypedClient(cfg);
15646
15740
  const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
15647
15741
  const result = await client.page.listWithTags.query({
15648
15742
  knowledge_store_id: ksId,
15649
15743
  searchTerm: opts.search,
15650
- topic_id: opts.tag,
15651
- limit: Number.parseInt(opts.limit ?? "20", 10)
15744
+ topic_id: opts.topic,
15745
+ limit: opts.limit
15652
15746
  });
15653
15747
  const pages = result.data;
15654
15748
  if (opts.json) {
@@ -15666,12 +15760,12 @@ function docsCommand() {
15666
15760
  formatDate(p2.created_at)
15667
15761
  ]), { rawData: pages });
15668
15762
  });
15669
- 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) => {
15763
+ 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) => {
15670
15764
  const cfg = requireConfig5();
15671
15765
  const client = createTypedClient(cfg);
15672
15766
  const page = await client.page.get.query({
15673
15767
  page_id: id,
15674
- version: opts.version ? Number.parseInt(opts.version, 10) : undefined
15768
+ version: opts.revision
15675
15769
  });
15676
15770
  if (opts.json) {
15677
15771
  printResult(page, opts);
@@ -15692,7 +15786,7 @@ function docsCommand() {
15692
15786
  ${page.body}`);
15693
15787
  }
15694
15788
  });
15695
- 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) => {
15789
+ 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) => {
15696
15790
  const cfg = requireConfig5();
15697
15791
  const client = createTypedClient(cfg);
15698
15792
  const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
@@ -15708,19 +15802,22 @@ ${page.body}`);
15708
15802
  }
15709
15803
  console.log(import_picocolors11.default.green(`Document "${opts.title}" created.`));
15710
15804
  });
15711
- 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) => {
15805
+ 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) => {
15806
+ if (opts.title === undefined && opts.body === undefined && opts.bodyFile === undefined) {
15807
+ throw new Error("Specify at least one of --title, --body, or --body-file.");
15808
+ }
15712
15809
  const cfg = requireConfig5();
15713
15810
  const client = createTypedClient(cfg);
15714
15811
  const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
15715
15812
  const body = readBody(opts);
15716
- const result = await client.page.update.mutate({
15813
+ await client.page.update.mutate({
15717
15814
  id,
15718
15815
  knowledge_store_id: ksId,
15719
15816
  title: opts.title,
15720
15817
  body
15721
15818
  });
15722
15819
  if (opts.json) {
15723
- printResult(result, opts);
15820
+ printResult({ success: true, id }, opts);
15724
15821
  return;
15725
15822
  }
15726
15823
  console.log(import_picocolors11.default.green("Document updated."));
@@ -15765,18 +15862,18 @@ ${page.body}`);
15765
15862
  formatDate(v.created_at)
15766
15863
  ]), { rawData: versions });
15767
15864
  });
15768
- 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) => {
15865
+ 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) => {
15769
15866
  const cfg = requireConfig5();
15770
15867
  const client = createTypedClient(cfg);
15771
15868
  await client.page.restoreVersion.mutate({
15772
15869
  page_id: id,
15773
- version_to_restore: Number.parseInt(opts.version, 10)
15870
+ version_to_restore: opts.revision
15774
15871
  });
15775
15872
  if (opts.json) {
15776
- printResult({ success: true, id, version: opts.version }, opts);
15873
+ printResult({ success: true, id, revision: opts.revision }, opts);
15777
15874
  return;
15778
15875
  }
15779
- console.log(import_picocolors11.default.green(`Document restored to version ${opts.version}.`));
15876
+ console.log(import_picocolors11.default.green(`Document restored to version ${opts.revision}.`));
15780
15877
  });
15781
15878
  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) => {
15782
15879
  const cfg = requireConfig5();
@@ -15802,31 +15899,19 @@ ${page.body}`);
15802
15899
  }
15803
15900
  console.log(import_picocolors11.default.green("Auto-tagging started."));
15804
15901
  });
15805
- 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) => {
15902
+ 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) => {
15806
15903
  const cfg = requireConfig5();
15807
15904
  const client = createTypedClient(cfg);
15808
15905
  const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
15809
- const fileIds = opts.files.split(",").map((id) => id.trim());
15810
- const importFn = {
15811
- github: (input) => client.docImports.importGithubFiles.mutate(input),
15812
- gitlab: (input) => client.docImports.importGitlabFiles.mutate(input),
15813
- azure_devops: (input) => client.docImports.importAzureDevopsFiles.mutate(input),
15814
- confluence: (input) => client.docImports.importConfluencePages.mutate(input),
15815
- notion: (input) => client.docImports.importNotionPages.mutate(input),
15816
- coda: (input) => client.docImports.importCodaPages.mutate(input)
15817
- };
15818
- const fn = importFn[platform2.toLowerCase()];
15819
- if (!fn) {
15820
- console.error(import_picocolors11.default.red(`Unknown platform: ${platform2}. Use: github, gitlab, azure_devops, confluence, notion, coda`));
15821
- process.exit(1);
15906
+ const fileIds = opts.files.split(",").map((id) => id.trim()).filter(Boolean);
15907
+ if (fileIds.length === 0) {
15908
+ throw new Error("--files must contain at least one file or page ID.");
15822
15909
  }
15823
- const idField = ["confluence", "notion", "coda"].includes(platform2.toLowerCase()) ? "page_ids" : "file_ids";
15824
15910
  try {
15825
- const result = await fn({
15826
- knowledge_store_id: ksId,
15827
- space_id: cfg.active_account.target.space_id,
15828
- [idField]: fileIds
15829
- });
15911
+ const result = await importDocuments(client, platform2, {
15912
+ knowledgeStoreId: ksId,
15913
+ spaceId: cfg.active_account.target.space_id
15914
+ }, fileIds);
15830
15915
  if (opts.json) {
15831
15916
  printResult(result, opts);
15832
15917
  return;
@@ -15850,10 +15935,10 @@ ${page.body}`);
15850
15935
  process.exit(1);
15851
15936
  }
15852
15937
  });
15853
- cmd.command("import-status").description("Check import task status").argument("<task-id>", "Import task ID").option("--json", "Output as JSON").action(async (taskId, opts) => {
15938
+ 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) => {
15854
15939
  const cfg = requireConfig5();
15855
- const client = createTypedClient(cfg);
15856
- const status = await client.docImports.getImportStatus.query(taskId);
15940
+ const response = await new Client(cfg).get(`/doc-imports/status/${encodeURIComponent(taskId)}`);
15941
+ const status = response.status === 404 ? null : await parseBackendResponse2(response);
15857
15942
  if (opts.json) {
15858
15943
  printResult(status, opts);
15859
15944
  return;
@@ -15960,17 +16045,25 @@ function requireConfig6() {
15960
16045
  }
15961
16046
  return cfg;
15962
16047
  }
16048
+ var DISPLAY_PLATFORMS = [
16049
+ "github",
16050
+ "gitlab",
16051
+ "azure_devops",
16052
+ "slack",
16053
+ "confluence",
16054
+ "notion",
16055
+ "coda",
16056
+ "teams"
16057
+ ];
15963
16058
  var NANGO_PROBES = {
15964
16059
  gitlab: [
15965
16060
  { provider: "gitlab", providerConfigKey: "gitlab" },
15966
16061
  { provider: "gitlab", providerConfigKey: "gitlab-pat" }
15967
16062
  ],
15968
- "gitlab-pat": [{ provider: "gitlab", providerConfigKey: "gitlab-pat" }],
15969
16063
  confluence: [
15970
16064
  { provider: "confluence", providerConfigKey: "confluence" },
15971
16065
  { provider: "confluence", providerConfigKey: "confluence-basic" }
15972
16066
  ],
15973
- "confluence-basic": [{ provider: "confluence", providerConfigKey: "confluence-basic" }],
15974
16067
  notion: [{ provider: "notion", providerConfigKey: "notion" }],
15975
16068
  coda: [{ provider: "coda", providerConfigKey: "coda" }],
15976
16069
  azure_devops: [
@@ -15978,32 +16071,20 @@ var NANGO_PROBES = {
15978
16071
  { provider: "azure_devops", providerConfigKey: "azure-devops" }
15979
16072
  ]
15980
16073
  };
15981
- var DISPLAY_PLATFORMS = [
15982
- "github",
15983
- "gitlab",
15984
- "azure_devops",
15985
- "slack",
15986
- "confluence",
15987
- "notion",
15988
- "coda",
15989
- "teams"
15990
- ];
15991
16074
  async function probeConnection(client, orgId, platform4) {
15992
16075
  const probes = NANGO_PROBES[platform4];
15993
16076
  if (!probes) {
15994
- return { queryable: false, connected: false, connection: null };
16077
+ return { queryable: false, connected: null, connection: null };
15995
16078
  }
15996
16079
  for (const probe of probes) {
15997
- try {
15998
- const conn = await client.nango.getConnection.query({
15999
- provider: probe.provider,
16000
- providerConfigKey: probe.providerConfigKey,
16001
- orgId
16002
- });
16003
- if (conn != null) {
16004
- return { queryable: true, connected: true, connection: conn };
16005
- }
16006
- } catch {}
16080
+ const conn = await client.nango.getConnection.query({
16081
+ provider: probe.provider,
16082
+ providerConfigKey: probe.providerConfigKey,
16083
+ orgId
16084
+ });
16085
+ if (conn != null) {
16086
+ return { queryable: true, connected: true, connection: conn };
16087
+ }
16007
16088
  }
16008
16089
  return { queryable: true, connected: false, connection: null };
16009
16090
  }
@@ -16022,19 +16103,19 @@ function integrationsCommand() {
16022
16103
  }
16023
16104
  printTable(["Platform", "Status"], results.map((r2) => [
16024
16105
  r2.platform,
16025
- r2.connected ? import_picocolors15.default.green("connected") : import_picocolors15.default.dim("not connected")
16106
+ r2.connected === null ? import_picocolors15.default.dim("status unavailable") : r2.connected ? import_picocolors15.default.green("connected") : import_picocolors15.default.dim("not connected")
16026
16107
  ]), { rawData: results });
16027
16108
  });
16028
- 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) => {
16109
+ 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) => {
16029
16110
  const cfg = requireConfig6();
16030
16111
  const client = createTypedClient(cfg);
16031
16112
  const { queryable, connected, connection } = await probeConnection(client, cfg.active_account.target.org_id, platform4);
16032
16113
  if (!queryable) {
16033
16114
  if (opts.json) {
16034
- printResult({ platform: platform4, connected: false, note: "not queryable via nango" }, opts);
16115
+ printResult({ platform: platform4, connected: null, note: "connection status unavailable via CLI" }, opts);
16035
16116
  return;
16036
16117
  }
16037
- console.log(`${platform4}: ${import_picocolors15.default.dim("not connected (not queryable)")}`);
16118
+ console.log(`${platform4}: ${import_picocolors15.default.dim("connection status unavailable via CLI")}`);
16038
16119
  return;
16039
16120
  }
16040
16121
  if (opts.json) {
@@ -16070,10 +16151,10 @@ function integrationsCommand() {
16070
16151
  }
16071
16152
  console.log(import_picocolors15.default.green(`Joined Slack channel ${channelId}.`));
16072
16153
  });
16073
- cmd.command("github-collaborators").description("List GitHub repository collaborators").option("--json", "Output as JSON").action(async (opts) => {
16154
+ 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) => {
16074
16155
  const cfg = requireConfig6();
16075
16156
  const client = createTypedClient(cfg);
16076
- const collaborators = await client.githubRepository.getCollaborators.query(0);
16157
+ const collaborators = await client.githubRepository.getCollaborators.query(repositoryId);
16077
16158
  if (opts.json) {
16078
16159
  printResult(collaborators, opts);
16079
16160
  return;
@@ -16101,7 +16182,7 @@ function requireConfig7() {
16101
16182
  }
16102
16183
  function knowledgeCommand() {
16103
16184
  const cmd = new Command("knowledge").description("Search and browse your knowledge base");
16104
- 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) => {
16185
+ 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) => {
16105
16186
  const cfg = requireConfig7();
16106
16187
  const client = createTypedClient(cfg);
16107
16188
  const dataSources = await client.dataSource.list.query({
@@ -16127,15 +16208,14 @@ function knowledgeCommand() {
16127
16208
  console.log(import_picocolors16.default.dim("No results found."));
16128
16209
  return;
16129
16210
  }
16130
- const limit = Number.parseInt(opts.limit ?? "10", 10);
16131
- const limited = results.slice(0, limit);
16211
+ const limited = results.slice(0, opts.limit);
16132
16212
  printTable(["Title", "Type"], limited.map((r2) => [
16133
16213
  truncate(r2.title ?? "(untitled)", 60),
16134
16214
  r2.entity_type ?? "—"
16135
16215
  ]), { json: false, rawData: limited });
16136
- if (results.length > limit) {
16216
+ if (results.length > opts.limit) {
16137
16217
  console.log(import_picocolors16.default.dim(`
16138
- ${results.length - limit} more results not shown.`));
16218
+ ${results.length - opts.limit} more results not shown.`));
16139
16219
  }
16140
16220
  });
16141
16221
  cmd.command("list").description("Show knowledge store information").option("--json", "Output as JSON").action(async (opts) => {
@@ -16170,28 +16250,11 @@ function requireConfig8() {
16170
16250
  return cfg;
16171
16251
  }
16172
16252
  function membersCommand() {
16173
- const cmd = new Command("members").description("Manage team members");
16174
- cmd.command("list").description("List team members and invitations").option("--json", "Output as JSON").action(async (opts) => {
16175
- const cfg = requireConfig8();
16176
- const client = createTypedClient(cfg);
16177
- const data = await client.invitations.getInvitations.query();
16178
- if (opts.json) {
16179
- printResult(data, opts);
16180
- return;
16181
- }
16182
- if (!data.items || data.items.length === 0) {
16183
- console.log(import_picocolors17.default.dim("No members or invitations found."));
16184
- return;
16185
- }
16186
- printTable(["Email", "Org"], data.items.map((m3) => [
16187
- m3.email ?? "—",
16188
- m3.org?.name ?? "—"
16189
- ]), { rawData: data });
16190
- });
16191
- 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) => {
16253
+ const cmd = new Command("members").description("Invite organization members");
16254
+ 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) => {
16192
16255
  const cfg = requireConfig8();
16193
16256
  const client = createTypedClient(cfg);
16194
- const role = opts.role.toUpperCase() === "ADMIN" ? "ADMIN" : "MEMBER";
16257
+ const role = opts.role === "admin" ? "ADMIN" : "MEMBER";
16195
16258
  await client.invitations.invite.mutate({
16196
16259
  orgId: cfg.active_account.target.org_id,
16197
16260
  email,
@@ -16203,49 +16266,6 @@ function membersCommand() {
16203
16266
  }
16204
16267
  console.log(import_picocolors17.default.green(`Invitation sent to ${email} as ${role}.`));
16205
16268
  });
16206
- cmd.command("requests").description("List pending access requests").option("--json", "Output as JSON").action(async (opts) => {
16207
- const cfg = requireConfig8();
16208
- const client = createTypedClient(cfg);
16209
- const data = await client.invitations.getInvitations.query();
16210
- if (opts.json) {
16211
- printResult(data, opts);
16212
- return;
16213
- }
16214
- if (!data.items || data.items.length === 0) {
16215
- console.log(import_picocolors17.default.dim("No pending access requests."));
16216
- return;
16217
- }
16218
- printTable(["Email", "Org"], data.items.map((r2) => [
16219
- r2.email ?? "—",
16220
- r2.org?.name ?? "—"
16221
- ]), { rawData: data });
16222
- });
16223
- cmd.command("approve").description("Approve an access request").argument("<email>", "Email of requester").option("--json", "Output as JSON").action(async (email, opts) => {
16224
- const cfg = requireConfig8();
16225
- const client = createTypedClient(cfg);
16226
- await client.invitations.acceptInvitation.mutate({
16227
- orgId: cfg.active_account.target.org_id,
16228
- email
16229
- });
16230
- if (opts.json) {
16231
- printResult({ success: true, email, action: "approved" }, opts);
16232
- return;
16233
- }
16234
- console.log(import_picocolors17.default.green(`Access request from ${email} approved.`));
16235
- });
16236
- cmd.command("deny").description("Deny an access request").argument("<email>", "Email of requester").option("--json", "Output as JSON").action(async (email, opts) => {
16237
- const cfg = requireConfig8();
16238
- const client = createTypedClient(cfg);
16239
- await client.invitations.rejectInvitation.mutate({
16240
- orgId: cfg.active_account.target.org_id,
16241
- email
16242
- });
16243
- if (opts.json) {
16244
- printResult({ success: true, email, action: "denied" }, opts);
16245
- return;
16246
- }
16247
- console.log(import_picocolors17.default.green(`Access request from ${email} denied.`));
16248
- });
16249
16269
  return cmd;
16250
16270
  }
16251
16271
 
@@ -16459,7 +16479,7 @@ function reviewCommand() {
16459
16479
  console.log("");
16460
16480
  console.log(change.diff);
16461
16481
  });
16462
- 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) => {
16482
+ 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) => {
16463
16483
  const cfg = requireConfig10();
16464
16484
  const client = createTypedClient(cfg);
16465
16485
  if (opts.body !== undefined && opts.bodyFile !== undefined) {
@@ -16484,6 +16504,10 @@ function reviewCommand() {
16484
16504
  console.error(import_picocolors19.default.red("Draft replies support --body only (no --title)."));
16485
16505
  process.exit(1);
16486
16506
  }
16507
+ if (body === undefined) {
16508
+ console.error(import_picocolors19.default.red("Draft replies require --body or --body-file."));
16509
+ process.exit(1);
16510
+ }
16487
16511
  await requireDraft(client, id);
16488
16512
  await client.messages.saveDraft.mutate({
16489
16513
  messageId: bareMessageId(id),
@@ -16588,7 +16612,7 @@ function reviewCommand() {
16588
16612
  console.log(import_picocolors19.default.green(`Review ${name}: ${truncateId(id)}`));
16589
16613
  });
16590
16614
  }
16591
- 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) => {
16615
+ 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) => {
16592
16616
  const cfg = requireConfig10();
16593
16617
  const client = createTypedClient(cfg);
16594
16618
  if (isDraftId(id)) {
@@ -16681,6 +16705,9 @@ function sourcesCommand() {
16681
16705
  console.log(import_picocolors20.default.green(`Data source sync triggered for ${id.slice(0, 8)}.`));
16682
16706
  });
16683
16707
  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) => {
16708
+ if (opts.name === undefined && opts.description === undefined) {
16709
+ throw new Error("Specify at least one of --name or --description.");
16710
+ }
16684
16711
  const cfg = requireConfig11();
16685
16712
  const client = createTypedClient(cfg);
16686
16713
  const result = await client.dataSource.update.mutate({
@@ -16709,8 +16736,37 @@ function sourcesCommand() {
16709
16736
 
16710
16737
  // src/commands/suggest.ts
16711
16738
  init_commander();
16712
- init_trpc();
16713
16739
  var import_picocolors21 = __toESM(require_picocolors(), 1);
16740
+
16741
+ // src/client/supabase.ts
16742
+ async function listSpaceDataSourceIds(config, spaceId) {
16743
+ const accessToken = config.active_account?.session.access_token;
16744
+ if (!accessToken)
16745
+ throw new Error("Not logged in. Run 'dosu login' first.");
16746
+ const endpoint = new URL("/rest/v1/space_data_source", getSupabaseURL());
16747
+ endpoint.searchParams.set("select", "data_source_id");
16748
+ endpoint.searchParams.set("space_id", `eq.${spaceId}`);
16749
+ const response = await fetch(endpoint, {
16750
+ headers: {
16751
+ apikey: getSupabaseAnonKey(),
16752
+ Authorization: `Bearer ${accessToken}`
16753
+ }
16754
+ });
16755
+ if (!response.ok) {
16756
+ throw new Error(`Failed to list this deployment's data sources (status ${response.status}).`);
16757
+ }
16758
+ const rows = await response.json();
16759
+ if (!Array.isArray(rows) || rows.some((row) => !isDataSourceLink(row))) {
16760
+ throw new Error("Supabase returned an invalid space_data_source response.");
16761
+ }
16762
+ return rows.map((row) => row.data_source_id);
16763
+ }
16764
+ function isDataSourceLink(value) {
16765
+ return value !== null && typeof value === "object" && "data_source_id" in value && typeof value.data_source_id === "string";
16766
+ }
16767
+
16768
+ // src/commands/suggest.ts
16769
+ init_trpc();
16714
16770
  function requireConfig12() {
16715
16771
  const cfg = requireLoginConfig();
16716
16772
  if (!cfg.active_account?.target?.space_id) {
@@ -16755,15 +16811,10 @@ function suggestCommand() {
16755
16811
  const cfg = requireConfig12();
16756
16812
  const client = createTypedClient(cfg);
16757
16813
  const ksId = await getKnowledgeStoreId3(client, cfg.active_account.target.space_id);
16758
- if (!cfg.active_account?.target?.org_id) {
16759
- console.error(import_picocolors21.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
16760
- process.exit(1);
16814
+ const dataSourceIds = await listSpaceDataSourceIds(cfg, cfg.active_account.target.space_id);
16815
+ if (dataSourceIds.length === 0) {
16816
+ throw new Error("No data sources are connected to the active deployment.");
16761
16817
  }
16762
- const dataSources = await client.dataSource.list.query({
16763
- org_id: cfg.active_account?.target?.org_id,
16764
- excluded_provider_slugs: []
16765
- });
16766
- const dataSourceIds = dataSources.map((ds) => ds.id).filter((id) => id !== null);
16767
16818
  const result = await client.suggestedDoc.generate.mutate({
16768
16819
  knowledgeStoreId: ksId,
16769
16820
  dataSourceIds
@@ -16866,7 +16917,11 @@ function requireConfig13() {
16866
16917
  }
16867
16918
  function threadsCommand() {
16868
16919
  const cmd = new Command("threads").description("List and manage conversation threads");
16869
- 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) => {
16920
+ cmd.command("list").description("List threads").addOption(new Option("--status <status>", "Filter by status").choices([
16921
+ "pending",
16922
+ "resolved",
16923
+ "archived"
16924
+ ])).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) => {
16870
16925
  const cfg = requireConfig13();
16871
16926
  const client = createTypedClient(cfg);
16872
16927
  const input = {
@@ -16884,7 +16939,7 @@ function threadsCommand() {
16884
16939
  search: undefined,
16885
16940
  space_id: cfg.active_account.target.space_id,
16886
16941
  workspaces: undefined,
16887
- limit: Math.min(Number.parseInt(opts.limit ?? "20", 10), 100)
16942
+ limit: opts.limit
16888
16943
  };
16889
16944
  if (opts.search)
16890
16945
  input.search = opts.search;
@@ -16916,14 +16971,14 @@ function threadsCommand() {
16916
16971
  formatDate(t2.created_at)
16917
16972
  ]), { rawData: threads });
16918
16973
  });
16919
- 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) => {
16974
+ 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) => {
16920
16975
  const cfg = requireConfig13();
16921
16976
  const client = createTypedClient(cfg);
16922
16977
  const [thread, messagesData] = await Promise.all([
16923
16978
  client.thread.get.query(id),
16924
16979
  client.messages.list.query({
16925
16980
  thread_id: id,
16926
- limit: Number.parseInt(opts.limit ?? "20", 10)
16981
+ limit: opts.limit
16927
16982
  })
16928
16983
  ]);
16929
16984
  if (opts.json) {
@@ -16994,7 +17049,7 @@ async function getKnowledgeStoreId4(client, spaceId) {
16994
17049
  return store.id;
16995
17050
  }
16996
17051
  function topicsCommand() {
16997
- const cmd = new Command("topics").alias("tags").description("Browse Topics in your knowledge base");
17052
+ const cmd = new Command("topics").description("Browse Topics in your knowledge base");
16998
17053
  cmd.command("list").description("List all topics").option("--json", "Output as JSON").action(async (opts) => {
16999
17054
  const cfg = requireConfig14();
17000
17055
  const client = createTypedClient(cfg);
@@ -17016,7 +17071,7 @@ function topicsCommand() {
17016
17071
  t2.description ?? "—"
17017
17072
  ]), { rawData: topics });
17018
17073
  });
17019
- 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) => {
17074
+ 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) => {
17020
17075
  const cfg = requireConfig14();
17021
17076
  const client = createTypedClient(cfg);
17022
17077
  const ksId = await getKnowledgeStoreId4(client, cfg.active_account.target.space_id);
@@ -17024,7 +17079,7 @@ function topicsCommand() {
17024
17079
  knowledge_store_id: ksId,
17025
17080
  topic_id: topicId,
17026
17081
  searchTerm: opts.search,
17027
- limit: Number.parseInt(opts.limit ?? "10", 10)
17082
+ limit: opts.limit
17028
17083
  });
17029
17084
  const pages = result.data;
17030
17085
  if (opts.json) {
@@ -17898,4 +17953,4 @@ execute().catch((err) => {
17898
17953
  process.exit(1);
17899
17954
  });
17900
17955
 
17901
- //# debugId=20790a5a-a63f-06a4-6475-6e2164756e21
17956
+ //# debugId=0e1efd83-4f86-ddb7-6475-6e2164756e21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dosu/cli",
3
- "version": "0.49.2",
3
+ "version": "0.49.4",
4
4
  "type": "module",
5
5
  "description": "Dosu CLI - Manage MCP servers for AI tools",
6
6
  "license": "MIT",