@automagik/omni 2.260730.4 → 2.260731.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.
@@ -0,0 +1,17 @@
1
+ -- Per-instance dispatch-failure message (#737).
2
+ --
3
+ -- Adds `agent_error_message` to `instances`: the customer-facing text sent
4
+ -- when agent dispatch fails on a non-handoff channel. NULL falls through to
5
+ -- the `OMNI_AGENT_DISPATCH_ERROR_MESSAGE` env var, then the built-in default
6
+ -- (see resolveDispatchErrorMessage in packages/api agent-dispatcher).
7
+ --
8
+ -- Hand-written following the 0043_hermes_channel precedent (additive,
9
+ -- idempotent, no rewrite: ADD COLUMN with no default does not rewrite the
10
+ -- table).
11
+
12
+ -- NOTE: no explicit BEGIN/COMMIT — the boot migrator executes this file on a
13
+ -- pooled postgres-js connection, which rejects raw transaction control
14
+ -- (UNSAFE_TRANSACTION). Single idempotent statement.
15
+
16
+ ALTER TABLE "instances"
17
+ ADD COLUMN IF NOT EXISTS "agent_error_message" text;
@@ -0,0 +1,24 @@
1
+ -- Per-instance dispatch-failure messages, plural (#737 follow-up).
2
+ --
3
+ -- Replaces the single-text `agent_error_message` (added in 0044) with a jsonb
4
+ -- string array `agent_error_messages`: operators can configure several
5
+ -- variants and the dispatcher picks one at random per failure. Any value
6
+ -- already stored in the old column is carried over as a one-element array.
7
+ --
8
+ -- Hand-written following the 0043/0044 precedent (snapshot drift keeps
9
+ -- drizzle-kit generate interactive). Additive + idempotent statements.
10
+
11
+ -- NOTE: no explicit BEGIN/COMMIT — the boot migrator executes this file on a
12
+ -- pooled postgres-js connection, which rejects raw transaction control
13
+ -- (UNSAFE_TRANSACTION).
14
+
15
+ ALTER TABLE "instances"
16
+ ADD COLUMN IF NOT EXISTS "agent_error_messages" jsonb;
17
+
18
+ UPDATE "instances"
19
+ SET "agent_error_messages" = to_jsonb(ARRAY["agent_error_message"])
20
+ WHERE "agent_error_message" IS NOT NULL
21
+ AND "agent_error_messages" IS NULL;
22
+
23
+ ALTER TABLE "instances"
24
+ DROP COLUMN IF EXISTS "agent_error_message";
@@ -309,6 +309,20 @@
309
309
  "when": 1784300000000,
310
310
  "tag": "0043_hermes_channel",
311
311
  "breakpoints": true
312
+ },
313
+ {
314
+ "idx": 44,
315
+ "version": "7",
316
+ "when": 1784400000000,
317
+ "tag": "0044_instance_agent_error_message",
318
+ "breakpoints": true
319
+ },
320
+ {
321
+ "idx": 45,
322
+ "version": "7",
323
+ "when": 1784500000000,
324
+ "tag": "0045_agent_error_messages_list",
325
+ "breakpoints": true
312
326
  }
313
327
  ]
314
328
  }
@@ -1 +1 @@
1
- {"version":3,"file":"instances.d.ts","sourceRoot":"","sources":["../../src/commands/instances.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqMpC,wBAAgB,sBAAsB,IAAI,OAAO,CAwzChD"}
1
+ {"version":3,"file":"instances.d.ts","sourceRoot":"","sources":["../../src/commands/instances.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyMpC,wBAAgB,sBAAsB,IAAI,OAAO,CAk0ChD"}
package/dist/index.js CHANGED
@@ -73072,6 +73072,7 @@ var init_schema2 = __esm(() => {
73072
73072
  agentId: uuid("agent_id").references(() => agents.id, { onDelete: "set null" }),
73073
73073
  agentTimeout: integer("agent_timeout").notNull().default(600),
73074
73074
  agentStreamMode: boolean("agent_stream_mode").notNull().default(false),
73075
+ agentErrorMessages: jsonb("agent_error_messages").$type(),
73075
73076
  agentReplyFilter: jsonb("agent_reply_filter").$type(),
73076
73077
  agentSessionStrategy: varchar("agent_session_strategy", { length: 20 }).notNull().default("per_chat").$type(),
73077
73078
  agentPrefixSenderName: boolean("agent_prefix_sender_name").notNull().default(true),
@@ -127654,7 +127655,7 @@ import { fileURLToPath } from "url";
127654
127655
  // package.json
127655
127656
  var package_default = {
127656
127657
  name: "@automagik/omni",
127657
- version: "2.260730.4",
127658
+ version: "2.260731.2",
127658
127659
  description: "LLM-optimized CLI for Omni",
127659
127660
  type: "module",
127660
127661
  bin: {
@@ -135176,6 +135177,10 @@ function applyAgentFields(body, opts) {
135176
135177
  setVal(body, "agentId", opts.agentFkId);
135177
135178
  if (opts.agentTimeout !== undefined)
135178
135179
  body.agentTimeout = opts.agentTimeout;
135180
+ if (Array.isArray(opts.agentErrorMessage)) {
135181
+ const messages2 = opts.agentErrorMessage;
135182
+ body.agentErrorMessages = messages2.length === 1 && messages2[0] === "null" ? null : messages2;
135183
+ }
135179
135184
  setBool(body, "agentStreamMode", opts.agentStreamMode);
135180
135185
  setVal(body, "agentSessionStrategy", opts.agentSessionStrategy);
135181
135186
  setBool(body, "agentPrefixSenderName", opts.agentPrefixSenderName);
@@ -135367,7 +135372,7 @@ function createInstancesCommand() {
135367
135372
  error(`Failed to get instance: ${message}`, undefined, 3);
135368
135373
  }
135369
135374
  });
135370
- instances.command("create").description("Create a new instance (supports all API fields)").requiredOption("--name <name>", "Instance name").requiredOption("--channel <type>", `Channel type (${VALID_CHANNELS2.join(", ")})`).option("--agent-fk-id <uuid>", 'Agent FK UUID (references agents table, use "null" to clear). When set without --reply-filter-mode, reply filter defaults to {mode:"all", onDm:true} so messages are dispatched instead of silently dropped (omni#443).').option("--agent-provider <id>", "Agent provider ID").option("--agent <id>", "Agent ID").option("--agent-type <type>", "Agent type: agent, team, or workflow").option("--agent-timeout <seconds>", "Agent timeout in seconds", (v) => Number.parseInt(v, 10)).option("--agent-stream-mode", "Enable streaming responses").option("--agent-session-strategy <strategy>", "Session strategy: per_user, per_chat, per_user_per_chat").option("--agent-prefix-sender-name", "Prefix messages with sender name").option("--no-agent-prefix-sender-name", "Disable sender name prefix").option("--agent-wait-for-media", "Wait for media processing before dispatch").option("--no-agent-wait-for-media", "Dispatch immediately without waiting for media").option("--agent-send-media-path", "Include file path in formatted media text").option("--no-agent-send-media-path", "Exclude file path from formatted media text").option("--agent-send-media-path-types <types>", "Content types that receive file path (comma-separated: image,video,document)").option("--reply-filter-mode <mode>", "Reply filter: all or filtered").option("--reply-on-dm", "Reply to DMs").option("--no-reply-on-dm", "Ignore DMs").option("--reply-on-mention", "Reply when @mentioned").option("--no-reply-on-mention", "Ignore @mentions").option("--reply-on-reply", "Reply when message is reply to bot").option("--no-reply-on-reply", "Ignore replies").option("--reply-on-name", "Reply when bot name appears in text").option("--no-reply-on-name", "Ignore name matches").option("--reply-name-patterns <patterns>", "Custom name patterns (comma-separated)").option("--enable-auto-split", "Split responses on double newlines").option("--no-enable-auto-split", "Disable auto-split").option("--message-format-mode <mode>", "Format mode: convert or passthrough").option("--debounce-mode <mode>", "Debounce mode: disabled, fixed, randomized, or presence").option("--debounce-min <ms>", "Minimum debounce delay in ms", (v) => Number.parseInt(v, 10)).option("--debounce-max <ms>", "Maximum debounce delay in ms", (v) => Number.parseInt(v, 10)).option("--debounce-restart-on-typing", "Restart debounce timer on typing").option("--debounce-group <ms>", "Group chat debounce in ms", (v) => Number.parseInt(v, 10)).option("--debounce-max-wait <ms>", "Presence-mode hard cap in ms (flush even under continuous typing)", (v) => Number.parseInt(v, 10)).option("--split-delay-mode <mode>", "Split delay mode: disabled, fixed, or randomized").option("--split-delay-fixed <ms>", "Fixed delay between split chunks in ms", (v) => Number.parseInt(v, 10)).option("--split-delay-min <ms>", "Minimum delay between split chunks in ms", (v) => Number.parseInt(v, 10)).option("--split-delay-max <ms>", "Maximum delay between split chunks in ms", (v) => Number.parseInt(v, 10)).option("--agent-gate", "Enable LLM response gate").option("--agent-gate-model <model>", "Model for response gate").option("--agent-gate-prompt <prompt>", "Custom gate prompt").option("--tts-voice <id>", "ElevenLabs voice ID").option("--tts-model <id>", "ElevenLabs model ID").option("--read-receipts <mode>", "Read receipts mode: on, off, or exclude-self").option("--access-mode <mode>", "Access mode: disabled, blocklist, or allowlist").option("--reaction-ack <mode>", "Reaction ack mode (on|off)").option("--reaction-ack-emoji <json>", "Per-channel emoji map as JSON").option("--ack-timeout <ms>", "Ack timeout in milliseconds", (v) => Number.parseInt(v, 10)).option("--agent-stalled-timeout-ms <ms>", "Idle threshold in ms before the internal turn.stalled event fires (no channel message is ever sent)", (v) => Number.parseInt(v, 10)).option("--token <token>", "Generic bot token (auto-resolves to channel-specific field)").option("--telegram-token <token>", "Telegram bot token").option("--discord-token <token>", "Discord bot token").option("--slack-bot-token <token>", "Slack bot token").option("--slack-app-token <token>", "Slack app token").option("--gupshup-callback-url <url>", "Gupshup Custom Integration callback URL").option("--gupshup-auth-token <token>", "Gupshup Custom Integration auth token").option("--gupshup-event-id <id>", "Gupshup event ID (default: nx_omni_agent_reply)").option("--gupshup-webhook-verify-token <token>", "Gupshup webhook verify token").option("--twilio-account-sid <sid>", "Twilio Account SID").option("--twilio-auth-token <token>", "Twilio Auth Token").option("--twilio-from <address>", "Twilio WhatsApp sender address (whatsapp:+E164)").option("--twilio-messaging-service-sid <sid>", "Twilio Messaging Service SID").option("--twilio-status-callback-url <url>", "Twilio outbound status callback URL").option("--twilio-webhook-url <url>", "Public Twilio webhook URL for signature validation").option("--twilio-validate-signature", "Validate X-Twilio-Signature on webhooks").option("--no-twilio-validate-signature", "Disable X-Twilio-Signature validation").option("--bridge-tmux-session <name>", 'Tmux session name the genie bridge spawns into for this instance (propagated as GENIE_TMUX_SESSION via NATS). Use "null" to clear.').option("--require-genie-signature", "Require a verified X-Genie-Signature on requests targeting this instance. Bearer-only requests will be rejected with 401.").option("--no-require-genie-signature", "Allow bearer-only requests targeting this instance (default).").option("--allow-first-party", "Process (do not drop) inbound messages whose sender matches another active instance owner. Lets this instance reply to messages from your own personal number.").option("--no-allow-first-party", "Drop inbound messages whose sender matches another active instance owner (default, loop-protection).").option("--is-default", "Set as default instance for channel").action(async (options) => {
135375
+ instances.command("create").description("Create a new instance (supports all API fields)").requiredOption("--name <name>", "Instance name").requiredOption("--channel <type>", `Channel type (${VALID_CHANNELS2.join(", ")})`).option("--agent-fk-id <uuid>", 'Agent FK UUID (references agents table, use "null" to clear). When set without --reply-filter-mode, reply filter defaults to {mode:"all", onDm:true} so messages are dispatched instead of silently dropped (omni#443).').option("--agent-provider <id>", "Agent provider ID").option("--agent <id>", "Agent ID").option("--agent-type <type>", "Agent type: agent, team, or workflow").option("--agent-timeout <seconds>", "Agent timeout in seconds", (v) => Number.parseInt(v, 10)).option("--agent-error-message <text>", 'Customer-facing reply when agent dispatch fails; repeat the flag for multiple variants (one is picked at random per failure). Use "null" to clear; falls back to OMNI_AGENT_DISPATCH_ERROR_MESSAGE env, then built-in default', (value, previous = []) => [...previous, value]).option("--agent-stream-mode", "Enable streaming responses").option("--agent-session-strategy <strategy>", "Session strategy: per_user, per_chat, per_user_per_chat").option("--agent-prefix-sender-name", "Prefix messages with sender name").option("--no-agent-prefix-sender-name", "Disable sender name prefix").option("--agent-wait-for-media", "Wait for media processing before dispatch").option("--no-agent-wait-for-media", "Dispatch immediately without waiting for media").option("--agent-send-media-path", "Include file path in formatted media text").option("--no-agent-send-media-path", "Exclude file path from formatted media text").option("--agent-send-media-path-types <types>", "Content types that receive file path (comma-separated: image,video,document)").option("--reply-filter-mode <mode>", "Reply filter: all or filtered").option("--reply-on-dm", "Reply to DMs").option("--no-reply-on-dm", "Ignore DMs").option("--reply-on-mention", "Reply when @mentioned").option("--no-reply-on-mention", "Ignore @mentions").option("--reply-on-reply", "Reply when message is reply to bot").option("--no-reply-on-reply", "Ignore replies").option("--reply-on-name", "Reply when bot name appears in text").option("--no-reply-on-name", "Ignore name matches").option("--reply-name-patterns <patterns>", "Custom name patterns (comma-separated)").option("--enable-auto-split", "Split responses on double newlines").option("--no-enable-auto-split", "Disable auto-split").option("--message-format-mode <mode>", "Format mode: convert or passthrough").option("--debounce-mode <mode>", "Debounce mode: disabled, fixed, randomized, or presence").option("--debounce-min <ms>", "Minimum debounce delay in ms", (v) => Number.parseInt(v, 10)).option("--debounce-max <ms>", "Maximum debounce delay in ms", (v) => Number.parseInt(v, 10)).option("--debounce-restart-on-typing", "Restart debounce timer on typing").option("--debounce-group <ms>", "Group chat debounce in ms", (v) => Number.parseInt(v, 10)).option("--debounce-max-wait <ms>", "Presence-mode hard cap in ms (flush even under continuous typing)", (v) => Number.parseInt(v, 10)).option("--split-delay-mode <mode>", "Split delay mode: disabled, fixed, or randomized").option("--split-delay-fixed <ms>", "Fixed delay between split chunks in ms", (v) => Number.parseInt(v, 10)).option("--split-delay-min <ms>", "Minimum delay between split chunks in ms", (v) => Number.parseInt(v, 10)).option("--split-delay-max <ms>", "Maximum delay between split chunks in ms", (v) => Number.parseInt(v, 10)).option("--agent-gate", "Enable LLM response gate").option("--agent-gate-model <model>", "Model for response gate").option("--agent-gate-prompt <prompt>", "Custom gate prompt").option("--tts-voice <id>", "ElevenLabs voice ID").option("--tts-model <id>", "ElevenLabs model ID").option("--read-receipts <mode>", "Read receipts mode: on, off, or exclude-self").option("--access-mode <mode>", "Access mode: disabled, blocklist, or allowlist").option("--reaction-ack <mode>", "Reaction ack mode (on|off)").option("--reaction-ack-emoji <json>", "Per-channel emoji map as JSON").option("--ack-timeout <ms>", "Ack timeout in milliseconds", (v) => Number.parseInt(v, 10)).option("--agent-stalled-timeout-ms <ms>", "Idle threshold in ms before the internal turn.stalled event fires (no channel message is ever sent)", (v) => Number.parseInt(v, 10)).option("--token <token>", "Generic bot token (auto-resolves to channel-specific field)").option("--telegram-token <token>", "Telegram bot token").option("--discord-token <token>", "Discord bot token").option("--slack-bot-token <token>", "Slack bot token").option("--slack-app-token <token>", "Slack app token").option("--gupshup-callback-url <url>", "Gupshup Custom Integration callback URL").option("--gupshup-auth-token <token>", "Gupshup Custom Integration auth token").option("--gupshup-event-id <id>", "Gupshup event ID (default: nx_omni_agent_reply)").option("--gupshup-webhook-verify-token <token>", "Gupshup webhook verify token").option("--twilio-account-sid <sid>", "Twilio Account SID").option("--twilio-auth-token <token>", "Twilio Auth Token").option("--twilio-from <address>", "Twilio WhatsApp sender address (whatsapp:+E164)").option("--twilio-messaging-service-sid <sid>", "Twilio Messaging Service SID").option("--twilio-status-callback-url <url>", "Twilio outbound status callback URL").option("--twilio-webhook-url <url>", "Public Twilio webhook URL for signature validation").option("--twilio-validate-signature", "Validate X-Twilio-Signature on webhooks").option("--no-twilio-validate-signature", "Disable X-Twilio-Signature validation").option("--bridge-tmux-session <name>", 'Tmux session name the genie bridge spawns into for this instance (propagated as GENIE_TMUX_SESSION via NATS). Use "null" to clear.').option("--require-genie-signature", "Require a verified X-Genie-Signature on requests targeting this instance. Bearer-only requests will be rejected with 401.").option("--no-require-genie-signature", "Allow bearer-only requests targeting this instance (default).").option("--allow-first-party", "Process (do not drop) inbound messages whose sender matches another active instance owner. Lets this instance reply to messages from your own personal number.").option("--no-allow-first-party", "Drop inbound messages whose sender matches another active instance owner (default, loop-protection).").option("--is-default", "Set as default instance for channel").action(async (options) => {
135371
135376
  const channel = options.channel;
135372
135377
  if (!VALID_CHANNELS2.includes(channel)) {
135373
135378
  error(`Invalid channel: ${channel}`, { validChannels: VALID_CHANNELS2 });
@@ -135670,7 +135675,7 @@ function createInstancesCommand() {
135670
135675
  throw new Error(err?.error?.message ?? `HTTP ${response.status}`);
135671
135676
  }
135672
135677
  }
135673
- instances.command("update <id>").description("Update an instance (supports all API fields)").option("--name <name>", "Instance name").option("--is-default", "Set as default instance for channel").option("--no-is-default", "Unset as default instance for channel").option("--agent-fk-id <uuid>", 'Agent FK UUID (references agents table, use "null" to clear). When assigning an agent on an instance with no reply filter, the filter defaults to {mode:"all", onDm:true} so messages are dispatched instead of silently dropped (omni#443).').option("--agent-provider <id>", 'Agent provider ID (use "null" to clear)').option("--agent <id>", 'Agent ID (use "null" to clear)').option("--agent-type <type>", "Agent type: agent, team, or workflow").option("--agent-timeout <seconds>", "Agent timeout in seconds", (v) => Number.parseInt(v, 10)).option("--agent-stream-mode", "Enable streaming responses").option("--no-agent-stream-mode", "Disable streaming responses").option("--agent-session-strategy <strategy>", "Session strategy: per_user, per_chat, per_user_per_chat").option("--agent-prefix-sender-name", "Prefix messages with sender name").option("--no-agent-prefix-sender-name", "Disable sender name prefix").option("--agent-wait-for-media", "Wait for media processing before dispatch").option("--no-agent-wait-for-media", "Dispatch immediately without waiting for media").option("--agent-send-media-path", "Include file path in formatted media text").option("--no-agent-send-media-path", "Exclude file path from formatted media text").option("--agent-send-media-path-types <types>", "Content types that receive file path (comma-separated: image,video,document)").option("--reply-filter-mode <mode>", "Reply filter: all or filtered").option("--reply-on-dm", "Reply to DMs (requires --reply-filter-mode filtered)").option("--no-reply-on-dm", "Ignore DMs").option("--reply-on-mention", "Reply when @mentioned").option("--no-reply-on-mention", "Ignore @mentions").option("--reply-on-reply", "Reply when message is reply to bot").option("--no-reply-on-reply", "Ignore replies").option("--reply-on-name", "Reply when bot name appears in text").option("--no-reply-on-name", "Ignore name matches").option("--reply-name-patterns <patterns>", "Custom name patterns (comma-separated)").option("--clear-reply-filter", "Remove reply filter (set to null)").option("--enable-auto-split", "Split responses on double newlines").option("--no-enable-auto-split", "Disable auto-split").option("--message-format-mode <mode>", "Format mode: convert or passthrough").option("--debounce-mode <mode>", "Debounce mode: disabled, fixed, randomized, or presence").option("--debounce-min <ms>", "Minimum debounce delay in ms", (v) => Number.parseInt(v, 10)).option("--debounce-max <ms>", "Maximum debounce delay in ms", (v) => Number.parseInt(v, 10)).option("--debounce-restart-on-typing", "Restart debounce timer on typing").option("--no-debounce-restart-on-typing", "Do not restart debounce on typing").option("--debounce-group <ms>", 'Group chat debounce in ms (use "null" to inherit)', (v) => v === "null" ? null : Number.parseInt(v, 10)).option("--debounce-max-wait <ms>", 'Presence-mode hard cap in ms (use "null" to inherit)', (v) => v === "null" ? null : Number.parseInt(v, 10)).option("--split-delay-mode <mode>", "Split delay mode: disabled, fixed, or randomized").option("--split-delay-fixed <ms>", "Fixed delay between split chunks in ms", (v) => Number.parseInt(v, 10)).option("--split-delay-min <ms>", "Minimum delay between split chunks in ms", (v) => Number.parseInt(v, 10)).option("--split-delay-max <ms>", "Maximum delay between split chunks in ms", (v) => Number.parseInt(v, 10)).option("--agent-gate", "Enable LLM response gate").option("--no-agent-gate", "Disable LLM response gate").option("--agent-gate-model <model>", 'Model for response gate (use "null" for default)').option("--agent-gate-prompt <prompt>", 'Custom gate prompt (use "null" for default)').option("--tts-voice <id>", 'ElevenLabs voice ID (use "null" to clear)').option("--tts-model <id>", 'ElevenLabs model ID (use "null" to clear)').option("--read-receipts <mode>", "Read receipts mode: on, off, or exclude-self").option("--access-mode <mode>", "Access mode: disabled, blocklist, or allowlist").option("--reaction-ack <mode>", "Reaction ack mode (on|off)").option("--reaction-ack-emoji <json>", "Per-channel emoji map as JSON").option("--ack-timeout <ms>", "Ack timeout in milliseconds", (v) => Number.parseInt(v, 10)).option("--agent-stalled-timeout-ms <ms>", "Idle threshold in ms before the internal turn.stalled event fires (no channel message is ever sent)", (v) => Number.parseInt(v, 10)).option("--token <token>", "Generic bot token (auto-resolves to channel-specific field)").option("--telegram-token <token>", 'Telegram bot token (use "null" to clear)').option("--discord-token <token>", 'Discord bot token (use "null" to clear)').option("--slack-bot-token <token>", 'Slack bot token (use "null" to clear)').option("--slack-app-token <token>", 'Slack app token (use "null" to clear)').option("--twilio-account-sid <sid>", 'Twilio Account SID (use "null" to clear)').option("--twilio-auth-token <token>", 'Twilio Auth Token (use "null" to clear)').option("--twilio-from <address>", 'Twilio WhatsApp sender address (use "null" to clear)').option("--twilio-messaging-service-sid <sid>", 'Twilio Messaging Service SID (use "null" to clear)').option("--twilio-status-callback-url <url>", 'Twilio outbound status callback URL (use "null" to clear)').option("--twilio-webhook-url <url>", 'Public Twilio webhook URL for signature validation (use "null" to clear)').option("--twilio-validate-signature", "Validate X-Twilio-Signature on webhooks").option("--no-twilio-validate-signature", "Disable X-Twilio-Signature validation").option("--trigger-events <events>", 'Trigger events (comma-separated, use "null" to clear)').option("--profile-name <name>", "Update WhatsApp display name (push name)").option("--bridge-tmux-session <name>", 'Tmux session name the genie bridge spawns into for this instance (propagated as GENIE_TMUX_SESSION via NATS). Use "null" to clear.').option("--require-genie-signature", "Require a verified X-Genie-Signature on requests targeting this instance. Bearer-only requests will be rejected with 401.").option("--no-require-genie-signature", "Allow bearer-only requests targeting this instance (default).").option("--allow-first-party", "Process (do not drop) inbound messages whose sender matches another active instance owner. Lets this instance reply to messages from your own personal number.").option("--no-allow-first-party", "Drop inbound messages whose sender matches another active instance owner (default, loop-protection).").action(async (rawId, options) => {
135678
+ instances.command("update <id>").description("Update an instance (supports all API fields)").option("--name <name>", "Instance name").option("--is-default", "Set as default instance for channel").option("--no-is-default", "Unset as default instance for channel").option("--agent-fk-id <uuid>", 'Agent FK UUID (references agents table, use "null" to clear). When assigning an agent on an instance with no reply filter, the filter defaults to {mode:"all", onDm:true} so messages are dispatched instead of silently dropped (omni#443).').option("--agent-provider <id>", 'Agent provider ID (use "null" to clear)').option("--agent <id>", 'Agent ID (use "null" to clear)').option("--agent-type <type>", "Agent type: agent, team, or workflow").option("--agent-timeout <seconds>", "Agent timeout in seconds", (v) => Number.parseInt(v, 10)).option("--agent-error-message <text>", 'Customer-facing reply when agent dispatch fails; repeat the flag for multiple variants (one is picked at random per failure). Use "null" to clear; falls back to OMNI_AGENT_DISPATCH_ERROR_MESSAGE env, then built-in default', (value, previous = []) => [...previous, value]).option("--agent-stream-mode", "Enable streaming responses").option("--no-agent-stream-mode", "Disable streaming responses").option("--agent-session-strategy <strategy>", "Session strategy: per_user, per_chat, per_user_per_chat").option("--agent-prefix-sender-name", "Prefix messages with sender name").option("--no-agent-prefix-sender-name", "Disable sender name prefix").option("--agent-wait-for-media", "Wait for media processing before dispatch").option("--no-agent-wait-for-media", "Dispatch immediately without waiting for media").option("--agent-send-media-path", "Include file path in formatted media text").option("--no-agent-send-media-path", "Exclude file path from formatted media text").option("--agent-send-media-path-types <types>", "Content types that receive file path (comma-separated: image,video,document)").option("--reply-filter-mode <mode>", "Reply filter: all or filtered").option("--reply-on-dm", "Reply to DMs (requires --reply-filter-mode filtered)").option("--no-reply-on-dm", "Ignore DMs").option("--reply-on-mention", "Reply when @mentioned").option("--no-reply-on-mention", "Ignore @mentions").option("--reply-on-reply", "Reply when message is reply to bot").option("--no-reply-on-reply", "Ignore replies").option("--reply-on-name", "Reply when bot name appears in text").option("--no-reply-on-name", "Ignore name matches").option("--reply-name-patterns <patterns>", "Custom name patterns (comma-separated)").option("--clear-reply-filter", "Remove reply filter (set to null)").option("--enable-auto-split", "Split responses on double newlines").option("--no-enable-auto-split", "Disable auto-split").option("--message-format-mode <mode>", "Format mode: convert or passthrough").option("--debounce-mode <mode>", "Debounce mode: disabled, fixed, randomized, or presence").option("--debounce-min <ms>", "Minimum debounce delay in ms", (v) => Number.parseInt(v, 10)).option("--debounce-max <ms>", "Maximum debounce delay in ms", (v) => Number.parseInt(v, 10)).option("--debounce-restart-on-typing", "Restart debounce timer on typing").option("--no-debounce-restart-on-typing", "Do not restart debounce on typing").option("--debounce-group <ms>", 'Group chat debounce in ms (use "null" to inherit)', (v) => v === "null" ? null : Number.parseInt(v, 10)).option("--debounce-max-wait <ms>", 'Presence-mode hard cap in ms (use "null" to inherit)', (v) => v === "null" ? null : Number.parseInt(v, 10)).option("--split-delay-mode <mode>", "Split delay mode: disabled, fixed, or randomized").option("--split-delay-fixed <ms>", "Fixed delay between split chunks in ms", (v) => Number.parseInt(v, 10)).option("--split-delay-min <ms>", "Minimum delay between split chunks in ms", (v) => Number.parseInt(v, 10)).option("--split-delay-max <ms>", "Maximum delay between split chunks in ms", (v) => Number.parseInt(v, 10)).option("--agent-gate", "Enable LLM response gate").option("--no-agent-gate", "Disable LLM response gate").option("--agent-gate-model <model>", 'Model for response gate (use "null" for default)').option("--agent-gate-prompt <prompt>", 'Custom gate prompt (use "null" for default)').option("--tts-voice <id>", 'ElevenLabs voice ID (use "null" to clear)').option("--tts-model <id>", 'ElevenLabs model ID (use "null" to clear)').option("--read-receipts <mode>", "Read receipts mode: on, off, or exclude-self").option("--access-mode <mode>", "Access mode: disabled, blocklist, or allowlist").option("--reaction-ack <mode>", "Reaction ack mode (on|off)").option("--reaction-ack-emoji <json>", "Per-channel emoji map as JSON").option("--ack-timeout <ms>", "Ack timeout in milliseconds", (v) => Number.parseInt(v, 10)).option("--agent-stalled-timeout-ms <ms>", "Idle threshold in ms before the internal turn.stalled event fires (no channel message is ever sent)", (v) => Number.parseInt(v, 10)).option("--token <token>", "Generic bot token (auto-resolves to channel-specific field)").option("--telegram-token <token>", 'Telegram bot token (use "null" to clear)').option("--discord-token <token>", 'Discord bot token (use "null" to clear)').option("--slack-bot-token <token>", 'Slack bot token (use "null" to clear)').option("--slack-app-token <token>", 'Slack app token (use "null" to clear)').option("--twilio-account-sid <sid>", 'Twilio Account SID (use "null" to clear)').option("--twilio-auth-token <token>", 'Twilio Auth Token (use "null" to clear)').option("--twilio-from <address>", 'Twilio WhatsApp sender address (use "null" to clear)').option("--twilio-messaging-service-sid <sid>", 'Twilio Messaging Service SID (use "null" to clear)').option("--twilio-status-callback-url <url>", 'Twilio outbound status callback URL (use "null" to clear)').option("--twilio-webhook-url <url>", 'Public Twilio webhook URL for signature validation (use "null" to clear)').option("--twilio-validate-signature", "Validate X-Twilio-Signature on webhooks").option("--no-twilio-validate-signature", "Disable X-Twilio-Signature validation").option("--trigger-events <events>", 'Trigger events (comma-separated, use "null" to clear)').option("--profile-name <name>", "Update WhatsApp display name (push name)").option("--bridge-tmux-session <name>", 'Tmux session name the genie bridge spawns into for this instance (propagated as GENIE_TMUX_SESSION via NATS). Use "null" to clear.').option("--require-genie-signature", "Require a verified X-Genie-Signature on requests targeting this instance. Bearer-only requests will be rejected with 401.").option("--no-require-genie-signature", "Allow bearer-only requests targeting this instance (default).").option("--allow-first-party", "Process (do not drop) inbound messages whose sender matches another active instance owner. Lets this instance reply to messages from your own personal number.").option("--no-allow-first-party", "Drop inbound messages whose sender matches another active instance owner (default, loop-protection).").action(async (rawId, options) => {
135674
135679
  const client = getClient();
135675
135680
  try {
135676
135681
  const id = await resolveInstanceId(rawId);
@@ -2614,7 +2614,7 @@ export interface components {
2614
2614
  * @description Channel type
2615
2615
  * @enum {string}
2616
2616
  */
2617
- channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "twilio-whatsapp" | "internal";
2617
+ channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "hermes" | "twilio-whatsapp" | "internal";
2618
2618
  /** @description Whether instance is active */
2619
2619
  isActive: boolean;
2620
2620
  /** @description Whether this is the default instance for channel */
@@ -2637,6 +2637,8 @@ export interface components {
2637
2637
  agentProviderId?: string | null;
2638
2638
  /** @description Agent timeout in seconds */
2639
2639
  agentTimeout: number;
2640
+ /** @description Customer-facing replies sent when agent dispatch fails; one is picked at random per failure (null/empty = env/default fallback) */
2641
+ agentErrorMessages?: string[] | null;
2640
2642
  /** @description Whether streaming is enabled */
2641
2643
  agentStreamMode: boolean;
2642
2644
  /**
@@ -2657,7 +2659,7 @@ export interface components {
2657
2659
  * @description Channel type
2658
2660
  * @enum {string}
2659
2661
  */
2660
- channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "twilio-whatsapp" | "internal";
2662
+ channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "hermes" | "twilio-whatsapp" | "internal";
2661
2663
  /**
2662
2664
  * Format: uuid
2663
2665
  * @description Agent UUID (agents table)
@@ -2668,6 +2670,8 @@ export interface components {
2668
2670
  * @default 600
2669
2671
  */
2670
2672
  agentTimeout: number;
2673
+ /** @description Customer-facing replies sent when agent dispatch fails; one is picked at random per failure (null/empty = env/default fallback) */
2674
+ agentErrorMessages?: string[] | null;
2671
2675
  /**
2672
2676
  * @description Enable streaming responses
2673
2677
  * @default false
@@ -2752,7 +2756,7 @@ export interface components {
2752
2756
  * @description Channel type ID
2753
2757
  * @enum {string}
2754
2758
  */
2755
- id: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "twilio-whatsapp" | "internal";
2759
+ id: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "hermes" | "twilio-whatsapp" | "internal";
2756
2760
  /** @description Human-readable channel name */
2757
2761
  name: string;
2758
2762
  /** @description Plugin version */
@@ -2864,6 +2868,8 @@ export interface components {
2864
2868
  */
2865
2869
  url?: string;
2866
2870
  }[];
2871
+ /** @description Ask the user to share their location (WhatsApp Cloud: native "Send location" button under the text) */
2872
+ requestLocation?: boolean;
2867
2873
  };
2868
2874
  TTSVoice: {
2869
2875
  /** @description ElevenLabs voice ID */
@@ -6095,7 +6101,7 @@ export interface operations {
6095
6101
  * @description Channel type
6096
6102
  * @enum {string}
6097
6103
  */
6098
- channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "twilio-whatsapp" | "internal";
6104
+ channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "hermes" | "twilio-whatsapp" | "internal";
6099
6105
  /** @description Whether instance is active */
6100
6106
  isActive: boolean;
6101
6107
  /** @description Whether this is the default instance for channel */
@@ -6118,6 +6124,8 @@ export interface operations {
6118
6124
  agentProviderId?: string | null;
6119
6125
  /** @description Agent timeout in seconds */
6120
6126
  agentTimeout: number;
6127
+ /** @description Customer-facing replies sent when agent dispatch fails; one is picked at random per failure (null/empty = env/default fallback) */
6128
+ agentErrorMessages?: string[] | null;
6121
6129
  /** @description Whether streaming is enabled */
6122
6130
  agentStreamMode: boolean;
6123
6131
  /**
@@ -6158,7 +6166,7 @@ export interface operations {
6158
6166
  * @description Channel type
6159
6167
  * @enum {string}
6160
6168
  */
6161
- channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "twilio-whatsapp" | "internal";
6169
+ channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "hermes" | "twilio-whatsapp" | "internal";
6162
6170
  /**
6163
6171
  * Format: uuid
6164
6172
  * @description Agent UUID (agents table)
@@ -6169,6 +6177,8 @@ export interface operations {
6169
6177
  * @default 600
6170
6178
  */
6171
6179
  agentTimeout?: number;
6180
+ /** @description Customer-facing replies sent when agent dispatch fails; one is picked at random per failure (null/empty = env/default fallback) */
6181
+ agentErrorMessages?: string[] | null;
6172
6182
  /**
6173
6183
  * @description Enable streaming responses
6174
6184
  * @default false
@@ -6204,7 +6214,7 @@ export interface operations {
6204
6214
  * @description Channel type
6205
6215
  * @enum {string}
6206
6216
  */
6207
- channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "twilio-whatsapp" | "internal";
6217
+ channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "hermes" | "twilio-whatsapp" | "internal";
6208
6218
  /** @description Whether instance is active */
6209
6219
  isActive: boolean;
6210
6220
  /** @description Whether this is the default instance for channel */
@@ -6227,6 +6237,8 @@ export interface operations {
6227
6237
  agentProviderId?: string | null;
6228
6238
  /** @description Agent timeout in seconds */
6229
6239
  agentTimeout: number;
6240
+ /** @description Customer-facing replies sent when agent dispatch fails; one is picked at random per failure (null/empty = env/default fallback) */
6241
+ agentErrorMessages?: string[] | null;
6230
6242
  /** @description Whether streaming is enabled */
6231
6243
  agentStreamMode: boolean;
6232
6244
  /**
@@ -6287,7 +6299,7 @@ export interface operations {
6287
6299
  * @description Channel type ID
6288
6300
  * @enum {string}
6289
6301
  */
6290
- id: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "twilio-whatsapp" | "internal";
6302
+ id: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "hermes" | "twilio-whatsapp" | "internal";
6291
6303
  /** @description Human-readable channel name */
6292
6304
  name: string;
6293
6305
  /** @description Plugin version */
@@ -6336,7 +6348,7 @@ export interface operations {
6336
6348
  * @description Channel type
6337
6349
  * @enum {string}
6338
6350
  */
6339
- channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "twilio-whatsapp" | "internal";
6351
+ channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "hermes" | "twilio-whatsapp" | "internal";
6340
6352
  /** @description Whether instance is active */
6341
6353
  isActive: boolean;
6342
6354
  /** @description Whether this is the default instance for channel */
@@ -6359,6 +6371,8 @@ export interface operations {
6359
6371
  agentProviderId?: string | null;
6360
6372
  /** @description Agent timeout in seconds */
6361
6373
  agentTimeout: number;
6374
+ /** @description Customer-facing replies sent when agent dispatch fails; one is picked at random per failure (null/empty = env/default fallback) */
6375
+ agentErrorMessages?: string[] | null;
6362
6376
  /** @description Whether streaming is enabled */
6363
6377
  agentStreamMode: boolean;
6364
6378
  /**
@@ -6464,7 +6478,7 @@ export interface operations {
6464
6478
  * @description Channel type
6465
6479
  * @enum {string}
6466
6480
  */
6467
- channel?: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "twilio-whatsapp" | "internal";
6481
+ channel?: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "hermes" | "twilio-whatsapp" | "internal";
6468
6482
  /**
6469
6483
  * Format: uuid
6470
6484
  * @description Agent UUID (agents table)
@@ -6475,6 +6489,8 @@ export interface operations {
6475
6489
  * @default 600
6476
6490
  */
6477
6491
  agentTimeout?: number;
6492
+ /** @description Customer-facing replies sent when agent dispatch fails; one is picked at random per failure (null/empty = env/default fallback) */
6493
+ agentErrorMessages?: string[] | null;
6478
6494
  /**
6479
6495
  * @description Enable streaming responses
6480
6496
  * @default false
@@ -6510,7 +6526,7 @@ export interface operations {
6510
6526
  * @description Channel type
6511
6527
  * @enum {string}
6512
6528
  */
6513
- channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "twilio-whatsapp" | "internal";
6529
+ channel: "whatsapp-baileys" | "whatsapp-cloud" | "discord" | "slack" | "telegram" | "a2a" | "gupshup" | "hermes" | "twilio-whatsapp" | "internal";
6514
6530
  /** @description Whether instance is active */
6515
6531
  isActive: boolean;
6516
6532
  /** @description Whether this is the default instance for channel */
@@ -6533,6 +6549,8 @@ export interface operations {
6533
6549
  agentProviderId?: string | null;
6534
6550
  /** @description Agent timeout in seconds */
6535
6551
  agentTimeout: number;
6552
+ /** @description Customer-facing replies sent when agent dispatch fails; one is picked at random per failure (null/empty = env/default fallback) */
6553
+ agentErrorMessages?: string[] | null;
6536
6554
  /** @description Whether streaming is enabled */
6537
6555
  agentStreamMode: boolean;
6538
6556
  /**
@@ -7425,6 +7443,8 @@ export interface operations {
7425
7443
  */
7426
7444
  url?: string;
7427
7445
  }[];
7446
+ /** @description Ask the user to share their location (WhatsApp Cloud: native "Send location" button under the text) */
7447
+ requestLocation?: boolean;
7428
7448
  };
7429
7449
  };
7430
7450
  };