@rudderhq/cli 0.2.9-canary.6 → 0.2.9-canary.7

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.
package/dist/index.js CHANGED
@@ -883,9 +883,27 @@ var init_chat = __esm({
883
883
  parentId: z8.string().uuid().optional().nullable(),
884
884
  assigneeAgentId: z8.string().uuid().optional().nullable(),
885
885
  assigneeUserId: z8.string().trim().optional().nullable(),
886
+ assigneeUnassignedReason: z8.string().trim().min(1).max(500).optional().nullable(),
886
887
  reviewerAgentId: z8.string().uuid().optional().nullable(),
887
888
  reviewerUserId: z8.string().trim().optional().nullable(),
888
889
  labelIds: z8.array(z8.string().uuid()).optional()
890
+ }).superRefine((proposal, ctx) => {
891
+ const hasAssignee = Boolean(proposal.assigneeAgentId || proposal.assigneeUserId);
892
+ const hasUnassignedReason = Boolean(proposal.assigneeUnassignedReason?.trim());
893
+ if (hasAssignee && hasUnassignedReason) {
894
+ ctx.addIssue({
895
+ code: z8.ZodIssueCode.custom,
896
+ message: "Issue proposals with an assignee must not also declare an unassigned reason",
897
+ path: ["assigneeUnassignedReason"]
898
+ });
899
+ }
900
+ if (!hasAssignee && !hasUnassignedReason) {
901
+ ctx.addIssue({
902
+ code: z8.ZodIssueCode.custom,
903
+ message: "Issue proposals without an owner must include assigneeUnassignedReason",
904
+ path: ["assigneeUnassignedReason"]
905
+ });
906
+ }
889
907
  });
890
908
  convertChatToIssueSchema = z8.object({
891
909
  messageId: z8.string().uuid().optional().nullable(),
@@ -8125,41 +8143,41 @@ var RudderApiClient = class {
8125
8143
  this.runId = opts.runId?.trim() || void 0;
8126
8144
  this.recoverAuth = opts.recoverAuth;
8127
8145
  }
8128
- get(path21, opts) {
8129
- return this.request(path21, { method: "GET" }, opts);
8146
+ get(path22, opts) {
8147
+ return this.request(path22, { method: "GET" }, opts);
8130
8148
  }
8131
- post(path21, body, opts) {
8132
- return this.request(path21, {
8149
+ post(path22, body, opts) {
8150
+ return this.request(path22, {
8133
8151
  method: "POST",
8134
8152
  body: body === void 0 ? void 0 : JSON.stringify(body)
8135
8153
  }, opts);
8136
8154
  }
8137
- postForm(path21, form, opts) {
8138
- return this.request(path21, {
8155
+ postForm(path22, form, opts) {
8156
+ return this.request(path22, {
8139
8157
  method: "POST",
8140
8158
  body: form
8141
8159
  }, opts);
8142
8160
  }
8143
- patch(path21, body, opts) {
8144
- return this.request(path21, {
8161
+ patch(path22, body, opts) {
8162
+ return this.request(path22, {
8145
8163
  method: "PATCH",
8146
8164
  body: body === void 0 ? void 0 : JSON.stringify(body)
8147
8165
  }, opts);
8148
8166
  }
8149
- put(path21, body, opts) {
8150
- return this.request(path21, {
8167
+ put(path22, body, opts) {
8168
+ return this.request(path22, {
8151
8169
  method: "PUT",
8152
8170
  body: body === void 0 ? void 0 : JSON.stringify(body)
8153
8171
  }, opts);
8154
8172
  }
8155
- delete(path21, opts) {
8156
- return this.request(path21, { method: "DELETE" }, opts);
8173
+ delete(path22, opts) {
8174
+ return this.request(path22, { method: "DELETE" }, opts);
8157
8175
  }
8158
8176
  setApiKey(apiKey) {
8159
8177
  this.apiKey = apiKey?.trim() || void 0;
8160
8178
  }
8161
- async request(path21, init, opts, hasRetriedAuth = false) {
8162
- const url = buildUrl(this.apiBase, path21);
8179
+ async request(path22, init, opts, hasRetriedAuth = false) {
8180
+ const url = buildUrl(this.apiBase, path22);
8163
8181
  const headers = {
8164
8182
  accept: "application/json",
8165
8183
  ...toStringRecord(init.headers)
@@ -8189,13 +8207,13 @@ var RudderApiClient = class {
8189
8207
  const apiError = await toApiError(response);
8190
8208
  if (!hasRetriedAuth && this.recoverAuth) {
8191
8209
  const recoveredToken = await this.recoverAuth({
8192
- path: path21,
8210
+ path: path22,
8193
8211
  method: String(init.method ?? "GET").toUpperCase(),
8194
8212
  error: apiError
8195
8213
  });
8196
8214
  if (recoveredToken) {
8197
8215
  this.setApiKey(recoveredToken);
8198
- return this.request(path21, init, opts, true);
8216
+ return this.request(path22, init, opts, true);
8199
8217
  }
8200
8218
  }
8201
8219
  throw apiError;
@@ -8214,8 +8232,8 @@ function shouldAttachAgentContext(method) {
8214
8232
  const normalized = String(method ?? "GET").toUpperCase();
8215
8233
  return normalized !== "GET" && normalized !== "HEAD";
8216
8234
  }
8217
- function buildUrl(apiBase, path21) {
8218
- const normalizedPath = path21.startsWith("/") ? path21 : `/${path21}`;
8235
+ function buildUrl(apiBase, path22) {
8236
+ const normalizedPath = path22.startsWith("/") ? path22 : `/${path22}`;
8219
8237
  const [pathname, query] = normalizedPath.split("?");
8220
8238
  const url = new URL2(apiBase);
8221
8239
  url.pathname = `${url.pathname.replace(/\/+$/, "")}${pathname}`;
@@ -10335,7 +10353,7 @@ var AGENT_CLI_CAPABILITIES = [
10335
10353
  },
10336
10354
  {
10337
10355
  id: "issue.documents.put",
10338
- command: "rudder issue documents put <issue> <key> --body <text>",
10356
+ command: "rudder issue documents put <issue> <key> --body-file <path>",
10339
10357
  category: "issue",
10340
10358
  description: "Create or update an issue document.",
10341
10359
  mutating: true,
@@ -10419,7 +10437,7 @@ var AGENT_CLI_CAPABILITIES = [
10419
10437
  },
10420
10438
  {
10421
10439
  id: "approval.comment",
10422
- command: "rudder approval comment <approval-id> --body <text>",
10440
+ command: "rudder approval comment <approval-id> --body-file <path>",
10423
10441
  category: "approval",
10424
10442
  description: "Add a comment to an approval.",
10425
10443
  mutating: true,
@@ -10662,14 +10680,13 @@ function registerIssueCommands(program) {
10662
10680
  { includeCompany: false }
10663
10681
  );
10664
10682
  addCommonClientOptions(
10665
- issue.command("update").description(getAgentCliCapabilityById("issue.update").description).argument("<issueId>", "Issue ID").option("--title <title>", "Issue title").option("--description <text>", "Issue description").option("--status <status>", "Issue status").option("--priority <priority>", "Issue priority").option("--assignee-agent-id <id>", "Assignee agent ID").option("--project-id <id>", "Project ID").option("--goal-id <id>", "Goal ID").option("--parent-id <id>", "Parent issue ID").option("--request-depth <n>", "Request depth integer").option("--billing-code <code>", "Billing code").option("--comment <text>", "Optional comment to add with update").option("--comment-file <path>", "Read optional update comment from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the update comment; may be repeated", collectImagePath, []).option("--hidden-at <iso8601|null>", "Set hiddenAt timestamp or literal 'null'").action(async (issueId, opts) => {
10683
+ issue.command("update").description(getAgentCliCapabilityById("issue.update").description).argument("<issueId>", "Issue ID").option("--title <title>", "Issue title").option("--description <text>", "Issue description").option("--status <status>", "Issue status").option("--priority <priority>", "Issue priority").option("--assignee-agent-id <id>", "Assignee agent ID").option("--project-id <id>", "Project ID").option("--goal-id <id>", "Goal ID").option("--parent-id <id>", "Parent issue ID").option("--request-depth <n>", "Request depth integer").option("--billing-code <code>", "Billing code").option("--comment-file <path>", "Read optional update comment from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the update comment; may be repeated", collectImagePath, []).option("--hidden-at <iso8601|null>", "Set hiddenAt timestamp or literal 'null'").action(async (issueId, opts) => {
10666
10684
  try {
10667
10685
  const ctx = resolveCommandContext(opts);
10668
- const commentText = await resolveTextInput({
10669
- text: opts.comment,
10686
+ const commentText = await resolveFileTextInput({
10670
10687
  file: opts.commentFile,
10671
- textOption: "--comment",
10672
10688
  fileOption: "--comment-file",
10689
+ removedTextOption: "--comment",
10673
10690
  required: false
10674
10691
  });
10675
10692
  const comment = await appendUploadedIssueImages(ctx, issueId, commentText, opts.image);
@@ -10695,14 +10712,13 @@ function registerIssueCommands(program) {
10695
10712
  })
10696
10713
  );
10697
10714
  addCommonClientOptions(
10698
- issue.command("comment").description(getAgentCliCapabilityById("issue.comment").description).argument("<issueId>", "Issue ID").option("--body <text>", "Comment body").option("--body-file <path>", "Read comment body from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the comment; may be repeated", collectImagePath, []).option("--reopen", "Reopen if issue is done/cancelled").action(async (issueId, opts) => {
10715
+ issue.command("comment").description(getAgentCliCapabilityById("issue.comment").description).argument("<issueId>", "Issue ID").option("--body-file <path>", "Read comment body from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the comment; may be repeated", collectImagePath, []).option("--reopen", "Reopen if issue is done/cancelled").action(async (issueId, opts) => {
10699
10716
  try {
10700
10717
  const ctx = resolveCommandContext(opts);
10701
- const bodyText = await resolveTextInput({
10702
- text: opts.body,
10718
+ const bodyText = await resolveFileTextInput({
10703
10719
  file: opts.bodyFile,
10704
- textOption: "--body",
10705
10720
  fileOption: "--body-file",
10721
+ removedTextOption: "--body",
10706
10722
  required: true
10707
10723
  });
10708
10724
  const body = await appendUploadedIssueImages(ctx, issueId, bodyText, opts.image);
@@ -10724,15 +10740,14 @@ function registerIssueCommands(program) {
10724
10740
  issue.command("review").description(getAgentCliCapabilityById("issue.review").description).argument("<issueId>", "Issue ID").requiredOption(
10725
10741
  "--decision <decision>",
10726
10742
  "Review decision: approve, request_changes, needs_followup, or blocked"
10727
- ).option("--comment <text>", "Required review comment").option("--comment-file <path>", "Read required review comment from a file, or '-' for stdin").action(async (issueId, opts) => {
10743
+ ).option("--comment-file <path>", "Read required review comment from a file, or '-' for stdin").action(async (issueId, opts) => {
10728
10744
  try {
10729
10745
  const ctx = resolveCommandContext(opts);
10730
10746
  const decision = parseReviewDecision(opts.decision);
10731
- const comment = await resolveTextInput({
10732
- text: opts.comment,
10747
+ const comment = await resolveFileTextInput({
10733
10748
  file: opts.commentFile,
10734
- textOption: "--comment",
10735
10749
  fileOption: "--comment-file",
10750
+ removedTextOption: "--comment",
10736
10751
  required: true
10737
10752
  });
10738
10753
  const updated = await ctx.api.patch(`/api/issues/${issueId}`, {
@@ -10765,14 +10780,13 @@ function registerIssueCommands(program) {
10765
10780
  })
10766
10781
  );
10767
10782
  addCommonClientOptions(
10768
- issue.command("done").description(getAgentCliCapabilityById("issue.done").description).argument("<issueId>", "Issue ID").option("--comment <text>", "Required completion comment").option("--comment-file <path>", "Read required completion comment from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the completion comment; may be repeated", collectImagePath, []).action(async (issueId, opts) => {
10783
+ issue.command("done").description(getAgentCliCapabilityById("issue.done").description).argument("<issueId>", "Issue ID").option("--comment-file <path>", "Read required completion comment from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the completion comment; may be repeated", collectImagePath, []).action(async (issueId, opts) => {
10769
10784
  try {
10770
10785
  const ctx = resolveCommandContext(opts);
10771
- const commentText = await resolveTextInput({
10772
- text: opts.comment,
10786
+ const commentText = await resolveFileTextInput({
10773
10787
  file: opts.commentFile,
10774
- textOption: "--comment",
10775
10788
  fileOption: "--comment-file",
10789
+ removedTextOption: "--comment",
10776
10790
  required: true
10777
10791
  });
10778
10792
  const comment = await appendUploadedIssueImages(ctx, issueId, commentText, opts.image);
@@ -10787,14 +10801,13 @@ function registerIssueCommands(program) {
10787
10801
  })
10788
10802
  );
10789
10803
  addCommonClientOptions(
10790
- issue.command("block").description(getAgentCliCapabilityById("issue.block").description).argument("<issueId>", "Issue ID").option("--comment <text>", "Required blocker comment").option("--comment-file <path>", "Read required blocker comment from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the blocker comment; may be repeated", collectImagePath, []).action(async (issueId, opts) => {
10804
+ issue.command("block").description(getAgentCliCapabilityById("issue.block").description).argument("<issueId>", "Issue ID").option("--comment-file <path>", "Read required blocker comment from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the blocker comment; may be repeated", collectImagePath, []).action(async (issueId, opts) => {
10791
10805
  try {
10792
10806
  const ctx = resolveCommandContext(opts);
10793
- const commentText = await resolveTextInput({
10794
- text: opts.comment,
10807
+ const commentText = await resolveFileTextInput({
10795
10808
  file: opts.commentFile,
10796
- textOption: "--comment",
10797
10809
  fileOption: "--comment-file",
10810
+ removedTextOption: "--comment",
10798
10811
  required: true
10799
10812
  });
10800
10813
  const comment = await appendUploadedIssueImages(ctx, issueId, commentText, opts.image);
@@ -10861,13 +10874,19 @@ function registerIssueCommands(program) {
10861
10874
  })
10862
10875
  );
10863
10876
  addCommonClientOptions(
10864
- documents.command("put").description(getAgentCliCapabilityById("issue.documents.put").description).argument("<issueId>", "Issue ID").argument("<key>", "Document key").requiredOption("--body <text>", "Document body").option("--title <text>", "Document title").option("--format <format>", "Document format", "markdown").option("--change-summary <text>", "Optional change summary").option("--base-revision-id <id>", "Latest revision id for optimistic concurrency").action(async (issueId, key, opts) => {
10877
+ documents.command("put").description(getAgentCliCapabilityById("issue.documents.put").description).argument("<issueId>", "Issue ID").argument("<key>", "Document key").option("--body-file <path>", "Read document body from a file, or '-' for stdin").option("--title <text>", "Document title").option("--format <format>", "Document format", "markdown").option("--change-summary <text>", "Optional change summary").option("--base-revision-id <id>", "Latest revision id for optimistic concurrency").action(async (issueId, key, opts) => {
10865
10878
  try {
10866
10879
  const ctx = resolveCommandContext(opts);
10880
+ const body = await resolveFileTextInput({
10881
+ file: opts.bodyFile,
10882
+ fileOption: "--body-file",
10883
+ removedTextOption: "--body",
10884
+ required: true
10885
+ });
10867
10886
  const payload = upsertIssueDocumentSchema.parse({
10868
10887
  title: opts.title,
10869
10888
  format: opts.format,
10870
- body: opts.body,
10889
+ body,
10871
10890
  changeSummary: opts.changeSummary,
10872
10891
  baseRevisionId: opts.baseRevisionId
10873
10892
  });
@@ -10940,16 +10959,14 @@ function collectNonEmptyOption(optionName) {
10940
10959
  return [...previous, trimmed];
10941
10960
  };
10942
10961
  }
10943
- async function resolveTextInput(opts) {
10944
- const hasText = opts.text !== void 0;
10945
- const hasFile = opts.file !== void 0;
10946
- if (hasText && hasFile) {
10947
- throw new Error(`Use either ${opts.textOption} or ${opts.fileOption}, not both`);
10962
+ async function resolveFileTextInput(opts) {
10963
+ if (opts.removedTextOption && process.argv.includes(opts.removedTextOption)) {
10964
+ throw new Error(`${opts.removedTextOption} was removed; write the body to a file and use ${opts.fileOption} <path> or ${opts.fileOption} - for stdin`);
10948
10965
  }
10949
- if (hasText) return opts.text;
10966
+ const hasFile = opts.file !== void 0;
10950
10967
  if (hasFile) return readTextInputFile(opts.file, opts.fileOption);
10951
10968
  if (opts.required) {
10952
- throw new Error(`Provide ${opts.textOption} <text> or ${opts.fileOption} <path>; use ${opts.fileOption} - for stdin`);
10969
+ throw new Error(`Provide ${opts.fileOption} <path>; use ${opts.fileOption} - for stdin`);
10953
10970
  }
10954
10971
  return void 0;
10955
10972
  }
@@ -11726,6 +11743,8 @@ function parseJsonObject(value, name) {
11726
11743
 
11727
11744
  // src/commands/client/approval.ts
11728
11745
  init_dist();
11746
+ import { readFile as readFile5 } from "node:fs/promises";
11747
+ import path19 from "node:path";
11729
11748
  function registerApprovalCommands(program) {
11730
11749
  const approval = program.command("approval").description("Approval operations");
11731
11750
  addCommonClientOptions(
@@ -11862,11 +11881,12 @@ function registerApprovalCommands(program) {
11862
11881
  })
11863
11882
  );
11864
11883
  addCommonClientOptions(
11865
- approval.command("comment").description(getAgentCliCapabilityById("approval.comment").description).argument("<approvalId>", "Approval ID").requiredOption("--body <text>", "Comment body").action(async (approvalId, opts) => {
11884
+ approval.command("comment").description(getAgentCliCapabilityById("approval.comment").description).argument("<approvalId>", "Approval ID").option("--body-file <path>", "Read comment body from a file, or '-' for stdin").action(async (approvalId, opts) => {
11866
11885
  try {
11867
11886
  const ctx = resolveCommandContext(opts);
11887
+ const body = await resolveBodyFile(opts.bodyFile);
11868
11888
  const created = await ctx.api.post(`/api/approvals/${approvalId}/comments`, {
11869
- body: opts.body
11889
+ body
11870
11890
  });
11871
11891
  printOutput(created, { json: ctx.json });
11872
11892
  } catch (err) {
@@ -11875,6 +11895,28 @@ function registerApprovalCommands(program) {
11875
11895
  })
11876
11896
  );
11877
11897
  }
11898
+ async function resolveBodyFile(inputPath) {
11899
+ if (!inputPath) {
11900
+ throw new Error("Provide --body-file <path>; use --body-file - for stdin");
11901
+ }
11902
+ return readTextInputFile2(inputPath, "--body-file");
11903
+ }
11904
+ async function readTextInputFile2(inputPath, optionName) {
11905
+ if (inputPath === "-") {
11906
+ return readStdinText2();
11907
+ }
11908
+ const resolvedPath = path19.resolve(process.cwd(), inputPath);
11909
+ return readFile5(resolvedPath, "utf8").catch((err) => {
11910
+ throw new Error(`Unable to read ${optionName} ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
11911
+ });
11912
+ }
11913
+ async function readStdinText2() {
11914
+ const chunks = [];
11915
+ for await (const chunk of process.stdin) {
11916
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
11917
+ }
11918
+ return Buffer.concat(chunks).toString("utf8");
11919
+ }
11878
11920
  function parseCsv3(value) {
11879
11921
  if (!value) return void 0;
11880
11922
  const rows = value.split(",").map((v) => v.trim()).filter(Boolean);
@@ -11904,8 +11946,8 @@ function registerActivityCommands(program) {
11904
11946
  if (opts.entityType) params.set("entityType", opts.entityType);
11905
11947
  if (opts.entityId) params.set("entityId", opts.entityId);
11906
11948
  const query = params.toString();
11907
- const path21 = `/api/orgs/${ctx.orgId}/activity${query ? `?${query}` : ""}`;
11908
- const rows = await ctx.api.get(path21) ?? [];
11949
+ const path22 = `/api/orgs/${ctx.orgId}/activity${query ? `?${query}` : ""}`;
11950
+ const rows = await ctx.api.get(path22) ?? [];
11909
11951
  if (ctx.json) {
11910
11952
  printOutput(rows, { json: true });
11911
11953
  return;
@@ -12074,11 +12116,11 @@ function parseCsv4(value) {
12074
12116
 
12075
12117
  // src/config/data-dir.ts
12076
12118
  init_home();
12077
- import path19 from "node:path";
12119
+ import path20 from "node:path";
12078
12120
  function applyDataDirOverride(options, support = {}) {
12079
12121
  const rawDataDir = options.dataDir?.trim();
12080
12122
  if (!rawDataDir) return null;
12081
- const resolvedDataDir = path19.resolve(expandHomePrefix(rawDataDir));
12123
+ const resolvedDataDir = path20.resolve(expandHomePrefix(rawDataDir));
12082
12124
  process.env.RUDDER_HOME = resolvedDataDir;
12083
12125
  if (support.hasConfigOption) {
12084
12126
  const hasConfigOverride = Boolean(options.config?.trim()) || Boolean(process.env.RUDDER_CONFIG?.trim());
@@ -12102,16 +12144,16 @@ init_env();
12102
12144
  init_local_env();
12103
12145
 
12104
12146
  // src/commands/client/plugin.ts
12105
- import path20 from "node:path";
12147
+ import path21 from "node:path";
12106
12148
  import pc15 from "picocolors";
12107
12149
  function resolvePackageArg(packageArg, isLocal) {
12108
12150
  if (!isLocal) return packageArg;
12109
- if (path20.isAbsolute(packageArg)) return packageArg;
12151
+ if (path21.isAbsolute(packageArg)) return packageArg;
12110
12152
  if (packageArg.startsWith("~")) {
12111
12153
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
12112
- return path20.resolve(home, packageArg.slice(1).replace(/^[\\/]/, ""));
12154
+ return path21.resolve(home, packageArg.slice(1).replace(/^[\\/]/, ""));
12113
12155
  }
12114
- return path20.resolve(process.cwd(), packageArg);
12156
+ return path21.resolve(process.cwd(), packageArg);
12115
12157
  }
12116
12158
  function formatPlugin(p16) {
12117
12159
  const statusColor = p16.status === "ready" ? pc15.green(p16.status) : p16.status === "error" ? pc15.red(p16.status) : p16.status === "disabled" ? pc15.dim(p16.status) : pc15.yellow(p16.status);