@automagik/omni 2.260703.1 → 2.260703.3

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,22 @@
1
+ -- Presence-debounce max-wait cap (presence-debounce-batching design, 2026-07).
2
+ --
3
+ -- Adds `message_debounce_max_wait_ms` to both the `instances` table and the
4
+ -- per-route `agent_routes` override table. It is the hard cap for the new
5
+ -- 'presence' debounce mode: a batch flushes at `firstBuffered + maxWaitMs`
6
+ -- even while the user keeps typing, so a continuously-composing user can never
7
+ -- starve the agent. NULL = no cap (the legacy fixed/randomized behavior).
8
+ --
9
+ -- The 'presence' mode itself is a TypeScript-layer literal (message-debouncer
10
+ -- DebounceConfig + the `debounceMode` const in schema.ts). The DB stores mode
11
+ -- as a free varchar(20) with no CHECK constraint, so no enum migration is
12
+ -- needed here — only the new nullable column.
13
+ --
14
+ -- Hand-written (not `drizzle-kit generate`) to match the repo convention from
15
+ -- 0032+ and avoid the gupshup column-rename prompts that block non-interactive
16
+ -- runs.
17
+
18
+ ALTER TABLE "instances"
19
+ ADD COLUMN IF NOT EXISTS "message_debounce_max_wait_ms" integer;
20
+
21
+ ALTER TABLE "agent_routes"
22
+ ADD COLUMN IF NOT EXISTS "message_debounce_max_wait_ms" integer;
@@ -260,6 +260,13 @@
260
260
  "when": 1777860000000,
261
261
  "tag": "0036_timestamptz_migration",
262
262
  "breakpoints": true
263
+ },
264
+ {
265
+ "idx": 37,
266
+ "version": "7",
267
+ "when": 1777950000000,
268
+ "tag": "0037_message_debounce_max_wait",
269
+ "breakpoints": true
263
270
  }
264
271
  ]
265
272
  }
@@ -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;AAiMpC,wBAAgB,sBAAsB,IAAI,OAAO,CAkuChD"}
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;AAkMpC,wBAAgB,sBAAsB,IAAI,OAAO,CAwuChD"}
package/dist/index.js CHANGED
@@ -31474,11 +31474,12 @@ var init_agent_route = __esm(() => {
31474
31474
  agentGateEnabled: exports_external.boolean().nullable(),
31475
31475
  agentGateModel: exports_external.string().max(120).nullable(),
31476
31476
  agentGatePrompt: exports_external.string().nullable(),
31477
- messageDebounceMode: exports_external.enum(["disabled", "fixed", "randomized"]).nullable(),
31477
+ messageDebounceMode: exports_external.enum(["disabled", "fixed", "randomized", "presence"]).nullable(),
31478
31478
  messageDebounceMinMs: exports_external.number().int().nonnegative().nullable(),
31479
31479
  messageDebounceMaxMs: exports_external.number().int().nonnegative().nullable(),
31480
31480
  messageDebounceGroupMs: exports_external.number().int().nonnegative().nullable(),
31481
31481
  messageDebounceRestartOnTyping: exports_external.boolean().nullable(),
31482
+ messageDebounceMaxWaitMs: exports_external.number().int().nonnegative().nullable(),
31482
31483
  messageSplitDelayMode: exports_external.enum(["disabled", "fixed", "randomized"]).nullable(),
31483
31484
  messageSplitDelayFixedMs: exports_external.number().int().nonnegative().nullable(),
31484
31485
  messageSplitDelayMinMs: exports_external.number().int().nonnegative().nullable(),
@@ -31509,11 +31510,12 @@ var init_agent_route = __esm(() => {
31509
31510
  agentGateEnabled: exports_external.boolean().optional(),
31510
31511
  agentGateModel: exports_external.string().max(120).optional(),
31511
31512
  agentGatePrompt: exports_external.string().optional(),
31512
- messageDebounceMode: exports_external.enum(["disabled", "fixed", "randomized"]).optional(),
31513
+ messageDebounceMode: exports_external.enum(["disabled", "fixed", "randomized", "presence"]).optional(),
31513
31514
  messageDebounceMinMs: exports_external.number().int().nonnegative().optional(),
31514
31515
  messageDebounceMaxMs: exports_external.number().int().nonnegative().optional(),
31515
31516
  messageDebounceGroupMs: exports_external.number().int().nonnegative().optional(),
31516
31517
  messageDebounceRestartOnTyping: exports_external.boolean().optional(),
31518
+ messageDebounceMaxWaitMs: exports_external.number().int().nonnegative().optional(),
31517
31519
  messageSplitDelayMode: exports_external.enum(["disabled", "fixed", "randomized"]).optional(),
31518
31520
  messageSplitDelayFixedMs: exports_external.number().int().nonnegative().optional(),
31519
31521
  messageSplitDelayMinMs: exports_external.number().int().nonnegative().optional(),
@@ -31543,11 +31545,12 @@ var init_agent_route = __esm(() => {
31543
31545
  agentGateEnabled: exports_external.boolean().optional().nullable(),
31544
31546
  agentGateModel: exports_external.string().max(120).optional().nullable(),
31545
31547
  agentGatePrompt: exports_external.string().optional().nullable(),
31546
- messageDebounceMode: exports_external.enum(["disabled", "fixed", "randomized"]).optional().nullable(),
31548
+ messageDebounceMode: exports_external.enum(["disabled", "fixed", "randomized", "presence"]).optional().nullable(),
31547
31549
  messageDebounceMinMs: exports_external.number().int().nonnegative().optional().nullable(),
31548
31550
  messageDebounceMaxMs: exports_external.number().int().nonnegative().optional().nullable(),
31549
31551
  messageDebounceGroupMs: exports_external.number().int().nonnegative().optional().nullable(),
31550
31552
  messageDebounceRestartOnTyping: exports_external.boolean().optional().nullable(),
31553
+ messageDebounceMaxWaitMs: exports_external.number().int().nonnegative().optional().nullable(),
31551
31554
  messageSplitDelayMode: exports_external.enum(["disabled", "fixed", "randomized"]).optional().nullable(),
31552
31555
  messageSplitDelayFixedMs: exports_external.number().int().nonnegative().optional().nullable(),
31553
31556
  messageSplitDelayMinMs: exports_external.number().int().nonnegative().optional().nullable(),
@@ -71343,7 +71346,7 @@ var init_schema2 = __esm(() => {
71343
71346
  agentTypes = ["agent", "team", "workflow"];
71344
71347
  agentSystems = ["claude", "agno", "openai", "gemini", "custom", "omni-internal"];
71345
71348
  agentEntityTypes = ["assistant", "workflow", "team", "tool"];
71346
- debounceMode = ["disabled", "fixed", "randomized"];
71349
+ debounceMode = ["disabled", "fixed", "randomized", "presence"];
71347
71350
  splitDelayMode = ["disabled", "fixed", "randomized"];
71348
71351
  replyFilterMode = ["all", "filtered"];
71349
71352
  agentSessionStrategies = ["per_user", "per_chat", "per_thread"];
@@ -71479,6 +71482,7 @@ var init_schema2 = __esm(() => {
71479
71482
  messageDebounceMaxMs: integer("message_debounce_max_ms"),
71480
71483
  messageDebounceGroupMs: integer("message_debounce_group_ms"),
71481
71484
  messageDebounceRestartOnTyping: boolean("message_debounce_restart_on_typing"),
71485
+ messageDebounceMaxWaitMs: integer("message_debounce_max_wait_ms"),
71482
71486
  messageSplitDelayMode: varchar("message_split_delay_mode", { length: 20 }).$type(),
71483
71487
  messageSplitDelayFixedMs: integer("message_split_delay_fixed_ms"),
71484
71488
  messageSplitDelayMinMs: integer("message_split_delay_min_ms"),
@@ -71632,6 +71636,7 @@ var init_schema2 = __esm(() => {
71632
71636
  messageDebounceGroupMs: integer("message_debounce_group_ms"),
71633
71637
  messageDebounceMaxMs: integer("message_debounce_max_ms").notNull().default(0),
71634
71638
  messageDebounceRestartOnTyping: boolean("message_debounce_restart_on_typing").notNull().default(false),
71639
+ messageDebounceMaxWaitMs: integer("message_debounce_max_wait_ms"),
71635
71640
  agentGateEnabled: boolean("agent_gate_enabled").notNull().default(false),
71636
71641
  agentGateModel: varchar("agent_gate_model", { length: 120 }),
71637
71642
  agentGatePrompt: text("agent_gate_prompt"),
@@ -125004,7 +125009,7 @@ import { fileURLToPath } from "url";
125004
125009
  // package.json
125005
125010
  var package_default = {
125006
125011
  name: "@automagik/omni",
125007
- version: "2.260703.1",
125012
+ version: "2.260703.3",
125008
125013
  description: "LLM-optimized CLI for Omni",
125009
125014
  type: "module",
125010
125015
  bin: {
@@ -132527,6 +132532,8 @@ function applyDebounceFields(body, opts) {
132527
132532
  setBool(body, "messageDebounceRestartOnTyping", opts.debounceRestartOnTyping);
132528
132533
  if (opts.debounceGroup !== undefined)
132529
132534
  body.messageDebounceGroupMs = opts.debounceGroup;
132535
+ if (opts.debounceMaxWait !== undefined)
132536
+ body.messageDebounceMaxWaitMs = opts.debounceMaxWait;
132530
132537
  }
132531
132538
  function applySplitDelayFields(body, opts) {
132532
132539
  setVal(body, "messageSplitDelayMode", opts.splitDelayMode);
@@ -132675,7 +132682,7 @@ function createInstancesCommand() {
132675
132682
  error(`Failed to get instance: ${message}`, undefined, 3);
132676
132683
  }
132677
132684
  });
132678
- 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, or randomized").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("--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("--is-default", "Set as default instance for channel").action(async (options) => {
132685
+ 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("--is-default", "Set as default instance for channel").action(async (options) => {
132679
132686
  const channel = options.channel;
132680
132687
  if (!VALID_CHANNELS2.includes(channel)) {
132681
132688
  error(`Invalid channel: ${channel}`, { validChannels: VALID_CHANNELS2 });
@@ -132943,7 +132950,7 @@ function createInstancesCommand() {
132943
132950
  throw new Error(err?.error?.message ?? `HTTP ${response.status}`);
132944
132951
  }
132945
132952
  }
132946
- 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, or randomized").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("--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).").action(async (rawId, options) => {
132953
+ 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).").action(async (rawId, options) => {
132947
132954
  const client = getClient();
132948
132955
  try {
132949
132956
  const id = await resolveInstanceId(rawId);
@@ -3789,7 +3789,7 @@ export interface components {
3789
3789
  * @description Debounce mode override
3790
3790
  * @enum {string|null}
3791
3791
  */
3792
- messageDebounceMode: "disabled" | "fixed" | "randomized" | null;
3792
+ messageDebounceMode: "disabled" | "fixed" | "randomized" | "presence" | null;
3793
3793
  /** @description Debounce min delay (ms) override */
3794
3794
  messageDebounceMinMs: number | null;
3795
3795
  /** @description Debounce max delay (ms) override */
@@ -3798,6 +3798,8 @@ export interface components {
3798
3798
  messageDebounceGroupMs: number | null;
3799
3799
  /** @description Restart debounce on typing override */
3800
3800
  messageDebounceRestartOnTyping: boolean | null;
3801
+ /** @description Presence-mode hard cap (ms) override; null = no cap */
3802
+ messageDebounceMaxWaitMs: number | null;
3801
3803
  /**
3802
3804
  * @description Split delay mode override
3803
3805
  * @enum {string|null}
@@ -3907,7 +3909,7 @@ export interface components {
3907
3909
  * @description Debounce mode
3908
3910
  * @enum {string}
3909
3911
  */
3910
- messageDebounceMode?: "disabled" | "fixed" | "randomized";
3912
+ messageDebounceMode?: "disabled" | "fixed" | "randomized" | "presence";
3911
3913
  /** @description Debounce min delay (ms) */
3912
3914
  messageDebounceMinMs?: number;
3913
3915
  /** @description Debounce max delay (ms) */
@@ -3916,6 +3918,8 @@ export interface components {
3916
3918
  messageDebounceGroupMs?: number;
3917
3919
  /** @description Restart debounce on typing */
3918
3920
  messageDebounceRestartOnTyping?: boolean;
3921
+ /** @description Presence-mode hard cap (ms); null = no cap */
3922
+ messageDebounceMaxWaitMs?: number;
3919
3923
  /**
3920
3924
  * @description Split delay mode
3921
3925
  * @enum {string}
@@ -4006,7 +4010,7 @@ export interface components {
4006
4010
  * @description Debounce mode
4007
4011
  * @enum {string|null}
4008
4012
  */
4009
- messageDebounceMode?: "disabled" | "fixed" | "randomized" | null;
4013
+ messageDebounceMode?: "disabled" | "fixed" | "randomized" | "presence" | null;
4010
4014
  /** @description Debounce min delay (ms) */
4011
4015
  messageDebounceMinMs?: number | null;
4012
4016
  /** @description Debounce max delay (ms) */
@@ -4015,6 +4019,8 @@ export interface components {
4015
4019
  messageDebounceGroupMs?: number | null;
4016
4020
  /** @description Restart debounce on typing */
4017
4021
  messageDebounceRestartOnTyping?: boolean | null;
4022
+ /** @description Presence-mode hard cap (ms); null = no cap */
4023
+ messageDebounceMaxWaitMs?: number | null;
4018
4024
  /**
4019
4025
  * @description Split delay mode
4020
4026
  * @enum {string|null}
@@ -11571,7 +11577,7 @@ export interface operations {
11571
11577
  * @description Debounce mode override
11572
11578
  * @enum {string|null}
11573
11579
  */
11574
- messageDebounceMode: "disabled" | "fixed" | "randomized" | null;
11580
+ messageDebounceMode: "disabled" | "fixed" | "randomized" | "presence" | null;
11575
11581
  /** @description Debounce min delay (ms) override */
11576
11582
  messageDebounceMinMs: number | null;
11577
11583
  /** @description Debounce max delay (ms) override */
@@ -11580,6 +11586,8 @@ export interface operations {
11580
11586
  messageDebounceGroupMs: number | null;
11581
11587
  /** @description Restart debounce on typing override */
11582
11588
  messageDebounceRestartOnTyping: boolean | null;
11589
+ /** @description Presence-mode hard cap (ms) override; null = no cap */
11590
+ messageDebounceMaxWaitMs: number | null;
11583
11591
  /**
11584
11592
  * @description Split delay mode override
11585
11593
  * @enum {string|null}
@@ -11726,7 +11734,7 @@ export interface operations {
11726
11734
  * @description Debounce mode
11727
11735
  * @enum {string}
11728
11736
  */
11729
- messageDebounceMode?: "disabled" | "fixed" | "randomized";
11737
+ messageDebounceMode?: "disabled" | "fixed" | "randomized" | "presence";
11730
11738
  /** @description Debounce min delay (ms) */
11731
11739
  messageDebounceMinMs?: number;
11732
11740
  /** @description Debounce max delay (ms) */
@@ -11735,6 +11743,8 @@ export interface operations {
11735
11743
  messageDebounceGroupMs?: number;
11736
11744
  /** @description Restart debounce on typing */
11737
11745
  messageDebounceRestartOnTyping?: boolean;
11746
+ /** @description Presence-mode hard cap (ms); null = no cap */
11747
+ messageDebounceMaxWaitMs?: number;
11738
11748
  /**
11739
11749
  * @description Split delay mode
11740
11750
  * @enum {string}
@@ -11860,7 +11870,7 @@ export interface operations {
11860
11870
  * @description Debounce mode override
11861
11871
  * @enum {string|null}
11862
11872
  */
11863
- messageDebounceMode: "disabled" | "fixed" | "randomized" | null;
11873
+ messageDebounceMode: "disabled" | "fixed" | "randomized" | "presence" | null;
11864
11874
  /** @description Debounce min delay (ms) override */
11865
11875
  messageDebounceMinMs: number | null;
11866
11876
  /** @description Debounce max delay (ms) override */
@@ -11869,6 +11879,8 @@ export interface operations {
11869
11879
  messageDebounceGroupMs: number | null;
11870
11880
  /** @description Restart debounce on typing override */
11871
11881
  messageDebounceRestartOnTyping: boolean | null;
11882
+ /** @description Presence-mode hard cap (ms) override; null = no cap */
11883
+ messageDebounceMaxWaitMs: number | null;
11872
11884
  /**
11873
11885
  * @description Split delay mode override
11874
11886
  * @enum {string|null}
@@ -12075,7 +12087,7 @@ export interface operations {
12075
12087
  * @description Debounce mode override
12076
12088
  * @enum {string|null}
12077
12089
  */
12078
- messageDebounceMode: "disabled" | "fixed" | "randomized" | null;
12090
+ messageDebounceMode: "disabled" | "fixed" | "randomized" | "presence" | null;
12079
12091
  /** @description Debounce min delay (ms) override */
12080
12092
  messageDebounceMinMs: number | null;
12081
12093
  /** @description Debounce max delay (ms) override */
@@ -12084,6 +12096,8 @@ export interface operations {
12084
12096
  messageDebounceGroupMs: number | null;
12085
12097
  /** @description Restart debounce on typing override */
12086
12098
  messageDebounceRestartOnTyping: boolean | null;
12099
+ /** @description Presence-mode hard cap (ms) override; null = no cap */
12100
+ messageDebounceMaxWaitMs: number | null;
12087
12101
  /**
12088
12102
  * @description Split delay mode override
12089
12103
  * @enum {string|null}
@@ -12304,7 +12318,7 @@ export interface operations {
12304
12318
  * @description Debounce mode
12305
12319
  * @enum {string|null}
12306
12320
  */
12307
- messageDebounceMode?: "disabled" | "fixed" | "randomized" | null;
12321
+ messageDebounceMode?: "disabled" | "fixed" | "randomized" | "presence" | null;
12308
12322
  /** @description Debounce min delay (ms) */
12309
12323
  messageDebounceMinMs?: number | null;
12310
12324
  /** @description Debounce max delay (ms) */
@@ -12313,6 +12327,8 @@ export interface operations {
12313
12327
  messageDebounceGroupMs?: number | null;
12314
12328
  /** @description Restart debounce on typing */
12315
12329
  messageDebounceRestartOnTyping?: boolean | null;
12330
+ /** @description Presence-mode hard cap (ms); null = no cap */
12331
+ messageDebounceMaxWaitMs?: number | null;
12316
12332
  /**
12317
12333
  * @description Split delay mode
12318
12334
  * @enum {string|null}
@@ -12432,7 +12448,7 @@ export interface operations {
12432
12448
  * @description Debounce mode override
12433
12449
  * @enum {string|null}
12434
12450
  */
12435
- messageDebounceMode: "disabled" | "fixed" | "randomized" | null;
12451
+ messageDebounceMode: "disabled" | "fixed" | "randomized" | "presence" | null;
12436
12452
  /** @description Debounce min delay (ms) override */
12437
12453
  messageDebounceMinMs: number | null;
12438
12454
  /** @description Debounce max delay (ms) override */
@@ -12441,6 +12457,8 @@ export interface operations {
12441
12457
  messageDebounceGroupMs: number | null;
12442
12458
  /** @description Restart debounce on typing override */
12443
12459
  messageDebounceRestartOnTyping: boolean | null;
12460
+ /** @description Presence-mode hard cap (ms) override; null = no cap */
12461
+ messageDebounceMaxWaitMs: number | null;
12444
12462
  /**
12445
12463
  * @description Split delay mode override
12446
12464
  * @enum {string|null}