@automagik/omni 2.260409.4 → 2.260409.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/db/drizzle/0016_instance_fallback_config.sql +3 -0
- package/db/drizzle/0017_drop_agent_fallback.sql +3 -0
- package/db/drizzle/meta/0016_snapshot.json +7045 -0
- package/db/drizzle/meta/0017_snapshot.json +7032 -0
- package/db/drizzle/meta/_journal.json +14 -0
- package/dist/commands/instances.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/server/index.js +28 -36
- package/package.json +1 -1
|
@@ -113,6 +113,20 @@
|
|
|
113
113
|
"when": 1775404179968,
|
|
114
114
|
"tag": "0015_burly_trauma",
|
|
115
115
|
"breakpoints": true
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"idx": 16,
|
|
119
|
+
"version": "7",
|
|
120
|
+
"when": 1775767816830,
|
|
121
|
+
"tag": "0016_instance_fallback_config",
|
|
122
|
+
"breakpoints": true
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"idx": 17,
|
|
126
|
+
"version": "7",
|
|
127
|
+
"when": 1775772342374,
|
|
128
|
+
"tag": "0017_drop_agent_fallback",
|
|
129
|
+
"breakpoints": true
|
|
116
130
|
}
|
|
117
131
|
]
|
|
118
132
|
}
|
|
@@ -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;
|
|
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;AAgKpC,wBAAgB,sBAAsB,IAAI,OAAO,CAgoChD"}
|
package/dist/index.js
CHANGED
|
@@ -76972,7 +76972,7 @@ import { fileURLToPath } from "url";
|
|
|
76972
76972
|
// package.json
|
|
76973
76973
|
var package_default = {
|
|
76974
76974
|
name: "@automagik/omni",
|
|
76975
|
-
version: "2.260409.
|
|
76975
|
+
version: "2.260409.6",
|
|
76976
76976
|
description: "LLM-optimized CLI for Omni",
|
|
76977
76977
|
type: "module",
|
|
76978
76978
|
bin: {
|
|
@@ -80766,7 +80766,7 @@ function getMediaType(path) {
|
|
|
80766
80766
|
}
|
|
80767
80767
|
async function closeTurn(client, action, successMsg, reason) {
|
|
80768
80768
|
try {
|
|
80769
|
-
const turnId = process.env.OMNI_TURN_ID;
|
|
80769
|
+
const turnId = process.env.OMNI_TURN_ID || undefined;
|
|
80770
80770
|
const extraHeaders = {};
|
|
80771
80771
|
if (process.env.OMNI_INSTANCE)
|
|
80772
80772
|
extraHeaders["x-omni-instance"] = process.env.OMNI_INSTANCE;
|
|
@@ -82847,6 +82847,11 @@ function applyAckFields(body, opts) {
|
|
|
82847
82847
|
body.ackTimeoutMs = Number(opts.ackTimeout);
|
|
82848
82848
|
}
|
|
82849
82849
|
}
|
|
82850
|
+
function applyStalledFields(body, opts) {
|
|
82851
|
+
if (opts.agentStalledTimeoutMs !== undefined) {
|
|
82852
|
+
body.agentStalledTimeoutMs = Number(opts.agentStalledTimeoutMs);
|
|
82853
|
+
}
|
|
82854
|
+
}
|
|
82850
82855
|
function buildInstanceBody(opts) {
|
|
82851
82856
|
const body = {};
|
|
82852
82857
|
applyAgentFields(body, opts);
|
|
@@ -82856,6 +82861,7 @@ function buildInstanceBody(opts) {
|
|
|
82856
82861
|
applyGateFields(body, opts);
|
|
82857
82862
|
applyMiscFields(body, opts);
|
|
82858
82863
|
applyAckFields(body, opts);
|
|
82864
|
+
applyStalledFields(body, opts);
|
|
82859
82865
|
return body;
|
|
82860
82866
|
}
|
|
82861
82867
|
async function resolveBase64Image(options) {
|
|
@@ -82932,7 +82938,7 @@ function createInstancesCommand() {
|
|
|
82932
82938
|
error(`Failed to get instance: ${message}`, undefined, 3);
|
|
82933
82939
|
}
|
|
82934
82940
|
});
|
|
82935
|
-
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)').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("--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("--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("--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-api-key <key>", "Gupshup API key").option("--gupshup-app-name <name>", "Gupshup app name").option("--gupshup-source-phone <phone>", "Gupshup source phone (E.164)").option("--gupshup-webhook-verify-token <token>", "Gupshup webhook verify token").option("--is-default", "Set as default instance for channel").action(async (options) => {
|
|
82941
|
+
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)').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("--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("--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-api-key <key>", "Gupshup API key").option("--gupshup-app-name <name>", "Gupshup app name").option("--gupshup-source-phone <phone>", "Gupshup source phone (E.164)").option("--gupshup-webhook-verify-token <token>", "Gupshup webhook verify token").option("--is-default", "Set as default instance for channel").action(async (options) => {
|
|
82936
82942
|
const channel = options.channel;
|
|
82937
82943
|
if (!VALID_CHANNELS2.includes(channel)) {
|
|
82938
82944
|
error(`Invalid channel: ${channel}`, { validChannels: VALID_CHANNELS2 });
|
|
@@ -83193,7 +83199,7 @@ function createInstancesCommand() {
|
|
|
83193
83199
|
throw new Error(err?.error?.message ?? `HTTP ${response.status}`);
|
|
83194
83200
|
}
|
|
83195
83201
|
}
|
|
83196
|
-
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)').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("--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("--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("--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("--trigger-events <events>", 'Trigger events (comma-separated, use "null" to clear)').option("--profile-name <name>", "Update WhatsApp display name (push name)").action(async (rawId, options) => {
|
|
83202
|
+
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)').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("--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("--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("--trigger-events <events>", 'Trigger events (comma-separated, use "null" to clear)').option("--profile-name <name>", "Update WhatsApp display name (push name)").action(async (rawId, options) => {
|
|
83197
83203
|
const client = getClient();
|
|
83198
83204
|
try {
|
|
83199
83205
|
const id = await resolveInstanceId(rawId);
|
package/dist/server/index.js
CHANGED
|
@@ -222829,7 +222829,7 @@ var init_sentry_scrub = __esm(() => {
|
|
|
222829
222829
|
var require_package8 = __commonJS((exports, module) => {
|
|
222830
222830
|
module.exports = {
|
|
222831
222831
|
name: "@omni/api",
|
|
222832
|
-
version: "2.260409.
|
|
222832
|
+
version: "2.260409.6",
|
|
222833
222833
|
type: "module",
|
|
222834
222834
|
exports: {
|
|
222835
222835
|
".": {
|
|
@@ -228600,6 +228600,7 @@ var init_schema2 = __esm(() => {
|
|
|
228600
228600
|
lastMessageAt: timestamp("last_message_at"),
|
|
228601
228601
|
replayEnabled: boolean("replay_enabled").notNull().default(true),
|
|
228602
228602
|
lastSeenAt: timestamp("last_seen_at"),
|
|
228603
|
+
agentStalledTimeoutMs: integer("agent_stalled_timeout_ms").notNull().default(600000),
|
|
228603
228604
|
agentChainToInstanceId: uuid("agent_chain_to_instance_id").references(() => instances.id, {
|
|
228604
228605
|
onDelete: "set null"
|
|
228605
228606
|
}),
|
|
@@ -359213,7 +359214,8 @@ var init_instances3 = __esm(() => {
|
|
|
359213
359214
|
markOnlineOnConnect: exports_external.boolean().default(true).describe("Mark the instance as online when connecting to WhatsApp (default: true). Set to false to preserve phone push notifications."),
|
|
359214
359215
|
reactionAck: exports_external.enum(["on", "off"]).default("off").describe("Reaction ack mode: on to send a reaction while agent processes"),
|
|
359215
359216
|
reactionAckEmoji: exports_external.record(exports_external.string()).optional().nullable().describe('Per-channel emoji map for reaction ack (e.g. {"whatsapp":"\\u2705"})'),
|
|
359216
|
-
ackTimeoutMs: exports_external.number().int().min(0).max(120000).default(30000).describe("Ack timeout in milliseconds (max 120000)")
|
|
359217
|
+
ackTimeoutMs: exports_external.number().int().min(0).max(120000).default(30000).describe("Ack timeout in milliseconds (max 120000)"),
|
|
359218
|
+
agentStalledTimeoutMs: exports_external.number().int().min(0).default(600000).describe("Idle threshold in ms before the internal turn.stalled event fires (no channel message is ever sent)")
|
|
359217
359219
|
});
|
|
359218
359220
|
updateInstanceSchema = createInstanceSchema.partial().extend({
|
|
359219
359221
|
agentId: exports_external.string().uuid().nullable().optional(),
|
|
@@ -359232,7 +359234,8 @@ var init_instances3 = __esm(() => {
|
|
|
359232
359234
|
groupHistorySize: exports_external.number().int().min(0).max(200).optional(),
|
|
359233
359235
|
reactionAck: exports_external.enum(["on", "off"]).optional(),
|
|
359234
359236
|
reactionAckEmoji: exports_external.record(exports_external.string()).nullable().optional(),
|
|
359235
|
-
ackTimeoutMs: exports_external.number().int().min(0).max(120000).optional()
|
|
359237
|
+
ackTimeoutMs: exports_external.number().int().min(0).max(120000).optional(),
|
|
359238
|
+
agentStalledTimeoutMs: exports_external.number().int().min(0).optional()
|
|
359236
359239
|
});
|
|
359237
359240
|
SENSITIVE_INSTANCE_FIELDS = [
|
|
359238
359241
|
"telegramBotToken",
|
|
@@ -362075,11 +362078,14 @@ var init_messages5 = __esm(() => {
|
|
|
362075
362078
|
});
|
|
362076
362079
|
}
|
|
362077
362080
|
const resolvedTo = await resolveRecipient(to, instance4.channel, services);
|
|
362081
|
+
let fromMe = false;
|
|
362078
362082
|
const chat2 = await services.chats.findByExternalIdSmart(instanceId, resolvedTo);
|
|
362079
362083
|
if (chat2) {
|
|
362080
362084
|
const target = await services.messages.getByExternalId(chat2.id, messageId);
|
|
362081
362085
|
if (!target) {
|
|
362082
362086
|
log90.warn("Target message not found in DB, sending reaction anyway", { messageId, chatId: chat2.id });
|
|
362087
|
+
} else {
|
|
362088
|
+
fromMe = target.isFromMe === true;
|
|
362083
362089
|
}
|
|
362084
362090
|
}
|
|
362085
362091
|
const outgoingMessage = {
|
|
@@ -362088,7 +362094,8 @@ var init_messages5 = __esm(() => {
|
|
|
362088
362094
|
type: "reaction",
|
|
362089
362095
|
emoji,
|
|
362090
362096
|
targetMessageId: messageId
|
|
362091
|
-
}
|
|
362097
|
+
},
|
|
362098
|
+
metadata: { fromMe }
|
|
362092
362099
|
};
|
|
362093
362100
|
const result = await plugin6.sendMessage(instanceId, outgoingMessage);
|
|
362094
362101
|
if (!result.success) {
|
|
@@ -363538,6 +363545,11 @@ function publishTurnNudge(instanceId, chatId, event) {
|
|
|
363538
363545
|
publish(topic, event);
|
|
363539
363546
|
log91.debug("Published turn.nudge", { turnId: event.turnId, nudgeCount: event.nudgeCount, instanceId });
|
|
363540
363547
|
}
|
|
363548
|
+
function publishTurnStalled(instanceId, chatId, event) {
|
|
363549
|
+
const topic = `omni.turn.stalled.${instanceId}.${chatId}`;
|
|
363550
|
+
publish(topic, event);
|
|
363551
|
+
log91.debug("Published turn.stalled", { turnId: event.turnId, instanceId, chatId });
|
|
363552
|
+
}
|
|
363541
363553
|
function publishTurnTimeout(instanceId, chatId, event) {
|
|
363542
363554
|
const topic = `omni.turn.timeout.${instanceId}.${chatId}`;
|
|
363543
363555
|
publish(topic, event);
|
|
@@ -369755,7 +369767,7 @@ class TurnMonitor {
|
|
|
369755
369767
|
log102.info("Turn monitor started", {
|
|
369756
369768
|
pollIntervalMs: POLL_INTERVAL_MS2,
|
|
369757
369769
|
nudgeMs: NUDGE_THRESHOLD_MS,
|
|
369758
|
-
|
|
369770
|
+
defaultStalledMs: DEFAULT_STALLED_THRESHOLD_MS,
|
|
369759
369771
|
timeoutMs: TIMEOUT_THRESHOLD_MS
|
|
369760
369772
|
});
|
|
369761
369773
|
this.intervalId = setInterval(() => this.tick(), POLL_INTERVAL_MS2);
|
|
@@ -369780,8 +369792,10 @@ class TurnMonitor {
|
|
|
369780
369792
|
await this.handleTimeout(turn.id, turn.instanceId, turn.chatId, idleSec, turn.nudgeCount);
|
|
369781
369793
|
continue;
|
|
369782
369794
|
}
|
|
369783
|
-
|
|
369784
|
-
|
|
369795
|
+
const instance4 = await this.deps.instanceService.getById(turn.instanceId).catch(() => null);
|
|
369796
|
+
const stalledThresholdMs = instance4?.agentStalledTimeoutMs ?? DEFAULT_STALLED_THRESHOLD_MS;
|
|
369797
|
+
if (idleMs >= stalledThresholdMs && turn.nudgeCount === 2) {
|
|
369798
|
+
await this.handleStalled(turn.id, turn.instanceId, turn.chatId, idleMs, stalledThresholdMs);
|
|
369785
369799
|
continue;
|
|
369786
369800
|
}
|
|
369787
369801
|
const expectedNudges = Math.floor(idleMs / NUDGE_THRESHOLD_MS);
|
|
@@ -369805,16 +369819,11 @@ class TurnMonitor {
|
|
|
369805
369819
|
});
|
|
369806
369820
|
log102.info("Turn nudge emitted", { turnId, nudgeCount, idleSec });
|
|
369807
369821
|
}
|
|
369808
|
-
async
|
|
369822
|
+
async handleStalled(turnId, instanceId, chatId, stalledAtMs, threshold) {
|
|
369809
369823
|
await this.deps.turnService.incrementNudge(turnId);
|
|
369810
|
-
|
|
369811
|
-
|
|
369812
|
-
|
|
369813
|
-
log102.info("Fallback message sent", { turnId, idleSec });
|
|
369814
|
-
} catch (error2) {
|
|
369815
|
-
log102.error("Failed to send fallback message", { turnId, error: String(error2) });
|
|
369816
|
-
}
|
|
369817
|
-
}
|
|
369824
|
+
const payload = { turnId, instanceId, chatId, stalledAtMs, threshold };
|
|
369825
|
+
publishTurnStalled(instanceId, chatId, payload);
|
|
369826
|
+
log102.warn("Turn stalled \u2014 internal event emitted (no channel message sent)", payload);
|
|
369818
369827
|
}
|
|
369819
369828
|
async handleTimeout(turnId, instanceId, chatId, idleSec, nudgeCount) {
|
|
369820
369829
|
const closed = await this.deps.turnService.close(turnId, {
|
|
@@ -369824,19 +369833,10 @@ class TurnMonitor {
|
|
|
369824
369833
|
if (!closed)
|
|
369825
369834
|
return;
|
|
369826
369835
|
const duration = closed.closedAt ? closed.closedAt.getTime() - closed.startedAt.getTime() : idleSec * 1000;
|
|
369827
|
-
const fallbackSent = !!this.deps.sendFallback;
|
|
369828
|
-
if (this.deps.sendFallback) {
|
|
369829
|
-
try {
|
|
369830
|
-
await this.deps.sendFallback(instanceId, chatId, "\u23F1 Request timed out. Please try again.");
|
|
369831
|
-
} catch (error2) {
|
|
369832
|
-
log102.error("Failed to send timeout fallback", { turnId, error: String(error2) });
|
|
369833
|
-
}
|
|
369834
|
-
}
|
|
369835
369836
|
publishTurnTimeout(instanceId, chatId, {
|
|
369836
369837
|
turnId,
|
|
369837
369838
|
duration,
|
|
369838
|
-
nudgeCount
|
|
369839
|
-
fallbackSent
|
|
369839
|
+
nudgeCount
|
|
369840
369840
|
});
|
|
369841
369841
|
publishTurnDone(instanceId, chatId, {
|
|
369842
369842
|
turnId,
|
|
@@ -369849,7 +369849,7 @@ class TurnMonitor {
|
|
|
369849
369849
|
log102.info("Turn force-closed (timeout)", { turnId, duration, nudgeCount });
|
|
369850
369850
|
}
|
|
369851
369851
|
}
|
|
369852
|
-
var log102, NUDGE_THRESHOLD_MS = 120000,
|
|
369852
|
+
var log102, NUDGE_THRESHOLD_MS = 120000, DEFAULT_STALLED_THRESHOLD_MS = 600000, TIMEOUT_THRESHOLD_MS = 1800000, POLL_INTERVAL_MS2 = 1e4;
|
|
369853
369853
|
var init_turn_monitor = __esm(() => {
|
|
369854
369854
|
init_src();
|
|
369855
369855
|
init_turn_events();
|
|
@@ -370152,15 +370152,7 @@ async function setupEventBusServices(eventBus, services, db3) {
|
|
|
370152
370152
|
try {
|
|
370153
370153
|
globalTurnMonitor = new TurnMonitor({
|
|
370154
370154
|
turnService: services.turns,
|
|
370155
|
-
|
|
370156
|
-
const instance4 = await services.instances.getById(instanceId);
|
|
370157
|
-
if (!instance4)
|
|
370158
|
-
return;
|
|
370159
|
-
const plugin6 = await getPlugin(instance4.channel);
|
|
370160
|
-
if (!plugin6)
|
|
370161
|
-
return;
|
|
370162
|
-
await plugin6.sendMessage(instanceId, { to: chatId, content: { type: "text", text: text3 } });
|
|
370163
|
-
}
|
|
370155
|
+
instanceService: services.instances
|
|
370164
370156
|
});
|
|
370165
370157
|
globalTurnMonitor.start();
|
|
370166
370158
|
log104.info("Turn monitor started");
|