@dosu/cli 0.28.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/dosu.js +90 -31
  2. package/package.json +1 -2
package/bin/dosu.js CHANGED
@@ -4577,7 +4577,7 @@ var init_dist4 = __esm(() => {
4577
4577
  function getVersionString() {
4578
4578
  return `v${VERSION}`;
4579
4579
  }
4580
- var VERSION = "0.28.0", INSTALL_CHANNEL = "npm";
4580
+ var VERSION = "0.29.0", INSTALL_CHANNEL = "npm";
4581
4581
 
4582
4582
  // src/debug/logger.ts
4583
4583
  import {
@@ -4710,6 +4710,9 @@ var init_logger = __esm(() => {
4710
4710
  };
4711
4711
  });
4712
4712
 
4713
+ // src/client/contract.ts
4714
+ var CLI_CONTRACT_HASH = "140d68a8c401";
4715
+
4713
4716
  // src/client/trpc.ts
4714
4717
  var exports_trpc = {};
4715
4718
  __export(exports_trpc, {
@@ -4727,7 +4730,7 @@ function createTypedClient(config) {
4727
4730
  return createTRPCClient({
4728
4731
  links: [
4729
4732
  httpLink({
4730
- url: `${webAppURL}/api/trpc`,
4733
+ url: `${webAppURL}/api/cli-trpc`,
4731
4734
  transformer: dist_default,
4732
4735
  async headers() {
4733
4736
  if (isTokenExpired(config)) {
@@ -4738,7 +4741,10 @@ function createTypedClient(config) {
4738
4741
  throw new Error("session expired. Run 'dosu login' to re-authenticate");
4739
4742
  }
4740
4743
  }
4741
- return { "Supabase-Access-Token": config.access_token };
4744
+ return {
4745
+ "Supabase-Access-Token": config.access_token,
4746
+ "x-dosu-cli-contract": CLI_CONTRACT_HASH
4747
+ };
4742
4748
  },
4743
4749
  async fetch(url, options) {
4744
4750
  const res = await globalThis.fetch(url, options);
@@ -4753,7 +4759,8 @@ function createTypedClient(config) {
4753
4759
  ...options,
4754
4760
  headers: {
4755
4761
  ...options?.headers,
4756
- "Supabase-Access-Token": config.access_token
4762
+ "Supabase-Access-Token": config.access_token,
4763
+ "x-dosu-cli-contract": CLI_CONTRACT_HASH
4757
4764
  }
4758
4765
  });
4759
4766
  }
@@ -10989,8 +10996,11 @@ function createAnonymousClient() {
10989
10996
  return createTRPCClient({
10990
10997
  links: [
10991
10998
  httpLink({
10992
- url: `${webAppURL}/api/trpc`,
10993
- transformer: dist_default
10999
+ url: `${webAppURL}/api/cli-trpc`,
11000
+ transformer: dist_default,
11001
+ headers: {
11002
+ "x-dosu-cli-contract": CLI_CONTRACT_HASH
11003
+ }
10994
11004
  })
10995
11005
  ]
10996
11006
  });
@@ -15431,7 +15441,10 @@ function integrationsCommand() {
15431
15441
  console.log(import_picocolors16.default.dim("No Slack channels found."));
15432
15442
  return;
15433
15443
  }
15434
- printTable(["ID", "Name"], channels.map((c3) => [c3.channel_id, c3.name ?? "(unnamed)"]), { rawData: channels });
15444
+ printTable(["ID", "Name"], channels.map((c3) => [
15445
+ c3.channel_id,
15446
+ c3.name ?? "(unnamed)"
15447
+ ]), { rawData: channels });
15435
15448
  });
15436
15449
  cmd.command("slack-join").description("Join a Slack channel").argument("<channel-id>", "Slack channel ID").option("--json", "Output as JSON").action(async (channelId, opts) => {
15437
15450
  const cfg = requireConfig6();
@@ -15481,7 +15494,7 @@ function knowledgeCommand() {
15481
15494
  org_id: cfg.org_id,
15482
15495
  excluded_provider_slugs: []
15483
15496
  });
15484
- const dataSourceIds = dataSources.map((ds) => ds.id);
15497
+ const dataSourceIds = dataSources.map((ds) => ds.id).filter((id) => id !== null);
15485
15498
  if (dataSourceIds.length === 0) {
15486
15499
  console.log(import_picocolors17.default.dim("No data sources connected. Add data sources in the Dosu dashboard."));
15487
15500
  return;
@@ -15502,7 +15515,10 @@ function knowledgeCommand() {
15502
15515
  }
15503
15516
  const limit = Number.parseInt(opts.limit ?? "10", 10);
15504
15517
  const limited = results.slice(0, limit);
15505
- printTable(["Title", "Type"], limited.map((r2) => [truncate(r2.title ?? "(untitled)", 60), r2.entity_type ?? "—"]), { json: false, rawData: limited });
15518
+ printTable(["Title", "Type"], limited.map((r2) => [
15519
+ truncate(r2.title ?? "(untitled)", 60),
15520
+ r2.entity_type ?? "—"
15521
+ ]), { json: false, rawData: limited });
15506
15522
  if (results.length > limit) {
15507
15523
  console.log(import_picocolors17.default.dim(`
15508
15524
  ${results.length - limit} more results not shown.`));
@@ -15553,7 +15569,10 @@ function membersCommand() {
15553
15569
  console.log(import_picocolors18.default.dim("No members or invitations found."));
15554
15570
  return;
15555
15571
  }
15556
- printTable(["Email", "Org"], data.items.map((m3) => [m3.email ?? "—", m3.org?.name ?? "—"]), { rawData: data });
15572
+ printTable(["Email", "Org"], data.items.map((m3) => [
15573
+ m3.email ?? "—",
15574
+ m3.org?.name ?? "—"
15575
+ ]), { rawData: data });
15557
15576
  });
15558
15577
  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) => {
15559
15578
  const cfg = requireConfig8();
@@ -15582,7 +15601,10 @@ function membersCommand() {
15582
15601
  console.log(import_picocolors18.default.dim("No pending access requests."));
15583
15602
  return;
15584
15603
  }
15585
- printTable(["Email", "Org"], data.items.map((r2) => [r2.email ?? "—", r2.org?.name ?? "—"]), { rawData: data });
15604
+ printTable(["Email", "Org"], data.items.map((r2) => [
15605
+ r2.email ?? "—",
15606
+ r2.org?.name ?? "—"
15607
+ ]), { rawData: data });
15586
15608
  });
15587
15609
  cmd.command("approve").description("Approve an access request").argument("<email>", "Email of requester").option("--json", "Output as JSON").action(async (email, opts) => {
15588
15610
  const cfg = requireConfig8();
@@ -15664,17 +15686,32 @@ function requireConfig10() {
15664
15686
  function isNotFound(err) {
15665
15687
  return isTRPCClientError(err) && err.data?.code === "NOT_FOUND";
15666
15688
  }
15667
- async function resolveChange(client, id) {
15689
+ function isInvalidId(err) {
15690
+ return isTRPCClientError(err) && err.data?.code === "UNPROCESSABLE_CONTENT";
15691
+ }
15692
+ var DRAFT_MESSAGE_ID_PREFIX = "draft_message:";
15693
+ function isDraftId(id) {
15694
+ return id.startsWith(DRAFT_MESSAGE_ID_PREFIX);
15695
+ }
15696
+ function bareMessageId(id) {
15697
+ return id.slice(DRAFT_MESSAGE_ID_PREFIX.length);
15698
+ }
15699
+ function truncateId(id) {
15700
+ return (isDraftId(id) ? bareMessageId(id) : id).slice(0, 8);
15701
+ }
15702
+ async function requireChange(client, id) {
15668
15703
  try {
15669
15704
  return await client.review.getChange.query({ id });
15670
15705
  } catch (err) {
15671
- if (isNotFound(err))
15672
- return null;
15706
+ if (isNotFound(err) || isInvalidId(err)) {
15707
+ console.error(import_picocolors20.default.red(`No review item found for '${id}'. Run 'dosu review list' to see pending items.`));
15708
+ process.exit(1);
15709
+ }
15673
15710
  throw err;
15674
15711
  }
15675
15712
  }
15676
15713
  async function requireDraft(client, id) {
15677
- const draft = await client.messages.getMessage.query(id);
15714
+ const draft = await client.messages.getMessage.query(bareMessageId(id));
15678
15715
  if (!draft) {
15679
15716
  console.error(import_picocolors20.default.red(`No review item found for '${id}'. Run 'dosu review list' to see pending items.`));
15680
15717
  process.exit(1);
@@ -15781,8 +15818,7 @@ function reviewCommand() {
15781
15818
  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) => {
15782
15819
  const cfg = requireConfig10();
15783
15820
  const client = createTypedClient(cfg);
15784
- const change = await resolveChange(client, id);
15785
- if (!change) {
15821
+ if (isDraftId(id)) {
15786
15822
  const draft = await requireDraft(client, id);
15787
15823
  if (opts.json) {
15788
15824
  printResult({ id, kind: "draft_message", title: draft.title, body: draft.body }, opts);
@@ -15794,6 +15830,7 @@ function reviewCommand() {
15794
15830
  console.log(draft.body ?? "");
15795
15831
  return;
15796
15832
  }
15833
+ const change = await requireChange(client, id);
15797
15834
  if (opts.json) {
15798
15835
  printResult(change, opts);
15799
15836
  return;
@@ -15824,14 +15861,16 @@ function reviewCommand() {
15824
15861
  console.error(import_picocolors20.default.red("Nothing to edit. Pass --title and/or --body/--body-file."));
15825
15862
  process.exit(1);
15826
15863
  }
15827
- const change = await resolveChange(client, id);
15828
- if (!change) {
15864
+ if (isDraftId(id)) {
15829
15865
  if (opts.title !== undefined) {
15830
15866
  console.error(import_picocolors20.default.red("Draft replies support --body only (no --title)."));
15831
15867
  process.exit(1);
15832
15868
  }
15833
15869
  await requireDraft(client, id);
15834
- await client.messages.saveDraft.mutate({ messageId: id, body });
15870
+ await client.messages.saveDraft.mutate({
15871
+ messageId: bareMessageId(id),
15872
+ body
15873
+ });
15835
15874
  } else {
15836
15875
  try {
15837
15876
  await client.page.updateReview.mutate({
@@ -15851,7 +15890,7 @@ function reviewCommand() {
15851
15890
  printResult({ success: true, id }, opts);
15852
15891
  return;
15853
15892
  }
15854
- console.log(import_picocolors20.default.green(`Review edited: ${id.slice(0, 8)}`));
15893
+ console.log(import_picocolors20.default.green(`Review edited: ${truncateId(id)}`));
15855
15894
  });
15856
15895
  cmd.command("context").description("Get review context for a thread").argument("<thread-id>", "Thread ID").option("--json", "Output as JSON").action(async (threadId, opts) => {
15857
15896
  const cfg = requireConfig10();
@@ -15882,7 +15921,7 @@ function reviewCommand() {
15882
15921
  cmd.command(name).description(`${verb} a review item (doc change or draft reply; shows a preview, requires --confirm)`).argument("<id>", "Review item ID (from `dosu review list`)").option("--confirm", "Apply without the interactive prompt").option("--json", "Output as JSON").action(async (id, opts) => {
15883
15922
  const cfg = requireConfig10();
15884
15923
  const client = createTypedClient(cfg);
15885
- const change = await resolveChange(client, id);
15924
+ const change = isDraftId(id) ? null : await requireChange(client, id);
15886
15925
  const draft = change ? null : await requireDraft(client, id);
15887
15926
  const noun = change ? "change" : "draft reply";
15888
15927
  if (!opts.json) {
@@ -15920,26 +15959,26 @@ function reviewCommand() {
15920
15959
  if (change) {
15921
15960
  await client.page.updatePublicationStatus.mutate({ page_version_id: id, action });
15922
15961
  } else if (action === "accept") {
15923
- await client.messages.publishMessage.mutate({ postId: id });
15962
+ await client.messages.publishMessage.mutate({ postId: bareMessageId(id) });
15924
15963
  } else {
15925
- await client.messages.deleteMessage.mutate(id);
15964
+ await client.messages.deleteMessage.mutate(bareMessageId(id));
15926
15965
  }
15927
15966
  if (opts.json) {
15928
15967
  printResult({ success: true, id, action }, opts);
15929
15968
  return;
15930
15969
  }
15931
- console.log(import_picocolors20.default.green(`Review ${name}: ${id.slice(0, 8)}`));
15970
+ console.log(import_picocolors20.default.green(`Review ${name}: ${truncateId(id)}`));
15932
15971
  });
15933
15972
  }
15934
15973
  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) => {
15935
15974
  const cfg = requireConfig10();
15936
15975
  const client = createTypedClient(cfg);
15937
- const change = await resolveChange(client, id);
15938
- if (!change) {
15976
+ if (isDraftId(id)) {
15939
15977
  await requireDraft(client, id);
15940
15978
  console.error(import_picocolors20.default.red("Revert is not supported for draft replies. A rejected draft is regenerated on the next agent run."));
15941
15979
  process.exit(1);
15942
15980
  }
15981
+ await requireChange(client, id);
15943
15982
  await client.page.updatePublicationStatus.mutate({
15944
15983
  page_version_id: id,
15945
15984
  action: "revert_to_pending"
@@ -15948,7 +15987,7 @@ function reviewCommand() {
15948
15987
  printResult({ success: true, id, action: "revert_to_pending" }, opts);
15949
15988
  return;
15950
15989
  }
15951
- console.log(import_picocolors20.default.green(`Review revert: ${id.slice(0, 8)}`));
15990
+ console.log(import_picocolors20.default.green(`Review revert: ${truncateId(id)}`));
15952
15991
  });
15953
15992
  return cmd;
15954
15993
  }
@@ -16106,7 +16145,7 @@ function suggestCommand() {
16106
16145
  org_id: cfg.org_id,
16107
16146
  excluded_provider_slugs: []
16108
16147
  });
16109
- const dataSourceIds = dataSources.map((ds) => ds.id);
16148
+ const dataSourceIds = dataSources.map((ds) => ds.id).filter((id) => id !== null);
16110
16149
  const result = await client.suggestedDoc.generate.mutate({
16111
16150
  knowledgeStoreId: ksId,
16112
16151
  dataSourceIds
@@ -16169,7 +16208,11 @@ function tagsCommand() {
16169
16208
  console.log(import_picocolors23.default.dim("No tags found."));
16170
16209
  return;
16171
16210
  }
16172
- printTable(["ID", "Name", "Description"], tags.map((t2) => [t2.topic_id.slice(0, 8), t2.name, t2.description ?? "—"]), { rawData: tags });
16211
+ printTable(["ID", "Name", "Description"], tags.map((t2) => [
16212
+ t2.topic_id.slice(0, 8),
16213
+ t2.name,
16214
+ t2.description ?? "—"
16215
+ ]), { rawData: tags });
16173
16216
  });
16174
16217
  cmd.command("remove").description("Remove a tag from a page").argument("<tag-id>", "Tag ID").argument("<page-id>", "Page ID").option("--json", "Output as JSON").action(async (tagId, pageId, opts) => {
16175
16218
  const cfg = requireConfig13();
@@ -16226,18 +16269,34 @@ function threadsCommand() {
16226
16269
  const cfg = requireConfig14();
16227
16270
  const client = createTypedClient(cfg);
16228
16271
  const input = {
16272
+ __testing_scope__: undefined,
16273
+ active: undefined,
16274
+ archived: undefined,
16275
+ channels: undefined,
16276
+ chatOnly: undefined,
16277
+ confidenceLevels: undefined,
16278
+ inbox_archived: undefined,
16279
+ previewOnly: undefined,
16280
+ providers: undefined,
16281
+ read: undefined,
16282
+ resolved: undefined,
16283
+ search: undefined,
16229
16284
  space_id: cfg.space_id,
16285
+ workspaces: undefined,
16230
16286
  limit: Math.min(Number.parseInt(opts.limit ?? "20", 10), 100)
16231
16287
  };
16232
16288
  if (opts.search)
16233
16289
  input.search = opts.search;
16234
16290
  if (opts.status === "resolved")
16235
16291
  input.resolved = true;
16236
- if (opts.status === "archived")
16292
+ if (opts.status === "archived") {
16237
16293
  input.archived = true;
16294
+ input.inbox_archived = true;
16295
+ }
16238
16296
  if (opts.status === "pending") {
16239
16297
  input.resolved = false;
16240
16298
  input.archived = false;
16299
+ input.inbox_archived = false;
16241
16300
  }
16242
16301
  const data = await client.thread.list.query(input);
16243
16302
  const threads = data.list;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dosu/cli",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "type": "module",
5
5
  "description": "Dosu CLI - Manage MCP servers for AI tools",
6
6
  "license": "MIT",
@@ -37,7 +37,6 @@
37
37
  "devDependencies": {
38
38
  "@biomejs/biome": "^2.5.0",
39
39
  "@clack/prompts": "^1.6.0",
40
- "@dosu/api-types": "0.0.36",
41
40
  "@semantic-release/changelog": "^6.0.3",
42
41
  "@semantic-release/exec": "^7.1.0",
43
42
  "@semantic-release/git": "^10.0.1",