@automagik/omni 2.260901.3 → 2.260902.2

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.
@@ -7,5 +7,10 @@
7
7
  * etc.
8
8
  */
9
9
  import { Command } from 'commander';
10
+ import { z } from 'zod';
10
11
  export declare function createSendCommand(): Command;
12
+ /** Test-only surface — not part of the CLI contract. */
13
+ export declare const __testables: {
14
+ sentBySchema: z.ZodEnum<["agent", "user"]>;
15
+ };
11
16
  //# sourceMappingURL=send.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgcpC,wBAAgB,iBAAiB,IAAI,OAAO,CAgG3C"}
1
+ {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA6dxB,wBAAgB,iBAAiB,IAAI,OAAO,CAiG3C;AAED,wDAAwD;AACxD,eAAO,MAAM,WAAW;;CAAmB,CAAC"}
@@ -7,7 +7,44 @@
7
7
  * omni webhooks update <id> [--name <name>] [--enabled]
8
8
  * omni webhooks delete <id>
9
9
  * omni webhooks trigger --type <event-type> --payload <json> [--instance <id>]
10
+ *
11
+ * The signature secret can come from argv (`--signature-secret`, visible in
12
+ * shell history and `ps`), an environment variable (`--signature-secret-env`),
13
+ * or stdin (`--signature-secret-stdin`, for `pass show ... | omni webhooks ...`).
10
14
  */
15
+ import type { WebhookSignatureConfigBody } from '@omni/sdk';
11
16
  import { Command } from 'commander';
17
+ interface SignatureSecretOptions {
18
+ signatureSecret?: string;
19
+ signatureSecretEnv?: string;
20
+ signatureSecretStdin?: boolean;
21
+ }
22
+ /**
23
+ * Resolve the signature secret from exactly one of the three sources, or
24
+ * undefined when none is given. Throws (caught by the command's error path)
25
+ * on conflicting flags, a missing/empty env var, empty stdin, or a value
26
+ * outside the API's bounds — the CLI fails before any request is sent.
27
+ */
28
+ declare function resolveSignatureSecret(options: SignatureSecretOptions, readStdin?: () => Promise<string>): Promise<string | undefined>;
29
+ /** Assemble a signatureConfig from the --signature-* flags, or undefined when none given. */
30
+ declare function buildSignatureConfig(options: {
31
+ signatureAlgorithm?: string;
32
+ signatureHeader?: string;
33
+ signaturePrefix?: string;
34
+ }): WebhookSignatureConfigBody | undefined;
35
+ /**
36
+ * Create-only pairing: the API rejects a `signatureConfig` without a secret
37
+ * and a secret without a config (CreateWebhookSourceSchema). Fail here, before
38
+ * the request, the same way the secret bounds do. Update is deliberately not
39
+ * covered — a secret-only update rotates the secret against the stored config.
40
+ */
41
+ declare function assertPairedSignatureOnCreate(signatureConfig: WebhookSignatureConfigBody | undefined, signatureSecret: string | undefined): void;
12
42
  export declare function createWebhooksCommand(): Command;
43
+ /** Test-only surface — not part of the CLI contract. */
44
+ export declare const __testables: {
45
+ resolveSignatureSecret: typeof resolveSignatureSecret;
46
+ buildSignatureConfig: typeof buildSignatureConfig;
47
+ assertPairedSignatureOnCreate: typeof assertPairedSignatureOnCreate;
48
+ };
49
+ export {};
13
50
  //# sourceMappingURL=webhooks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../src/commands/webhooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,wBAAgB,qBAAqB,IAAI,OAAO,CA0O/C"}
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../src/commands/webhooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,UAAU,sBAAsB;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAcD;;;;;GAKG;AACH,iBAAe,sBAAsB,CACnC,OAAO,EAAE,sBAAsB,EAC/B,SAAS,GAAE,MAAM,OAAO,CAAC,MAAM,CAAuB,GACrD,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAqC7B;AAED,6FAA6F;AAC7F,iBAAS,oBAAoB,CAAC,OAAO,EAAE;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,0BAA0B,GAAG,SAAS,CAczC;AAED;;;;;GAKG;AACH,iBAAS,6BAA6B,CACpC,eAAe,EAAE,0BAA0B,GAAG,SAAS,EACvD,eAAe,EAAE,MAAM,GAAG,SAAS,GAClC,IAAI,CAQN;AAED,wBAAgB,qBAAqB,IAAI,OAAO,CA2P/C;AAED,wDAAwD;AACxD,eAAO,MAAM,WAAW;;;;CAAkF,CAAC"}
package/dist/index.js CHANGED
@@ -128289,7 +128289,7 @@ import { fileURLToPath } from "url";
128289
128289
  // package.json
128290
128290
  var package_default = {
128291
128291
  name: "@automagik/omni",
128292
- version: "2.260901.3",
128292
+ version: "2.260902.2",
128293
128293
  description: "LLM-optimized CLI for Omni",
128294
128294
  type: "module",
128295
128295
  bin: {
@@ -140103,6 +140103,7 @@ function createSeeCommand() {
140103
140103
  import { existsSync as existsSync17, readFileSync as readFileSync14 } from "fs";
140104
140104
  import { basename as basename5, extname as extname5 } from "path";
140105
140105
  init_source();
140106
+ init_zod();
140106
140107
  init_config();
140107
140108
  init_output();
140108
140109
  init_output();
@@ -140127,6 +140128,16 @@ function parseLoadingMessages(value) {
140127
140128
  const messages3 = value?.split(",").map((item) => item.trim()).filter(Boolean);
140128
140129
  return messages3?.length ? messages3 : undefined;
140129
140130
  }
140131
+ var sentBySchema = exports_external.enum(["agent", "user"]);
140132
+ function resolveSentBy(value) {
140133
+ if (value === undefined)
140134
+ return;
140135
+ const parsed = sentBySchema.safeParse(value);
140136
+ if (!parsed.success) {
140137
+ error(`Invalid --sent-by: ${value}`, { validValues: sentBySchema.options });
140138
+ }
140139
+ return parsed.data;
140140
+ }
140130
140141
  var messageSenders = {
140131
140142
  async text(client, instanceId, options3) {
140132
140143
  const { to, text: text3 } = options3;
@@ -140137,7 +140148,8 @@ var messageSenders = {
140137
140148
  to,
140138
140149
  text: text3,
140139
140150
  replyTo: options3.replyTo,
140140
- threadId: options3.threadId
140151
+ threadId: options3.threadId,
140152
+ sentBy: resolveSentBy(options3.sentBy)
140141
140153
  });
140142
140154
  success("Message sent", result);
140143
140155
  },
@@ -140160,7 +140172,8 @@ var messageSenders = {
140160
140172
  filename,
140161
140173
  caption: options3.caption,
140162
140174
  voiceNote: options3.voice,
140163
- threadId: options3.threadId
140175
+ threadId: options3.threadId,
140176
+ sentBy: resolveSentBy(options3.sentBy)
140164
140177
  });
140165
140178
  success("Media sent", result);
140166
140179
  },
@@ -140188,7 +140201,8 @@ var messageSenders = {
140188
140201
  const result = await client.messages.sendSticker({
140189
140202
  instanceId,
140190
140203
  to,
140191
- ...isBase64 ? { base64: sticker } : { url: sticker }
140204
+ ...isBase64 ? { base64: sticker } : { url: sticker },
140205
+ sentBy: resolveSentBy(options3.sentBy)
140192
140206
  });
140193
140207
  success("Sticker sent", result);
140194
140208
  },
@@ -140207,7 +140221,8 @@ var messageSenders = {
140207
140221
  name,
140208
140222
  phone: options3.phone,
140209
140223
  email: options3.email
140210
- }
140224
+ },
140225
+ sentBy: resolveSentBy(options3.sentBy)
140211
140226
  });
140212
140227
  success("Contact sent", result);
140213
140228
  },
@@ -140224,7 +140239,8 @@ var messageSenders = {
140224
140239
  to,
140225
140240
  latitude: lat,
140226
140241
  longitude: lng,
140227
- address: options3.address
140242
+ address: options3.address,
140243
+ sentBy: resolveSentBy(options3.sentBy)
140228
140244
  });
140229
140245
  success("Location sent", result);
140230
140246
  },
@@ -140243,7 +140259,8 @@ var messageSenders = {
140243
140259
  question: poll,
140244
140260
  answers,
140245
140261
  multiSelect: options3.multiSelect,
140246
- durationHours: options3.duration
140262
+ durationHours: options3.duration,
140263
+ sentBy: resolveSentBy(options3.sentBy)
140247
140264
  });
140248
140265
  success("Poll sent", result);
140249
140266
  },
@@ -140257,7 +140274,8 @@ var messageSenders = {
140257
140274
  title: options3.title,
140258
140275
  description: options3.description,
140259
140276
  color: options3.color,
140260
- url: options3.url
140277
+ url: options3.url,
140278
+ sentBy: resolveSentBy(options3.sentBy)
140261
140279
  });
140262
140280
  success("Embed sent", result);
140263
140281
  },
@@ -140289,7 +140307,8 @@ var messageSenders = {
140289
140307
  to,
140290
140308
  text: tts,
140291
140309
  voiceId: options3.voiceId,
140292
- presenceDelay: options3.presenceDelay
140310
+ presenceDelay: options3.presenceDelay,
140311
+ sentBy: resolveSentBy(options3.sentBy)
140293
140312
  });
140294
140313
  success("TTS voice note sent", result);
140295
140314
  },
@@ -140309,7 +140328,8 @@ var messageSenders = {
140309
140328
  instanceId,
140310
140329
  to,
140311
140330
  messageId: message2,
140312
- fromChatId: fromChat
140331
+ fromChatId: fromChat,
140332
+ sentBy: resolveSentBy(options3.sentBy)
140313
140333
  });
140314
140334
  success("Message forwarded", result);
140315
140335
  }
@@ -140383,6 +140403,10 @@ function buildGroupedSendHelp() {
140383
140403
  {
140384
140404
  flags: "--to <recipient>",
140385
140405
  description: "Recipient: WA JID (5511@s.whatsapp.net), phone (+5511...), or Omni chat/person UUID"
140406
+ },
140407
+ {
140408
+ flags: "--sent-by <agent|user>",
140409
+ description: "Authorship: 'agent' attributes the send to the instance's configured agent (not for --reaction/--presence)"
140386
140410
  }
140387
140411
  ];
140388
140412
  const textOptions = [
@@ -140481,7 +140505,7 @@ function createSendCommand() {
140481
140505
  send.configureHelp({
140482
140506
  formatHelp: () => buildGroupedSendHelp()
140483
140507
  });
140484
- send.description("Send a message to a recipient").argument("[file]", "File to send as media (shorthand for --media, uses context for instance/chat)").option("--instance <id>", "Instance ID (uses default if not specified)").option("--to <recipient>", "Recipient: WA JID, phone number, or Omni chat/person UUID").option("--text <text>", "Send text message").option("--reply-to <id>", "Reply to a message ID").option("--thread-id <id>", "Thread/topic ID (Telegram forum topic, etc.)").option("--media <path>", "Send media file (image, audio, video, document)").option("--caption <text>", "Caption for media").option("--voice", "Send audio as voice note").option("--reaction <emoji>", "Send reaction emoji").option("--message <id>", "Message ID to react to").option("--sticker <url>", "Send sticker (URL or base64)").option("--contact", "Send contact card").option("--name <name>", "Contact name").option("--phone <phone>", "Contact phone number").option("--email <email>", "Contact email").option("--location", "Send location").option("--lat <latitude>", "Latitude", Number.parseFloat).option("--lng <longitude>", "Longitude", Number.parseFloat).option("--address <address>", "Location address").option("--poll <question>", "Send poll with question").option("--options <answers>", "Poll options (comma-separated)").option("--multi-select", "Allow multiple selections").option("--duration <hours>", "Poll duration in hours", Number.parseInt).option("--embed", "Send embed message").option("--title <title>", "Embed title").option("--description <desc>", "Embed description").option("--color <color>", "Embed color (hex)", Number.parseInt).option("--url <url>", "Embed URL").option("--presence <type>", "Send presence indicator (typing, recording, paused)").option("--status <text>", "Custom status text for channels that support it").option("--loading-messages <items>", "Comma-separated rotating loading messages").option("--tts <text>", "Send TTS voice note (text-to-speech)").option("--voice-id <id>", "ElevenLabs voice ID for TTS").option("--presence-delay <ms>", "Recording presence duration in ms", Number.parseInt).option("--forward", "Forward a message to another chat").option("--from-chat <chatId>", "Source chat ID for forwarding").action(async (file, options3) => {
140508
+ send.description("Send a message to a recipient").argument("[file]", "File to send as media (shorthand for --media, uses context for instance/chat)").option("--instance <id>", "Instance ID (uses default if not specified)").option("--to <recipient>", "Recipient: WA JID, phone number, or Omni chat/person UUID").option("--sent-by <agent|user>", "Authorship: 'agent' attributes the send to the instance's configured agent").option("--text <text>", "Send text message").option("--reply-to <id>", "Reply to a message ID").option("--thread-id <id>", "Thread/topic ID (Telegram forum topic, etc.)").option("--media <path>", "Send media file (image, audio, video, document)").option("--caption <text>", "Caption for media").option("--voice", "Send audio as voice note").option("--reaction <emoji>", "Send reaction emoji").option("--message <id>", "Message ID to react to").option("--sticker <url>", "Send sticker (URL or base64)").option("--contact", "Send contact card").option("--name <name>", "Contact name").option("--phone <phone>", "Contact phone number").option("--email <email>", "Contact email").option("--location", "Send location").option("--lat <latitude>", "Latitude", Number.parseFloat).option("--lng <longitude>", "Longitude", Number.parseFloat).option("--address <address>", "Location address").option("--poll <question>", "Send poll with question").option("--options <answers>", "Poll options (comma-separated)").option("--multi-select", "Allow multiple selections").option("--duration <hours>", "Poll duration in hours", Number.parseInt).option("--embed", "Send embed message").option("--title <title>", "Embed title").option("--description <desc>", "Embed description").option("--color <color>", "Embed color (hex)", Number.parseInt).option("--url <url>", "Embed URL").option("--presence <type>", "Send presence indicator (typing, recording, paused)").option("--status <text>", "Custom status text for channels that support it").option("--loading-messages <items>", "Comma-separated rotating loading messages").option("--tts <text>", "Send TTS voice note (text-to-speech)").option("--voice-id <id>", "ElevenLabs voice ID for TTS").option("--presence-delay <ms>", "Recording presence duration in ms", Number.parseInt).option("--forward", "Forward a message to another chat").option("--from-chat <chatId>", "Source chat ID for forwarding").action(async (file, options3) => {
140485
140509
  if (file && !options3.media) {
140486
140510
  options3.media = file;
140487
140511
  if (!options3.to) {
@@ -142578,8 +142602,59 @@ ${lines.join(`
142578
142602
  }
142579
142603
 
142580
142604
  // src/commands/webhooks.ts
142605
+ init_zod();
142581
142606
  init_output();
142582
142607
  var SIGNATURE_ALGORITHMS = ["hmac-sha256", "hmac-sha1", "token-match"];
142608
+ var signatureSecretSchema = exports_external.string().min(8, "at least 8 characters").max(512, "at most 512 characters");
142609
+ var SECRET_SOURCE_FLAGS = "--signature-secret, --signature-secret-env, --signature-secret-stdin";
142610
+ async function readSecretFromStdin() {
142611
+ if (process.stdin.isTTY) {
142612
+ throw new Error('--signature-secret-stdin requires piped stdin (e.g. `printf %s "$SECRET" | omni webhooks ...`)');
142613
+ }
142614
+ const chunks = [];
142615
+ for await (const chunk of process.stdin) {
142616
+ chunks.push(Buffer.from(chunk));
142617
+ }
142618
+ return Buffer.concat(chunks).toString("utf-8");
142619
+ }
142620
+ async function resolveSignatureSecret(options3, readStdin = readSecretFromStdin) {
142621
+ const sources = [
142622
+ options3.signatureSecret !== undefined,
142623
+ options3.signatureSecretEnv !== undefined,
142624
+ options3.signatureSecretStdin === true
142625
+ ].filter(Boolean).length;
142626
+ if (sources === 0)
142627
+ return;
142628
+ if (sources > 1) {
142629
+ throw new Error(`Use only one of ${SECRET_SOURCE_FLAGS}`);
142630
+ }
142631
+ let raw2;
142632
+ let origin;
142633
+ if (options3.signatureSecretEnv !== undefined) {
142634
+ const name = options3.signatureSecretEnv;
142635
+ if (!name)
142636
+ throw new Error("--signature-secret-env requires a variable name");
142637
+ raw2 = process.env[name];
142638
+ origin = `environment variable ${name}`;
142639
+ if (raw2 === undefined || raw2 === "") {
142640
+ throw new Error(`${origin} is not set or empty`);
142641
+ }
142642
+ } else if (options3.signatureSecretStdin) {
142643
+ raw2 = (await readStdin()).replace(/\r?\n$/, "");
142644
+ origin = "stdin";
142645
+ if (!raw2)
142646
+ throw new Error("no secret received on stdin");
142647
+ } else {
142648
+ raw2 = options3.signatureSecret;
142649
+ origin = "--signature-secret";
142650
+ }
142651
+ const parsed = signatureSecretSchema.safeParse(raw2);
142652
+ if (!parsed.success) {
142653
+ const reason = parsed.error.issues.map((issue) => issue.message).join("; ");
142654
+ throw new Error(`Invalid signature secret from ${origin}: ${reason}`);
142655
+ }
142656
+ return parsed.data;
142657
+ }
142583
142658
  function buildSignatureConfig(options3) {
142584
142659
  const { signatureAlgorithm, signatureHeader, signaturePrefix } = options3;
142585
142660
  if (!signatureAlgorithm && !signatureHeader && !signaturePrefix)
@@ -142596,6 +142671,14 @@ function buildSignatureConfig(options3) {
142596
142671
  }
142597
142672
  return { algorithm, header: signatureHeader, prefix: signaturePrefix };
142598
142673
  }
142674
+ function assertPairedSignatureOnCreate(signatureConfig, signatureSecret) {
142675
+ if (signatureConfig === undefined === (signatureSecret === undefined))
142676
+ return;
142677
+ if (signatureConfig === undefined) {
142678
+ throw new Error(`a signature secret (${SECRET_SOURCE_FLAGS}) requires --signature-algorithm and --signature-header`);
142679
+ }
142680
+ throw new Error(`--signature-algorithm and --signature-header require a signature secret (${SECRET_SOURCE_FLAGS})`);
142681
+ }
142599
142682
  function createWebhooksCommand() {
142600
142683
  const webhooks = new Command("webhooks").description("Manage webhook sources");
142601
142684
  webhooks.command("list").description("List webhook sources").option("--enabled", "Show only enabled sources").option("--disabled", "Show only disabled sources").action(async (options3) => {
@@ -142632,7 +142715,7 @@ function createWebhooksCommand() {
142632
142715
  error(`Failed to get webhook source: ${message2}`);
142633
142716
  }
142634
142717
  });
142635
- webhooks.command("create").description("Create a webhook source").requiredOption("--name <name>", "Webhook source name").option("--description <desc>", "Description").option("--disabled", "Create in disabled state").option("--headers <json>", `Expected headers as JSON (e.g., '{"X-Secret": true}')`).option("--signature-algorithm <alg>", "Signature verification: hmac-sha256, hmac-sha1, or token-match").option("--signature-header <name>", "Header carrying the signature/token (e.g., X-Hub-Signature-256)").option("--signature-prefix <prefix>", "Prefix before the hex digest (e.g., 'sha256=')").option("--signature-secret <secret>", "Shared secret for signature verification (write-only)").action(async (options3) => {
142718
+ webhooks.command("create").description("Create a webhook source").requiredOption("--name <name>", "Webhook source name").option("--description <desc>", "Description").option("--disabled", "Create in disabled state").option("--headers <json>", `Expected headers as JSON (e.g., '{"X-Secret": true}')`).option("--signature-algorithm <alg>", "Signature verification: hmac-sha256, hmac-sha1, or token-match").option("--signature-header <name>", "Header carrying the signature/token (e.g., X-Hub-Signature-256)").option("--signature-prefix <prefix>", "Prefix before the hex digest (e.g., 'sha256=')").option("--signature-secret <secret>", "Shared secret for signature verification (write-only). Visible in shell history and process lists \u2014 prefer --signature-secret-env or --signature-secret-stdin").option("--signature-secret-env <VAR>", "Read the shared secret from environment variable VAR").option("--signature-secret-stdin", "Read the shared secret from stdin (trailing newline stripped)").action(async (options3) => {
142636
142719
  const client = getClient();
142637
142720
  try {
142638
142721
  let expectedHeaders;
@@ -142644,13 +142727,15 @@ function createWebhooksCommand() {
142644
142727
  }
142645
142728
  }
142646
142729
  const signatureConfig = buildSignatureConfig(options3);
142730
+ const signatureSecret = await resolveSignatureSecret(options3);
142731
+ assertPairedSignatureOnCreate(signatureConfig, signatureSecret);
142647
142732
  const source = await client.webhooks.createSource({
142648
142733
  name: options3.name,
142649
142734
  description: options3.description,
142650
142735
  enabled: !options3.disabled,
142651
142736
  expectedHeaders,
142652
142737
  signatureConfig,
142653
- signatureSecret: options3.signatureSecret
142738
+ signatureSecret
142654
142739
  });
142655
142740
  const details = {
142656
142741
  id: source.id,
@@ -142666,7 +142751,7 @@ function createWebhooksCommand() {
142666
142751
  error(`Failed to create webhook source: ${message2}`);
142667
142752
  }
142668
142753
  });
142669
- webhooks.command("update <id>").description("Update a webhook source").option("--name <name>", "New name").option("--description <desc>", "New description").option("--enable", "Enable the webhook").option("--disable", "Disable the webhook").option("--signature-algorithm <alg>", "Signature verification: hmac-sha256, hmac-sha1, or token-match").option("--signature-header <name>", "Header carrying the signature/token (e.g., X-Hub-Signature-256)").option("--signature-prefix <prefix>", "Prefix before the hex digest (e.g., 'sha256=')").option("--signature-secret <secret>", "Shared secret for signature verification (write-only)").option("--clear-signature", "Remove the signature config and stored secret").action(async (id, options3) => {
142754
+ webhooks.command("update <id>").description("Update a webhook source").option("--name <name>", "New name").option("--description <desc>", "New description").option("--enable", "Enable the webhook").option("--disable", "Disable the webhook").option("--signature-algorithm <alg>", "Signature verification: hmac-sha256, hmac-sha1, or token-match").option("--signature-header <name>", "Header carrying the signature/token (e.g., X-Hub-Signature-256)").option("--signature-prefix <prefix>", "Prefix before the hex digest (e.g., 'sha256=')").option("--signature-secret <secret>", "Shared secret for signature verification (write-only). Visible in shell history and process lists \u2014 prefer --signature-secret-env or --signature-secret-stdin").option("--signature-secret-env <VAR>", "Read the shared secret from environment variable VAR").option("--signature-secret-stdin", "Read the shared secret from stdin (trailing newline stripped)").option("--clear-signature", "Remove the signature config and stored secret").action(async (id, options3) => {
142670
142755
  const resolvedId = await resolveWebhookId(id);
142671
142756
  const client = getClient();
142672
142757
  try {
@@ -142685,8 +142770,9 @@ function createWebhooksCommand() {
142685
142770
  const signatureConfig = buildSignatureConfig(options3);
142686
142771
  if (signatureConfig)
142687
142772
  updates.signatureConfig = signatureConfig;
142688
- if (options3.signatureSecret)
142689
- updates.signatureSecret = options3.signatureSecret;
142773
+ const signatureSecret = await resolveSignatureSecret(options3);
142774
+ if (signatureSecret)
142775
+ updates.signatureSecret = signatureSecret;
142690
142776
  }
142691
142777
  const source = await client.webhooks.updateSource(resolvedId, updates);
142692
142778
  success(`Webhook source updated: ${source.id}`, {
@@ -261,6 +261,12 @@ export interface CreateInstanceBody {
261
261
  twilioWebhookUrl?: string;
262
262
  twilioValidateSignature?: boolean;
263
263
  }
264
+ /**
265
+ * Authorship marker accepted by the send routes (#912). 'agent' attributes the
266
+ * message to the instance's configured agent server-side — the agent id is
267
+ * never taken from the caller.
268
+ */
269
+ export type SentBy = 'agent' | 'user';
264
270
  /**
265
271
  * Body for sending a message
266
272
  */
@@ -270,6 +276,12 @@ export interface SendMessageBody {
270
276
  text: string;
271
277
  replyTo?: string;
272
278
  threadId?: string;
279
+ /**
280
+ * Authorship of this send. 'agent' attributes the message to the instance's
281
+ * configured agent (the response echoes the resolved `senderAgentId`, null
282
+ * when the instance has no configured agent). Default: unattributed.
283
+ */
284
+ sentBy?: SentBy;
273
285
  }
274
286
  /**
275
287
  * Query parameters for listing events
@@ -622,26 +634,33 @@ export interface ListWebhookSourcesParams {
622
634
  enabled?: boolean;
623
635
  }
624
636
  /**
625
- * Signature verification contract for a webhook source (issue #928)
637
+ * Signature verification contract for a webhook source (issue #928).
638
+ * Derived from the generated OpenAPI component so it cannot drift from the API.
626
639
  */
627
- export interface WebhookSignatureConfigBody {
628
- algorithm: 'hmac-sha256' | 'hmac-sha1' | 'token-match';
629
- /** Header carrying the signature/token (e.g. 'X-Hub-Signature-256') */
630
- header: string;
631
- /** Prefix before the hex digest (e.g. 'sha256=') */
632
- prefix?: string;
633
- }
640
+ export type WebhookSignatureConfigBody = components['schemas']['WebhookSignatureConfig'];
634
641
  /**
635
- * Body for creating a webhook source
642
+ * Body for creating a webhook source.
643
+ *
644
+ * Hand-written on purpose: the generated `CreateWebhookSourceRequest` marks
645
+ * `enabled` as required because the API schema gives it a default, while for
646
+ * a caller it is optional. Field set and semantics mirror that component.
636
647
  */
637
648
  export interface CreateWebhookSourceBody {
638
649
  name: string;
639
650
  description?: string;
640
651
  expectedHeaders?: Record<string, boolean>;
641
- /** Required for the source to be reachable on the public ingress route */
652
+ /**
653
+ * Required for the source to be reachable on the public ingress route.
654
+ * Always paired with `signatureSecret`: a config without a stored secret is
655
+ * rejected, and clearing the config (null) also clears the stored secret.
656
+ */
642
657
  signatureConfig?: WebhookSignatureConfigBody | null;
643
- /** Shared secret used by signatureConfig (write-only, never returned) */
658
+ /**
659
+ * Shared secret used by signatureConfig (write-only, never returned; 8-512
660
+ * chars). Cannot be set without a signatureConfig; null clears it.
661
+ */
644
662
  signatureSecret?: string | null;
663
+ /** Defaults to true server-side */
645
664
  enabled?: boolean;
646
665
  }
647
666
  /**
@@ -696,9 +715,15 @@ export interface SendMediaBody {
696
715
  caption?: string;
697
716
  voiceNote?: boolean;
698
717
  threadId?: string;
718
+ /**
719
+ * Authorship of this send. 'agent' attributes the message to the instance's
720
+ * configured agent (the response echoes the resolved `senderAgentId`, null
721
+ * when the instance has no configured agent). Default: unattributed.
722
+ */
723
+ sentBy?: SentBy;
699
724
  }
700
725
  /**
701
- * Body for sending a reaction
726
+ * Body for sending a reaction (no `sentBy`: reactions are not attributable sends)
702
727
  */
703
728
  export interface SendReactionBody {
704
729
  instanceId: string;
@@ -721,6 +746,12 @@ export interface SendForwardBody {
721
746
  to: string;
722
747
  messageId: string;
723
748
  fromChatId: string;
749
+ /**
750
+ * Authorship of this send. 'agent' attributes the message to the instance's
751
+ * configured agent (the response echoes the resolved `senderAgentId`, null
752
+ * when the instance has no configured agent). Default: unattributed.
753
+ */
754
+ sentBy?: SentBy;
724
755
  }
725
756
  /**
726
757
  * Body for sending a sticker
@@ -730,6 +761,12 @@ export interface SendStickerBody {
730
761
  to: string;
731
762
  url?: string;
732
763
  base64?: string;
764
+ /**
765
+ * Authorship of this send. 'agent' attributes the message to the instance's
766
+ * configured agent (the response echoes the resolved `senderAgentId`, null
767
+ * when the instance has no configured agent). Default: unattributed.
768
+ */
769
+ sentBy?: SentBy;
733
770
  }
734
771
  /**
735
772
  * Body for sending a contact
@@ -743,6 +780,12 @@ export interface SendContactBody {
743
780
  email?: string;
744
781
  organization?: string;
745
782
  };
783
+ /**
784
+ * Authorship of this send. 'agent' attributes the message to the instance's
785
+ * configured agent (the response echoes the resolved `senderAgentId`, null
786
+ * when the instance has no configured agent). Default: unattributed.
787
+ */
788
+ sentBy?: SentBy;
746
789
  }
747
790
  /**
748
791
  * Body for sending a TTS voice note
@@ -756,6 +799,12 @@ export interface SendTtsBody {
756
799
  stability?: number;
757
800
  similarityBoost?: number;
758
801
  presenceDelay?: number;
802
+ /**
803
+ * Authorship of this send. 'agent' attributes the message to the instance's
804
+ * configured agent (the response echoes the resolved `senderAgentId`, null
805
+ * when the instance has no configured agent). Default: unattributed.
806
+ */
807
+ sentBy?: SentBy;
759
808
  }
760
809
  /**
761
810
  * TTS voice configuration
@@ -775,6 +824,8 @@ export interface TtsResponse {
775
824
  audioSizeKb: number;
776
825
  durationMs: number;
777
826
  timestamp: number;
827
+ /** Present when the request set `sentBy: 'agent'`; null when the instance has no configured agent */
828
+ senderAgentId?: string | null;
778
829
  }
779
830
  /**
780
831
  * Body for sending a location
@@ -786,6 +837,12 @@ export interface SendLocationBody {
786
837
  longitude: number;
787
838
  name?: string;
788
839
  address?: string;
840
+ /**
841
+ * Authorship of this send. 'agent' attributes the message to the instance's
842
+ * configured agent (the response echoes the resolved `senderAgentId`, null
843
+ * when the instance has no configured agent). Default: unattributed.
844
+ */
845
+ sentBy?: SentBy;
789
846
  }
790
847
  /**
791
848
  * Body for sending a poll (Discord)
@@ -798,6 +855,12 @@ export interface SendPollBody {
798
855
  durationHours?: number;
799
856
  multiSelect?: boolean;
800
857
  replyTo?: string;
858
+ /**
859
+ * Authorship of this send. 'agent' attributes the message to the instance's
860
+ * configured agent (the response echoes the resolved `senderAgentId`, null
861
+ * when the instance has no configured agent). Default: unattributed.
862
+ */
863
+ sentBy?: SentBy;
801
864
  }
802
865
  /**
803
866
  * Body for sending an embed (Discord)
@@ -827,6 +890,12 @@ export interface SendEmbedBody {
827
890
  inline?: boolean;
828
891
  }>;
829
892
  replyTo?: string;
893
+ /**
894
+ * Authorship of this send. 'agent' attributes the message to the instance's
895
+ * configured agent (the response echoes the resolved `senderAgentId`, null
896
+ * when the instance has no configured agent). Default: unattributed.
897
+ */
898
+ sentBy?: SentBy;
830
899
  }
831
900
  /**
832
901
  * Body for connecting an instance