metheus-governance-mcp-cli 0.2.256 → 0.2.258
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/cli.mjs +2247 -2240
- package/lib/runner-delivery.mjs +1 -5
- package/lib/runner-orchestration.mjs +696 -713
- package/lib/selftest-runner-scenarios.mjs +3507 -3507
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -133,21 +133,21 @@ import {
|
|
|
133
133
|
tryRegister,
|
|
134
134
|
withWorkspaceDirArg,
|
|
135
135
|
} from "./lib/client-registration.mjs";
|
|
136
|
-
import {
|
|
137
|
-
applyPendingAgeSelection,
|
|
138
|
-
buildTelegramBotReplyEnvelope,
|
|
139
|
-
buildTelegramMessageEnvelopeFromParsedArchive as buildRunnerTelegramMessageEnvelopeFromParsedArchive,
|
|
140
|
-
buildRunnerRouteStateFromComment,
|
|
141
|
-
buildProcessableArchiveLogicalKey,
|
|
142
|
-
findEarlierProcessableArchiveDuplicate,
|
|
143
|
-
findRecentTelegramMessageEnvelope,
|
|
144
|
-
isTelegramLocalInboundEnvelopeForRoute,
|
|
145
|
-
isInboundArchiveKind,
|
|
146
|
-
normalizeTelegramMessageEnvelope as normalizeRunnerTelegramMessageEnvelope,
|
|
147
|
-
normalizeArchiveCommentRecord,
|
|
148
|
-
selectPendingArchiveComments,
|
|
149
|
-
printRunnerResult,
|
|
150
|
-
} from "./lib/runner-helpers.mjs";
|
|
136
|
+
import {
|
|
137
|
+
applyPendingAgeSelection,
|
|
138
|
+
buildTelegramBotReplyEnvelope,
|
|
139
|
+
buildTelegramMessageEnvelopeFromParsedArchive as buildRunnerTelegramMessageEnvelopeFromParsedArchive,
|
|
140
|
+
buildRunnerRouteStateFromComment,
|
|
141
|
+
buildProcessableArchiveLogicalKey,
|
|
142
|
+
findEarlierProcessableArchiveDuplicate,
|
|
143
|
+
findRecentTelegramMessageEnvelope,
|
|
144
|
+
isTelegramLocalInboundEnvelopeForRoute,
|
|
145
|
+
isInboundArchiveKind,
|
|
146
|
+
normalizeTelegramMessageEnvelope as normalizeRunnerTelegramMessageEnvelope,
|
|
147
|
+
normalizeArchiveCommentRecord,
|
|
148
|
+
selectPendingArchiveComments,
|
|
149
|
+
printRunnerResult,
|
|
150
|
+
} from "./lib/runner-helpers.mjs";
|
|
151
151
|
import {
|
|
152
152
|
createProjectContextItem as createProjectContextItemImpl,
|
|
153
153
|
createProjectEvidence as createProjectEvidenceImpl,
|
|
@@ -186,30 +186,30 @@ import {
|
|
|
186
186
|
resolveRunnerWorkspaceSelection,
|
|
187
187
|
runRunnerAIExecution,
|
|
188
188
|
} from "./lib/runner-execution.mjs";
|
|
189
|
-
import {
|
|
190
|
-
buildRunnerResponderAdjudicationFromConversationContext,
|
|
191
|
-
buildRunnerResponderAdjudicationFromHumanIntent,
|
|
192
|
-
processRunnerSelectedRecord,
|
|
193
|
-
resolveHumanIntentContext,
|
|
194
|
-
resolvePublicConversationContext,
|
|
195
|
-
resolveRunnerHumanInboundVisibility,
|
|
196
|
-
resolveRunnerResponderAdjudication,
|
|
197
|
-
resolveRunnerStartupLoopAdjudication,
|
|
198
|
-
selectRunnerPendingWork,
|
|
199
|
-
} from "./lib/runner-orchestration.mjs";
|
|
189
|
+
import {
|
|
190
|
+
buildRunnerResponderAdjudicationFromConversationContext,
|
|
191
|
+
buildRunnerResponderAdjudicationFromHumanIntent,
|
|
192
|
+
processRunnerSelectedRecord,
|
|
193
|
+
resolveHumanIntentContext,
|
|
194
|
+
resolvePublicConversationContext,
|
|
195
|
+
resolveRunnerHumanInboundVisibility,
|
|
196
|
+
resolveRunnerResponderAdjudication,
|
|
197
|
+
resolveRunnerStartupLoopAdjudication,
|
|
198
|
+
selectRunnerPendingWork,
|
|
199
|
+
} from "./lib/runner-orchestration.mjs";
|
|
200
200
|
import {
|
|
201
201
|
archiveLocalTelegramMessagesForRoute,
|
|
202
202
|
maybeSendRunnerChatAction,
|
|
203
203
|
startRunnerTypingHeartbeat,
|
|
204
204
|
} from "./lib/runner-runtime.mjs";
|
|
205
|
-
import {
|
|
206
|
-
deleteTelegramWebhook,
|
|
207
|
-
getTelegramBotMe,
|
|
208
|
-
getTelegramUpdates,
|
|
209
|
-
listTelegramChatAdministrators,
|
|
210
|
-
getTelegramWebhookInfo,
|
|
211
|
-
sendLocalProviderChatAction,
|
|
212
|
-
verifyLocalProviderToken,
|
|
205
|
+
import {
|
|
206
|
+
deleteTelegramWebhook,
|
|
207
|
+
getTelegramBotMe,
|
|
208
|
+
getTelegramUpdates,
|
|
209
|
+
listTelegramChatAdministrators,
|
|
210
|
+
getTelegramWebhookInfo,
|
|
211
|
+
sendLocalProviderChatAction,
|
|
212
|
+
verifyLocalProviderToken,
|
|
213
213
|
} from "./lib/provider-local-transport.mjs";
|
|
214
214
|
|
|
215
215
|
const DEFAULT_SITE_URL = "https://metheus.gesiaplatform.com";
|
|
@@ -1922,24 +1922,24 @@ function mergeRunnerStateRecords(preferred, fallback) {
|
|
|
1922
1922
|
}
|
|
1923
1923
|
return allowUndefined ? undefined : 0;
|
|
1924
1924
|
};
|
|
1925
|
-
const pickArrayField = (key, normalizer = (value) => String(value || "").trim()) => {
|
|
1926
|
-
if (hasOwn(primary, key)) {
|
|
1927
|
-
const value = uniqueOrderedStrings(ensureArray(primary[key]), normalizer).filter(Boolean);
|
|
1928
|
-
if (value.length) {
|
|
1929
|
-
return value;
|
|
1930
|
-
}
|
|
1931
|
-
}
|
|
1932
|
-
return uniqueOrderedStrings(ensureArray(secondary[key]), normalizer).filter(Boolean);
|
|
1933
|
-
};
|
|
1934
|
-
const pickObjectField = (key) => {
|
|
1935
|
-
if (hasOwn(primary, key)) {
|
|
1936
|
-
const value = safeObject(primary[key]);
|
|
1937
|
-
if (Object.keys(value).length) {
|
|
1938
|
-
return value;
|
|
1939
|
-
}
|
|
1940
|
-
}
|
|
1941
|
-
return safeObject(secondary[key]);
|
|
1942
|
-
};
|
|
1925
|
+
const pickArrayField = (key, normalizer = (value) => String(value || "").trim()) => {
|
|
1926
|
+
if (hasOwn(primary, key)) {
|
|
1927
|
+
const value = uniqueOrderedStrings(ensureArray(primary[key]), normalizer).filter(Boolean);
|
|
1928
|
+
if (value.length) {
|
|
1929
|
+
return value;
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
return uniqueOrderedStrings(ensureArray(secondary[key]), normalizer).filter(Boolean);
|
|
1933
|
+
};
|
|
1934
|
+
const pickObjectField = (key) => {
|
|
1935
|
+
if (hasOwn(primary, key)) {
|
|
1936
|
+
const value = safeObject(primary[key]);
|
|
1937
|
+
if (Object.keys(value).length) {
|
|
1938
|
+
return value;
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
return safeObject(secondary[key]);
|
|
1942
|
+
};
|
|
1943
1943
|
return {
|
|
1944
1944
|
last_processed_comment_id: pickStringField("last_processed_comment_id"),
|
|
1945
1945
|
last_processed_created_at: pickStringField("last_processed_created_at"),
|
|
@@ -1947,16 +1947,16 @@ function mergeRunnerStateRecords(preferred, fallback) {
|
|
|
1947
1947
|
last_source_kind: pickStringField("last_source_kind"),
|
|
1948
1948
|
last_error: pickStringField("last_error", { allowBlank: true }),
|
|
1949
1949
|
updated_at: firstNonEmptyString([primary.updated_at, secondary.updated_at, new Date().toISOString()]),
|
|
1950
|
-
last_action: pickStringField("last_action"),
|
|
1951
|
-
last_reason: pickStringField("last_reason"),
|
|
1952
|
-
last_trigger: pickStringField("last_trigger"),
|
|
1953
|
-
last_visibility_status: pickStringField("last_visibility_status"),
|
|
1954
|
-
last_visibility_reason: pickStringField("last_visibility_reason", { allowBlank: true }),
|
|
1955
|
-
last_visibility_source: pickStringField("last_visibility_source", { allowBlank: true }),
|
|
1956
|
-
last_reply_message_id: pickNumberField("last_reply_message_id", { allowUndefined: true }),
|
|
1957
|
-
last_conversation_id: pickStringField("last_conversation_id"),
|
|
1958
|
-
last_conversation_stage: pickStringField("last_conversation_stage"),
|
|
1959
|
-
last_speaker_bot_username: pickStringField("last_speaker_bot_username"),
|
|
1950
|
+
last_action: pickStringField("last_action"),
|
|
1951
|
+
last_reason: pickStringField("last_reason"),
|
|
1952
|
+
last_trigger: pickStringField("last_trigger"),
|
|
1953
|
+
last_visibility_status: pickStringField("last_visibility_status"),
|
|
1954
|
+
last_visibility_reason: pickStringField("last_visibility_reason", { allowBlank: true }),
|
|
1955
|
+
last_visibility_source: pickStringField("last_visibility_source", { allowBlank: true }),
|
|
1956
|
+
last_reply_message_id: pickNumberField("last_reply_message_id", { allowUndefined: true }),
|
|
1957
|
+
last_conversation_id: pickStringField("last_conversation_id"),
|
|
1958
|
+
last_conversation_stage: pickStringField("last_conversation_stage"),
|
|
1959
|
+
last_speaker_bot_username: pickStringField("last_speaker_bot_username"),
|
|
1960
1960
|
local_receive_mode: pickStringField("local_receive_mode"),
|
|
1961
1961
|
local_telegram_polling_ready: Boolean(primary.local_telegram_polling_ready || secondary.local_telegram_polling_ready),
|
|
1962
1962
|
local_telegram_webhook_cleared_url: pickStringField("local_telegram_webhook_cleared_url", { allowBlank: true }),
|
|
@@ -1989,16 +1989,16 @@ function mergeRunnerStateRecords(preferred, fallback) {
|
|
|
1989
1989
|
last_followup_response_contract_validation_reason: pickStringField("last_followup_response_contract_validation_reason"),
|
|
1990
1990
|
last_followup_assignment_validation_status: pickStringField("last_followup_assignment_validation_status"),
|
|
1991
1991
|
last_followup_assignment_validation_reason: pickStringField("last_followup_assignment_validation_reason"),
|
|
1992
|
-
last_followup_delivery_status: pickStringField("last_followup_delivery_status"),
|
|
1993
|
-
last_followup_archive_status: pickStringField("last_followup_archive_status"),
|
|
1994
|
-
last_followup_transport_error: pickStringField("last_followup_transport_error"),
|
|
1995
|
-
last_followup_archive_error: pickStringField("last_followup_archive_error"),
|
|
1996
|
-
last_followup_source_message_envelope: pickObjectField("last_followup_source_message_envelope"),
|
|
1997
|
-
last_followup_last_reply_message_envelope: pickObjectField("last_followup_last_reply_message_envelope"),
|
|
1998
|
-
last_followup_attempted_delivery_envelope: pickObjectField("last_followup_attempted_delivery_envelope"),
|
|
1999
|
-
recent_local_inbound_envelopes: pickObjectField("recent_local_inbound_envelopes"),
|
|
2000
|
-
last_candidate_bot_usernames: pickArrayField("last_candidate_bot_usernames", normalizeTelegramMentionUsername),
|
|
2001
|
-
last_contract_validation_targets: pickArrayField("last_contract_validation_targets", normalizeTelegramMentionUsername),
|
|
1992
|
+
last_followup_delivery_status: pickStringField("last_followup_delivery_status"),
|
|
1993
|
+
last_followup_archive_status: pickStringField("last_followup_archive_status"),
|
|
1994
|
+
last_followup_transport_error: pickStringField("last_followup_transport_error"),
|
|
1995
|
+
last_followup_archive_error: pickStringField("last_followup_archive_error"),
|
|
1996
|
+
last_followup_source_message_envelope: pickObjectField("last_followup_source_message_envelope"),
|
|
1997
|
+
last_followup_last_reply_message_envelope: pickObjectField("last_followup_last_reply_message_envelope"),
|
|
1998
|
+
last_followup_attempted_delivery_envelope: pickObjectField("last_followup_attempted_delivery_envelope"),
|
|
1999
|
+
recent_local_inbound_envelopes: pickObjectField("recent_local_inbound_envelopes"),
|
|
2000
|
+
last_candidate_bot_usernames: pickArrayField("last_candidate_bot_usernames", normalizeTelegramMentionUsername),
|
|
2001
|
+
last_contract_validation_targets: pickArrayField("last_contract_validation_targets", normalizeTelegramMentionUsername),
|
|
2002
2002
|
last_normalized_execution_contract_targets: pickArrayField("last_normalized_execution_contract_targets", normalizeTelegramMentionUsername),
|
|
2003
2003
|
last_normalized_execution_next_responders: pickArrayField("last_normalized_execution_next_responders", normalizeTelegramMentionUsername),
|
|
2004
2004
|
last_followup_execution_contract_targets: pickArrayField("last_followup_execution_contract_targets", normalizeTelegramMentionUsername),
|
|
@@ -2084,10 +2084,10 @@ function migrateBotRunnerStateRoutes(routes, runnerConfig) {
|
|
|
2084
2084
|
};
|
|
2085
2085
|
}
|
|
2086
2086
|
|
|
2087
|
-
function loadBotRunnerState() {
|
|
2088
|
-
const filePath = botRunnerStateFilePath();
|
|
2089
|
-
waitForBotRunnerStateLockRelease(filePath);
|
|
2090
|
-
try {
|
|
2087
|
+
function loadBotRunnerState() {
|
|
2088
|
+
const filePath = botRunnerStateFilePath();
|
|
2089
|
+
waitForBotRunnerStateLockRelease(filePath);
|
|
2090
|
+
try {
|
|
2091
2091
|
if (!fs.existsSync(filePath)) {
|
|
2092
2092
|
return {
|
|
2093
2093
|
filePath,
|
|
@@ -2137,102 +2137,102 @@ function loadBotRunnerState() {
|
|
|
2137
2137
|
remainingAnonymousKeys: [],
|
|
2138
2138
|
};
|
|
2139
2139
|
}
|
|
2140
|
-
}
|
|
2141
|
-
|
|
2142
|
-
function sleepSyncMs(delayMs) {
|
|
2143
|
-
const ms = Number(delayMs) || 0;
|
|
2144
|
-
if (!(ms > 0)) {
|
|
2145
|
-
return;
|
|
2146
|
-
}
|
|
2147
|
-
const sleepBuffer = new SharedArrayBuffer(4);
|
|
2148
|
-
const sleepArray = new Int32Array(sleepBuffer);
|
|
2149
|
-
Atomics.wait(sleepArray, 0, 0, ms);
|
|
2150
|
-
}
|
|
2151
|
-
|
|
2152
|
-
function botRunnerStateLockFilePath(filePath) {
|
|
2153
|
-
const normalizedPath = String(filePath || "").trim();
|
|
2154
|
-
return normalizedPath ? `${normalizedPath}.lock` : "";
|
|
2155
|
-
}
|
|
2156
|
-
|
|
2157
|
-
function tryReleaseStaleBotRunnerStateLock(lockPath, staleMs = 60000) {
|
|
2158
|
-
const normalizedPath = String(lockPath || "").trim();
|
|
2159
|
-
if (!normalizedPath) {
|
|
2160
|
-
return false;
|
|
2161
|
-
}
|
|
2162
|
-
try {
|
|
2163
|
-
const stats = fs.statSync(normalizedPath);
|
|
2164
|
-
const ageMs = Date.now() - Number(stats.mtimeMs || 0);
|
|
2165
|
-
if (Number.isFinite(ageMs) && ageMs >= staleMs) {
|
|
2166
|
-
fs.rmSync(normalizedPath, { force: true });
|
|
2167
|
-
return true;
|
|
2168
|
-
}
|
|
2169
|
-
} catch {}
|
|
2170
|
-
return false;
|
|
2171
|
-
}
|
|
2172
|
-
|
|
2173
|
-
function waitForBotRunnerStateLockRelease(filePath, timeoutMs = 5000, staleMs = 60000) {
|
|
2174
|
-
const lockPath = botRunnerStateLockFilePath(filePath);
|
|
2175
|
-
if (!lockPath) {
|
|
2176
|
-
return;
|
|
2177
|
-
}
|
|
2178
|
-
const deadlineMs = Date.now() + Math.max(0, Number(timeoutMs) || 0);
|
|
2179
|
-
while (fs.existsSync(lockPath)) {
|
|
2180
|
-
tryReleaseStaleBotRunnerStateLock(lockPath, staleMs);
|
|
2181
|
-
if (!fs.existsSync(lockPath)) {
|
|
2182
|
-
return;
|
|
2183
|
-
}
|
|
2184
|
-
if (Date.now() >= deadlineMs) {
|
|
2185
|
-
return;
|
|
2186
|
-
}
|
|
2187
|
-
sleepSyncMs(25);
|
|
2188
|
-
}
|
|
2189
|
-
}
|
|
2190
|
-
|
|
2191
|
-
function withBotRunnerStateFileLock(filePath, callback, timeoutMs = 5000, staleMs = 60000) {
|
|
2192
|
-
const lockPath = botRunnerStateLockFilePath(filePath);
|
|
2193
|
-
if (!lockPath) {
|
|
2194
|
-
return callback();
|
|
2195
|
-
}
|
|
2196
|
-
const deadlineMs = Date.now() + Math.max(0, Number(timeoutMs) || 0);
|
|
2197
|
-
let lockFD = null;
|
|
2198
|
-
while (lockFD === null) {
|
|
2199
|
-
try {
|
|
2200
|
-
lockFD = fs.openSync(lockPath, "wx");
|
|
2201
|
-
fs.writeFileSync(lockFD, `${process.pid} ${new Date().toISOString()}\n`, "utf8");
|
|
2202
|
-
break;
|
|
2203
|
-
} catch (error) {
|
|
2204
|
-
const errorCode = String(error?.code || "").trim().toUpperCase();
|
|
2205
|
-
if (!["EEXIST", "EPERM", "EBUSY"].includes(errorCode)) {
|
|
2206
|
-
throw error;
|
|
2207
|
-
}
|
|
2208
|
-
tryReleaseStaleBotRunnerStateLock(lockPath, staleMs);
|
|
2209
|
-
if (Date.now() >= deadlineMs) {
|
|
2210
|
-
throw error;
|
|
2211
|
-
}
|
|
2212
|
-
sleepSyncMs(25);
|
|
2213
|
-
}
|
|
2214
|
-
}
|
|
2215
|
-
try {
|
|
2216
|
-
return callback();
|
|
2217
|
-
} finally {
|
|
2218
|
-
try {
|
|
2219
|
-
if (lockFD !== null) {
|
|
2220
|
-
fs.closeSync(lockFD);
|
|
2221
|
-
}
|
|
2222
|
-
} catch {}
|
|
2223
|
-
try {
|
|
2224
|
-
if (fs.existsSync(lockPath)) {
|
|
2225
|
-
fs.rmSync(lockPath, { force: true });
|
|
2226
|
-
}
|
|
2227
|
-
} catch {}
|
|
2228
|
-
}
|
|
2229
|
-
}
|
|
2230
|
-
|
|
2231
|
-
function writeTextFileAtomic(filePath, text) {
|
|
2232
|
-
const normalizedPath = String(filePath || "").trim();
|
|
2233
|
-
if (!normalizedPath) {
|
|
2234
|
-
throw new Error("filePath is required");
|
|
2235
|
-
}
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
function sleepSyncMs(delayMs) {
|
|
2143
|
+
const ms = Number(delayMs) || 0;
|
|
2144
|
+
if (!(ms > 0)) {
|
|
2145
|
+
return;
|
|
2146
|
+
}
|
|
2147
|
+
const sleepBuffer = new SharedArrayBuffer(4);
|
|
2148
|
+
const sleepArray = new Int32Array(sleepBuffer);
|
|
2149
|
+
Atomics.wait(sleepArray, 0, 0, ms);
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
function botRunnerStateLockFilePath(filePath) {
|
|
2153
|
+
const normalizedPath = String(filePath || "").trim();
|
|
2154
|
+
return normalizedPath ? `${normalizedPath}.lock` : "";
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
function tryReleaseStaleBotRunnerStateLock(lockPath, staleMs = 60000) {
|
|
2158
|
+
const normalizedPath = String(lockPath || "").trim();
|
|
2159
|
+
if (!normalizedPath) {
|
|
2160
|
+
return false;
|
|
2161
|
+
}
|
|
2162
|
+
try {
|
|
2163
|
+
const stats = fs.statSync(normalizedPath);
|
|
2164
|
+
const ageMs = Date.now() - Number(stats.mtimeMs || 0);
|
|
2165
|
+
if (Number.isFinite(ageMs) && ageMs >= staleMs) {
|
|
2166
|
+
fs.rmSync(normalizedPath, { force: true });
|
|
2167
|
+
return true;
|
|
2168
|
+
}
|
|
2169
|
+
} catch {}
|
|
2170
|
+
return false;
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2173
|
+
function waitForBotRunnerStateLockRelease(filePath, timeoutMs = 5000, staleMs = 60000) {
|
|
2174
|
+
const lockPath = botRunnerStateLockFilePath(filePath);
|
|
2175
|
+
if (!lockPath) {
|
|
2176
|
+
return;
|
|
2177
|
+
}
|
|
2178
|
+
const deadlineMs = Date.now() + Math.max(0, Number(timeoutMs) || 0);
|
|
2179
|
+
while (fs.existsSync(lockPath)) {
|
|
2180
|
+
tryReleaseStaleBotRunnerStateLock(lockPath, staleMs);
|
|
2181
|
+
if (!fs.existsSync(lockPath)) {
|
|
2182
|
+
return;
|
|
2183
|
+
}
|
|
2184
|
+
if (Date.now() >= deadlineMs) {
|
|
2185
|
+
return;
|
|
2186
|
+
}
|
|
2187
|
+
sleepSyncMs(25);
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
function withBotRunnerStateFileLock(filePath, callback, timeoutMs = 5000, staleMs = 60000) {
|
|
2192
|
+
const lockPath = botRunnerStateLockFilePath(filePath);
|
|
2193
|
+
if (!lockPath) {
|
|
2194
|
+
return callback();
|
|
2195
|
+
}
|
|
2196
|
+
const deadlineMs = Date.now() + Math.max(0, Number(timeoutMs) || 0);
|
|
2197
|
+
let lockFD = null;
|
|
2198
|
+
while (lockFD === null) {
|
|
2199
|
+
try {
|
|
2200
|
+
lockFD = fs.openSync(lockPath, "wx");
|
|
2201
|
+
fs.writeFileSync(lockFD, `${process.pid} ${new Date().toISOString()}\n`, "utf8");
|
|
2202
|
+
break;
|
|
2203
|
+
} catch (error) {
|
|
2204
|
+
const errorCode = String(error?.code || "").trim().toUpperCase();
|
|
2205
|
+
if (!["EEXIST", "EPERM", "EBUSY"].includes(errorCode)) {
|
|
2206
|
+
throw error;
|
|
2207
|
+
}
|
|
2208
|
+
tryReleaseStaleBotRunnerStateLock(lockPath, staleMs);
|
|
2209
|
+
if (Date.now() >= deadlineMs) {
|
|
2210
|
+
throw error;
|
|
2211
|
+
}
|
|
2212
|
+
sleepSyncMs(25);
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
try {
|
|
2216
|
+
return callback();
|
|
2217
|
+
} finally {
|
|
2218
|
+
try {
|
|
2219
|
+
if (lockFD !== null) {
|
|
2220
|
+
fs.closeSync(lockFD);
|
|
2221
|
+
}
|
|
2222
|
+
} catch {}
|
|
2223
|
+
try {
|
|
2224
|
+
if (fs.existsSync(lockPath)) {
|
|
2225
|
+
fs.rmSync(lockPath, { force: true });
|
|
2226
|
+
}
|
|
2227
|
+
} catch {}
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
function writeTextFileAtomic(filePath, text) {
|
|
2232
|
+
const normalizedPath = String(filePath || "").trim();
|
|
2233
|
+
if (!normalizedPath) {
|
|
2234
|
+
throw new Error("filePath is required");
|
|
2235
|
+
}
|
|
2236
2236
|
const directoryPath = path.dirname(normalizedPath);
|
|
2237
2237
|
fs.mkdirSync(directoryPath, { recursive: true });
|
|
2238
2238
|
const tempPath = path.join(
|
|
@@ -2240,41 +2240,41 @@ function writeTextFileAtomic(filePath, text) {
|
|
|
2240
2240
|
`.${path.basename(normalizedPath)}.${process.pid}.${Date.now()}.tmp`,
|
|
2241
2241
|
);
|
|
2242
2242
|
fs.writeFileSync(tempPath, text, "utf8");
|
|
2243
|
-
const renameRetryDelaysMs = [0, 20, 50, 100, 200];
|
|
2244
|
-
let lastRenameError = null;
|
|
2245
|
-
try {
|
|
2246
|
-
for (const delayMs of renameRetryDelaysMs) {
|
|
2247
|
-
if (delayMs > 0) {
|
|
2248
|
-
sleepSyncMs(delayMs);
|
|
2249
|
-
}
|
|
2250
|
-
try {
|
|
2251
|
-
fs.renameSync(tempPath, normalizedPath);
|
|
2252
|
-
lastRenameError = null;
|
|
2253
|
-
break;
|
|
2254
|
-
} catch (error) {
|
|
2255
|
-
lastRenameError = error;
|
|
2256
|
-
try {
|
|
2257
|
-
fs.copyFileSync(tempPath, normalizedPath);
|
|
2258
|
-
lastRenameError = null;
|
|
2259
|
-
break;
|
|
2260
|
-
} catch (copyError) {
|
|
2261
|
-
lastRenameError = copyError;
|
|
2262
|
-
try {
|
|
2263
|
-
fs.writeFileSync(normalizedPath, text, "utf8");
|
|
2264
|
-
lastRenameError = null;
|
|
2265
|
-
break;
|
|
2266
|
-
} catch (writeError) {
|
|
2267
|
-
lastRenameError = writeError;
|
|
2268
|
-
}
|
|
2269
|
-
const errorCode = String(
|
|
2270
|
-
lastRenameError?.code || copyError?.code || error?.code || "",
|
|
2271
|
-
).trim().toUpperCase();
|
|
2272
|
-
if (!["EPERM", "EBUSY", "ENOTEMPTY"].includes(errorCode)) {
|
|
2273
|
-
throw lastRenameError;
|
|
2274
|
-
}
|
|
2275
|
-
}
|
|
2276
|
-
}
|
|
2277
|
-
}
|
|
2243
|
+
const renameRetryDelaysMs = [0, 20, 50, 100, 200];
|
|
2244
|
+
let lastRenameError = null;
|
|
2245
|
+
try {
|
|
2246
|
+
for (const delayMs of renameRetryDelaysMs) {
|
|
2247
|
+
if (delayMs > 0) {
|
|
2248
|
+
sleepSyncMs(delayMs);
|
|
2249
|
+
}
|
|
2250
|
+
try {
|
|
2251
|
+
fs.renameSync(tempPath, normalizedPath);
|
|
2252
|
+
lastRenameError = null;
|
|
2253
|
+
break;
|
|
2254
|
+
} catch (error) {
|
|
2255
|
+
lastRenameError = error;
|
|
2256
|
+
try {
|
|
2257
|
+
fs.copyFileSync(tempPath, normalizedPath);
|
|
2258
|
+
lastRenameError = null;
|
|
2259
|
+
break;
|
|
2260
|
+
} catch (copyError) {
|
|
2261
|
+
lastRenameError = copyError;
|
|
2262
|
+
try {
|
|
2263
|
+
fs.writeFileSync(normalizedPath, text, "utf8");
|
|
2264
|
+
lastRenameError = null;
|
|
2265
|
+
break;
|
|
2266
|
+
} catch (writeError) {
|
|
2267
|
+
lastRenameError = writeError;
|
|
2268
|
+
}
|
|
2269
|
+
const errorCode = String(
|
|
2270
|
+
lastRenameError?.code || copyError?.code || error?.code || "",
|
|
2271
|
+
).trim().toUpperCase();
|
|
2272
|
+
if (!["EPERM", "EBUSY", "ENOTEMPTY"].includes(errorCode)) {
|
|
2273
|
+
throw lastRenameError;
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2278
2278
|
if (lastRenameError) {
|
|
2279
2279
|
throw lastRenameError;
|
|
2280
2280
|
}
|
|
@@ -2287,188 +2287,188 @@ function writeTextFileAtomic(filePath, text) {
|
|
|
2287
2287
|
}
|
|
2288
2288
|
}
|
|
2289
2289
|
|
|
2290
|
-
function saveBotRunnerState(nextState) {
|
|
2291
|
-
const filePath = botRunnerStateFilePath();
|
|
2292
|
-
return withBotRunnerStateFileLock(filePath, () => {
|
|
2293
|
-
let current = {};
|
|
2294
|
-
try {
|
|
2295
|
-
current = safeObject(tryJsonParse(fs.readFileSync(filePath, "utf8")));
|
|
2296
|
-
} catch {}
|
|
2297
|
-
const stateEntryTimestampMs = (...values) => {
|
|
2298
|
-
for (const value of values) {
|
|
2299
|
-
const ms = Date.parse(String(value || "").trim());
|
|
2300
|
-
if (Number.isFinite(ms)) {
|
|
2301
|
-
return ms;
|
|
2302
|
-
}
|
|
2303
|
-
}
|
|
2304
|
-
return 0;
|
|
2305
|
-
};
|
|
2306
|
-
const mergeRunnerStateRoutes = (currentRoutesRaw, nextRoutesRaw) => {
|
|
2307
|
-
const currentRoutes = safeObject(currentRoutesRaw);
|
|
2308
|
-
const nextRoutes = safeObject(nextRoutesRaw);
|
|
2309
|
-
const merged = {
|
|
2310
|
-
...currentRoutes,
|
|
2311
|
-
};
|
|
2312
|
-
const mergeConversationSessions = (currentSessionsRaw, nextSessionsRaw) => {
|
|
2313
|
-
const currentSessions = safeObject(currentSessionsRaw);
|
|
2314
|
-
const nextSessions = safeObject(nextSessionsRaw);
|
|
2315
|
-
const mergedSessions = {
|
|
2316
|
-
...currentSessions,
|
|
2317
|
-
};
|
|
2318
|
-
for (const [conversationID, nextSessionRaw] of Object.entries(nextSessions)) {
|
|
2319
|
-
const currentSession = safeObject(currentSessions[conversationID]);
|
|
2320
|
-
const nextSession = safeObject(nextSessionRaw);
|
|
2321
|
-
if (!Object.keys(currentSession).length) {
|
|
2322
|
-
mergedSessions[conversationID] = nextSession;
|
|
2323
|
-
continue;
|
|
2324
|
-
}
|
|
2325
|
-
const currentMs = stateEntryTimestampMs(
|
|
2326
|
-
currentSession.updated_at,
|
|
2327
|
-
currentSession.last_activity_at,
|
|
2328
|
-
currentSession.closed_at,
|
|
2329
|
-
currentSession.started_at,
|
|
2330
|
-
currentSession.expires_at,
|
|
2331
|
-
);
|
|
2332
|
-
const nextMs = stateEntryTimestampMs(
|
|
2333
|
-
nextSession.updated_at,
|
|
2334
|
-
nextSession.last_activity_at,
|
|
2335
|
-
nextSession.closed_at,
|
|
2336
|
-
nextSession.started_at,
|
|
2337
|
-
nextSession.expires_at,
|
|
2338
|
-
);
|
|
2339
|
-
mergedSessions[conversationID] = nextMs >= currentMs
|
|
2340
|
-
? {
|
|
2341
|
-
...currentSession,
|
|
2342
|
-
...nextSession,
|
|
2343
|
-
}
|
|
2344
|
-
: {
|
|
2345
|
-
...nextSession,
|
|
2346
|
-
...currentSession,
|
|
2347
|
-
};
|
|
2348
|
-
}
|
|
2349
|
-
return mergedSessions;
|
|
2350
|
-
};
|
|
2351
|
-
for (const [routeKey, nextRouteRaw] of Object.entries(nextRoutes)) {
|
|
2352
|
-
const currentRoute = safeObject(currentRoutes[routeKey]);
|
|
2353
|
-
const nextRoute = safeObject(nextRouteRaw);
|
|
2354
|
-
if (!Object.keys(currentRoute).length) {
|
|
2355
|
-
merged[routeKey] = nextRoute;
|
|
2356
|
-
continue;
|
|
2357
|
-
}
|
|
2358
|
-
const preferredRoute = prefersRunnerStateRecord(nextRoute, currentRoute) ? nextRoute : currentRoute;
|
|
2359
|
-
const fallbackRoute = preferredRoute === nextRoute ? currentRoute : nextRoute;
|
|
2360
|
-
merged[routeKey] = cleanupRunnerStateRecord({
|
|
2361
|
-
...mergeRunnerStateRecords(preferredRoute, fallbackRoute),
|
|
2362
|
-
conversation_sessions: mergeConversationSessions(
|
|
2363
|
-
currentRoute.conversation_sessions,
|
|
2364
|
-
nextRoute.conversation_sessions,
|
|
2365
|
-
),
|
|
2366
|
-
});
|
|
2367
|
-
}
|
|
2368
|
-
return merged;
|
|
2369
|
-
};
|
|
2370
|
-
const mergeRunnerStateRequests = (currentRequestsRaw, nextRequestsRaw) => {
|
|
2371
|
-
const currentRequests = normalizeBotRunnerRequests(currentRequestsRaw);
|
|
2372
|
-
const nextRequests = normalizeBotRunnerRequests(nextRequestsRaw);
|
|
2373
|
-
const merged = {
|
|
2374
|
-
...currentRequests,
|
|
2375
|
-
};
|
|
2376
|
-
for (const [requestKey, nextRequestRaw] of Object.entries(nextRequests)) {
|
|
2377
|
-
const currentRequest = safeObject(currentRequests[requestKey]);
|
|
2378
|
-
const nextRequest = safeObject(nextRequestRaw);
|
|
2379
|
-
const currentMs = stateEntryTimestampMs(
|
|
2380
|
-
currentRequest.updated_at,
|
|
2381
|
-
currentRequest.completed_at,
|
|
2382
|
-
currentRequest.closed_at,
|
|
2383
|
-
currentRequest.claimed_at,
|
|
2384
|
-
);
|
|
2385
|
-
const nextMs = stateEntryTimestampMs(
|
|
2386
|
-
nextRequest.updated_at,
|
|
2387
|
-
nextRequest.completed_at,
|
|
2388
|
-
nextRequest.closed_at,
|
|
2389
|
-
nextRequest.claimed_at,
|
|
2390
|
-
);
|
|
2391
|
-
if (!Object.keys(currentRequest).length) {
|
|
2392
|
-
merged[requestKey] = nextRequest;
|
|
2393
|
-
continue;
|
|
2394
|
-
}
|
|
2395
|
-
merged[requestKey] = nextMs >= currentMs
|
|
2396
|
-
? {
|
|
2397
|
-
...currentRequest,
|
|
2398
|
-
...nextRequest,
|
|
2399
|
-
}
|
|
2400
|
-
: currentRequest;
|
|
2401
|
-
}
|
|
2402
|
-
return normalizeBotRunnerRequests(merged);
|
|
2403
|
-
};
|
|
2404
|
-
const mergeRunnerStateExcludedComments = (currentExcludedRaw, nextExcludedRaw) => {
|
|
2405
|
-
const currentExcluded = normalizeBotRunnerExcludedComments(currentExcludedRaw);
|
|
2406
|
-
const nextExcluded = normalizeBotRunnerExcludedComments(nextExcludedRaw);
|
|
2407
|
-
const merged = {
|
|
2408
|
-
...currentExcluded,
|
|
2409
|
-
};
|
|
2410
|
-
for (const [commentID, nextEntryRaw] of Object.entries(nextExcluded)) {
|
|
2411
|
-
const currentEntry = safeObject(currentExcluded[commentID]);
|
|
2412
|
-
const nextEntry = safeObject(nextEntryRaw);
|
|
2413
|
-
const currentMs = stateEntryTimestampMs(currentEntry.excluded_at);
|
|
2414
|
-
const nextMs = stateEntryTimestampMs(nextEntry.excluded_at);
|
|
2415
|
-
if (!Object.keys(currentEntry).length || nextMs >= currentMs) {
|
|
2416
|
-
merged[commentID] = {
|
|
2417
|
-
...currentEntry,
|
|
2418
|
-
...nextEntry,
|
|
2419
|
-
};
|
|
2420
|
-
}
|
|
2421
|
-
}
|
|
2422
|
-
return normalizeBotRunnerExcludedComments(merged);
|
|
2423
|
-
};
|
|
2424
|
-
const mergeRunnerStateConsumedComments = (currentConsumedRaw, nextConsumedRaw) => {
|
|
2425
|
-
const currentConsumed = normalizeBotRunnerConsumedComments(currentConsumedRaw);
|
|
2426
|
-
const nextConsumed = normalizeBotRunnerConsumedComments(nextConsumedRaw);
|
|
2427
|
-
const merged = {
|
|
2428
|
-
...currentConsumed,
|
|
2429
|
-
};
|
|
2430
|
-
for (const [commentID, nextEntryRaw] of Object.entries(nextConsumed)) {
|
|
2431
|
-
const currentEntry = safeObject(currentConsumed[commentID]);
|
|
2432
|
-
const nextEntry = safeObject(nextEntryRaw);
|
|
2433
|
-
const currentMs = stateEntryTimestampMs(currentEntry.consumed_at);
|
|
2434
|
-
const nextMs = stateEntryTimestampMs(nextEntry.consumed_at);
|
|
2435
|
-
if (!Object.keys(currentEntry).length || nextMs >= currentMs) {
|
|
2436
|
-
merged[commentID] = {
|
|
2437
|
-
...currentEntry,
|
|
2438
|
-
...nextEntry,
|
|
2439
|
-
};
|
|
2440
|
-
}
|
|
2441
|
-
}
|
|
2442
|
-
return normalizeBotRunnerConsumedComments(merged);
|
|
2443
|
-
};
|
|
2444
|
-
const payload = {
|
|
2445
|
-
version: 1,
|
|
2446
|
-
updated_at: new Date().toISOString(),
|
|
2447
|
-
routes: mergeRunnerStateRoutes(
|
|
2448
|
-
current.routes,
|
|
2449
|
-
nextState?.routes ?? current.routes,
|
|
2450
|
-
),
|
|
2451
|
-
shared_inboxes: {
|
|
2452
|
-
...safeObject(current.shared_inboxes ?? current.sharedInboxes),
|
|
2453
|
-
...safeObject(nextState?.sharedInboxes ?? nextState?.shared_inboxes),
|
|
2454
|
-
},
|
|
2455
|
-
excluded_comments: mergeRunnerStateExcludedComments(
|
|
2456
|
-
current.excluded_comments ?? current.excludedComments,
|
|
2457
|
-
nextState?.excludedComments ?? nextState?.excluded_comments ?? current.excluded_comments ?? current.excludedComments,
|
|
2458
|
-
),
|
|
2459
|
-
requests: mergeRunnerStateRequests(
|
|
2460
|
-
current.requests,
|
|
2461
|
-
nextState?.requests ?? current.requests,
|
|
2462
|
-
),
|
|
2463
|
-
consumed_comments: mergeRunnerStateConsumedComments(
|
|
2464
|
-
current.consumed_comments ?? current.consumedComments,
|
|
2465
|
-
nextState?.consumedComments ?? nextState?.consumed_comments ?? current.consumed_comments ?? current.consumedComments,
|
|
2466
|
-
),
|
|
2467
|
-
};
|
|
2468
|
-
writeTextFileAtomic(filePath, `${JSON.stringify(payload, null, 2)}\n`);
|
|
2469
|
-
return filePath;
|
|
2470
|
-
});
|
|
2471
|
-
}
|
|
2290
|
+
function saveBotRunnerState(nextState) {
|
|
2291
|
+
const filePath = botRunnerStateFilePath();
|
|
2292
|
+
return withBotRunnerStateFileLock(filePath, () => {
|
|
2293
|
+
let current = {};
|
|
2294
|
+
try {
|
|
2295
|
+
current = safeObject(tryJsonParse(fs.readFileSync(filePath, "utf8")));
|
|
2296
|
+
} catch {}
|
|
2297
|
+
const stateEntryTimestampMs = (...values) => {
|
|
2298
|
+
for (const value of values) {
|
|
2299
|
+
const ms = Date.parse(String(value || "").trim());
|
|
2300
|
+
if (Number.isFinite(ms)) {
|
|
2301
|
+
return ms;
|
|
2302
|
+
}
|
|
2303
|
+
}
|
|
2304
|
+
return 0;
|
|
2305
|
+
};
|
|
2306
|
+
const mergeRunnerStateRoutes = (currentRoutesRaw, nextRoutesRaw) => {
|
|
2307
|
+
const currentRoutes = safeObject(currentRoutesRaw);
|
|
2308
|
+
const nextRoutes = safeObject(nextRoutesRaw);
|
|
2309
|
+
const merged = {
|
|
2310
|
+
...currentRoutes,
|
|
2311
|
+
};
|
|
2312
|
+
const mergeConversationSessions = (currentSessionsRaw, nextSessionsRaw) => {
|
|
2313
|
+
const currentSessions = safeObject(currentSessionsRaw);
|
|
2314
|
+
const nextSessions = safeObject(nextSessionsRaw);
|
|
2315
|
+
const mergedSessions = {
|
|
2316
|
+
...currentSessions,
|
|
2317
|
+
};
|
|
2318
|
+
for (const [conversationID, nextSessionRaw] of Object.entries(nextSessions)) {
|
|
2319
|
+
const currentSession = safeObject(currentSessions[conversationID]);
|
|
2320
|
+
const nextSession = safeObject(nextSessionRaw);
|
|
2321
|
+
if (!Object.keys(currentSession).length) {
|
|
2322
|
+
mergedSessions[conversationID] = nextSession;
|
|
2323
|
+
continue;
|
|
2324
|
+
}
|
|
2325
|
+
const currentMs = stateEntryTimestampMs(
|
|
2326
|
+
currentSession.updated_at,
|
|
2327
|
+
currentSession.last_activity_at,
|
|
2328
|
+
currentSession.closed_at,
|
|
2329
|
+
currentSession.started_at,
|
|
2330
|
+
currentSession.expires_at,
|
|
2331
|
+
);
|
|
2332
|
+
const nextMs = stateEntryTimestampMs(
|
|
2333
|
+
nextSession.updated_at,
|
|
2334
|
+
nextSession.last_activity_at,
|
|
2335
|
+
nextSession.closed_at,
|
|
2336
|
+
nextSession.started_at,
|
|
2337
|
+
nextSession.expires_at,
|
|
2338
|
+
);
|
|
2339
|
+
mergedSessions[conversationID] = nextMs >= currentMs
|
|
2340
|
+
? {
|
|
2341
|
+
...currentSession,
|
|
2342
|
+
...nextSession,
|
|
2343
|
+
}
|
|
2344
|
+
: {
|
|
2345
|
+
...nextSession,
|
|
2346
|
+
...currentSession,
|
|
2347
|
+
};
|
|
2348
|
+
}
|
|
2349
|
+
return mergedSessions;
|
|
2350
|
+
};
|
|
2351
|
+
for (const [routeKey, nextRouteRaw] of Object.entries(nextRoutes)) {
|
|
2352
|
+
const currentRoute = safeObject(currentRoutes[routeKey]);
|
|
2353
|
+
const nextRoute = safeObject(nextRouteRaw);
|
|
2354
|
+
if (!Object.keys(currentRoute).length) {
|
|
2355
|
+
merged[routeKey] = nextRoute;
|
|
2356
|
+
continue;
|
|
2357
|
+
}
|
|
2358
|
+
const preferredRoute = prefersRunnerStateRecord(nextRoute, currentRoute) ? nextRoute : currentRoute;
|
|
2359
|
+
const fallbackRoute = preferredRoute === nextRoute ? currentRoute : nextRoute;
|
|
2360
|
+
merged[routeKey] = cleanupRunnerStateRecord({
|
|
2361
|
+
...mergeRunnerStateRecords(preferredRoute, fallbackRoute),
|
|
2362
|
+
conversation_sessions: mergeConversationSessions(
|
|
2363
|
+
currentRoute.conversation_sessions,
|
|
2364
|
+
nextRoute.conversation_sessions,
|
|
2365
|
+
),
|
|
2366
|
+
});
|
|
2367
|
+
}
|
|
2368
|
+
return merged;
|
|
2369
|
+
};
|
|
2370
|
+
const mergeRunnerStateRequests = (currentRequestsRaw, nextRequestsRaw) => {
|
|
2371
|
+
const currentRequests = normalizeBotRunnerRequests(currentRequestsRaw);
|
|
2372
|
+
const nextRequests = normalizeBotRunnerRequests(nextRequestsRaw);
|
|
2373
|
+
const merged = {
|
|
2374
|
+
...currentRequests,
|
|
2375
|
+
};
|
|
2376
|
+
for (const [requestKey, nextRequestRaw] of Object.entries(nextRequests)) {
|
|
2377
|
+
const currentRequest = safeObject(currentRequests[requestKey]);
|
|
2378
|
+
const nextRequest = safeObject(nextRequestRaw);
|
|
2379
|
+
const currentMs = stateEntryTimestampMs(
|
|
2380
|
+
currentRequest.updated_at,
|
|
2381
|
+
currentRequest.completed_at,
|
|
2382
|
+
currentRequest.closed_at,
|
|
2383
|
+
currentRequest.claimed_at,
|
|
2384
|
+
);
|
|
2385
|
+
const nextMs = stateEntryTimestampMs(
|
|
2386
|
+
nextRequest.updated_at,
|
|
2387
|
+
nextRequest.completed_at,
|
|
2388
|
+
nextRequest.closed_at,
|
|
2389
|
+
nextRequest.claimed_at,
|
|
2390
|
+
);
|
|
2391
|
+
if (!Object.keys(currentRequest).length) {
|
|
2392
|
+
merged[requestKey] = nextRequest;
|
|
2393
|
+
continue;
|
|
2394
|
+
}
|
|
2395
|
+
merged[requestKey] = nextMs >= currentMs
|
|
2396
|
+
? {
|
|
2397
|
+
...currentRequest,
|
|
2398
|
+
...nextRequest,
|
|
2399
|
+
}
|
|
2400
|
+
: currentRequest;
|
|
2401
|
+
}
|
|
2402
|
+
return normalizeBotRunnerRequests(merged);
|
|
2403
|
+
};
|
|
2404
|
+
const mergeRunnerStateExcludedComments = (currentExcludedRaw, nextExcludedRaw) => {
|
|
2405
|
+
const currentExcluded = normalizeBotRunnerExcludedComments(currentExcludedRaw);
|
|
2406
|
+
const nextExcluded = normalizeBotRunnerExcludedComments(nextExcludedRaw);
|
|
2407
|
+
const merged = {
|
|
2408
|
+
...currentExcluded,
|
|
2409
|
+
};
|
|
2410
|
+
for (const [commentID, nextEntryRaw] of Object.entries(nextExcluded)) {
|
|
2411
|
+
const currentEntry = safeObject(currentExcluded[commentID]);
|
|
2412
|
+
const nextEntry = safeObject(nextEntryRaw);
|
|
2413
|
+
const currentMs = stateEntryTimestampMs(currentEntry.excluded_at);
|
|
2414
|
+
const nextMs = stateEntryTimestampMs(nextEntry.excluded_at);
|
|
2415
|
+
if (!Object.keys(currentEntry).length || nextMs >= currentMs) {
|
|
2416
|
+
merged[commentID] = {
|
|
2417
|
+
...currentEntry,
|
|
2418
|
+
...nextEntry,
|
|
2419
|
+
};
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
return normalizeBotRunnerExcludedComments(merged);
|
|
2423
|
+
};
|
|
2424
|
+
const mergeRunnerStateConsumedComments = (currentConsumedRaw, nextConsumedRaw) => {
|
|
2425
|
+
const currentConsumed = normalizeBotRunnerConsumedComments(currentConsumedRaw);
|
|
2426
|
+
const nextConsumed = normalizeBotRunnerConsumedComments(nextConsumedRaw);
|
|
2427
|
+
const merged = {
|
|
2428
|
+
...currentConsumed,
|
|
2429
|
+
};
|
|
2430
|
+
for (const [commentID, nextEntryRaw] of Object.entries(nextConsumed)) {
|
|
2431
|
+
const currentEntry = safeObject(currentConsumed[commentID]);
|
|
2432
|
+
const nextEntry = safeObject(nextEntryRaw);
|
|
2433
|
+
const currentMs = stateEntryTimestampMs(currentEntry.consumed_at);
|
|
2434
|
+
const nextMs = stateEntryTimestampMs(nextEntry.consumed_at);
|
|
2435
|
+
if (!Object.keys(currentEntry).length || nextMs >= currentMs) {
|
|
2436
|
+
merged[commentID] = {
|
|
2437
|
+
...currentEntry,
|
|
2438
|
+
...nextEntry,
|
|
2439
|
+
};
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
return normalizeBotRunnerConsumedComments(merged);
|
|
2443
|
+
};
|
|
2444
|
+
const payload = {
|
|
2445
|
+
version: 1,
|
|
2446
|
+
updated_at: new Date().toISOString(),
|
|
2447
|
+
routes: mergeRunnerStateRoutes(
|
|
2448
|
+
current.routes,
|
|
2449
|
+
nextState?.routes ?? current.routes,
|
|
2450
|
+
),
|
|
2451
|
+
shared_inboxes: {
|
|
2452
|
+
...safeObject(current.shared_inboxes ?? current.sharedInboxes),
|
|
2453
|
+
...safeObject(nextState?.sharedInboxes ?? nextState?.shared_inboxes),
|
|
2454
|
+
},
|
|
2455
|
+
excluded_comments: mergeRunnerStateExcludedComments(
|
|
2456
|
+
current.excluded_comments ?? current.excludedComments,
|
|
2457
|
+
nextState?.excludedComments ?? nextState?.excluded_comments ?? current.excluded_comments ?? current.excludedComments,
|
|
2458
|
+
),
|
|
2459
|
+
requests: mergeRunnerStateRequests(
|
|
2460
|
+
current.requests,
|
|
2461
|
+
nextState?.requests ?? current.requests,
|
|
2462
|
+
),
|
|
2463
|
+
consumed_comments: mergeRunnerStateConsumedComments(
|
|
2464
|
+
current.consumed_comments ?? current.consumedComments,
|
|
2465
|
+
nextState?.consumedComments ?? nextState?.consumed_comments ?? current.consumed_comments ?? current.consumedComments,
|
|
2466
|
+
),
|
|
2467
|
+
};
|
|
2468
|
+
writeTextFileAtomic(filePath, `${JSON.stringify(payload, null, 2)}\n`);
|
|
2469
|
+
return filePath;
|
|
2470
|
+
});
|
|
2471
|
+
}
|
|
2472
2472
|
|
|
2473
2473
|
function normalizeBotRunnerExcludedComments(rawExcluded, nowMs = Date.now()) {
|
|
2474
2474
|
const normalized = {};
|
|
@@ -2525,388 +2525,382 @@ function isActiveRunnerRequestStatus(rawStatus) {
|
|
|
2525
2525
|
return status === "planned" || status === "claimed" || status === "running";
|
|
2526
2526
|
}
|
|
2527
2527
|
|
|
2528
|
-
function normalizeRunnerWorkItemStatus(rawStatus) {
|
|
2529
|
-
const status = String(rawStatus || "").trim().toLowerCase();
|
|
2530
|
-
return ["backlog", "doing", "review", "done", "canceled"].includes(status)
|
|
2531
|
-
? status
|
|
2532
|
-
: "";
|
|
2533
|
-
}
|
|
2534
|
-
|
|
2535
|
-
function truncateRunnerReplyChainText(rawValue, maxLength = 280) {
|
|
2536
|
-
const text = String(rawValue || "").trim().replace(/\s+/g, " ");
|
|
2537
|
-
if (!text) return "";
|
|
2538
|
-
if (!(maxLength > 0) || text.length <= maxLength) {
|
|
2539
|
-
return text;
|
|
2540
|
-
}
|
|
2541
|
-
return `${text.slice(0, Math.max(0, maxLength - 3)).trimEnd()}...`;
|
|
2542
|
-
}
|
|
2543
|
-
|
|
2544
|
-
function buildRunnerReplyChainSpeakerType(parsedArchiveRaw) {
|
|
2545
|
-
const parsedArchive = safeObject(parsedArchiveRaw);
|
|
2546
|
-
const kind = String(parsedArchive.kind || "").trim().toLowerCase();
|
|
2547
|
-
if (kind === "bot_reply" || parsedArchive.senderIsBot === true) {
|
|
2548
|
-
return "bot";
|
|
2549
|
-
}
|
|
2550
|
-
return "human";
|
|
2551
|
-
}
|
|
2552
|
-
|
|
2553
|
-
function buildRunnerReplyChainSpeakerLabel(parsedArchiveRaw) {
|
|
2554
|
-
const parsedArchive = safeObject(parsedArchiveRaw);
|
|
2555
|
-
const username = normalizeTelegramMentionUsername(
|
|
2556
|
-
parsedArchive.botUsername
|
|
2557
|
-
|| parsedArchive.username
|
|
2558
|
-
|| parsedArchive.replyToUsername
|
|
2559
|
-
|| parsedArchive.conversationTargetBotUsername,
|
|
2560
|
-
);
|
|
2561
|
-
if (username) {
|
|
2562
|
-
return `@${username}`;
|
|
2563
|
-
}
|
|
2564
|
-
return firstNonEmptyString([
|
|
2565
|
-
parsedArchive.sender,
|
|
2566
|
-
parsedArchive.botName,
|
|
2567
|
-
parsedArchive.replyToSender,
|
|
2568
|
-
parsedArchive.chatTitle,
|
|
2569
|
-
buildRunnerReplyChainSpeakerType(parsedArchive) === "bot" ? "bot" : "human",
|
|
2570
|
-
]);
|
|
2571
|
-
}
|
|
2572
|
-
|
|
2573
|
-
function normalizeRunnerReplyChainSnapshot(rawSnapshot) {
|
|
2574
|
-
const snapshot = safeObject(rawSnapshot);
|
|
2575
|
-
const messageID = intFromRawAllowZero(snapshot.message_id || snapshot.messageID, 0);
|
|
2576
|
-
const messageThreadID = intFromRawAllowZero(snapshot.message_thread_id || snapshot.messageThreadID, 0);
|
|
2577
|
-
const replyToMessageID = intFromRawAllowZero(snapshot.reply_to_message_id || snapshot.replyToMessageID, 0);
|
|
2578
|
-
const speakerType = String(snapshot.speaker_type || snapshot.speakerType || "").trim().toLowerCase();
|
|
2579
|
-
const body = truncateRunnerReplyChainText(snapshot.body || "");
|
|
2580
|
-
if (!(messageID > 0) && !body) {
|
|
2581
|
-
return null;
|
|
2582
|
-
}
|
|
2583
|
-
return {
|
|
2584
|
-
message_id: messageID || undefined,
|
|
2585
|
-
message_thread_id: messageThreadID || undefined,
|
|
2586
|
-
reply_to_message_id: replyToMessageID || undefined,
|
|
2587
|
-
speaker_type: speakerType === "bot" ? "bot" : "human",
|
|
2588
|
-
speaker_label: String(snapshot.speaker_label || snapshot.speakerLabel || "").trim(),
|
|
2589
|
-
body,
|
|
2590
|
-
};
|
|
2591
|
-
}
|
|
2592
|
-
|
|
2593
|
-
function buildRunnerReplyChainSnapshotFromMessageEnvelope(envelopeRaw, overrides = {}) {
|
|
2594
|
-
const envelope = normalizeRunnerTelegramMessageEnvelope(envelopeRaw);
|
|
2595
|
-
if (!Object.keys(envelope).length) {
|
|
2596
|
-
return null;
|
|
2597
|
-
}
|
|
2598
|
-
return normalizeRunnerReplyChainSnapshot({
|
|
2599
|
-
message_id: envelope.message_id,
|
|
2600
|
-
message_thread_id: envelope.message_thread_id,
|
|
2601
|
-
reply_to_message_id: envelope.reply_to_message_id,
|
|
2602
|
-
speaker_type: firstNonEmptyString([
|
|
2603
|
-
overrides.speaker_type,
|
|
2604
|
-
envelope.sender_is_bot === true ? "bot" : "human",
|
|
2605
|
-
]),
|
|
2606
|
-
speaker_label: firstNonEmptyString([
|
|
2607
|
-
overrides.speaker_label,
|
|
2608
|
-
envelope.sender_username ? `@${String(envelope.sender_username || "").trim().replace(/^@+/, "")}` : "",
|
|
2609
|
-
envelope.sender,
|
|
2610
|
-
]),
|
|
2611
|
-
body: firstNonEmptyString([overrides.body, envelope.body]),
|
|
2612
|
-
});
|
|
2613
|
-
}
|
|
2614
|
-
|
|
2615
|
-
function normalizeRunnerReplyChainContext(rawContext) {
|
|
2616
|
-
const context = safeObject(rawContext);
|
|
2617
|
-
const normalized = {
|
|
2618
|
-
conversation_id: String(context.conversation_id || context.conversationID || "").trim(),
|
|
2619
|
-
current_message_id: intFromRawAllowZero(context.current_message_id || context.currentMessageID, 0) || undefined,
|
|
2620
|
-
current_message_thread_id: intFromRawAllowZero(
|
|
2621
|
-
context.current_message_thread_id || context.currentMessageThreadID,
|
|
2622
|
-
0,
|
|
2623
|
-
) || undefined,
|
|
2624
|
-
parent_message_id: intFromRawAllowZero(context.parent_message_id || context.parentMessageID, 0) || undefined,
|
|
2625
|
-
root_message_id: intFromRawAllowZero(context.root_message_id || context.rootMessageID, 0) || undefined,
|
|
2626
|
-
current_turn_relation: String(context.current_turn_relation || context.currentTurnRelation || "").trim(),
|
|
2627
|
-
root_message: normalizeRunnerReplyChainSnapshot(context.root_message || context.rootMessage),
|
|
2628
|
-
parent_message: normalizeRunnerReplyChainSnapshot(context.parent_message || context.parentMessage),
|
|
2629
|
-
latest_prior_bot_reply: normalizeRunnerReplyChainSnapshot(
|
|
2630
|
-
context.latest_prior_bot_reply || context.latestPriorBotReply,
|
|
2631
|
-
),
|
|
2632
|
-
recent_chain_messages: ensureArray(context.recent_chain_messages || context.recentChainMessages)
|
|
2633
|
-
.map((item) => normalizeRunnerReplyChainSnapshot(item))
|
|
2634
|
-
.filter(Boolean)
|
|
2635
|
-
.slice(-4),
|
|
2636
|
-
};
|
|
2637
|
-
if (
|
|
2638
|
-
!normalized.conversation_id
|
|
2639
|
-
&& !(normalized.current_message_id > 0)
|
|
2640
|
-
&& !(normalized.current_message_thread_id > 0)
|
|
2641
|
-
&& !(normalized.parent_message_id > 0)
|
|
2642
|
-
&& !(normalized.root_message_id > 0)
|
|
2643
|
-
&& !normalized.current_turn_relation
|
|
2644
|
-
&& !normalized.root_message
|
|
2645
|
-
&& !normalized.parent_message
|
|
2646
|
-
&& !normalized.latest_prior_bot_reply
|
|
2647
|
-
&& !normalized.recent_chain_messages.length
|
|
2648
|
-
) {
|
|
2649
|
-
return {};
|
|
2650
|
-
}
|
|
2651
|
-
return normalized;
|
|
2652
|
-
}
|
|
2653
|
-
|
|
2654
|
-
function findRunnerRouteLocalInboundEnvelope(routeStateRaw, parsedArchiveRaw) {
|
|
2655
|
-
const routeState = safeObject(routeStateRaw);
|
|
2656
|
-
const parsedArchive = safeObject(parsedArchiveRaw);
|
|
2657
|
-
const chatID = String(parsedArchive.chatID || parsedArchive.chatId || "").trim();
|
|
2658
|
-
const messageID = intFromRawAllowZero(parsedArchive.messageID, 0);
|
|
2659
|
-
return findRunnerRouteLocalInboundEnvelopeByMessage(routeState, {
|
|
2660
|
-
chatID,
|
|
2661
|
-
messageID,
|
|
2662
|
-
});
|
|
2663
|
-
}
|
|
2664
|
-
|
|
2665
|
-
function findRunnerRouteLocalInboundEnvelopeByMessage(routeStateRaw, {
|
|
2666
|
-
chatID = "",
|
|
2667
|
-
messageID = 0,
|
|
2668
|
-
} = {}) {
|
|
2669
|
-
const routeState = safeObject(routeStateRaw);
|
|
2670
|
-
const normalizedChatID = String(chatID || "").trim();
|
|
2671
|
-
const normalizedMessageID = intFromRawAllowZero(messageID, 0);
|
|
2672
|
-
if (!normalizedChatID || !(normalizedMessageID > 0)) {
|
|
2673
|
-
return {};
|
|
2674
|
-
}
|
|
2675
|
-
return findRecentTelegramMessageEnvelope(routeState.recent_local_inbound_envelopes, {
|
|
2676
|
-
chatID: normalizedChatID,
|
|
2677
|
-
messageID: normalizedMessageID,
|
|
2678
|
-
});
|
|
2679
|
-
}
|
|
2680
|
-
|
|
2681
|
-
function mergeRunnerSourceMessageEnvelopes(primaryRaw, fallbackRaw) {
|
|
2682
|
-
const primary = normalizeRunnerTelegramMessageEnvelope(primaryRaw);
|
|
2683
|
-
const fallback = normalizeRunnerTelegramMessageEnvelope(fallbackRaw);
|
|
2684
|
-
return normalizeRunnerTelegramMessageEnvelope({
|
|
2685
|
-
...fallback,
|
|
2686
|
-
...primary,
|
|
2687
|
-
chat_id: firstNonEmptyString([primary.chat_id, fallback.chat_id]),
|
|
2688
|
-
message_id: intFromRawAllowZero(primary.message_id || fallback.message_id, 0) || undefined,
|
|
2689
|
-
message_thread_id: intFromRawAllowZero(
|
|
2690
|
-
primary.message_thread_id || fallback.message_thread_id,
|
|
2691
|
-
0,
|
|
2692
|
-
) || undefined,
|
|
2693
|
-
reply_to_message_id: intFromRawAllowZero(
|
|
2694
|
-
primary.reply_to_message_id || fallback.reply_to_message_id,
|
|
2695
|
-
0,
|
|
2696
|
-
) || undefined,
|
|
2697
|
-
body: firstNonEmptyString([primary.body, fallback.body]),
|
|
2698
|
-
source_origin: firstNonEmptyString([primary.source_origin, fallback.source_origin]),
|
|
2699
|
-
source_route_key: firstNonEmptyString([primary.source_route_key, fallback.source_route_key]),
|
|
2700
|
-
source_bot_username: firstNonEmptyString([primary.source_bot_username, fallback.source_bot_username]),
|
|
2701
|
-
});
|
|
2702
|
-
}
|
|
2703
|
-
|
|
2704
|
-
function scoreRunnerSourceMessageEnvelopeAuthority(rawEnvelope) {
|
|
2705
|
-
const envelope = normalizeRunnerTelegramMessageEnvelope(rawEnvelope);
|
|
2706
|
-
if (!String(envelope.chat_id || "").trim() || !(intFromRawAllowZero(envelope.message_id, 0) > 0)) {
|
|
2707
|
-
return 0;
|
|
2708
|
-
}
|
|
2709
|
-
const origin = String(envelope.source_origin || "").trim().toLowerCase();
|
|
2710
|
-
let score = 0;
|
|
2711
|
-
switch (origin) {
|
|
2712
|
-
case "local_telegram_inbound":
|
|
2713
|
-
score = 500;
|
|
2714
|
-
break;
|
|
2715
|
-
case "
|
|
2716
|
-
score =
|
|
2717
|
-
break;
|
|
2718
|
-
|
|
2719
|
-
score =
|
|
2720
|
-
break;
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
if (
|
|
2740
|
-
return fallback;
|
|
2741
|
-
}
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
const
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
if (isTelegramLocalInboundEnvelopeForRoute(
|
|
2765
|
-
routeKey,
|
|
2766
|
-
botUsername: fallbackBotSelector,
|
|
2767
|
-
})) {
|
|
2768
|
-
return
|
|
2769
|
-
}
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
});
|
|
2779
|
-
}
|
|
2780
|
-
|
|
2781
|
-
function normalizeBotRunnerRequests(rawRequests, nowMs = Date.now()) {
|
|
2782
|
-
const normalized = {};
|
|
2783
|
-
for (const [requestKeyRaw, entryRaw] of Object.entries(safeObject(rawRequests))) {
|
|
2528
|
+
function normalizeRunnerWorkItemStatus(rawStatus) {
|
|
2529
|
+
const status = String(rawStatus || "").trim().toLowerCase();
|
|
2530
|
+
return ["backlog", "doing", "review", "done", "canceled"].includes(status)
|
|
2531
|
+
? status
|
|
2532
|
+
: "";
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2535
|
+
function truncateRunnerReplyChainText(rawValue, maxLength = 280) {
|
|
2536
|
+
const text = String(rawValue || "").trim().replace(/\s+/g, " ");
|
|
2537
|
+
if (!text) return "";
|
|
2538
|
+
if (!(maxLength > 0) || text.length <= maxLength) {
|
|
2539
|
+
return text;
|
|
2540
|
+
}
|
|
2541
|
+
return `${text.slice(0, Math.max(0, maxLength - 3)).trimEnd()}...`;
|
|
2542
|
+
}
|
|
2543
|
+
|
|
2544
|
+
function buildRunnerReplyChainSpeakerType(parsedArchiveRaw) {
|
|
2545
|
+
const parsedArchive = safeObject(parsedArchiveRaw);
|
|
2546
|
+
const kind = String(parsedArchive.kind || "").trim().toLowerCase();
|
|
2547
|
+
if (kind === "bot_reply" || parsedArchive.senderIsBot === true) {
|
|
2548
|
+
return "bot";
|
|
2549
|
+
}
|
|
2550
|
+
return "human";
|
|
2551
|
+
}
|
|
2552
|
+
|
|
2553
|
+
function buildRunnerReplyChainSpeakerLabel(parsedArchiveRaw) {
|
|
2554
|
+
const parsedArchive = safeObject(parsedArchiveRaw);
|
|
2555
|
+
const username = normalizeTelegramMentionUsername(
|
|
2556
|
+
parsedArchive.botUsername
|
|
2557
|
+
|| parsedArchive.username
|
|
2558
|
+
|| parsedArchive.replyToUsername
|
|
2559
|
+
|| parsedArchive.conversationTargetBotUsername,
|
|
2560
|
+
);
|
|
2561
|
+
if (username) {
|
|
2562
|
+
return `@${username}`;
|
|
2563
|
+
}
|
|
2564
|
+
return firstNonEmptyString([
|
|
2565
|
+
parsedArchive.sender,
|
|
2566
|
+
parsedArchive.botName,
|
|
2567
|
+
parsedArchive.replyToSender,
|
|
2568
|
+
parsedArchive.chatTitle,
|
|
2569
|
+
buildRunnerReplyChainSpeakerType(parsedArchive) === "bot" ? "bot" : "human",
|
|
2570
|
+
]);
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
function normalizeRunnerReplyChainSnapshot(rawSnapshot) {
|
|
2574
|
+
const snapshot = safeObject(rawSnapshot);
|
|
2575
|
+
const messageID = intFromRawAllowZero(snapshot.message_id || snapshot.messageID, 0);
|
|
2576
|
+
const messageThreadID = intFromRawAllowZero(snapshot.message_thread_id || snapshot.messageThreadID, 0);
|
|
2577
|
+
const replyToMessageID = intFromRawAllowZero(snapshot.reply_to_message_id || snapshot.replyToMessageID, 0);
|
|
2578
|
+
const speakerType = String(snapshot.speaker_type || snapshot.speakerType || "").trim().toLowerCase();
|
|
2579
|
+
const body = truncateRunnerReplyChainText(snapshot.body || "");
|
|
2580
|
+
if (!(messageID > 0) && !body) {
|
|
2581
|
+
return null;
|
|
2582
|
+
}
|
|
2583
|
+
return {
|
|
2584
|
+
message_id: messageID || undefined,
|
|
2585
|
+
message_thread_id: messageThreadID || undefined,
|
|
2586
|
+
reply_to_message_id: replyToMessageID || undefined,
|
|
2587
|
+
speaker_type: speakerType === "bot" ? "bot" : "human",
|
|
2588
|
+
speaker_label: String(snapshot.speaker_label || snapshot.speakerLabel || "").trim(),
|
|
2589
|
+
body,
|
|
2590
|
+
};
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2593
|
+
function buildRunnerReplyChainSnapshotFromMessageEnvelope(envelopeRaw, overrides = {}) {
|
|
2594
|
+
const envelope = normalizeRunnerTelegramMessageEnvelope(envelopeRaw);
|
|
2595
|
+
if (!Object.keys(envelope).length) {
|
|
2596
|
+
return null;
|
|
2597
|
+
}
|
|
2598
|
+
return normalizeRunnerReplyChainSnapshot({
|
|
2599
|
+
message_id: envelope.message_id,
|
|
2600
|
+
message_thread_id: envelope.message_thread_id,
|
|
2601
|
+
reply_to_message_id: envelope.reply_to_message_id,
|
|
2602
|
+
speaker_type: firstNonEmptyString([
|
|
2603
|
+
overrides.speaker_type,
|
|
2604
|
+
envelope.sender_is_bot === true ? "bot" : "human",
|
|
2605
|
+
]),
|
|
2606
|
+
speaker_label: firstNonEmptyString([
|
|
2607
|
+
overrides.speaker_label,
|
|
2608
|
+
envelope.sender_username ? `@${String(envelope.sender_username || "").trim().replace(/^@+/, "")}` : "",
|
|
2609
|
+
envelope.sender,
|
|
2610
|
+
]),
|
|
2611
|
+
body: firstNonEmptyString([overrides.body, envelope.body]),
|
|
2612
|
+
});
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2615
|
+
function normalizeRunnerReplyChainContext(rawContext) {
|
|
2616
|
+
const context = safeObject(rawContext);
|
|
2617
|
+
const normalized = {
|
|
2618
|
+
conversation_id: String(context.conversation_id || context.conversationID || "").trim(),
|
|
2619
|
+
current_message_id: intFromRawAllowZero(context.current_message_id || context.currentMessageID, 0) || undefined,
|
|
2620
|
+
current_message_thread_id: intFromRawAllowZero(
|
|
2621
|
+
context.current_message_thread_id || context.currentMessageThreadID,
|
|
2622
|
+
0,
|
|
2623
|
+
) || undefined,
|
|
2624
|
+
parent_message_id: intFromRawAllowZero(context.parent_message_id || context.parentMessageID, 0) || undefined,
|
|
2625
|
+
root_message_id: intFromRawAllowZero(context.root_message_id || context.rootMessageID, 0) || undefined,
|
|
2626
|
+
current_turn_relation: String(context.current_turn_relation || context.currentTurnRelation || "").trim(),
|
|
2627
|
+
root_message: normalizeRunnerReplyChainSnapshot(context.root_message || context.rootMessage),
|
|
2628
|
+
parent_message: normalizeRunnerReplyChainSnapshot(context.parent_message || context.parentMessage),
|
|
2629
|
+
latest_prior_bot_reply: normalizeRunnerReplyChainSnapshot(
|
|
2630
|
+
context.latest_prior_bot_reply || context.latestPriorBotReply,
|
|
2631
|
+
),
|
|
2632
|
+
recent_chain_messages: ensureArray(context.recent_chain_messages || context.recentChainMessages)
|
|
2633
|
+
.map((item) => normalizeRunnerReplyChainSnapshot(item))
|
|
2634
|
+
.filter(Boolean)
|
|
2635
|
+
.slice(-4),
|
|
2636
|
+
};
|
|
2637
|
+
if (
|
|
2638
|
+
!normalized.conversation_id
|
|
2639
|
+
&& !(normalized.current_message_id > 0)
|
|
2640
|
+
&& !(normalized.current_message_thread_id > 0)
|
|
2641
|
+
&& !(normalized.parent_message_id > 0)
|
|
2642
|
+
&& !(normalized.root_message_id > 0)
|
|
2643
|
+
&& !normalized.current_turn_relation
|
|
2644
|
+
&& !normalized.root_message
|
|
2645
|
+
&& !normalized.parent_message
|
|
2646
|
+
&& !normalized.latest_prior_bot_reply
|
|
2647
|
+
&& !normalized.recent_chain_messages.length
|
|
2648
|
+
) {
|
|
2649
|
+
return {};
|
|
2650
|
+
}
|
|
2651
|
+
return normalized;
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2654
|
+
function findRunnerRouteLocalInboundEnvelope(routeStateRaw, parsedArchiveRaw) {
|
|
2655
|
+
const routeState = safeObject(routeStateRaw);
|
|
2656
|
+
const parsedArchive = safeObject(parsedArchiveRaw);
|
|
2657
|
+
const chatID = String(parsedArchive.chatID || parsedArchive.chatId || "").trim();
|
|
2658
|
+
const messageID = intFromRawAllowZero(parsedArchive.messageID, 0);
|
|
2659
|
+
return findRunnerRouteLocalInboundEnvelopeByMessage(routeState, {
|
|
2660
|
+
chatID,
|
|
2661
|
+
messageID,
|
|
2662
|
+
});
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2665
|
+
function findRunnerRouteLocalInboundEnvelopeByMessage(routeStateRaw, {
|
|
2666
|
+
chatID = "",
|
|
2667
|
+
messageID = 0,
|
|
2668
|
+
} = {}) {
|
|
2669
|
+
const routeState = safeObject(routeStateRaw);
|
|
2670
|
+
const normalizedChatID = String(chatID || "").trim();
|
|
2671
|
+
const normalizedMessageID = intFromRawAllowZero(messageID, 0);
|
|
2672
|
+
if (!normalizedChatID || !(normalizedMessageID > 0)) {
|
|
2673
|
+
return {};
|
|
2674
|
+
}
|
|
2675
|
+
return findRecentTelegramMessageEnvelope(routeState.recent_local_inbound_envelopes, {
|
|
2676
|
+
chatID: normalizedChatID,
|
|
2677
|
+
messageID: normalizedMessageID,
|
|
2678
|
+
});
|
|
2679
|
+
}
|
|
2680
|
+
|
|
2681
|
+
function mergeRunnerSourceMessageEnvelopes(primaryRaw, fallbackRaw) {
|
|
2682
|
+
const primary = normalizeRunnerTelegramMessageEnvelope(primaryRaw);
|
|
2683
|
+
const fallback = normalizeRunnerTelegramMessageEnvelope(fallbackRaw);
|
|
2684
|
+
return normalizeRunnerTelegramMessageEnvelope({
|
|
2685
|
+
...fallback,
|
|
2686
|
+
...primary,
|
|
2687
|
+
chat_id: firstNonEmptyString([primary.chat_id, fallback.chat_id]),
|
|
2688
|
+
message_id: intFromRawAllowZero(primary.message_id || fallback.message_id, 0) || undefined,
|
|
2689
|
+
message_thread_id: intFromRawAllowZero(
|
|
2690
|
+
primary.message_thread_id || fallback.message_thread_id,
|
|
2691
|
+
0,
|
|
2692
|
+
) || undefined,
|
|
2693
|
+
reply_to_message_id: intFromRawAllowZero(
|
|
2694
|
+
primary.reply_to_message_id || fallback.reply_to_message_id,
|
|
2695
|
+
0,
|
|
2696
|
+
) || undefined,
|
|
2697
|
+
body: firstNonEmptyString([primary.body, fallback.body]),
|
|
2698
|
+
source_origin: firstNonEmptyString([primary.source_origin, fallback.source_origin]),
|
|
2699
|
+
source_route_key: firstNonEmptyString([primary.source_route_key, fallback.source_route_key]),
|
|
2700
|
+
source_bot_username: firstNonEmptyString([primary.source_bot_username, fallback.source_bot_username]),
|
|
2701
|
+
});
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
function scoreRunnerSourceMessageEnvelopeAuthority(rawEnvelope) {
|
|
2705
|
+
const envelope = normalizeRunnerTelegramMessageEnvelope(rawEnvelope);
|
|
2706
|
+
if (!String(envelope.chat_id || "").trim() || !(intFromRawAllowZero(envelope.message_id, 0) > 0)) {
|
|
2707
|
+
return 0;
|
|
2708
|
+
}
|
|
2709
|
+
const origin = String(envelope.source_origin || "").trim().toLowerCase();
|
|
2710
|
+
let score = 0;
|
|
2711
|
+
switch (origin) {
|
|
2712
|
+
case "local_telegram_inbound":
|
|
2713
|
+
score = 500;
|
|
2714
|
+
break;
|
|
2715
|
+
case "archive_reconstructed":
|
|
2716
|
+
score = 100;
|
|
2717
|
+
break;
|
|
2718
|
+
default:
|
|
2719
|
+
score = 50;
|
|
2720
|
+
break;
|
|
2721
|
+
}
|
|
2722
|
+
if (String(envelope.source_route_key || "").trim()) score += 10;
|
|
2723
|
+
if (String(envelope.source_bot_username || "").trim()) score += 10;
|
|
2724
|
+
if (intFromRawAllowZero(envelope.reply_to_message_id, 0) > 0) score += 1;
|
|
2725
|
+
return score;
|
|
2726
|
+
}
|
|
2727
|
+
|
|
2728
|
+
function selectAuthoritativeRunnerSourceMessageEnvelope(primaryRaw, fallbackRaw) {
|
|
2729
|
+
const primary = normalizeRunnerTelegramMessageEnvelope(primaryRaw);
|
|
2730
|
+
const fallback = normalizeRunnerTelegramMessageEnvelope(fallbackRaw);
|
|
2731
|
+
const primaryScore = scoreRunnerSourceMessageEnvelopeAuthority(primary);
|
|
2732
|
+
const fallbackScore = scoreRunnerSourceMessageEnvelopeAuthority(fallback);
|
|
2733
|
+
if (!(primaryScore > 0)) {
|
|
2734
|
+
return fallback;
|
|
2735
|
+
}
|
|
2736
|
+
if (!(fallbackScore > 0)) {
|
|
2737
|
+
return primary;
|
|
2738
|
+
}
|
|
2739
|
+
if (primaryScore === fallbackScore) {
|
|
2740
|
+
return mergeRunnerSourceMessageEnvelopes(primary, fallback);
|
|
2741
|
+
}
|
|
2742
|
+
return primaryScore > fallbackScore ? primary : fallback;
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2745
|
+
function buildRunnerSourceMessageEnvelope({
|
|
2746
|
+
routeState = {},
|
|
2747
|
+
routeKey = "",
|
|
2748
|
+
normalizedRoute = null,
|
|
2749
|
+
parsedArchive = null,
|
|
2750
|
+
}) {
|
|
2751
|
+
const localEnvelope = findRunnerRouteLocalInboundEnvelope(routeState, parsedArchive);
|
|
2752
|
+
const fallbackBotSelector = normalizeTelegramMentionUsername(
|
|
2753
|
+
normalizedRoute?.botName
|
|
2754
|
+
|| normalizedRoute?.serverBotName
|
|
2755
|
+
|| "",
|
|
2756
|
+
);
|
|
2757
|
+
const archivedSourceEnvelope = buildRunnerTelegramMessageEnvelopeFromParsedArchive(parsedArchive);
|
|
2758
|
+
if (isTelegramLocalInboundEnvelopeForRoute(localEnvelope, {
|
|
2759
|
+
routeKey,
|
|
2760
|
+
botUsername: fallbackBotSelector,
|
|
2761
|
+
})) {
|
|
2762
|
+
return localEnvelope;
|
|
2763
|
+
}
|
|
2764
|
+
if (isTelegramLocalInboundEnvelopeForRoute(archivedSourceEnvelope, {
|
|
2765
|
+
routeKey,
|
|
2766
|
+
botUsername: fallbackBotSelector,
|
|
2767
|
+
})) {
|
|
2768
|
+
return archivedSourceEnvelope;
|
|
2769
|
+
}
|
|
2770
|
+
return buildRunnerTelegramMessageEnvelopeFromParsedArchive(parsedArchive, {
|
|
2771
|
+
source_origin: "archive_reconstructed",
|
|
2772
|
+
});
|
|
2773
|
+
}
|
|
2774
|
+
|
|
2775
|
+
function normalizeBotRunnerRequests(rawRequests, nowMs = Date.now()) {
|
|
2776
|
+
const normalized = {};
|
|
2777
|
+
for (const [requestKeyRaw, entryRaw] of Object.entries(safeObject(rawRequests))) {
|
|
2784
2778
|
const requestKey = String(requestKeyRaw || safeObject(entryRaw).request_key || "").trim();
|
|
2785
2779
|
if (!requestKey) continue;
|
|
2786
2780
|
const entry = safeObject(entryRaw);
|
|
2787
2781
|
const status = normalizeRunnerRequestStatus(entry.status);
|
|
2788
2782
|
const updatedAt = firstNonEmptyString([entry.updated_at, entry.updatedAt, entry.completed_at, entry.completedAt, entry.closed_at, entry.closedAt, entry.claimed_at, entry.claimedAt]);
|
|
2789
2783
|
const updatedAtMs = Date.parse(updatedAt);
|
|
2790
|
-
if (isFinalRunnerRequestStatus(status) && Number.isFinite(updatedAtMs) && nowMs - updatedAtMs > BOT_RUNNER_REQUEST_KEEP_MS) {
|
|
2791
|
-
continue;
|
|
2792
|
-
}
|
|
2793
|
-
const fallbackSourceMessageEnvelope = intFromRawAllowZero(entry.source_message_id || entry.sourceMessageID, 0) > 0
|
|
2794
|
-
? {
|
|
2795
|
-
chat_id: entry.chat_id || entry.chatID,
|
|
2796
|
-
message_id: entry.source_message_id || entry.sourceMessageID,
|
|
2797
|
-
message_thread_id: entry.source_message_thread_id || entry.sourceMessageThreadID,
|
|
2798
|
-
body: entry.source_message_body || entry.sourceMessageBody,
|
|
2799
|
-
sender: "human",
|
|
2800
|
-
sender_is_bot: false,
|
|
2801
|
-
source_origin: entry.source_message_origin || entry.sourceMessageOrigin,
|
|
2802
|
-
source_route_key: entry.source_message_route_key || entry.sourceMessageRouteKey,
|
|
2803
|
-
source_bot_username: entry.source_message_bot_username || entry.sourceMessageBotUsername,
|
|
2804
|
-
}
|
|
2805
|
-
: {};
|
|
2806
|
-
const normalizedSourceMessageEnvelope = normalizeRunnerTelegramMessageEnvelope({
|
|
2807
|
-
...safeObject(
|
|
2808
|
-
normalizeRunnerTelegramMessageEnvelope(
|
|
2809
|
-
entry.source_message_envelope
|
|
2810
|
-
|| entry.sourceMessageEnvelope
|
|
2811
|
-
|| fallbackSourceMessageEnvelope,
|
|
2812
|
-
),
|
|
2813
|
-
),
|
|
2814
|
-
chat_id: firstNonEmptyString([
|
|
2815
|
-
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).chat_id,
|
|
2816
|
-
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).chatID,
|
|
2817
|
-
entry.chat_id,
|
|
2818
|
-
entry.chatID,
|
|
2819
|
-
]),
|
|
2820
|
-
message_id: intFromRawAllowZero(
|
|
2821
|
-
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).message_id
|
|
2822
|
-
|| safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).messageID
|
|
2823
|
-
|| entry.source_message_id
|
|
2824
|
-
|| entry.sourceMessageID,
|
|
2825
|
-
0,
|
|
2826
|
-
) || undefined,
|
|
2827
|
-
message_thread_id: intFromRawAllowZero(
|
|
2828
|
-
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).message_thread_id
|
|
2829
|
-
|| safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).messageThreadID
|
|
2830
|
-
|| entry.source_message_thread_id
|
|
2831
|
-
|| entry.sourceMessageThreadID,
|
|
2832
|
-
0,
|
|
2833
|
-
) || undefined,
|
|
2834
|
-
body: firstNonEmptyString([
|
|
2835
|
-
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).body,
|
|
2836
|
-
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).text,
|
|
2837
|
-
entry.source_message_body,
|
|
2838
|
-
entry.sourceMessageBody,
|
|
2839
|
-
]),
|
|
2840
|
-
source_origin: firstNonEmptyString([
|
|
2841
|
-
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).source_origin,
|
|
2842
|
-
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).sourceOrigin,
|
|
2843
|
-
entry.source_message_origin,
|
|
2844
|
-
entry.sourceMessageOrigin,
|
|
2845
|
-
]),
|
|
2846
|
-
source_route_key: firstNonEmptyString([
|
|
2847
|
-
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).source_route_key,
|
|
2848
|
-
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).sourceRouteKey,
|
|
2849
|
-
entry.source_message_route_key,
|
|
2850
|
-
entry.sourceMessageRouteKey,
|
|
2851
|
-
]),
|
|
2852
|
-
source_bot_username: firstNonEmptyString([
|
|
2853
|
-
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).source_bot_username,
|
|
2854
|
-
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).sourceBotUsername,
|
|
2855
|
-
entry.source_message_bot_username,
|
|
2856
|
-
entry.sourceMessageBotUsername,
|
|
2857
|
-
]),
|
|
2858
|
-
});
|
|
2859
|
-
normalized[requestKey] = {
|
|
2860
|
-
request_key: requestKey,
|
|
2861
|
-
project_id: String(entry.project_id || entry.projectID || "").trim(),
|
|
2862
|
-
provider: String(entry.provider || "").trim(),
|
|
2863
|
-
chat_id: firstNonEmptyString([
|
|
2864
|
-
entry.chat_id,
|
|
2865
|
-
entry.chatID,
|
|
2866
|
-
normalizedSourceMessageEnvelope.chat_id,
|
|
2867
|
-
]),
|
|
2868
|
-
source_message_id: intFromRawAllowZero(
|
|
2869
|
-
entry.source_message_id
|
|
2870
|
-
|| entry.sourceMessageID
|
|
2871
|
-
|| normalizedSourceMessageEnvelope.message_id,
|
|
2872
|
-
0,
|
|
2873
|
-
) || undefined,
|
|
2874
|
-
source_message_thread_id: intFromRawAllowZero(
|
|
2875
|
-
entry.source_message_thread_id
|
|
2876
|
-
|| entry.sourceMessageThreadID
|
|
2877
|
-
|| normalizedSourceMessageEnvelope.message_thread_id,
|
|
2878
|
-
0,
|
|
2879
|
-
) || undefined,
|
|
2880
|
-
source_message_body: firstNonEmptyString([
|
|
2881
|
-
entry.source_message_body,
|
|
2882
|
-
entry.sourceMessageBody,
|
|
2883
|
-
normalizedSourceMessageEnvelope.body,
|
|
2884
|
-
]),
|
|
2885
|
-
source_message_origin: String(
|
|
2886
|
-
entry.source_message_origin
|
|
2887
|
-
|| entry.sourceMessageOrigin
|
|
2888
|
-
|| normalizedSourceMessageEnvelope.source_origin
|
|
2889
|
-
|| "",
|
|
2890
|
-
).trim().toLowerCase(),
|
|
2891
|
-
source_message_route_key: String(
|
|
2892
|
-
entry.source_message_route_key
|
|
2893
|
-
|| entry.sourceMessageRouteKey
|
|
2894
|
-
|| normalizedSourceMessageEnvelope.source_route_key
|
|
2895
|
-
|| "",
|
|
2896
|
-
).trim(),
|
|
2897
|
-
source_message_bot_username: normalizeTelegramMentionUsername(
|
|
2898
|
-
entry.source_message_bot_username
|
|
2899
|
-
|| entry.sourceMessageBotUsername
|
|
2900
|
-
|| normalizedSourceMessageEnvelope.source_bot_username,
|
|
2901
|
-
),
|
|
2902
|
-
source_message_envelope: normalizedSourceMessageEnvelope,
|
|
2903
|
-
root_comment_id: String(entry.root_comment_id || entry.rootCommentID || "").trim(),
|
|
2904
|
-
root_comment_kind: String(entry.root_comment_kind || entry.rootCommentKind || "").trim().toLowerCase(),
|
|
2905
|
-
conversation_id: String(entry.conversation_id || entry.conversationId || "").trim(),
|
|
2906
|
-
reply_chain_context: normalizeRunnerReplyChainContext(entry.reply_chain_context || entry.replyChainContext),
|
|
2907
|
-
selected_bot_usernames: ensureArray(entry.selected_bot_usernames || entry.selectedBotUsernames)
|
|
2908
|
-
.map((value) => normalizeTelegramMentionUsername(value))
|
|
2909
|
-
.filter(Boolean),
|
|
2784
|
+
if (isFinalRunnerRequestStatus(status) && Number.isFinite(updatedAtMs) && nowMs - updatedAtMs > BOT_RUNNER_REQUEST_KEEP_MS) {
|
|
2785
|
+
continue;
|
|
2786
|
+
}
|
|
2787
|
+
const fallbackSourceMessageEnvelope = intFromRawAllowZero(entry.source_message_id || entry.sourceMessageID, 0) > 0
|
|
2788
|
+
? {
|
|
2789
|
+
chat_id: entry.chat_id || entry.chatID,
|
|
2790
|
+
message_id: entry.source_message_id || entry.sourceMessageID,
|
|
2791
|
+
message_thread_id: entry.source_message_thread_id || entry.sourceMessageThreadID,
|
|
2792
|
+
body: entry.source_message_body || entry.sourceMessageBody,
|
|
2793
|
+
sender: "human",
|
|
2794
|
+
sender_is_bot: false,
|
|
2795
|
+
source_origin: entry.source_message_origin || entry.sourceMessageOrigin,
|
|
2796
|
+
source_route_key: entry.source_message_route_key || entry.sourceMessageRouteKey,
|
|
2797
|
+
source_bot_username: entry.source_message_bot_username || entry.sourceMessageBotUsername,
|
|
2798
|
+
}
|
|
2799
|
+
: {};
|
|
2800
|
+
const normalizedSourceMessageEnvelope = normalizeRunnerTelegramMessageEnvelope({
|
|
2801
|
+
...safeObject(
|
|
2802
|
+
normalizeRunnerTelegramMessageEnvelope(
|
|
2803
|
+
entry.source_message_envelope
|
|
2804
|
+
|| entry.sourceMessageEnvelope
|
|
2805
|
+
|| fallbackSourceMessageEnvelope,
|
|
2806
|
+
),
|
|
2807
|
+
),
|
|
2808
|
+
chat_id: firstNonEmptyString([
|
|
2809
|
+
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).chat_id,
|
|
2810
|
+
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).chatID,
|
|
2811
|
+
entry.chat_id,
|
|
2812
|
+
entry.chatID,
|
|
2813
|
+
]),
|
|
2814
|
+
message_id: intFromRawAllowZero(
|
|
2815
|
+
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).message_id
|
|
2816
|
+
|| safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).messageID
|
|
2817
|
+
|| entry.source_message_id
|
|
2818
|
+
|| entry.sourceMessageID,
|
|
2819
|
+
0,
|
|
2820
|
+
) || undefined,
|
|
2821
|
+
message_thread_id: intFromRawAllowZero(
|
|
2822
|
+
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).message_thread_id
|
|
2823
|
+
|| safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).messageThreadID
|
|
2824
|
+
|| entry.source_message_thread_id
|
|
2825
|
+
|| entry.sourceMessageThreadID,
|
|
2826
|
+
0,
|
|
2827
|
+
) || undefined,
|
|
2828
|
+
body: firstNonEmptyString([
|
|
2829
|
+
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).body,
|
|
2830
|
+
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).text,
|
|
2831
|
+
entry.source_message_body,
|
|
2832
|
+
entry.sourceMessageBody,
|
|
2833
|
+
]),
|
|
2834
|
+
source_origin: firstNonEmptyString([
|
|
2835
|
+
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).source_origin,
|
|
2836
|
+
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).sourceOrigin,
|
|
2837
|
+
entry.source_message_origin,
|
|
2838
|
+
entry.sourceMessageOrigin,
|
|
2839
|
+
]),
|
|
2840
|
+
source_route_key: firstNonEmptyString([
|
|
2841
|
+
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).source_route_key,
|
|
2842
|
+
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).sourceRouteKey,
|
|
2843
|
+
entry.source_message_route_key,
|
|
2844
|
+
entry.sourceMessageRouteKey,
|
|
2845
|
+
]),
|
|
2846
|
+
source_bot_username: firstNonEmptyString([
|
|
2847
|
+
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).source_bot_username,
|
|
2848
|
+
safeObject(entry.source_message_envelope || entry.sourceMessageEnvelope).sourceBotUsername,
|
|
2849
|
+
entry.source_message_bot_username,
|
|
2850
|
+
entry.sourceMessageBotUsername,
|
|
2851
|
+
]),
|
|
2852
|
+
});
|
|
2853
|
+
normalized[requestKey] = {
|
|
2854
|
+
request_key: requestKey,
|
|
2855
|
+
project_id: String(entry.project_id || entry.projectID || "").trim(),
|
|
2856
|
+
provider: String(entry.provider || "").trim(),
|
|
2857
|
+
chat_id: firstNonEmptyString([
|
|
2858
|
+
entry.chat_id,
|
|
2859
|
+
entry.chatID,
|
|
2860
|
+
normalizedSourceMessageEnvelope.chat_id,
|
|
2861
|
+
]),
|
|
2862
|
+
source_message_id: intFromRawAllowZero(
|
|
2863
|
+
entry.source_message_id
|
|
2864
|
+
|| entry.sourceMessageID
|
|
2865
|
+
|| normalizedSourceMessageEnvelope.message_id,
|
|
2866
|
+
0,
|
|
2867
|
+
) || undefined,
|
|
2868
|
+
source_message_thread_id: intFromRawAllowZero(
|
|
2869
|
+
entry.source_message_thread_id
|
|
2870
|
+
|| entry.sourceMessageThreadID
|
|
2871
|
+
|| normalizedSourceMessageEnvelope.message_thread_id,
|
|
2872
|
+
0,
|
|
2873
|
+
) || undefined,
|
|
2874
|
+
source_message_body: firstNonEmptyString([
|
|
2875
|
+
entry.source_message_body,
|
|
2876
|
+
entry.sourceMessageBody,
|
|
2877
|
+
normalizedSourceMessageEnvelope.body,
|
|
2878
|
+
]),
|
|
2879
|
+
source_message_origin: String(
|
|
2880
|
+
entry.source_message_origin
|
|
2881
|
+
|| entry.sourceMessageOrigin
|
|
2882
|
+
|| normalizedSourceMessageEnvelope.source_origin
|
|
2883
|
+
|| "",
|
|
2884
|
+
).trim().toLowerCase(),
|
|
2885
|
+
source_message_route_key: String(
|
|
2886
|
+
entry.source_message_route_key
|
|
2887
|
+
|| entry.sourceMessageRouteKey
|
|
2888
|
+
|| normalizedSourceMessageEnvelope.source_route_key
|
|
2889
|
+
|| "",
|
|
2890
|
+
).trim(),
|
|
2891
|
+
source_message_bot_username: normalizeTelegramMentionUsername(
|
|
2892
|
+
entry.source_message_bot_username
|
|
2893
|
+
|| entry.sourceMessageBotUsername
|
|
2894
|
+
|| normalizedSourceMessageEnvelope.source_bot_username,
|
|
2895
|
+
),
|
|
2896
|
+
source_message_envelope: normalizedSourceMessageEnvelope,
|
|
2897
|
+
root_comment_id: String(entry.root_comment_id || entry.rootCommentID || "").trim(),
|
|
2898
|
+
root_comment_kind: String(entry.root_comment_kind || entry.rootCommentKind || "").trim().toLowerCase(),
|
|
2899
|
+
conversation_id: String(entry.conversation_id || entry.conversationId || "").trim(),
|
|
2900
|
+
reply_chain_context: normalizeRunnerReplyChainContext(entry.reply_chain_context || entry.replyChainContext),
|
|
2901
|
+
selected_bot_usernames: ensureArray(entry.selected_bot_usernames || entry.selectedBotUsernames)
|
|
2902
|
+
.map((value) => normalizeTelegramMentionUsername(value))
|
|
2903
|
+
.filter(Boolean),
|
|
2910
2904
|
conversation_allowed_responders: ensureArray(entry.conversation_allowed_responders || entry.conversationAllowedResponders)
|
|
2911
2905
|
.map((value) => normalizeTelegramMentionUsername(value))
|
|
2912
2906
|
.filter(Boolean),
|
|
@@ -3020,37 +3014,37 @@ function normalizeBotRunnerRequests(rawRequests, nowMs = Date.now()) {
|
|
|
3020
3014
|
root_thread_id: String(entry.root_thread_id || entry.rootThreadID || "").trim(),
|
|
3021
3015
|
root_work_item_created_at: firstNonEmptyString([entry.root_work_item_created_at, entry.rootWorkItemCreatedAt]),
|
|
3022
3016
|
root_work_item_last_error: String(entry.root_work_item_last_error || entry.rootWorkItemLastError || "").trim(),
|
|
3023
|
-
last_comment_id: String(entry.last_comment_id || entry.lastCommentID || "").trim(),
|
|
3024
|
-
last_comment_kind: String(entry.last_comment_kind || entry.lastCommentKind || "").trim().toLowerCase(),
|
|
3025
|
-
last_source_message_id: intFromRawAllowZero(entry.last_source_message_id || entry.lastSourceMessageID, 0) || undefined,
|
|
3026
|
-
last_source_message_thread_id: intFromRawAllowZero(
|
|
3027
|
-
entry.last_source_message_thread_id || entry.lastSourceMessageThreadID,
|
|
3028
|
-
0,
|
|
3029
|
-
) || undefined,
|
|
3030
|
-
last_reply_message_id: intFromRawAllowZero(entry.last_reply_message_id || entry.lastReplyMessageID, 0) || undefined,
|
|
3031
|
-
last_reply_message_thread_id: intFromRawAllowZero(
|
|
3032
|
-
entry.last_reply_message_thread_id || entry.lastReplyMessageThreadID,
|
|
3033
|
-
0,
|
|
3034
|
-
) || undefined,
|
|
3035
|
-
last_reply_to_message_id: intFromRawAllowZero(
|
|
3036
|
-
entry.last_reply_to_message_id || entry.lastReplyToMessageID,
|
|
3037
|
-
0,
|
|
3038
|
-
) || undefined,
|
|
3039
|
-
last_reply_message_envelope: normalizeRunnerTelegramMessageEnvelope(
|
|
3040
|
-
entry.last_reply_message_envelope
|
|
3041
|
-
|| entry.lastReplyMessageEnvelope
|
|
3042
|
-
|| {},
|
|
3043
|
-
),
|
|
3044
|
-
attempted_delivery_envelope: normalizeRunnerTelegramMessageEnvelope(
|
|
3045
|
-
entry.attempted_delivery_envelope
|
|
3046
|
-
|| entry.attemptedDeliveryEnvelope
|
|
3047
|
-
|| {},
|
|
3048
|
-
),
|
|
3049
|
-
updated_at: updatedAt || new Date(nowMs).toISOString(),
|
|
3050
|
-
};
|
|
3051
|
-
}
|
|
3052
|
-
return normalized;
|
|
3053
|
-
}
|
|
3017
|
+
last_comment_id: String(entry.last_comment_id || entry.lastCommentID || "").trim(),
|
|
3018
|
+
last_comment_kind: String(entry.last_comment_kind || entry.lastCommentKind || "").trim().toLowerCase(),
|
|
3019
|
+
last_source_message_id: intFromRawAllowZero(entry.last_source_message_id || entry.lastSourceMessageID, 0) || undefined,
|
|
3020
|
+
last_source_message_thread_id: intFromRawAllowZero(
|
|
3021
|
+
entry.last_source_message_thread_id || entry.lastSourceMessageThreadID,
|
|
3022
|
+
0,
|
|
3023
|
+
) || undefined,
|
|
3024
|
+
last_reply_message_id: intFromRawAllowZero(entry.last_reply_message_id || entry.lastReplyMessageID, 0) || undefined,
|
|
3025
|
+
last_reply_message_thread_id: intFromRawAllowZero(
|
|
3026
|
+
entry.last_reply_message_thread_id || entry.lastReplyMessageThreadID,
|
|
3027
|
+
0,
|
|
3028
|
+
) || undefined,
|
|
3029
|
+
last_reply_to_message_id: intFromRawAllowZero(
|
|
3030
|
+
entry.last_reply_to_message_id || entry.lastReplyToMessageID,
|
|
3031
|
+
0,
|
|
3032
|
+
) || undefined,
|
|
3033
|
+
last_reply_message_envelope: normalizeRunnerTelegramMessageEnvelope(
|
|
3034
|
+
entry.last_reply_message_envelope
|
|
3035
|
+
|| entry.lastReplyMessageEnvelope
|
|
3036
|
+
|| {},
|
|
3037
|
+
),
|
|
3038
|
+
attempted_delivery_envelope: normalizeRunnerTelegramMessageEnvelope(
|
|
3039
|
+
entry.attempted_delivery_envelope
|
|
3040
|
+
|| entry.attemptedDeliveryEnvelope
|
|
3041
|
+
|| {},
|
|
3042
|
+
),
|
|
3043
|
+
updated_at: updatedAt || new Date(nowMs).toISOString(),
|
|
3044
|
+
};
|
|
3045
|
+
}
|
|
3046
|
+
return normalized;
|
|
3047
|
+
}
|
|
3054
3048
|
|
|
3055
3049
|
function normalizeBotRunnerConsumedComments(rawConsumed, nowMs = Date.now()) {
|
|
3056
3050
|
const normalized = {};
|
|
@@ -3257,40 +3251,40 @@ function uniqueOrderedStrings(values, normalizer = (value) => String(value || ""
|
|
|
3257
3251
|
return output;
|
|
3258
3252
|
}
|
|
3259
3253
|
|
|
3260
|
-
function buildRunnerRequestKey({
|
|
3261
|
-
normalizedRoute,
|
|
3262
|
-
selectedRecord,
|
|
3263
|
-
selectedBotUsernames = [],
|
|
3264
|
-
normalizedIntent = "",
|
|
3265
|
-
conversationID = "",
|
|
3266
|
-
}) {
|
|
3267
|
-
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
3268
|
-
const chatID = String(parsed.chatID || parsed.chatId || "").trim() || "-";
|
|
3269
|
-
const messageID = intFromRawAllowZero(parsed.messageID, 0);
|
|
3270
|
-
const kind = String(parsed.kind || "").trim().toLowerCase() || "-";
|
|
3271
|
-
const responders = uniqueOrderedStrings(selectedBotUsernames, normalizeTelegramMentionUsername).join(",") || "-";
|
|
3272
|
-
const intent = String(normalizedIntent || "").trim().toLowerCase() || "-";
|
|
3273
|
-
const resolvedConversationID = String(conversationID || parsed.conversationID || "").trim() || "-";
|
|
3274
|
-
return [
|
|
3275
|
-
String(normalizedRoute?.projectID || "").trim() || "-",
|
|
3276
|
-
String(normalizedRoute?.provider || "").trim() || "-",
|
|
3277
|
-
chatID,
|
|
3278
|
-
String(messageID || "-"),
|
|
3279
|
-
kind,
|
|
3280
|
-
responders,
|
|
3281
|
-
intent,
|
|
3282
|
-
resolvedConversationID,
|
|
3283
|
-
].join("::");
|
|
3284
|
-
}
|
|
3285
|
-
|
|
3286
|
-
function resolveRunnerRequestClaimIntent({
|
|
3287
|
-
normalizedIntent = "",
|
|
3288
|
-
selectedRecord,
|
|
3289
|
-
}) {
|
|
3290
|
-
void selectedRecord;
|
|
3291
|
-
const explicitIntent = String(normalizedIntent || "").trim().toLowerCase();
|
|
3292
|
-
return explicitIntent;
|
|
3293
|
-
}
|
|
3254
|
+
function buildRunnerRequestKey({
|
|
3255
|
+
normalizedRoute,
|
|
3256
|
+
selectedRecord,
|
|
3257
|
+
selectedBotUsernames = [],
|
|
3258
|
+
normalizedIntent = "",
|
|
3259
|
+
conversationID = "",
|
|
3260
|
+
}) {
|
|
3261
|
+
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
3262
|
+
const chatID = String(parsed.chatID || parsed.chatId || "").trim() || "-";
|
|
3263
|
+
const messageID = intFromRawAllowZero(parsed.messageID, 0);
|
|
3264
|
+
const kind = String(parsed.kind || "").trim().toLowerCase() || "-";
|
|
3265
|
+
const responders = uniqueOrderedStrings(selectedBotUsernames, normalizeTelegramMentionUsername).join(",") || "-";
|
|
3266
|
+
const intent = String(normalizedIntent || "").trim().toLowerCase() || "-";
|
|
3267
|
+
const resolvedConversationID = String(conversationID || parsed.conversationID || "").trim() || "-";
|
|
3268
|
+
return [
|
|
3269
|
+
String(normalizedRoute?.projectID || "").trim() || "-",
|
|
3270
|
+
String(normalizedRoute?.provider || "").trim() || "-",
|
|
3271
|
+
chatID,
|
|
3272
|
+
String(messageID || "-"),
|
|
3273
|
+
kind,
|
|
3274
|
+
responders,
|
|
3275
|
+
intent,
|
|
3276
|
+
resolvedConversationID,
|
|
3277
|
+
].join("::");
|
|
3278
|
+
}
|
|
3279
|
+
|
|
3280
|
+
function resolveRunnerRequestClaimIntent({
|
|
3281
|
+
normalizedIntent = "",
|
|
3282
|
+
selectedRecord,
|
|
3283
|
+
}) {
|
|
3284
|
+
void selectedRecord;
|
|
3285
|
+
const explicitIntent = String(normalizedIntent || "").trim().toLowerCase();
|
|
3286
|
+
return explicitIntent;
|
|
3287
|
+
}
|
|
3294
3288
|
|
|
3295
3289
|
function buildSyntheticReplyChainConversationID(normalizedRoute, chatID, anchorMessageID) {
|
|
3296
3290
|
const provider = String(normalizedRoute?.provider || "").trim() || "unknown";
|
|
@@ -3595,9 +3589,9 @@ function runnerRequestPreferredExecutionContractTargets(entryRaw) {
|
|
|
3595
3589
|
);
|
|
3596
3590
|
}
|
|
3597
3591
|
|
|
3598
|
-
function runnerRequestPreferredNextExpectedResponders(entryRaw) {
|
|
3599
|
-
const entry = safeObject(entryRaw);
|
|
3600
|
-
return uniqueOrderedStrings(
|
|
3592
|
+
function runnerRequestPreferredNextExpectedResponders(entryRaw) {
|
|
3593
|
+
const entry = safeObject(entryRaw);
|
|
3594
|
+
return uniqueOrderedStrings(
|
|
3601
3595
|
ensureArray(entry.next_expected_responders).length
|
|
3602
3596
|
? entry.next_expected_responders
|
|
3603
3597
|
: ensureArray(entry.followup_next_expected_responders).length
|
|
@@ -3605,40 +3599,40 @@ function runnerRequestPreferredNextExpectedResponders(entryRaw) {
|
|
|
3605
3599
|
: ensureArray(entry.root_next_expected_responders).length
|
|
3606
3600
|
? entry.root_next_expected_responders
|
|
3607
3601
|
: [],
|
|
3608
|
-
normalizeTelegramMentionUsername,
|
|
3609
|
-
);
|
|
3610
|
-
}
|
|
3611
|
-
|
|
3612
|
-
function runnerRequestPreferredAuthoritySelectedBotUsernames(entryRaw) {
|
|
3613
|
-
const entry = safeObject(entryRaw);
|
|
3614
|
-
const normalizedSummaryBot = normalizeTelegramMentionUsername(entry.conversation_summary_bot);
|
|
3615
|
-
return uniqueOrderedStrings(
|
|
3616
|
-
runnerRequestPreferredNextExpectedResponders(entry).length
|
|
3617
|
-
? runnerRequestPreferredNextExpectedResponders(entry)
|
|
3618
|
-
: runnerRequestPreferredExecutionContractTargets(entry).length
|
|
3619
|
-
? runnerRequestPreferredExecutionContractTargets(entry)
|
|
3620
|
-
: ensureArray(entry.selected_bot_usernames).length
|
|
3621
|
-
? entry.selected_bot_usernames
|
|
3622
|
-
: ensureArray(entry.conversation_initial_responders).length
|
|
3623
|
-
? entry.conversation_initial_responders
|
|
3624
|
-
: normalizedSummaryBot
|
|
3625
|
-
? [normalizedSummaryBot]
|
|
3626
|
-
: [],
|
|
3627
|
-
normalizeTelegramMentionUsername,
|
|
3628
|
-
);
|
|
3629
|
-
}
|
|
3630
|
-
|
|
3631
|
-
function extractRunnerExplicitSelectedBotUsernamesFromParsed(parsedArchiveRaw) {
|
|
3632
|
-
const parsedArchive = safeObject(parsedArchiveRaw);
|
|
3633
|
-
return uniqueOrderedStrings(
|
|
3634
|
-
ensureArray(parsedArchive.mentionUsernames).length
|
|
3635
|
-
? parsedArchive.mentionUsernames
|
|
3636
|
-
: String(parsedArchive.replyToUsername || "").trim()
|
|
3637
|
-
? [parsedArchive.replyToUsername]
|
|
3638
|
-
: [],
|
|
3639
|
-
normalizeTelegramMentionUsername,
|
|
3640
|
-
);
|
|
3641
|
-
}
|
|
3602
|
+
normalizeTelegramMentionUsername,
|
|
3603
|
+
);
|
|
3604
|
+
}
|
|
3605
|
+
|
|
3606
|
+
function runnerRequestPreferredAuthoritySelectedBotUsernames(entryRaw) {
|
|
3607
|
+
const entry = safeObject(entryRaw);
|
|
3608
|
+
const normalizedSummaryBot = normalizeTelegramMentionUsername(entry.conversation_summary_bot);
|
|
3609
|
+
return uniqueOrderedStrings(
|
|
3610
|
+
runnerRequestPreferredNextExpectedResponders(entry).length
|
|
3611
|
+
? runnerRequestPreferredNextExpectedResponders(entry)
|
|
3612
|
+
: runnerRequestPreferredExecutionContractTargets(entry).length
|
|
3613
|
+
? runnerRequestPreferredExecutionContractTargets(entry)
|
|
3614
|
+
: ensureArray(entry.selected_bot_usernames).length
|
|
3615
|
+
? entry.selected_bot_usernames
|
|
3616
|
+
: ensureArray(entry.conversation_initial_responders).length
|
|
3617
|
+
? entry.conversation_initial_responders
|
|
3618
|
+
: normalizedSummaryBot
|
|
3619
|
+
? [normalizedSummaryBot]
|
|
3620
|
+
: [],
|
|
3621
|
+
normalizeTelegramMentionUsername,
|
|
3622
|
+
);
|
|
3623
|
+
}
|
|
3624
|
+
|
|
3625
|
+
function extractRunnerExplicitSelectedBotUsernamesFromParsed(parsedArchiveRaw) {
|
|
3626
|
+
const parsedArchive = safeObject(parsedArchiveRaw);
|
|
3627
|
+
return uniqueOrderedStrings(
|
|
3628
|
+
ensureArray(parsedArchive.mentionUsernames).length
|
|
3629
|
+
? parsedArchive.mentionUsernames
|
|
3630
|
+
: String(parsedArchive.replyToUsername || "").trim()
|
|
3631
|
+
? [parsedArchive.replyToUsername]
|
|
3632
|
+
: [],
|
|
3633
|
+
normalizeTelegramMentionUsername,
|
|
3634
|
+
);
|
|
3635
|
+
}
|
|
3642
3636
|
|
|
3643
3637
|
function runnerRequestPreferredAIReplyPreview(entryRaw) {
|
|
3644
3638
|
const entry = safeObject(entryRaw);
|
|
@@ -3750,26 +3744,26 @@ function runnerRequestPreferredArchiveError(entryRaw) {
|
|
|
3750
3744
|
).trim();
|
|
3751
3745
|
}
|
|
3752
3746
|
|
|
3753
|
-
function buildRunnerValidationAndDeliverySummary({
|
|
3754
|
-
aiReplyPreview = "",
|
|
3755
|
-
executionContractType = "",
|
|
3756
|
-
executionContractTargets = [],
|
|
3757
|
-
nextExpectedResponders = [],
|
|
3747
|
+
function buildRunnerValidationAndDeliverySummary({
|
|
3748
|
+
aiReplyPreview = "",
|
|
3749
|
+
executionContractType = "",
|
|
3750
|
+
executionContractTargets = [],
|
|
3751
|
+
nextExpectedResponders = [],
|
|
3758
3752
|
responseContractValidationStatus = "",
|
|
3759
3753
|
responseContractValidationReason = "",
|
|
3760
3754
|
responseContractValidationTargets = [],
|
|
3761
3755
|
assignmentValidationStatus = "",
|
|
3762
3756
|
assignmentValidationReason = "",
|
|
3763
3757
|
assignmentValidationModes = [],
|
|
3764
|
-
deliveryStatus = "",
|
|
3765
|
-
archiveStatus = "",
|
|
3766
|
-
transportError = "",
|
|
3767
|
-
archiveError = "",
|
|
3768
|
-
sourceMessageEnvelope = {},
|
|
3769
|
-
lastReplyMessageEnvelope = {},
|
|
3770
|
-
attemptedDeliveryEnvelope = {},
|
|
3771
|
-
} = {}) {
|
|
3772
|
-
return {
|
|
3758
|
+
deliveryStatus = "",
|
|
3759
|
+
archiveStatus = "",
|
|
3760
|
+
transportError = "",
|
|
3761
|
+
archiveError = "",
|
|
3762
|
+
sourceMessageEnvelope = {},
|
|
3763
|
+
lastReplyMessageEnvelope = {},
|
|
3764
|
+
attemptedDeliveryEnvelope = {},
|
|
3765
|
+
} = {}) {
|
|
3766
|
+
return {
|
|
3773
3767
|
ai_reply_preview: String(aiReplyPreview || "").trim(),
|
|
3774
3768
|
execution_contract_type: String(executionContractType || "").trim().toLowerCase(),
|
|
3775
3769
|
execution_contract_targets: uniqueOrderedStrings(
|
|
@@ -3792,15 +3786,15 @@ function buildRunnerValidationAndDeliverySummary({
|
|
|
3792
3786
|
ensureArray(assignmentValidationModes),
|
|
3793
3787
|
(value) => String(value || "").trim().toLowerCase(),
|
|
3794
3788
|
),
|
|
3795
|
-
delivery_status: String(deliveryStatus || "").trim().toLowerCase(),
|
|
3796
|
-
archive_status: String(archiveStatus || "").trim().toLowerCase(),
|
|
3797
|
-
transport_error: String(transportError || "").trim(),
|
|
3798
|
-
archive_error: String(archiveError || "").trim(),
|
|
3799
|
-
source_message_envelope: safeObject(sourceMessageEnvelope),
|
|
3800
|
-
last_reply_message_envelope: safeObject(lastReplyMessageEnvelope),
|
|
3801
|
-
attempted_delivery_envelope: safeObject(attemptedDeliveryEnvelope),
|
|
3802
|
-
};
|
|
3803
|
-
}
|
|
3789
|
+
delivery_status: String(deliveryStatus || "").trim().toLowerCase(),
|
|
3790
|
+
archive_status: String(archiveStatus || "").trim().toLowerCase(),
|
|
3791
|
+
transport_error: String(transportError || "").trim(),
|
|
3792
|
+
archive_error: String(archiveError || "").trim(),
|
|
3793
|
+
source_message_envelope: safeObject(sourceMessageEnvelope),
|
|
3794
|
+
last_reply_message_envelope: safeObject(lastReplyMessageEnvelope),
|
|
3795
|
+
attempted_delivery_envelope: safeObject(attemptedDeliveryEnvelope),
|
|
3796
|
+
};
|
|
3797
|
+
}
|
|
3804
3798
|
|
|
3805
3799
|
function buildRunnerRequestRootWorkItemSummary(entryRaw) {
|
|
3806
3800
|
const entry = safeObject(entryRaw);
|
|
@@ -3816,8 +3810,8 @@ function buildRunnerRequestRootWorkItemSummary(entryRaw) {
|
|
|
3816
3810
|
};
|
|
3817
3811
|
}
|
|
3818
3812
|
|
|
3819
|
-
function buildRunnerRouteLastResultSummary(routeStateRaw) {
|
|
3820
|
-
const routeState = safeObject(routeStateRaw);
|
|
3813
|
+
function buildRunnerRouteLastResultSummary(routeStateRaw) {
|
|
3814
|
+
const routeState = safeObject(routeStateRaw);
|
|
3821
3815
|
const executionContractType = String(
|
|
3822
3816
|
routeState.last_followup_execution_contract_type
|
|
3823
3817
|
|| routeState.last_normalized_execution_contract_type
|
|
@@ -3865,18 +3859,18 @@ function buildRunnerRouteLastResultSummary(routeStateRaw) {
|
|
|
3865
3859
|
ensureArray(routeState.last_followup_assignment_validation_modes),
|
|
3866
3860
|
(value) => String(value || "").trim().toLowerCase(),
|
|
3867
3861
|
);
|
|
3868
|
-
return {
|
|
3869
|
-
action: String(routeState.last_action || "").trim(),
|
|
3870
|
-
reason: String(routeState.last_reason || "").trim(),
|
|
3871
|
-
visibility_status: String(routeState.last_visibility_status || "").trim(),
|
|
3872
|
-
visibility_reason: String(routeState.last_visibility_reason || "").trim(),
|
|
3873
|
-
visibility_source: String(routeState.last_visibility_source || "").trim(),
|
|
3874
|
-
candidate_bot_usernames: uniqueOrderedStrings(
|
|
3875
|
-
ensureArray(routeState.last_candidate_bot_usernames),
|
|
3876
|
-
normalizeTelegramMentionUsername,
|
|
3877
|
-
),
|
|
3878
|
-
intent_type: String(routeState.last_intent_type || "").trim(),
|
|
3879
|
-
...buildRunnerValidationAndDeliverySummary({
|
|
3862
|
+
return {
|
|
3863
|
+
action: String(routeState.last_action || "").trim(),
|
|
3864
|
+
reason: String(routeState.last_reason || "").trim(),
|
|
3865
|
+
visibility_status: String(routeState.last_visibility_status || "").trim(),
|
|
3866
|
+
visibility_reason: String(routeState.last_visibility_reason || "").trim(),
|
|
3867
|
+
visibility_source: String(routeState.last_visibility_source || "").trim(),
|
|
3868
|
+
candidate_bot_usernames: uniqueOrderedStrings(
|
|
3869
|
+
ensureArray(routeState.last_candidate_bot_usernames),
|
|
3870
|
+
normalizeTelegramMentionUsername,
|
|
3871
|
+
),
|
|
3872
|
+
intent_type: String(routeState.last_intent_type || "").trim(),
|
|
3873
|
+
...buildRunnerValidationAndDeliverySummary({
|
|
3880
3874
|
aiReplyPreview: routeState.last_followup_ai_reply_preview,
|
|
3881
3875
|
executionContractType,
|
|
3882
3876
|
executionContractTargets,
|
|
@@ -3886,15 +3880,15 @@ function buildRunnerRouteLastResultSummary(routeStateRaw) {
|
|
|
3886
3880
|
responseContractValidationTargets,
|
|
3887
3881
|
assignmentValidationStatus,
|
|
3888
3882
|
assignmentValidationReason,
|
|
3889
|
-
assignmentValidationModes,
|
|
3890
|
-
deliveryStatus: routeState.last_followup_delivery_status,
|
|
3891
|
-
archiveStatus: routeState.last_followup_archive_status,
|
|
3892
|
-
transportError: routeState.last_followup_transport_error,
|
|
3893
|
-
archiveError: routeState.last_followup_archive_error,
|
|
3894
|
-
sourceMessageEnvelope: routeState.last_followup_source_message_envelope,
|
|
3895
|
-
lastReplyMessageEnvelope: routeState.last_followup_last_reply_message_envelope,
|
|
3896
|
-
attemptedDeliveryEnvelope: routeState.last_followup_attempted_delivery_envelope,
|
|
3897
|
-
}),
|
|
3883
|
+
assignmentValidationModes,
|
|
3884
|
+
deliveryStatus: routeState.last_followup_delivery_status,
|
|
3885
|
+
archiveStatus: routeState.last_followup_archive_status,
|
|
3886
|
+
transportError: routeState.last_followup_transport_error,
|
|
3887
|
+
archiveError: routeState.last_followup_archive_error,
|
|
3888
|
+
sourceMessageEnvelope: routeState.last_followup_source_message_envelope,
|
|
3889
|
+
lastReplyMessageEnvelope: routeState.last_followup_last_reply_message_envelope,
|
|
3890
|
+
attemptedDeliveryEnvelope: routeState.last_followup_attempted_delivery_envelope,
|
|
3891
|
+
}),
|
|
3898
3892
|
workspace_dir: String(routeState.last_workspace_dir || "").trim(),
|
|
3899
3893
|
artifact_validation: String(routeState.last_artifact_validation || "").trim(),
|
|
3900
3894
|
artifact_paths: ensureArray(routeState.last_artifact_paths).map((item) => String(item || "").trim()).filter(Boolean),
|
|
@@ -4058,10 +4052,10 @@ async function loadRunnerArchiveThreadMessageIndex({
|
|
|
4058
4052
|
}
|
|
4059
4053
|
}
|
|
4060
4054
|
|
|
4061
|
-
async function findRunnerArchiveThreadMessageByID({
|
|
4062
|
-
runtime,
|
|
4063
|
-
threadID,
|
|
4064
|
-
messageID,
|
|
4055
|
+
async function findRunnerArchiveThreadMessageByID({
|
|
4056
|
+
runtime,
|
|
4057
|
+
threadID,
|
|
4058
|
+
messageID,
|
|
4065
4059
|
cache = null,
|
|
4066
4060
|
}) {
|
|
4067
4061
|
const nextCache = await loadRunnerArchiveThreadMessageIndex({
|
|
@@ -4069,244 +4063,244 @@ async function findRunnerArchiveThreadMessageByID({
|
|
|
4069
4063
|
threadID,
|
|
4070
4064
|
cache,
|
|
4071
4065
|
});
|
|
4072
|
-
return {
|
|
4073
|
-
cache: nextCache,
|
|
4074
|
-
record: safeObject(nextCache.messageIndex.get(intFromRawAllowZero(messageID, 0))),
|
|
4075
|
-
};
|
|
4076
|
-
}
|
|
4077
|
-
|
|
4078
|
-
function buildRunnerReplyChainSnapshotFromParsedArchive(parsedArchiveRaw, overrides = {}) {
|
|
4079
|
-
const parsedArchive = safeObject(parsedArchiveRaw);
|
|
4080
|
-
return buildRunnerReplyChainSnapshotFromMessageEnvelope(
|
|
4081
|
-
buildRunnerTelegramMessageEnvelopeFromParsedArchive(parsedArchive, overrides),
|
|
4082
|
-
{
|
|
4083
|
-
speaker_type: firstNonEmptyString([
|
|
4084
|
-
overrides.speaker_type,
|
|
4085
|
-
buildRunnerReplyChainSpeakerType(parsedArchive),
|
|
4086
|
-
]),
|
|
4087
|
-
speaker_label: firstNonEmptyString([
|
|
4088
|
-
overrides.speaker_label,
|
|
4089
|
-
buildRunnerReplyChainSpeakerLabel(parsedArchive),
|
|
4090
|
-
]),
|
|
4091
|
-
body: truncateRunnerReplyChainText(
|
|
4092
|
-
firstNonEmptyString([overrides.body, parsedArchive.body]),
|
|
4093
|
-
),
|
|
4094
|
-
},
|
|
4095
|
-
);
|
|
4096
|
-
}
|
|
4097
|
-
|
|
4098
|
-
function buildRunnerReplyChainSnapshotFromArchiveRecord(recordRaw) {
|
|
4099
|
-
const record = safeObject(recordRaw);
|
|
4100
|
-
const parsedArchive = safeObject(record.parsedArchive || parseArchivedChatComment(record.body));
|
|
4101
|
-
return buildRunnerReplyChainSnapshotFromParsedArchive(parsedArchive);
|
|
4102
|
-
}
|
|
4103
|
-
|
|
4104
|
-
function buildRunnerReplyChainSnapshotFromRequestSource(requestRaw) {
|
|
4105
|
-
const request = safeObject(requestRaw);
|
|
4106
|
-
const explicitEnvelope = normalizeRunnerTelegramMessageEnvelope(
|
|
4107
|
-
request.source_message_envelope || request.sourceMessageEnvelope,
|
|
4108
|
-
);
|
|
4109
|
-
const fallbackEnvelope = intFromRawAllowZero(request.source_message_id, 0) > 0
|
|
4110
|
-
? {
|
|
4111
|
-
chat_id: request.chat_id,
|
|
4112
|
-
message_id: request.source_message_id,
|
|
4113
|
-
message_thread_id: request.source_message_thread_id,
|
|
4114
|
-
body: request.source_message_body,
|
|
4115
|
-
sender: "human",
|
|
4116
|
-
sender_is_bot: false,
|
|
4117
|
-
}
|
|
4118
|
-
: null;
|
|
4119
|
-
return buildRunnerReplyChainSnapshotFromMessageEnvelope(
|
|
4120
|
-
explicitEnvelope && Object.keys(explicitEnvelope).length
|
|
4121
|
-
? explicitEnvelope
|
|
4122
|
-
: fallbackEnvelope,
|
|
4123
|
-
{
|
|
4124
|
-
speaker_type: "human",
|
|
4125
|
-
speaker_label: "human",
|
|
4126
|
-
},
|
|
4127
|
-
);
|
|
4128
|
-
}
|
|
4129
|
-
|
|
4130
|
-
function buildRunnerReplyChainSnapshotFromRequestReply(requestRaw) {
|
|
4131
|
-
const request = safeObject(requestRaw);
|
|
4132
|
-
const preview = runnerRequestPreferredAIReplyPreview(request);
|
|
4133
|
-
if (!preview) {
|
|
4134
|
-
return null;
|
|
4135
|
-
}
|
|
4136
|
-
const explicitEnvelope = normalizeRunnerTelegramMessageEnvelope(
|
|
4137
|
-
request.last_reply_message_envelope || request.lastReplyMessageEnvelope,
|
|
4138
|
-
);
|
|
4139
|
-
return buildRunnerReplyChainSnapshotFromMessageEnvelope(
|
|
4140
|
-
explicitEnvelope && intFromRawAllowZero(explicitEnvelope.message_id, 0) > 0
|
|
4141
|
-
? explicitEnvelope
|
|
4142
|
-
: null,
|
|
4143
|
-
{
|
|
4144
|
-
speaker_type: "bot",
|
|
4145
|
-
speaker_label: firstNonEmptyString([
|
|
4146
|
-
request.conversation_summary_bot ? `@${String(request.conversation_summary_bot || "").trim().replace(/^@+/, "")}` : "",
|
|
4147
|
-
ensureArray(request.selected_bot_usernames)[0]
|
|
4148
|
-
? `@${String(ensureArray(request.selected_bot_usernames)[0] || "").trim().replace(/^@+/, "")}`
|
|
4149
|
-
: "",
|
|
4150
|
-
"bot",
|
|
4151
|
-
]),
|
|
4152
|
-
body: preview,
|
|
4153
|
-
},
|
|
4154
|
-
);
|
|
4155
|
-
}
|
|
4156
|
-
|
|
4157
|
-
function uniqueRunnerReplyChainSnapshots(snapshots, limit = 4) {
|
|
4158
|
-
const normalized = [];
|
|
4159
|
-
const seen = new Set();
|
|
4160
|
-
for (const snapshotRaw of ensureArray(snapshots)) {
|
|
4161
|
-
const snapshot = normalizeRunnerReplyChainSnapshot(snapshotRaw);
|
|
4162
|
-
if (!snapshot) continue;
|
|
4163
|
-
const key = snapshot.message_id
|
|
4164
|
-
? `message:${snapshot.message_id}`
|
|
4165
|
-
: `body:${snapshot.speaker_type}:${String(snapshot.body || "").trim()}`;
|
|
4166
|
-
if (seen.has(key)) continue;
|
|
4167
|
-
seen.add(key);
|
|
4168
|
-
normalized.push(snapshot);
|
|
4169
|
-
}
|
|
4170
|
-
return normalized.slice(-(Math.max(1, intFromRawAllowZero(limit, 4) || 4)));
|
|
4171
|
-
}
|
|
4172
|
-
|
|
4173
|
-
async function buildRunnerAuthorityReplyChainContext({
|
|
4174
|
-
selectedRecord,
|
|
4175
|
-
replyChainContext = null,
|
|
4176
|
-
authoritySource = null,
|
|
4177
|
-
runtime,
|
|
4178
|
-
archiveThreadID = "",
|
|
4179
|
-
}) {
|
|
4180
|
-
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
4181
|
-
const normalizedReplyChainContext = safeObject(replyChainContext);
|
|
4182
|
-
const referencedRequest = safeObject(
|
|
4183
|
-
authoritySource?.request_key
|
|
4184
|
-
? authoritySource
|
|
4185
|
-
: normalizedReplyChainContext.referencedRequest,
|
|
4186
|
-
);
|
|
4187
|
-
const normalizedArchiveThreadID = firstNonEmptyString([
|
|
4188
|
-
archiveThreadID,
|
|
4189
|
-
selectedRecord?.thread_id,
|
|
4190
|
-
selectedRecord?.threadID,
|
|
4191
|
-
selectedRecord?.threadId,
|
|
4192
|
-
]);
|
|
4193
|
-
const conversationID = firstNonEmptyString([
|
|
4194
|
-
normalizedReplyChainContext.conversationID,
|
|
4195
|
-
parsed.conversationID,
|
|
4196
|
-
referencedRequest.conversation_id,
|
|
4197
|
-
]);
|
|
4198
|
-
const currentMessageID = intFromRawAllowZero(parsed.messageID, 0);
|
|
4199
|
-
const parentMessageID = intFromRawAllowZero(
|
|
4200
|
-
parsed.replyToMessageID || normalizedReplyChainContext.replyToMessageID,
|
|
4201
|
-
0,
|
|
4202
|
-
);
|
|
4203
|
-
let archiveThreadCache = null;
|
|
4204
|
-
const loadArchiveSnapshot = async (messageID) => {
|
|
4205
|
-
if (!(messageID > 0) || !normalizedArchiveThreadID || !runtime?.baseURL || !runtime?.token) {
|
|
4206
|
-
return null;
|
|
4207
|
-
}
|
|
4208
|
-
const lookup = await findRunnerArchiveThreadMessageByID({
|
|
4209
|
-
runtime,
|
|
4210
|
-
threadID: normalizedArchiveThreadID,
|
|
4211
|
-
messageID,
|
|
4212
|
-
cache: archiveThreadCache,
|
|
4213
|
-
});
|
|
4214
|
-
archiveThreadCache = lookup.cache;
|
|
4215
|
-
return buildRunnerReplyChainSnapshotFromArchiveRecord(lookup.record);
|
|
4216
|
-
};
|
|
4217
|
-
|
|
4218
|
-
const ancestorSnapshots = [];
|
|
4219
|
-
let nextReplyToMessageID = parentMessageID;
|
|
4220
|
-
const visitedMessageIDs = new Set();
|
|
4221
|
-
for (let hop = 0; hop < 8 && nextReplyToMessageID > 0; hop += 1) {
|
|
4222
|
-
if (visitedMessageIDs.has(nextReplyToMessageID)) {
|
|
4223
|
-
break;
|
|
4224
|
-
}
|
|
4225
|
-
visitedMessageIDs.add(nextReplyToMessageID);
|
|
4226
|
-
const archivedLookup = await findRunnerArchiveThreadMessageByID({
|
|
4227
|
-
runtime,
|
|
4228
|
-
threadID: normalizedArchiveThreadID,
|
|
4229
|
-
messageID: nextReplyToMessageID,
|
|
4230
|
-
cache: archiveThreadCache,
|
|
4231
|
-
});
|
|
4232
|
-
archiveThreadCache = archivedLookup.cache;
|
|
4233
|
-
const archivedRecord = safeObject(archivedLookup.record);
|
|
4234
|
-
if (!Object.keys(archivedRecord).length) {
|
|
4235
|
-
break;
|
|
4236
|
-
}
|
|
4237
|
-
const snapshot = buildRunnerReplyChainSnapshotFromArchiveRecord(archivedRecord);
|
|
4238
|
-
if (snapshot) {
|
|
4239
|
-
ancestorSnapshots.unshift(snapshot);
|
|
4240
|
-
}
|
|
4241
|
-
const archivedParsed = safeObject(archivedRecord.parsedArchive || parseArchivedChatComment(archivedRecord.body));
|
|
4242
|
-
nextReplyToMessageID = intFromRawAllowZero(archivedParsed.replyToMessageID, 0);
|
|
4243
|
-
}
|
|
4244
|
-
|
|
4245
|
-
let parentMessage = ancestorSnapshots.length
|
|
4246
|
-
? safeObject(ancestorSnapshots[ancestorSnapshots.length - 1])
|
|
4247
|
-
: {};
|
|
4248
|
-
let rootMessage = safeObject(
|
|
4249
|
-
ancestorSnapshots.find((item) => String(item?.speaker_type || "").trim().toLowerCase() === "human"),
|
|
4250
|
-
);
|
|
4251
|
-
let latestPriorBotReply = safeObject(
|
|
4252
|
-
[...ancestorSnapshots].reverse().find((item) => String(item?.speaker_type || "").trim().toLowerCase() === "bot"),
|
|
4253
|
-
);
|
|
4254
|
-
|
|
4255
|
-
const requestRootMessage = buildRunnerReplyChainSnapshotFromRequestSource(referencedRequest);
|
|
4256
|
-
const requestLatestBotReply = buildRunnerReplyChainSnapshotFromRequestReply(referencedRequest);
|
|
4257
|
-
|
|
4258
|
-
if (!Object.keys(parentMessage).length && parentMessageID > 0) {
|
|
4259
|
-
parentMessage = safeObject(await loadArchiveSnapshot(parentMessageID));
|
|
4260
|
-
}
|
|
4261
|
-
if (!Object.keys(rootMessage).length) {
|
|
4262
|
-
rootMessage = safeObject(requestRootMessage);
|
|
4263
|
-
}
|
|
4264
|
-
if (
|
|
4265
|
-
Object.keys(requestLatestBotReply || {}).length
|
|
4266
|
-
&& (
|
|
4267
|
-
!Object.keys(latestPriorBotReply).length
|
|
4268
|
-
|| intFromRawAllowZero(requestLatestBotReply.message_id, 0) > intFromRawAllowZero(latestPriorBotReply.message_id, 0)
|
|
4269
|
-
)
|
|
4270
|
-
) {
|
|
4271
|
-
latestPriorBotReply = safeObject(requestLatestBotReply);
|
|
4272
|
-
}
|
|
4273
|
-
if (!Object.keys(latestPriorBotReply).length) {
|
|
4274
|
-
latestPriorBotReply = safeObject(requestLatestBotReply);
|
|
4275
|
-
}
|
|
4276
|
-
if (!Object.keys(rootMessage).length && !parentMessageID && currentMessageID > 0) {
|
|
4277
|
-
rootMessage = safeObject(buildRunnerReplyChainSnapshotFromParsedArchive(parsed));
|
|
4278
|
-
}
|
|
4279
|
-
|
|
4280
|
-
const recentChainMessages = uniqueRunnerReplyChainSnapshots(
|
|
4281
|
-
[
|
|
4282
|
-
...ancestorSnapshots,
|
|
4283
|
-
requestLatestBotReply,
|
|
4284
|
-
parentMessage,
|
|
4285
|
-
latestPriorBotReply,
|
|
4286
|
-
].filter(Boolean),
|
|
4287
|
-
4,
|
|
4288
|
-
);
|
|
4289
|
-
const currentTurnRelation = Object.keys(parentMessage).length
|
|
4290
|
-
? "reply_to_parent_message"
|
|
4291
|
-
: conversationID
|
|
4292
|
-
? "same_conversation_followup"
|
|
4293
|
-
: "standalone_message";
|
|
4294
|
-
return normalizeRunnerReplyChainContext({
|
|
4295
|
-
conversation_id: conversationID,
|
|
4296
|
-
current_message_id: currentMessageID,
|
|
4297
|
-
current_message_thread_id: intFromRawAllowZero(parsed.messageThreadID, 0) || undefined,
|
|
4298
|
-
parent_message_id: parentMessageID,
|
|
4299
|
-
root_message_id: intFromRawAllowZero(rootMessage.message_id, 0) || undefined,
|
|
4300
|
-
current_turn_relation: currentTurnRelation,
|
|
4301
|
-
root_message: rootMessage,
|
|
4302
|
-
parent_message: parentMessage,
|
|
4303
|
-
latest_prior_bot_reply: latestPriorBotReply,
|
|
4304
|
-
recent_chain_messages: recentChainMessages,
|
|
4305
|
-
});
|
|
4306
|
-
}
|
|
4307
|
-
|
|
4308
|
-
function resolveRunnerReplyChainConversationContext(state, normalizedRoute, selectedRecord) {
|
|
4309
|
-
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
4066
|
+
return {
|
|
4067
|
+
cache: nextCache,
|
|
4068
|
+
record: safeObject(nextCache.messageIndex.get(intFromRawAllowZero(messageID, 0))),
|
|
4069
|
+
};
|
|
4070
|
+
}
|
|
4071
|
+
|
|
4072
|
+
function buildRunnerReplyChainSnapshotFromParsedArchive(parsedArchiveRaw, overrides = {}) {
|
|
4073
|
+
const parsedArchive = safeObject(parsedArchiveRaw);
|
|
4074
|
+
return buildRunnerReplyChainSnapshotFromMessageEnvelope(
|
|
4075
|
+
buildRunnerTelegramMessageEnvelopeFromParsedArchive(parsedArchive, overrides),
|
|
4076
|
+
{
|
|
4077
|
+
speaker_type: firstNonEmptyString([
|
|
4078
|
+
overrides.speaker_type,
|
|
4079
|
+
buildRunnerReplyChainSpeakerType(parsedArchive),
|
|
4080
|
+
]),
|
|
4081
|
+
speaker_label: firstNonEmptyString([
|
|
4082
|
+
overrides.speaker_label,
|
|
4083
|
+
buildRunnerReplyChainSpeakerLabel(parsedArchive),
|
|
4084
|
+
]),
|
|
4085
|
+
body: truncateRunnerReplyChainText(
|
|
4086
|
+
firstNonEmptyString([overrides.body, parsedArchive.body]),
|
|
4087
|
+
),
|
|
4088
|
+
},
|
|
4089
|
+
);
|
|
4090
|
+
}
|
|
4091
|
+
|
|
4092
|
+
function buildRunnerReplyChainSnapshotFromArchiveRecord(recordRaw) {
|
|
4093
|
+
const record = safeObject(recordRaw);
|
|
4094
|
+
const parsedArchive = safeObject(record.parsedArchive || parseArchivedChatComment(record.body));
|
|
4095
|
+
return buildRunnerReplyChainSnapshotFromParsedArchive(parsedArchive);
|
|
4096
|
+
}
|
|
4097
|
+
|
|
4098
|
+
function buildRunnerReplyChainSnapshotFromRequestSource(requestRaw) {
|
|
4099
|
+
const request = safeObject(requestRaw);
|
|
4100
|
+
const explicitEnvelope = normalizeRunnerTelegramMessageEnvelope(
|
|
4101
|
+
request.source_message_envelope || request.sourceMessageEnvelope,
|
|
4102
|
+
);
|
|
4103
|
+
const fallbackEnvelope = intFromRawAllowZero(request.source_message_id, 0) > 0
|
|
4104
|
+
? {
|
|
4105
|
+
chat_id: request.chat_id,
|
|
4106
|
+
message_id: request.source_message_id,
|
|
4107
|
+
message_thread_id: request.source_message_thread_id,
|
|
4108
|
+
body: request.source_message_body,
|
|
4109
|
+
sender: "human",
|
|
4110
|
+
sender_is_bot: false,
|
|
4111
|
+
}
|
|
4112
|
+
: null;
|
|
4113
|
+
return buildRunnerReplyChainSnapshotFromMessageEnvelope(
|
|
4114
|
+
explicitEnvelope && Object.keys(explicitEnvelope).length
|
|
4115
|
+
? explicitEnvelope
|
|
4116
|
+
: fallbackEnvelope,
|
|
4117
|
+
{
|
|
4118
|
+
speaker_type: "human",
|
|
4119
|
+
speaker_label: "human",
|
|
4120
|
+
},
|
|
4121
|
+
);
|
|
4122
|
+
}
|
|
4123
|
+
|
|
4124
|
+
function buildRunnerReplyChainSnapshotFromRequestReply(requestRaw) {
|
|
4125
|
+
const request = safeObject(requestRaw);
|
|
4126
|
+
const preview = runnerRequestPreferredAIReplyPreview(request);
|
|
4127
|
+
if (!preview) {
|
|
4128
|
+
return null;
|
|
4129
|
+
}
|
|
4130
|
+
const explicitEnvelope = normalizeRunnerTelegramMessageEnvelope(
|
|
4131
|
+
request.last_reply_message_envelope || request.lastReplyMessageEnvelope,
|
|
4132
|
+
);
|
|
4133
|
+
return buildRunnerReplyChainSnapshotFromMessageEnvelope(
|
|
4134
|
+
explicitEnvelope && intFromRawAllowZero(explicitEnvelope.message_id, 0) > 0
|
|
4135
|
+
? explicitEnvelope
|
|
4136
|
+
: null,
|
|
4137
|
+
{
|
|
4138
|
+
speaker_type: "bot",
|
|
4139
|
+
speaker_label: firstNonEmptyString([
|
|
4140
|
+
request.conversation_summary_bot ? `@${String(request.conversation_summary_bot || "").trim().replace(/^@+/, "")}` : "",
|
|
4141
|
+
ensureArray(request.selected_bot_usernames)[0]
|
|
4142
|
+
? `@${String(ensureArray(request.selected_bot_usernames)[0] || "").trim().replace(/^@+/, "")}`
|
|
4143
|
+
: "",
|
|
4144
|
+
"bot",
|
|
4145
|
+
]),
|
|
4146
|
+
body: preview,
|
|
4147
|
+
},
|
|
4148
|
+
);
|
|
4149
|
+
}
|
|
4150
|
+
|
|
4151
|
+
function uniqueRunnerReplyChainSnapshots(snapshots, limit = 4) {
|
|
4152
|
+
const normalized = [];
|
|
4153
|
+
const seen = new Set();
|
|
4154
|
+
for (const snapshotRaw of ensureArray(snapshots)) {
|
|
4155
|
+
const snapshot = normalizeRunnerReplyChainSnapshot(snapshotRaw);
|
|
4156
|
+
if (!snapshot) continue;
|
|
4157
|
+
const key = snapshot.message_id
|
|
4158
|
+
? `message:${snapshot.message_id}`
|
|
4159
|
+
: `body:${snapshot.speaker_type}:${String(snapshot.body || "").trim()}`;
|
|
4160
|
+
if (seen.has(key)) continue;
|
|
4161
|
+
seen.add(key);
|
|
4162
|
+
normalized.push(snapshot);
|
|
4163
|
+
}
|
|
4164
|
+
return normalized.slice(-(Math.max(1, intFromRawAllowZero(limit, 4) || 4)));
|
|
4165
|
+
}
|
|
4166
|
+
|
|
4167
|
+
async function buildRunnerAuthorityReplyChainContext({
|
|
4168
|
+
selectedRecord,
|
|
4169
|
+
replyChainContext = null,
|
|
4170
|
+
authoritySource = null,
|
|
4171
|
+
runtime,
|
|
4172
|
+
archiveThreadID = "",
|
|
4173
|
+
}) {
|
|
4174
|
+
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
4175
|
+
const normalizedReplyChainContext = safeObject(replyChainContext);
|
|
4176
|
+
const referencedRequest = safeObject(
|
|
4177
|
+
authoritySource?.request_key
|
|
4178
|
+
? authoritySource
|
|
4179
|
+
: normalizedReplyChainContext.referencedRequest,
|
|
4180
|
+
);
|
|
4181
|
+
const normalizedArchiveThreadID = firstNonEmptyString([
|
|
4182
|
+
archiveThreadID,
|
|
4183
|
+
selectedRecord?.thread_id,
|
|
4184
|
+
selectedRecord?.threadID,
|
|
4185
|
+
selectedRecord?.threadId,
|
|
4186
|
+
]);
|
|
4187
|
+
const conversationID = firstNonEmptyString([
|
|
4188
|
+
normalizedReplyChainContext.conversationID,
|
|
4189
|
+
parsed.conversationID,
|
|
4190
|
+
referencedRequest.conversation_id,
|
|
4191
|
+
]);
|
|
4192
|
+
const currentMessageID = intFromRawAllowZero(parsed.messageID, 0);
|
|
4193
|
+
const parentMessageID = intFromRawAllowZero(
|
|
4194
|
+
parsed.replyToMessageID || normalizedReplyChainContext.replyToMessageID,
|
|
4195
|
+
0,
|
|
4196
|
+
);
|
|
4197
|
+
let archiveThreadCache = null;
|
|
4198
|
+
const loadArchiveSnapshot = async (messageID) => {
|
|
4199
|
+
if (!(messageID > 0) || !normalizedArchiveThreadID || !runtime?.baseURL || !runtime?.token) {
|
|
4200
|
+
return null;
|
|
4201
|
+
}
|
|
4202
|
+
const lookup = await findRunnerArchiveThreadMessageByID({
|
|
4203
|
+
runtime,
|
|
4204
|
+
threadID: normalizedArchiveThreadID,
|
|
4205
|
+
messageID,
|
|
4206
|
+
cache: archiveThreadCache,
|
|
4207
|
+
});
|
|
4208
|
+
archiveThreadCache = lookup.cache;
|
|
4209
|
+
return buildRunnerReplyChainSnapshotFromArchiveRecord(lookup.record);
|
|
4210
|
+
};
|
|
4211
|
+
|
|
4212
|
+
const ancestorSnapshots = [];
|
|
4213
|
+
let nextReplyToMessageID = parentMessageID;
|
|
4214
|
+
const visitedMessageIDs = new Set();
|
|
4215
|
+
for (let hop = 0; hop < 8 && nextReplyToMessageID > 0; hop += 1) {
|
|
4216
|
+
if (visitedMessageIDs.has(nextReplyToMessageID)) {
|
|
4217
|
+
break;
|
|
4218
|
+
}
|
|
4219
|
+
visitedMessageIDs.add(nextReplyToMessageID);
|
|
4220
|
+
const archivedLookup = await findRunnerArchiveThreadMessageByID({
|
|
4221
|
+
runtime,
|
|
4222
|
+
threadID: normalizedArchiveThreadID,
|
|
4223
|
+
messageID: nextReplyToMessageID,
|
|
4224
|
+
cache: archiveThreadCache,
|
|
4225
|
+
});
|
|
4226
|
+
archiveThreadCache = archivedLookup.cache;
|
|
4227
|
+
const archivedRecord = safeObject(archivedLookup.record);
|
|
4228
|
+
if (!Object.keys(archivedRecord).length) {
|
|
4229
|
+
break;
|
|
4230
|
+
}
|
|
4231
|
+
const snapshot = buildRunnerReplyChainSnapshotFromArchiveRecord(archivedRecord);
|
|
4232
|
+
if (snapshot) {
|
|
4233
|
+
ancestorSnapshots.unshift(snapshot);
|
|
4234
|
+
}
|
|
4235
|
+
const archivedParsed = safeObject(archivedRecord.parsedArchive || parseArchivedChatComment(archivedRecord.body));
|
|
4236
|
+
nextReplyToMessageID = intFromRawAllowZero(archivedParsed.replyToMessageID, 0);
|
|
4237
|
+
}
|
|
4238
|
+
|
|
4239
|
+
let parentMessage = ancestorSnapshots.length
|
|
4240
|
+
? safeObject(ancestorSnapshots[ancestorSnapshots.length - 1])
|
|
4241
|
+
: {};
|
|
4242
|
+
let rootMessage = safeObject(
|
|
4243
|
+
ancestorSnapshots.find((item) => String(item?.speaker_type || "").trim().toLowerCase() === "human"),
|
|
4244
|
+
);
|
|
4245
|
+
let latestPriorBotReply = safeObject(
|
|
4246
|
+
[...ancestorSnapshots].reverse().find((item) => String(item?.speaker_type || "").trim().toLowerCase() === "bot"),
|
|
4247
|
+
);
|
|
4248
|
+
|
|
4249
|
+
const requestRootMessage = buildRunnerReplyChainSnapshotFromRequestSource(referencedRequest);
|
|
4250
|
+
const requestLatestBotReply = buildRunnerReplyChainSnapshotFromRequestReply(referencedRequest);
|
|
4251
|
+
|
|
4252
|
+
if (!Object.keys(parentMessage).length && parentMessageID > 0) {
|
|
4253
|
+
parentMessage = safeObject(await loadArchiveSnapshot(parentMessageID));
|
|
4254
|
+
}
|
|
4255
|
+
if (!Object.keys(rootMessage).length) {
|
|
4256
|
+
rootMessage = safeObject(requestRootMessage);
|
|
4257
|
+
}
|
|
4258
|
+
if (
|
|
4259
|
+
Object.keys(requestLatestBotReply || {}).length
|
|
4260
|
+
&& (
|
|
4261
|
+
!Object.keys(latestPriorBotReply).length
|
|
4262
|
+
|| intFromRawAllowZero(requestLatestBotReply.message_id, 0) > intFromRawAllowZero(latestPriorBotReply.message_id, 0)
|
|
4263
|
+
)
|
|
4264
|
+
) {
|
|
4265
|
+
latestPriorBotReply = safeObject(requestLatestBotReply);
|
|
4266
|
+
}
|
|
4267
|
+
if (!Object.keys(latestPriorBotReply).length) {
|
|
4268
|
+
latestPriorBotReply = safeObject(requestLatestBotReply);
|
|
4269
|
+
}
|
|
4270
|
+
if (!Object.keys(rootMessage).length && !parentMessageID && currentMessageID > 0) {
|
|
4271
|
+
rootMessage = safeObject(buildRunnerReplyChainSnapshotFromParsedArchive(parsed));
|
|
4272
|
+
}
|
|
4273
|
+
|
|
4274
|
+
const recentChainMessages = uniqueRunnerReplyChainSnapshots(
|
|
4275
|
+
[
|
|
4276
|
+
...ancestorSnapshots,
|
|
4277
|
+
requestLatestBotReply,
|
|
4278
|
+
parentMessage,
|
|
4279
|
+
latestPriorBotReply,
|
|
4280
|
+
].filter(Boolean),
|
|
4281
|
+
4,
|
|
4282
|
+
);
|
|
4283
|
+
const currentTurnRelation = Object.keys(parentMessage).length
|
|
4284
|
+
? "reply_to_parent_message"
|
|
4285
|
+
: conversationID
|
|
4286
|
+
? "same_conversation_followup"
|
|
4287
|
+
: "standalone_message";
|
|
4288
|
+
return normalizeRunnerReplyChainContext({
|
|
4289
|
+
conversation_id: conversationID,
|
|
4290
|
+
current_message_id: currentMessageID,
|
|
4291
|
+
current_message_thread_id: intFromRawAllowZero(parsed.messageThreadID, 0) || undefined,
|
|
4292
|
+
parent_message_id: parentMessageID,
|
|
4293
|
+
root_message_id: intFromRawAllowZero(rootMessage.message_id, 0) || undefined,
|
|
4294
|
+
current_turn_relation: currentTurnRelation,
|
|
4295
|
+
root_message: rootMessage,
|
|
4296
|
+
parent_message: parentMessage,
|
|
4297
|
+
latest_prior_bot_reply: latestPriorBotReply,
|
|
4298
|
+
recent_chain_messages: recentChainMessages,
|
|
4299
|
+
});
|
|
4300
|
+
}
|
|
4301
|
+
|
|
4302
|
+
function resolveRunnerReplyChainConversationContext(state, normalizedRoute, selectedRecord) {
|
|
4303
|
+
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
4310
4304
|
const explicitConversationID = String(parsed.conversationID || "").trim();
|
|
4311
4305
|
if (explicitConversationID) {
|
|
4312
4306
|
return {
|
|
@@ -4534,9 +4528,9 @@ function upsertRunnerRequest(state, requestKey, patch = {}) {
|
|
|
4534
4528
|
};
|
|
4535
4529
|
}
|
|
4536
4530
|
|
|
4537
|
-
function upsertRunnerConsumedComment(state, commentIDRaw, patch = {}) {
|
|
4538
|
-
const commentID = String(commentIDRaw || "").trim();
|
|
4539
|
-
const currentState = safeObject(state);
|
|
4531
|
+
function upsertRunnerConsumedComment(state, commentIDRaw, patch = {}) {
|
|
4532
|
+
const commentID = String(commentIDRaw || "").trim();
|
|
4533
|
+
const currentState = safeObject(state);
|
|
4540
4534
|
const consumedComments = normalizeBotRunnerConsumedComments(currentState.consumedComments || currentState.consumed_comments);
|
|
4541
4535
|
const ledgerKey = buildRunnerConsumedCommentLedgerKey(commentID, patch.route_key, patch.comment_kind);
|
|
4542
4536
|
const existing = safeObject(consumedComments[ledgerKey]);
|
|
@@ -4550,85 +4544,85 @@ function upsertRunnerConsumedComment(state, commentIDRaw, patch = {}) {
|
|
|
4550
4544
|
request_status: normalizeRunnerRequestStatus(patch.request_status || existing.request_status),
|
|
4551
4545
|
};
|
|
4552
4546
|
consumedComments[ledgerKey] = nextEntry;
|
|
4553
|
-
return {
|
|
4554
|
-
consumedComments,
|
|
4555
|
-
consumedComment: nextEntry,
|
|
4556
|
-
};
|
|
4557
|
-
}
|
|
4558
|
-
|
|
4559
|
-
function resolveRunnerHumanCommentAuthorityContext({
|
|
4560
|
-
normalizedRoute,
|
|
4561
|
-
selectedRecord,
|
|
4562
|
-
replyChainContext = null,
|
|
4563
|
-
referencedRequest = null,
|
|
4564
|
-
sharedConversationSource = null,
|
|
4565
|
-
selectedBotUsernames = [],
|
|
4566
|
-
normalizedSharedHumanIntent = null,
|
|
4567
|
-
resolvedNormalizedIntent = "",
|
|
4568
|
-
}) {
|
|
4569
|
-
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
4570
|
-
const explicitCurrentSelectedBotUsernames = extractRunnerExplicitSelectedBotUsernamesFromParsed(parsed);
|
|
4571
|
-
const replyChain = safeObject(replyChainContext);
|
|
4572
|
-
const referenced = safeObject(referencedRequest);
|
|
4573
|
-
const sharedSource = safeObject(sharedConversationSource);
|
|
4574
|
-
const sharedIntent = safeObject(normalizedSharedHumanIntent);
|
|
4575
|
-
const authoritySource = Object.keys(referenced).length
|
|
4576
|
-
? referenced
|
|
4577
|
-
: Object.keys(sharedSource).length
|
|
4578
|
-
? sharedSource
|
|
4579
|
-
: {};
|
|
4580
|
-
const currentMessageID = intFromRawAllowZero(parsed.messageID, 0);
|
|
4581
|
-
const resolvedConversationID = firstNonEmptyString([
|
|
4582
|
-
parsed.conversationID,
|
|
4583
|
-
replyChain.conversationID,
|
|
4584
|
-
authoritySource.conversation_id,
|
|
4585
|
-
Object.keys(sharedIntent).length > 0
|
|
4586
|
-
? buildSyntheticHumanOpeningConversationID(
|
|
4587
|
-
normalizedRoute,
|
|
4588
|
-
String(parsed.chatID || parsed.chatId || "").trim(),
|
|
4589
|
-
currentMessageID,
|
|
4590
|
-
)
|
|
4591
|
-
: "",
|
|
4592
|
-
]);
|
|
4593
|
-
const explicitSelectedBotUsernames = uniqueOrderedStrings(
|
|
4594
|
-
selectedBotUsernames,
|
|
4595
|
-
normalizeTelegramMentionUsername,
|
|
4596
|
-
);
|
|
4597
|
-
const authoritySelectedBotUsernames = uniqueOrderedStrings(
|
|
4598
|
-
explicitCurrentSelectedBotUsernames.length > 0
|
|
4599
|
-
? explicitCurrentSelectedBotUsernames
|
|
4600
|
-
: explicitSelectedBotUsernames.length > 0
|
|
4601
|
-
? explicitSelectedBotUsernames
|
|
4602
|
-
: resolvedConversationID && runnerRequestPreferredAuthoritySelectedBotUsernames(authoritySource).length
|
|
4603
|
-
? runnerRequestPreferredAuthoritySelectedBotUsernames(authoritySource)
|
|
4604
|
-
: [],
|
|
4605
|
-
normalizeTelegramMentionUsername,
|
|
4606
|
-
);
|
|
4607
|
-
const preferredNormalizedIntent = String(
|
|
4608
|
-
sharedIntent.intentType
|
|
4609
|
-
|| resolvedNormalizedIntent
|
|
4610
|
-
|| authoritySource.normalized_intent
|
|
4611
|
-
|| "",
|
|
4612
|
-
).trim().toLowerCase();
|
|
4613
|
-
return {
|
|
4614
|
-
authoritySource,
|
|
4615
|
-
conversationID: String(resolvedConversationID || "").trim(),
|
|
4616
|
-
selectedBotUsernames: authoritySelectedBotUsernames,
|
|
4617
|
-
normalizedIntent: preferredNormalizedIntent,
|
|
4618
|
-
};
|
|
4619
|
-
}
|
|
4620
|
-
|
|
4621
|
-
async function claimRunnerRequestForHumanComment({
|
|
4622
|
-
normalizedRoute,
|
|
4623
|
-
routeKey,
|
|
4624
|
-
selectedRecord,
|
|
4625
|
-
selectedBotUsernames = [],
|
|
4626
|
-
normalizedIntent = "",
|
|
4627
|
-
sharedHumanIntent = null,
|
|
4628
|
-
runtime = null,
|
|
4629
|
-
archiveThreadID = "",
|
|
4630
|
-
authoritativeSourceMessageEnvelope = {},
|
|
4631
|
-
}) {
|
|
4547
|
+
return {
|
|
4548
|
+
consumedComments,
|
|
4549
|
+
consumedComment: nextEntry,
|
|
4550
|
+
};
|
|
4551
|
+
}
|
|
4552
|
+
|
|
4553
|
+
function resolveRunnerHumanCommentAuthorityContext({
|
|
4554
|
+
normalizedRoute,
|
|
4555
|
+
selectedRecord,
|
|
4556
|
+
replyChainContext = null,
|
|
4557
|
+
referencedRequest = null,
|
|
4558
|
+
sharedConversationSource = null,
|
|
4559
|
+
selectedBotUsernames = [],
|
|
4560
|
+
normalizedSharedHumanIntent = null,
|
|
4561
|
+
resolvedNormalizedIntent = "",
|
|
4562
|
+
}) {
|
|
4563
|
+
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
4564
|
+
const explicitCurrentSelectedBotUsernames = extractRunnerExplicitSelectedBotUsernamesFromParsed(parsed);
|
|
4565
|
+
const replyChain = safeObject(replyChainContext);
|
|
4566
|
+
const referenced = safeObject(referencedRequest);
|
|
4567
|
+
const sharedSource = safeObject(sharedConversationSource);
|
|
4568
|
+
const sharedIntent = safeObject(normalizedSharedHumanIntent);
|
|
4569
|
+
const authoritySource = Object.keys(referenced).length
|
|
4570
|
+
? referenced
|
|
4571
|
+
: Object.keys(sharedSource).length
|
|
4572
|
+
? sharedSource
|
|
4573
|
+
: {};
|
|
4574
|
+
const currentMessageID = intFromRawAllowZero(parsed.messageID, 0);
|
|
4575
|
+
const resolvedConversationID = firstNonEmptyString([
|
|
4576
|
+
parsed.conversationID,
|
|
4577
|
+
replyChain.conversationID,
|
|
4578
|
+
authoritySource.conversation_id,
|
|
4579
|
+
Object.keys(sharedIntent).length > 0
|
|
4580
|
+
? buildSyntheticHumanOpeningConversationID(
|
|
4581
|
+
normalizedRoute,
|
|
4582
|
+
String(parsed.chatID || parsed.chatId || "").trim(),
|
|
4583
|
+
currentMessageID,
|
|
4584
|
+
)
|
|
4585
|
+
: "",
|
|
4586
|
+
]);
|
|
4587
|
+
const explicitSelectedBotUsernames = uniqueOrderedStrings(
|
|
4588
|
+
selectedBotUsernames,
|
|
4589
|
+
normalizeTelegramMentionUsername,
|
|
4590
|
+
);
|
|
4591
|
+
const authoritySelectedBotUsernames = uniqueOrderedStrings(
|
|
4592
|
+
explicitCurrentSelectedBotUsernames.length > 0
|
|
4593
|
+
? explicitCurrentSelectedBotUsernames
|
|
4594
|
+
: explicitSelectedBotUsernames.length > 0
|
|
4595
|
+
? explicitSelectedBotUsernames
|
|
4596
|
+
: resolvedConversationID && runnerRequestPreferredAuthoritySelectedBotUsernames(authoritySource).length
|
|
4597
|
+
? runnerRequestPreferredAuthoritySelectedBotUsernames(authoritySource)
|
|
4598
|
+
: [],
|
|
4599
|
+
normalizeTelegramMentionUsername,
|
|
4600
|
+
);
|
|
4601
|
+
const preferredNormalizedIntent = String(
|
|
4602
|
+
sharedIntent.intentType
|
|
4603
|
+
|| resolvedNormalizedIntent
|
|
4604
|
+
|| authoritySource.normalized_intent
|
|
4605
|
+
|| "",
|
|
4606
|
+
).trim().toLowerCase();
|
|
4607
|
+
return {
|
|
4608
|
+
authoritySource,
|
|
4609
|
+
conversationID: String(resolvedConversationID || "").trim(),
|
|
4610
|
+
selectedBotUsernames: authoritySelectedBotUsernames,
|
|
4611
|
+
normalizedIntent: preferredNormalizedIntent,
|
|
4612
|
+
};
|
|
4613
|
+
}
|
|
4614
|
+
|
|
4615
|
+
async function claimRunnerRequestForHumanComment({
|
|
4616
|
+
normalizedRoute,
|
|
4617
|
+
routeKey,
|
|
4618
|
+
selectedRecord,
|
|
4619
|
+
selectedBotUsernames = [],
|
|
4620
|
+
normalizedIntent = "",
|
|
4621
|
+
sharedHumanIntent = null,
|
|
4622
|
+
runtime = null,
|
|
4623
|
+
archiveThreadID = "",
|
|
4624
|
+
authoritativeSourceMessageEnvelope = {},
|
|
4625
|
+
}) {
|
|
4632
4626
|
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
4633
4627
|
const commentKind = String(parsed.kind || "").trim().toLowerCase();
|
|
4634
4628
|
if (!isInboundArchiveKind(commentKind)) {
|
|
@@ -4637,45 +4631,45 @@ async function claimRunnerRequestForHumanComment({
|
|
|
4637
4631
|
reason: "non_human_comment_cannot_create_request",
|
|
4638
4632
|
};
|
|
4639
4633
|
}
|
|
4640
|
-
const currentState = loadBotRunnerState();
|
|
4641
|
-
const currentRouteState = safeObject(safeObject(currentState.routes)[String(routeKey || "").trim()]);
|
|
4642
|
-
const replyChainResolution = await resolveRunnerReplyChainConversationContextWithServerFallback({
|
|
4643
|
-
state: currentState,
|
|
4634
|
+
const currentState = loadBotRunnerState();
|
|
4635
|
+
const currentRouteState = safeObject(safeObject(currentState.routes)[String(routeKey || "").trim()]);
|
|
4636
|
+
const replyChainResolution = await resolveRunnerReplyChainConversationContextWithServerFallback({
|
|
4637
|
+
state: currentState,
|
|
4644
4638
|
normalizedRoute,
|
|
4645
4639
|
selectedRecord,
|
|
4646
4640
|
runtime,
|
|
4647
4641
|
archiveThreadID,
|
|
4648
4642
|
});
|
|
4649
4643
|
const replyChainContext = safeObject(replyChainResolution.replyChainContext);
|
|
4650
|
-
const referencedRequest = safeObject(replyChainContext.referencedRequest);
|
|
4651
|
-
const resolvedNormalizedIntent = resolveRunnerRequestClaimIntent({
|
|
4652
|
-
normalizedIntent,
|
|
4653
|
-
selectedRecord,
|
|
4654
|
-
});
|
|
4655
|
-
let stateForClaim = safeObject(replyChainResolution.state);
|
|
4656
|
-
const normalizedSharedHumanIntent = safeObject(sharedHumanIntent);
|
|
4657
|
-
const provisionalConversationID = String(
|
|
4658
|
-
parsed.conversationID
|
|
4659
|
-
|| replyChainContext.conversationID
|
|
4660
|
-
|| "",
|
|
4661
|
-
).trim();
|
|
4662
|
-
const provisionalNormalizedIntent = String(
|
|
4663
|
-
normalizedSharedHumanIntent.intentType
|
|
4664
|
-
|| resolvedNormalizedIntent
|
|
4665
|
-
|| referencedRequest.normalized_intent
|
|
4666
|
-
|| "",
|
|
4667
|
-
).trim().toLowerCase();
|
|
4668
|
-
const provisionalRequestKey = buildRunnerRequestKey({
|
|
4669
|
-
normalizedRoute,
|
|
4670
|
-
selectedRecord,
|
|
4671
|
-
selectedBotUsernames,
|
|
4672
|
-
normalizedIntent: provisionalNormalizedIntent,
|
|
4673
|
-
conversationID: provisionalConversationID,
|
|
4674
|
-
});
|
|
4675
|
-
const baseConversationID = provisionalConversationID;
|
|
4676
|
-
if (
|
|
4677
|
-
Object.keys(referencedRequest).length > 0
|
|
4678
|
-
&& baseConversationID
|
|
4644
|
+
const referencedRequest = safeObject(replyChainContext.referencedRequest);
|
|
4645
|
+
const resolvedNormalizedIntent = resolveRunnerRequestClaimIntent({
|
|
4646
|
+
normalizedIntent,
|
|
4647
|
+
selectedRecord,
|
|
4648
|
+
});
|
|
4649
|
+
let stateForClaim = safeObject(replyChainResolution.state);
|
|
4650
|
+
const normalizedSharedHumanIntent = safeObject(sharedHumanIntent);
|
|
4651
|
+
const provisionalConversationID = String(
|
|
4652
|
+
parsed.conversationID
|
|
4653
|
+
|| replyChainContext.conversationID
|
|
4654
|
+
|| "",
|
|
4655
|
+
).trim();
|
|
4656
|
+
const provisionalNormalizedIntent = String(
|
|
4657
|
+
normalizedSharedHumanIntent.intentType
|
|
4658
|
+
|| resolvedNormalizedIntent
|
|
4659
|
+
|| referencedRequest.normalized_intent
|
|
4660
|
+
|| "",
|
|
4661
|
+
).trim().toLowerCase();
|
|
4662
|
+
const provisionalRequestKey = buildRunnerRequestKey({
|
|
4663
|
+
normalizedRoute,
|
|
4664
|
+
selectedRecord,
|
|
4665
|
+
selectedBotUsernames,
|
|
4666
|
+
normalizedIntent: provisionalNormalizedIntent,
|
|
4667
|
+
conversationID: provisionalConversationID,
|
|
4668
|
+
});
|
|
4669
|
+
const baseConversationID = provisionalConversationID;
|
|
4670
|
+
if (
|
|
4671
|
+
Object.keys(referencedRequest).length > 0
|
|
4672
|
+
&& baseConversationID
|
|
4679
4673
|
&& !String(referencedRequest.conversation_id || "").trim()
|
|
4680
4674
|
&& String(referencedRequest.request_key || "").trim()
|
|
4681
4675
|
) {
|
|
@@ -4703,44 +4697,44 @@ async function claimRunnerRequestForHumanComment({
|
|
|
4703
4697
|
&& runtime?.baseURL
|
|
4704
4698
|
&& runtime?.token
|
|
4705
4699
|
) {
|
|
4706
|
-
sharedConversationSource = safeObject(await findServerRunnerConversationSourceRequestForMessageID({
|
|
4707
|
-
normalizedRoute,
|
|
4708
|
-
runtime,
|
|
4709
|
-
chatID: String(parsed.chatID || parsed.chatId || "").trim(),
|
|
4710
|
-
messageID: currentMessageID,
|
|
4711
|
-
excludeRequestKey: provisionalRequestKey,
|
|
4712
|
-
}));
|
|
4713
|
-
}
|
|
4714
|
-
const authorityContext = resolveRunnerHumanCommentAuthorityContext({
|
|
4715
|
-
normalizedRoute,
|
|
4716
|
-
selectedRecord,
|
|
4717
|
-
replyChainContext,
|
|
4718
|
-
referencedRequest,
|
|
4719
|
-
sharedConversationSource,
|
|
4720
|
-
selectedBotUsernames,
|
|
4721
|
-
normalizedSharedHumanIntent,
|
|
4722
|
-
resolvedNormalizedIntent,
|
|
4723
|
-
});
|
|
4724
|
-
const authoritySource = safeObject(authorityContext.authoritySource);
|
|
4725
|
-
const authorityReplyChainContext = await buildRunnerAuthorityReplyChainContext({
|
|
4726
|
-
selectedRecord,
|
|
4727
|
-
replyChainContext,
|
|
4728
|
-
authoritySource,
|
|
4729
|
-
runtime,
|
|
4730
|
-
archiveThreadID,
|
|
4731
|
-
});
|
|
4732
|
-
const resolvedConversationID = String(authorityContext.conversationID || "").trim();
|
|
4733
|
-
const preferredNormalizedIntent = String(authorityContext.normalizedIntent || "").trim().toLowerCase();
|
|
4734
|
-
const requestSelectedBotUsernames = ensureArray(authorityContext.selectedBotUsernames);
|
|
4735
|
-
const requestKey = buildRunnerRequestKey({
|
|
4736
|
-
normalizedRoute,
|
|
4737
|
-
selectedRecord,
|
|
4738
|
-
selectedBotUsernames: requestSelectedBotUsernames,
|
|
4739
|
-
normalizedIntent: preferredNormalizedIntent,
|
|
4740
|
-
conversationID: resolvedConversationID,
|
|
4741
|
-
});
|
|
4742
|
-
const requests = normalizeBotRunnerRequests(stateForClaim.requests);
|
|
4743
|
-
const existing = safeObject(requests[requestKey]);
|
|
4700
|
+
sharedConversationSource = safeObject(await findServerRunnerConversationSourceRequestForMessageID({
|
|
4701
|
+
normalizedRoute,
|
|
4702
|
+
runtime,
|
|
4703
|
+
chatID: String(parsed.chatID || parsed.chatId || "").trim(),
|
|
4704
|
+
messageID: currentMessageID,
|
|
4705
|
+
excludeRequestKey: provisionalRequestKey,
|
|
4706
|
+
}));
|
|
4707
|
+
}
|
|
4708
|
+
const authorityContext = resolveRunnerHumanCommentAuthorityContext({
|
|
4709
|
+
normalizedRoute,
|
|
4710
|
+
selectedRecord,
|
|
4711
|
+
replyChainContext,
|
|
4712
|
+
referencedRequest,
|
|
4713
|
+
sharedConversationSource,
|
|
4714
|
+
selectedBotUsernames,
|
|
4715
|
+
normalizedSharedHumanIntent,
|
|
4716
|
+
resolvedNormalizedIntent,
|
|
4717
|
+
});
|
|
4718
|
+
const authoritySource = safeObject(authorityContext.authoritySource);
|
|
4719
|
+
const authorityReplyChainContext = await buildRunnerAuthorityReplyChainContext({
|
|
4720
|
+
selectedRecord,
|
|
4721
|
+
replyChainContext,
|
|
4722
|
+
authoritySource,
|
|
4723
|
+
runtime,
|
|
4724
|
+
archiveThreadID,
|
|
4725
|
+
});
|
|
4726
|
+
const resolvedConversationID = String(authorityContext.conversationID || "").trim();
|
|
4727
|
+
const preferredNormalizedIntent = String(authorityContext.normalizedIntent || "").trim().toLowerCase();
|
|
4728
|
+
const requestSelectedBotUsernames = ensureArray(authorityContext.selectedBotUsernames);
|
|
4729
|
+
const requestKey = buildRunnerRequestKey({
|
|
4730
|
+
normalizedRoute,
|
|
4731
|
+
selectedRecord,
|
|
4732
|
+
selectedBotUsernames: requestSelectedBotUsernames,
|
|
4733
|
+
normalizedIntent: preferredNormalizedIntent,
|
|
4734
|
+
conversationID: resolvedConversationID,
|
|
4735
|
+
});
|
|
4736
|
+
const requests = normalizeBotRunnerRequests(stateForClaim.requests);
|
|
4737
|
+
const existing = safeObject(requests[requestKey]);
|
|
4744
4738
|
if (isFinalRunnerRequestStatus(existing.status)) {
|
|
4745
4739
|
return {
|
|
4746
4740
|
ok: false,
|
|
@@ -4758,126 +4752,126 @@ async function claimRunnerRequestForHumanComment({
|
|
|
4758
4752
|
reason: "request_already_claimed",
|
|
4759
4753
|
requestKey,
|
|
4760
4754
|
};
|
|
4761
|
-
}
|
|
4762
|
-
const nowISO = new Date().toISOString();
|
|
4763
|
-
const sourceMessageEnvelope = selectAuthoritativeRunnerSourceMessageEnvelope(
|
|
4764
|
-
authoritativeSourceMessageEnvelope,
|
|
4765
|
-
buildRunnerSourceMessageEnvelope({
|
|
4766
|
-
routeState: currentRouteState,
|
|
4767
|
-
routeKey,
|
|
4768
|
-
normalizedRoute,
|
|
4769
|
-
parsedArchive: parsed,
|
|
4770
|
-
}),
|
|
4771
|
-
);
|
|
4772
|
-
const { requests: nextRequests, request } = upsertRunnerRequest(stateForClaim, requestKey, {
|
|
4773
|
-
project_id: String(normalizedRoute?.projectID || "").trim(),
|
|
4774
|
-
provider: String(normalizedRoute?.provider || "").trim(),
|
|
4775
|
-
chat_id: String(parsed.chatID || parsed.chatId || "").trim(),
|
|
4776
|
-
source_message_id: intFromRawAllowZero(parsed.messageID, 0) || undefined,
|
|
4777
|
-
source_message_thread_id: intFromRawAllowZero(parsed.messageThreadID, 0) || undefined,
|
|
4778
|
-
source_message_body: String(parsed.body || "").trim(),
|
|
4779
|
-
source_message_origin: String(sourceMessageEnvelope.source_origin || "").trim().toLowerCase(),
|
|
4780
|
-
source_message_route_key: String(sourceMessageEnvelope.source_route_key || "").trim(),
|
|
4781
|
-
source_message_bot_username: normalizeTelegramMentionUsername(sourceMessageEnvelope.source_bot_username),
|
|
4782
|
-
source_message_envelope: sourceMessageEnvelope,
|
|
4783
|
-
root_comment_id: String(selectedRecord?.id || "").trim(),
|
|
4784
|
-
root_comment_kind: commentKind,
|
|
4785
|
-
conversation_id: resolvedConversationID,
|
|
4786
|
-
reply_chain_context: authorityReplyChainContext,
|
|
4787
|
-
selected_bot_usernames: uniqueOrderedStrings(requestSelectedBotUsernames, normalizeTelegramMentionUsername),
|
|
4788
|
-
conversation_intent_mode: String(
|
|
4789
|
-
normalizedSharedHumanIntent.intentMode
|
|
4790
|
-
|| existing.conversation_intent_mode
|
|
4791
|
-
|| authoritySource.conversation_intent_mode
|
|
4792
|
-
|| "",
|
|
4793
|
-
).trim().toLowerCase(),
|
|
4794
|
-
conversation_lead_bot: normalizeTelegramMentionUsername(
|
|
4795
|
-
normalizedSharedHumanIntent.leadBotSelector
|
|
4796
|
-
|| existing.conversation_lead_bot
|
|
4797
|
-
|| authoritySource.conversation_lead_bot,
|
|
4798
|
-
),
|
|
4799
|
-
conversation_summary_bot: normalizeTelegramMentionUsername(
|
|
4800
|
-
normalizedSharedHumanIntent.summaryBotSelector
|
|
4801
|
-
|| existing.conversation_summary_bot
|
|
4802
|
-
|| authoritySource.conversation_summary_bot,
|
|
4803
|
-
),
|
|
4804
|
-
conversation_participants: uniqueOrderedStrings(
|
|
4805
|
-
ensureArray(normalizedSharedHumanIntent.participantSelectors).length
|
|
4806
|
-
? normalizedSharedHumanIntent.participantSelectors
|
|
4807
|
-
: ensureArray(existing.conversation_participants).length
|
|
4808
|
-
? existing.conversation_participants
|
|
4809
|
-
: ensureArray(authoritySource.conversation_participants).length
|
|
4810
|
-
? authoritySource.conversation_participants
|
|
4811
|
-
: [],
|
|
4812
|
-
normalizeTelegramMentionUsername,
|
|
4813
|
-
),
|
|
4814
|
-
conversation_initial_responders: uniqueOrderedStrings(
|
|
4815
|
-
ensureArray(normalizedSharedHumanIntent.initialResponderSelectors).length
|
|
4816
|
-
? normalizedSharedHumanIntent.initialResponderSelectors
|
|
4817
|
-
: ensureArray(existing.conversation_initial_responders).length
|
|
4818
|
-
? existing.conversation_initial_responders
|
|
4819
|
-
: ensureArray(authoritySource.conversation_initial_responders).length
|
|
4820
|
-
? authoritySource.conversation_initial_responders
|
|
4821
|
-
: [],
|
|
4822
|
-
normalizeTelegramMentionUsername,
|
|
4823
|
-
),
|
|
4824
|
-
conversation_allowed_responders: uniqueOrderedStrings(
|
|
4825
|
-
ensureArray(normalizedSharedHumanIntent.allowedResponderSelectors).length
|
|
4826
|
-
? normalizedSharedHumanIntent.allowedResponderSelectors
|
|
4827
|
-
: ensureArray(existing.conversation_allowed_responders).length
|
|
4828
|
-
? existing.conversation_allowed_responders
|
|
4829
|
-
: ensureArray(authoritySource.conversation_allowed_responders).length
|
|
4830
|
-
? authoritySource.conversation_allowed_responders
|
|
4831
|
-
: [],
|
|
4832
|
-
normalizeTelegramMentionUsername,
|
|
4833
|
-
),
|
|
4834
|
-
conversation_allow_bot_to_bot: normalizedSharedHumanIntent.allowBotToBot === true
|
|
4835
|
-
|| existing.conversation_allow_bot_to_bot === true
|
|
4836
|
-
|| authoritySource.conversation_allow_bot_to_bot === true,
|
|
4837
|
-
conversation_reply_expectation: String(
|
|
4838
|
-
normalizedSharedHumanIntent.replyExpectation
|
|
4839
|
-
|| existing.conversation_reply_expectation
|
|
4840
|
-
|| authoritySource.conversation_reply_expectation
|
|
4841
|
-
|| "",
|
|
4842
|
-
).trim().toLowerCase(),
|
|
4843
|
-
execution_contract_type: runnerRequestPreferredExecutionContractType(existing)
|
|
4844
|
-
|| runnerRequestPreferredExecutionContractType(authoritySource),
|
|
4845
|
-
execution_contract_actionable: runnerRequestPreferredExecutionContractActionable(existing)
|
|
4846
|
-
|| runnerRequestPreferredExecutionContractActionable(authoritySource),
|
|
4847
|
-
execution_contract_targets: uniqueOrderedStrings(
|
|
4848
|
-
runnerRequestPreferredExecutionContractTargets(existing).length
|
|
4849
|
-
? runnerRequestPreferredExecutionContractTargets(existing)
|
|
4850
|
-
: runnerRequestPreferredExecutionContractTargets(authoritySource),
|
|
4851
|
-
normalizeTelegramMentionUsername,
|
|
4852
|
-
),
|
|
4853
|
-
next_expected_responders: uniqueOrderedStrings(
|
|
4854
|
-
runnerRequestPreferredNextExpectedResponders(existing).length
|
|
4855
|
-
? runnerRequestPreferredNextExpectedResponders(existing)
|
|
4856
|
-
: runnerRequestPreferredNextExpectedResponders(authoritySource),
|
|
4857
|
-
normalizeTelegramMentionUsername,
|
|
4858
|
-
),
|
|
4859
|
-
normalized_intent: String(preferredNormalizedIntent || existing.normalized_intent || "").trim().toLowerCase(),
|
|
4860
|
-
status: "claimed",
|
|
4861
|
-
claimed_by_route: String(routeKey || "").trim(),
|
|
4862
|
-
claimed_at: firstNonEmptyString([existing.claimed_at, nowISO]) || nowISO,
|
|
4863
|
-
root_work_item_id: String(existing.root_work_item_id || authoritySource.root_work_item_id || "").trim(),
|
|
4864
|
-
root_work_item_title: String(existing.root_work_item_title || authoritySource.root_work_item_title || "").trim(),
|
|
4865
|
-
root_work_item_status: normalizeRunnerWorkItemStatus(
|
|
4866
|
-
existing.root_work_item_status || authoritySource.root_work_item_status,
|
|
4867
|
-
),
|
|
4868
|
-
root_thread_id: String(existing.root_thread_id || authoritySource.root_thread_id || "").trim(),
|
|
4869
|
-
root_work_item_created_at: firstNonEmptyString([
|
|
4870
|
-
existing.root_work_item_created_at,
|
|
4871
|
-
authoritySource.root_work_item_created_at,
|
|
4872
|
-
]),
|
|
4873
|
-
root_work_item_last_error: String(
|
|
4874
|
-
existing.root_work_item_last_error || authoritySource.root_work_item_last_error || "",
|
|
4875
|
-
).trim(),
|
|
4876
|
-
last_comment_id: String(selectedRecord?.id || "").trim(),
|
|
4877
|
-
last_comment_kind: commentKind,
|
|
4878
|
-
last_source_message_id: intFromRawAllowZero(parsed.messageID, 0) || undefined,
|
|
4879
|
-
last_source_message_thread_id: intFromRawAllowZero(parsed.messageThreadID, 0) || undefined,
|
|
4880
|
-
});
|
|
4755
|
+
}
|
|
4756
|
+
const nowISO = new Date().toISOString();
|
|
4757
|
+
const sourceMessageEnvelope = selectAuthoritativeRunnerSourceMessageEnvelope(
|
|
4758
|
+
authoritativeSourceMessageEnvelope,
|
|
4759
|
+
buildRunnerSourceMessageEnvelope({
|
|
4760
|
+
routeState: currentRouteState,
|
|
4761
|
+
routeKey,
|
|
4762
|
+
normalizedRoute,
|
|
4763
|
+
parsedArchive: parsed,
|
|
4764
|
+
}),
|
|
4765
|
+
);
|
|
4766
|
+
const { requests: nextRequests, request } = upsertRunnerRequest(stateForClaim, requestKey, {
|
|
4767
|
+
project_id: String(normalizedRoute?.projectID || "").trim(),
|
|
4768
|
+
provider: String(normalizedRoute?.provider || "").trim(),
|
|
4769
|
+
chat_id: String(parsed.chatID || parsed.chatId || "").trim(),
|
|
4770
|
+
source_message_id: intFromRawAllowZero(parsed.messageID, 0) || undefined,
|
|
4771
|
+
source_message_thread_id: intFromRawAllowZero(parsed.messageThreadID, 0) || undefined,
|
|
4772
|
+
source_message_body: String(parsed.body || "").trim(),
|
|
4773
|
+
source_message_origin: String(sourceMessageEnvelope.source_origin || "").trim().toLowerCase(),
|
|
4774
|
+
source_message_route_key: String(sourceMessageEnvelope.source_route_key || "").trim(),
|
|
4775
|
+
source_message_bot_username: normalizeTelegramMentionUsername(sourceMessageEnvelope.source_bot_username),
|
|
4776
|
+
source_message_envelope: sourceMessageEnvelope,
|
|
4777
|
+
root_comment_id: String(selectedRecord?.id || "").trim(),
|
|
4778
|
+
root_comment_kind: commentKind,
|
|
4779
|
+
conversation_id: resolvedConversationID,
|
|
4780
|
+
reply_chain_context: authorityReplyChainContext,
|
|
4781
|
+
selected_bot_usernames: uniqueOrderedStrings(requestSelectedBotUsernames, normalizeTelegramMentionUsername),
|
|
4782
|
+
conversation_intent_mode: String(
|
|
4783
|
+
normalizedSharedHumanIntent.intentMode
|
|
4784
|
+
|| existing.conversation_intent_mode
|
|
4785
|
+
|| authoritySource.conversation_intent_mode
|
|
4786
|
+
|| "",
|
|
4787
|
+
).trim().toLowerCase(),
|
|
4788
|
+
conversation_lead_bot: normalizeTelegramMentionUsername(
|
|
4789
|
+
normalizedSharedHumanIntent.leadBotSelector
|
|
4790
|
+
|| existing.conversation_lead_bot
|
|
4791
|
+
|| authoritySource.conversation_lead_bot,
|
|
4792
|
+
),
|
|
4793
|
+
conversation_summary_bot: normalizeTelegramMentionUsername(
|
|
4794
|
+
normalizedSharedHumanIntent.summaryBotSelector
|
|
4795
|
+
|| existing.conversation_summary_bot
|
|
4796
|
+
|| authoritySource.conversation_summary_bot,
|
|
4797
|
+
),
|
|
4798
|
+
conversation_participants: uniqueOrderedStrings(
|
|
4799
|
+
ensureArray(normalizedSharedHumanIntent.participantSelectors).length
|
|
4800
|
+
? normalizedSharedHumanIntent.participantSelectors
|
|
4801
|
+
: ensureArray(existing.conversation_participants).length
|
|
4802
|
+
? existing.conversation_participants
|
|
4803
|
+
: ensureArray(authoritySource.conversation_participants).length
|
|
4804
|
+
? authoritySource.conversation_participants
|
|
4805
|
+
: [],
|
|
4806
|
+
normalizeTelegramMentionUsername,
|
|
4807
|
+
),
|
|
4808
|
+
conversation_initial_responders: uniqueOrderedStrings(
|
|
4809
|
+
ensureArray(normalizedSharedHumanIntent.initialResponderSelectors).length
|
|
4810
|
+
? normalizedSharedHumanIntent.initialResponderSelectors
|
|
4811
|
+
: ensureArray(existing.conversation_initial_responders).length
|
|
4812
|
+
? existing.conversation_initial_responders
|
|
4813
|
+
: ensureArray(authoritySource.conversation_initial_responders).length
|
|
4814
|
+
? authoritySource.conversation_initial_responders
|
|
4815
|
+
: [],
|
|
4816
|
+
normalizeTelegramMentionUsername,
|
|
4817
|
+
),
|
|
4818
|
+
conversation_allowed_responders: uniqueOrderedStrings(
|
|
4819
|
+
ensureArray(normalizedSharedHumanIntent.allowedResponderSelectors).length
|
|
4820
|
+
? normalizedSharedHumanIntent.allowedResponderSelectors
|
|
4821
|
+
: ensureArray(existing.conversation_allowed_responders).length
|
|
4822
|
+
? existing.conversation_allowed_responders
|
|
4823
|
+
: ensureArray(authoritySource.conversation_allowed_responders).length
|
|
4824
|
+
? authoritySource.conversation_allowed_responders
|
|
4825
|
+
: [],
|
|
4826
|
+
normalizeTelegramMentionUsername,
|
|
4827
|
+
),
|
|
4828
|
+
conversation_allow_bot_to_bot: normalizedSharedHumanIntent.allowBotToBot === true
|
|
4829
|
+
|| existing.conversation_allow_bot_to_bot === true
|
|
4830
|
+
|| authoritySource.conversation_allow_bot_to_bot === true,
|
|
4831
|
+
conversation_reply_expectation: String(
|
|
4832
|
+
normalizedSharedHumanIntent.replyExpectation
|
|
4833
|
+
|| existing.conversation_reply_expectation
|
|
4834
|
+
|| authoritySource.conversation_reply_expectation
|
|
4835
|
+
|| "",
|
|
4836
|
+
).trim().toLowerCase(),
|
|
4837
|
+
execution_contract_type: runnerRequestPreferredExecutionContractType(existing)
|
|
4838
|
+
|| runnerRequestPreferredExecutionContractType(authoritySource),
|
|
4839
|
+
execution_contract_actionable: runnerRequestPreferredExecutionContractActionable(existing)
|
|
4840
|
+
|| runnerRequestPreferredExecutionContractActionable(authoritySource),
|
|
4841
|
+
execution_contract_targets: uniqueOrderedStrings(
|
|
4842
|
+
runnerRequestPreferredExecutionContractTargets(existing).length
|
|
4843
|
+
? runnerRequestPreferredExecutionContractTargets(existing)
|
|
4844
|
+
: runnerRequestPreferredExecutionContractTargets(authoritySource),
|
|
4845
|
+
normalizeTelegramMentionUsername,
|
|
4846
|
+
),
|
|
4847
|
+
next_expected_responders: uniqueOrderedStrings(
|
|
4848
|
+
runnerRequestPreferredNextExpectedResponders(existing).length
|
|
4849
|
+
? runnerRequestPreferredNextExpectedResponders(existing)
|
|
4850
|
+
: runnerRequestPreferredNextExpectedResponders(authoritySource),
|
|
4851
|
+
normalizeTelegramMentionUsername,
|
|
4852
|
+
),
|
|
4853
|
+
normalized_intent: String(preferredNormalizedIntent || existing.normalized_intent || "").trim().toLowerCase(),
|
|
4854
|
+
status: "claimed",
|
|
4855
|
+
claimed_by_route: String(routeKey || "").trim(),
|
|
4856
|
+
claimed_at: firstNonEmptyString([existing.claimed_at, nowISO]) || nowISO,
|
|
4857
|
+
root_work_item_id: String(existing.root_work_item_id || authoritySource.root_work_item_id || "").trim(),
|
|
4858
|
+
root_work_item_title: String(existing.root_work_item_title || authoritySource.root_work_item_title || "").trim(),
|
|
4859
|
+
root_work_item_status: normalizeRunnerWorkItemStatus(
|
|
4860
|
+
existing.root_work_item_status || authoritySource.root_work_item_status,
|
|
4861
|
+
),
|
|
4862
|
+
root_thread_id: String(existing.root_thread_id || authoritySource.root_thread_id || "").trim(),
|
|
4863
|
+
root_work_item_created_at: firstNonEmptyString([
|
|
4864
|
+
existing.root_work_item_created_at,
|
|
4865
|
+
authoritySource.root_work_item_created_at,
|
|
4866
|
+
]),
|
|
4867
|
+
root_work_item_last_error: String(
|
|
4868
|
+
existing.root_work_item_last_error || authoritySource.root_work_item_last_error || "",
|
|
4869
|
+
).trim(),
|
|
4870
|
+
last_comment_id: String(selectedRecord?.id || "").trim(),
|
|
4871
|
+
last_comment_kind: commentKind,
|
|
4872
|
+
last_source_message_id: intFromRawAllowZero(parsed.messageID, 0) || undefined,
|
|
4873
|
+
last_source_message_thread_id: intFromRawAllowZero(parsed.messageThreadID, 0) || undefined,
|
|
4874
|
+
});
|
|
4881
4875
|
const { consumedComments: nextConsumedComments } = upsertRunnerConsumedComment(stateForClaim, selectedRecord?.id, {
|
|
4882
4876
|
project_id: String(normalizedRoute?.projectID || "").trim(),
|
|
4883
4877
|
provider: String(normalizedRoute?.provider || "").trim(),
|
|
@@ -5390,7 +5384,7 @@ function buildRunnerRootWorkItemTransitionPath(currentStatusRaw, targetStatusRaw
|
|
|
5390
5384
|
return [];
|
|
5391
5385
|
}
|
|
5392
5386
|
|
|
5393
|
-
function buildRunnerRouteFollowupSnapshotPatch(selectedRecordRaw, resultRaw = {}) {
|
|
5387
|
+
function buildRunnerRouteFollowupSnapshotPatch(selectedRecordRaw, resultRaw = {}) {
|
|
5394
5388
|
const parsed = safeObject(safeObject(selectedRecordRaw).parsedArchive);
|
|
5395
5389
|
const commentKind = String(parsed.kind || "").trim().toLowerCase();
|
|
5396
5390
|
if (["telegram_message", "telegram_edited_message"].includes(commentKind)) {
|
|
@@ -5429,26 +5423,26 @@ function buildRunnerRouteFollowupSnapshotPatch(selectedRecordRaw, resultRaw = {}
|
|
|
5429
5423
|
ensureArray(result.assignment_validation_modes),
|
|
5430
5424
|
(value) => String(value || "").trim().toLowerCase(),
|
|
5431
5425
|
),
|
|
5432
|
-
last_followup_delivery_status: String(result.delivery_status || "").trim().toLowerCase(),
|
|
5433
|
-
last_followup_archive_status: String(result.archive_status || "").trim().toLowerCase(),
|
|
5434
|
-
last_followup_transport_error: String(result.transport_error || "").trim(),
|
|
5435
|
-
last_followup_archive_error: String(result.archive_error || "").trim(),
|
|
5436
|
-
last_followup_source_message_envelope: normalizeRunnerTelegramMessageEnvelope(result.source_message_envelope),
|
|
5437
|
-
last_followup_last_reply_message_envelope: normalizeRunnerTelegramMessageEnvelope(result.last_reply_message_envelope),
|
|
5438
|
-
last_followup_attempted_delivery_envelope: normalizeRunnerTelegramMessageEnvelope(result.attempted_delivery_envelope),
|
|
5439
|
-
});
|
|
5440
|
-
}
|
|
5441
|
-
|
|
5442
|
-
function buildRunnerRequestRecoveryPatchFromRouteState(currentStateRaw, requestRaw, routeKeyHint = "") {
|
|
5443
|
-
const currentState = safeObject(currentStateRaw);
|
|
5444
|
-
const request = safeObject(requestRaw);
|
|
5445
|
-
const requestKey = String(request.request_key || "").trim();
|
|
5446
|
-
if (!requestKey) {
|
|
5447
|
-
return {};
|
|
5448
|
-
}
|
|
5449
|
-
const requestSourceMessageID = intFromRawAllowZero(request.last_source_message_id, 0)
|
|
5450
|
-
|| intFromRawAllowZero(request.source_message_id, 0)
|
|
5451
|
-
|| intFromRawAllowZero(safeObject(request.source_message_envelope).message_id, 0);
|
|
5426
|
+
last_followup_delivery_status: String(result.delivery_status || "").trim().toLowerCase(),
|
|
5427
|
+
last_followup_archive_status: String(result.archive_status || "").trim().toLowerCase(),
|
|
5428
|
+
last_followup_transport_error: String(result.transport_error || "").trim(),
|
|
5429
|
+
last_followup_archive_error: String(result.archive_error || "").trim(),
|
|
5430
|
+
last_followup_source_message_envelope: normalizeRunnerTelegramMessageEnvelope(result.source_message_envelope),
|
|
5431
|
+
last_followup_last_reply_message_envelope: normalizeRunnerTelegramMessageEnvelope(result.last_reply_message_envelope),
|
|
5432
|
+
last_followup_attempted_delivery_envelope: normalizeRunnerTelegramMessageEnvelope(result.attempted_delivery_envelope),
|
|
5433
|
+
});
|
|
5434
|
+
}
|
|
5435
|
+
|
|
5436
|
+
function buildRunnerRequestRecoveryPatchFromRouteState(currentStateRaw, requestRaw, routeKeyHint = "") {
|
|
5437
|
+
const currentState = safeObject(currentStateRaw);
|
|
5438
|
+
const request = safeObject(requestRaw);
|
|
5439
|
+
const requestKey = String(request.request_key || "").trim();
|
|
5440
|
+
if (!requestKey) {
|
|
5441
|
+
return {};
|
|
5442
|
+
}
|
|
5443
|
+
const requestSourceMessageID = intFromRawAllowZero(request.last_source_message_id, 0)
|
|
5444
|
+
|| intFromRawAllowZero(request.source_message_id, 0)
|
|
5445
|
+
|| intFromRawAllowZero(safeObject(request.source_message_envelope).message_id, 0);
|
|
5452
5446
|
const routeKeys = uniqueOrderedStrings(
|
|
5453
5447
|
[
|
|
5454
5448
|
routeKeyHint,
|
|
@@ -5456,14 +5450,14 @@ function buildRunnerRequestRecoveryPatchFromRouteState(currentStateRaw, requestR
|
|
|
5456
5450
|
],
|
|
5457
5451
|
(value) => String(value || "").trim(),
|
|
5458
5452
|
).filter(Boolean);
|
|
5459
|
-
for (const routeKey of routeKeys) {
|
|
5460
|
-
const routeState = safeObject(safeObject(currentState.routes)[routeKey]);
|
|
5453
|
+
for (const routeKey of routeKeys) {
|
|
5454
|
+
const routeState = safeObject(safeObject(currentState.routes)[routeKey]);
|
|
5461
5455
|
if (!Object.keys(routeState).length) {
|
|
5462
5456
|
continue;
|
|
5463
5457
|
}
|
|
5464
|
-
const routeSourceMessageID = intFromRawAllowZero(routeState.last_source_message_id, 0)
|
|
5465
|
-
|| intFromRawAllowZero(routeState.source_message_id, 0)
|
|
5466
|
-
|| intFromRawAllowZero(safeObject(routeState.last_followup_source_message_envelope).message_id, 0);
|
|
5458
|
+
const routeSourceMessageID = intFromRawAllowZero(routeState.last_source_message_id, 0)
|
|
5459
|
+
|| intFromRawAllowZero(routeState.source_message_id, 0)
|
|
5460
|
+
|| intFromRawAllowZero(safeObject(routeState.last_followup_source_message_envelope).message_id, 0);
|
|
5467
5461
|
if (requestSourceMessageID && routeSourceMessageID && requestSourceMessageID !== routeSourceMessageID) {
|
|
5468
5462
|
continue;
|
|
5469
5463
|
}
|
|
@@ -5519,69 +5513,69 @@ function buildRunnerRequestRecoveryPatchFromRouteState(currentStateRaw, requestR
|
|
|
5519
5513
|
setFollowupStringPatch("followup_assignment_validation_status", ["last_followup_assignment_validation_status", "last_assignment_validation_status"]);
|
|
5520
5514
|
setFollowupStringPatch("followup_assignment_validation_reason", ["last_followup_assignment_validation_reason", "last_assignment_validation_reason"]);
|
|
5521
5515
|
setFollowupArrayPatch("followup_assignment_validation_modes", ["last_followup_assignment_validation_modes"], (value) => String(value || "").trim().toLowerCase());
|
|
5522
|
-
setFollowupStringPatch("followup_delivery_status", ["last_followup_delivery_status"]);
|
|
5523
|
-
setFollowupStringPatch("followup_archive_status", ["last_followup_archive_status"]);
|
|
5524
|
-
setFollowupStringPatch("followup_transport_error", ["last_followup_transport_error"]);
|
|
5525
|
-
setFollowupStringPatch("followup_archive_error", ["last_followup_archive_error"]);
|
|
5526
|
-
const routeFollowupDeliveryStatus = String(routeState.last_followup_delivery_status || "").trim().toLowerCase();
|
|
5527
|
-
const routeFollowupDelivered = ["delivered", "dry_run"].includes(routeFollowupDeliveryStatus);
|
|
5528
|
-
const routeLocalRecoveredSourceEnvelope = normalizeRunnerTelegramMessageEnvelope(
|
|
5529
|
-
findRunnerRouteLocalInboundEnvelopeByMessage(routeState, {
|
|
5530
|
-
chatID: String(request.chat_id || request.chatID || "").trim(),
|
|
5531
|
-
messageID: requestSourceMessageID || routeSourceMessageID,
|
|
5532
|
-
}),
|
|
5533
|
-
);
|
|
5534
|
-
const recoveredSourceEnvelope = mergeRunnerSourceMessageEnvelopes(
|
|
5535
|
-
routeState.last_followup_source_message_envelope,
|
|
5536
|
-
routeLocalRecoveredSourceEnvelope,
|
|
5537
|
-
);
|
|
5538
|
-
if (Object.keys(recoveredSourceEnvelope).length) {
|
|
5539
|
-
if (!Object.keys(safeObject(request.source_message_envelope)).length) {
|
|
5540
|
-
patch.source_message_envelope = recoveredSourceEnvelope;
|
|
5541
|
-
}
|
|
5542
|
-
if (!(intFromRawAllowZero(request.source_message_id, 0) > 0)) {
|
|
5543
|
-
const recoveredMessageID = intFromRawAllowZero(recoveredSourceEnvelope.message_id, 0);
|
|
5544
|
-
if (recoveredMessageID > 0) {
|
|
5545
|
-
patch.source_message_id = recoveredMessageID;
|
|
5546
|
-
}
|
|
5547
|
-
}
|
|
5548
|
-
if (!(intFromRawAllowZero(request.source_message_thread_id, 0) > 0)) {
|
|
5549
|
-
const recoveredThreadID = intFromRawAllowZero(recoveredSourceEnvelope.message_thread_id, 0);
|
|
5550
|
-
if (recoveredThreadID > 0) {
|
|
5551
|
-
patch.source_message_thread_id = recoveredThreadID;
|
|
5552
|
-
}
|
|
5553
|
-
}
|
|
5554
|
-
if (!String(request.source_message_body || "").trim() && String(recoveredSourceEnvelope.body || "").trim()) {
|
|
5555
|
-
patch.source_message_body = String(recoveredSourceEnvelope.body || "").trim();
|
|
5556
|
-
}
|
|
5557
|
-
if (!String(request.source_message_origin || "").trim() && String(recoveredSourceEnvelope.source_origin || "").trim()) {
|
|
5558
|
-
patch.source_message_origin = String(recoveredSourceEnvelope.source_origin || "").trim().toLowerCase();
|
|
5559
|
-
}
|
|
5560
|
-
if (!String(request.source_message_route_key || "").trim() && String(recoveredSourceEnvelope.source_route_key || "").trim()) {
|
|
5561
|
-
patch.source_message_route_key = String(recoveredSourceEnvelope.source_route_key || "").trim();
|
|
5562
|
-
}
|
|
5563
|
-
if (
|
|
5564
|
-
!normalizeTelegramMentionUsername(request.source_message_bot_username)
|
|
5565
|
-
&& normalizeTelegramMentionUsername(recoveredSourceEnvelope.source_bot_username)
|
|
5566
|
-
) {
|
|
5567
|
-
patch.source_message_bot_username = normalizeTelegramMentionUsername(
|
|
5568
|
-
recoveredSourceEnvelope.source_bot_username,
|
|
5569
|
-
);
|
|
5570
|
-
}
|
|
5571
|
-
}
|
|
5572
|
-
if (!Object.keys(safeObject(request.last_reply_message_envelope)).length && routeFollowupDelivered) {
|
|
5573
|
-
const recoveredReplyEnvelope = normalizeRunnerTelegramMessageEnvelope(routeState.last_followup_last_reply_message_envelope);
|
|
5574
|
-
if (intFromRawAllowZero(recoveredReplyEnvelope.message_id, 0) > 0) {
|
|
5575
|
-
patch.last_reply_message_envelope = recoveredReplyEnvelope;
|
|
5576
|
-
}
|
|
5577
|
-
}
|
|
5578
|
-
if (!Object.keys(safeObject(request.attempted_delivery_envelope)).length) {
|
|
5579
|
-
const recoveredAttemptEnvelope = normalizeRunnerTelegramMessageEnvelope(routeState.last_followup_attempted_delivery_envelope);
|
|
5580
|
-
if (Object.keys(recoveredAttemptEnvelope).length) {
|
|
5581
|
-
patch.attempted_delivery_envelope = recoveredAttemptEnvelope;
|
|
5582
|
-
}
|
|
5583
|
-
}
|
|
5584
|
-
const requestStatus = normalizeRunnerRequestStatus(request.status);
|
|
5516
|
+
setFollowupStringPatch("followup_delivery_status", ["last_followup_delivery_status"]);
|
|
5517
|
+
setFollowupStringPatch("followup_archive_status", ["last_followup_archive_status"]);
|
|
5518
|
+
setFollowupStringPatch("followup_transport_error", ["last_followup_transport_error"]);
|
|
5519
|
+
setFollowupStringPatch("followup_archive_error", ["last_followup_archive_error"]);
|
|
5520
|
+
const routeFollowupDeliveryStatus = String(routeState.last_followup_delivery_status || "").trim().toLowerCase();
|
|
5521
|
+
const routeFollowupDelivered = ["delivered", "dry_run"].includes(routeFollowupDeliveryStatus);
|
|
5522
|
+
const routeLocalRecoveredSourceEnvelope = normalizeRunnerTelegramMessageEnvelope(
|
|
5523
|
+
findRunnerRouteLocalInboundEnvelopeByMessage(routeState, {
|
|
5524
|
+
chatID: String(request.chat_id || request.chatID || "").trim(),
|
|
5525
|
+
messageID: requestSourceMessageID || routeSourceMessageID,
|
|
5526
|
+
}),
|
|
5527
|
+
);
|
|
5528
|
+
const recoveredSourceEnvelope = mergeRunnerSourceMessageEnvelopes(
|
|
5529
|
+
routeState.last_followup_source_message_envelope,
|
|
5530
|
+
routeLocalRecoveredSourceEnvelope,
|
|
5531
|
+
);
|
|
5532
|
+
if (Object.keys(recoveredSourceEnvelope).length) {
|
|
5533
|
+
if (!Object.keys(safeObject(request.source_message_envelope)).length) {
|
|
5534
|
+
patch.source_message_envelope = recoveredSourceEnvelope;
|
|
5535
|
+
}
|
|
5536
|
+
if (!(intFromRawAllowZero(request.source_message_id, 0) > 0)) {
|
|
5537
|
+
const recoveredMessageID = intFromRawAllowZero(recoveredSourceEnvelope.message_id, 0);
|
|
5538
|
+
if (recoveredMessageID > 0) {
|
|
5539
|
+
patch.source_message_id = recoveredMessageID;
|
|
5540
|
+
}
|
|
5541
|
+
}
|
|
5542
|
+
if (!(intFromRawAllowZero(request.source_message_thread_id, 0) > 0)) {
|
|
5543
|
+
const recoveredThreadID = intFromRawAllowZero(recoveredSourceEnvelope.message_thread_id, 0);
|
|
5544
|
+
if (recoveredThreadID > 0) {
|
|
5545
|
+
patch.source_message_thread_id = recoveredThreadID;
|
|
5546
|
+
}
|
|
5547
|
+
}
|
|
5548
|
+
if (!String(request.source_message_body || "").trim() && String(recoveredSourceEnvelope.body || "").trim()) {
|
|
5549
|
+
patch.source_message_body = String(recoveredSourceEnvelope.body || "").trim();
|
|
5550
|
+
}
|
|
5551
|
+
if (!String(request.source_message_origin || "").trim() && String(recoveredSourceEnvelope.source_origin || "").trim()) {
|
|
5552
|
+
patch.source_message_origin = String(recoveredSourceEnvelope.source_origin || "").trim().toLowerCase();
|
|
5553
|
+
}
|
|
5554
|
+
if (!String(request.source_message_route_key || "").trim() && String(recoveredSourceEnvelope.source_route_key || "").trim()) {
|
|
5555
|
+
patch.source_message_route_key = String(recoveredSourceEnvelope.source_route_key || "").trim();
|
|
5556
|
+
}
|
|
5557
|
+
if (
|
|
5558
|
+
!normalizeTelegramMentionUsername(request.source_message_bot_username)
|
|
5559
|
+
&& normalizeTelegramMentionUsername(recoveredSourceEnvelope.source_bot_username)
|
|
5560
|
+
) {
|
|
5561
|
+
patch.source_message_bot_username = normalizeTelegramMentionUsername(
|
|
5562
|
+
recoveredSourceEnvelope.source_bot_username,
|
|
5563
|
+
);
|
|
5564
|
+
}
|
|
5565
|
+
}
|
|
5566
|
+
if (!Object.keys(safeObject(request.last_reply_message_envelope)).length && routeFollowupDelivered) {
|
|
5567
|
+
const recoveredReplyEnvelope = normalizeRunnerTelegramMessageEnvelope(routeState.last_followup_last_reply_message_envelope);
|
|
5568
|
+
if (intFromRawAllowZero(recoveredReplyEnvelope.message_id, 0) > 0) {
|
|
5569
|
+
patch.last_reply_message_envelope = recoveredReplyEnvelope;
|
|
5570
|
+
}
|
|
5571
|
+
}
|
|
5572
|
+
if (!Object.keys(safeObject(request.attempted_delivery_envelope)).length) {
|
|
5573
|
+
const recoveredAttemptEnvelope = normalizeRunnerTelegramMessageEnvelope(routeState.last_followup_attempted_delivery_envelope);
|
|
5574
|
+
if (Object.keys(recoveredAttemptEnvelope).length) {
|
|
5575
|
+
patch.attempted_delivery_envelope = recoveredAttemptEnvelope;
|
|
5576
|
+
}
|
|
5577
|
+
}
|
|
5578
|
+
const requestStatus = normalizeRunnerRequestStatus(request.status);
|
|
5585
5579
|
if (!isFinalRunnerRequestStatus(requestStatus)) {
|
|
5586
5580
|
const routeAction = String(routeState.last_action || "").trim().toLowerCase();
|
|
5587
5581
|
if (routeAction === "replied") {
|
|
@@ -5741,49 +5735,49 @@ function peekRunnerContinuationRequestForBotReply({
|
|
|
5741
5735
|
|| safeObject(sessionMatch.routeState).last_request_key
|
|
5742
5736
|
|| "",
|
|
5743
5737
|
).trim();
|
|
5744
|
-
if (
|
|
5745
|
-
fallbackRequestKey
|
|
5746
|
-
&& String(session.status || "").trim().toLowerCase() === "open"
|
|
5747
|
-
) {
|
|
5748
|
-
const fallbackRequest = safeObject(normalizeBotRunnerRequests(currentState.requests)[fallbackRequestKey]);
|
|
5749
|
-
const fallbackSourceMessageID = intFromRawAllowZero(
|
|
5750
|
-
fallbackRequest.source_message_id
|
|
5751
|
-
|| safeObject(sessionMatch.routeState).last_source_message_id
|
|
5752
|
-
|| safeObject(sessionMatch.routeState).source_message_id
|
|
5753
|
-
|| safeObject(safeObject(sessionMatch.routeState).last_followup_source_message_envelope).message_id,
|
|
5754
|
-
0,
|
|
5755
|
-
);
|
|
5756
|
-
const fallbackLocalSourceEnvelope = normalizeRunnerTelegramMessageEnvelope(
|
|
5757
|
-
findRunnerRouteLocalInboundEnvelopeByMessage(sessionMatch.routeState, {
|
|
5758
|
-
chatID: String(parsed.chatID || parsed.chatId || "").trim(),
|
|
5759
|
-
messageID: fallbackSourceMessageID,
|
|
5760
|
-
}),
|
|
5761
|
-
);
|
|
5762
|
-
const fallbackSourceEnvelope = mergeRunnerSourceMessageEnvelopes(
|
|
5763
|
-
safeObject(sessionMatch.routeState).last_followup_source_message_envelope,
|
|
5764
|
-
fallbackLocalSourceEnvelope,
|
|
5765
|
-
);
|
|
5766
|
-
const nowISO = new Date().toISOString();
|
|
5767
|
-
const seedRequest = Object.keys(fallbackRequest).length
|
|
5768
|
-
? fallbackRequest
|
|
5769
|
-
: {
|
|
5770
|
-
request_key: fallbackRequestKey,
|
|
5771
|
-
project_id: String(normalizedRoute?.projectID || "").trim(),
|
|
5772
|
-
provider: String(normalizedRoute?.provider || "").trim(),
|
|
5773
|
-
chat_id: String(parsed.chatID || parsed.chatId || "").trim(),
|
|
5774
|
-
source_message_id: intFromRawAllowZero(fallbackSourceEnvelope.message_id, 0) || undefined,
|
|
5775
|
-
source_message_thread_id: intFromRawAllowZero(fallbackSourceEnvelope.message_thread_id, 0) || undefined,
|
|
5776
|
-
source_message_body: String(fallbackSourceEnvelope.body || "").trim(),
|
|
5777
|
-
source_message_origin: String(fallbackSourceEnvelope.source_origin || "").trim().toLowerCase(),
|
|
5778
|
-
source_message_route_key: String(fallbackSourceEnvelope.source_route_key || "").trim(),
|
|
5779
|
-
source_message_bot_username: normalizeTelegramMentionUsername(
|
|
5780
|
-
fallbackSourceEnvelope.source_bot_username,
|
|
5781
|
-
),
|
|
5782
|
-
source_message_envelope: fallbackSourceEnvelope,
|
|
5783
|
-
conversation_id: conversationID,
|
|
5784
|
-
selected_bot_usernames: ensureArray(session.participants),
|
|
5785
|
-
conversation_allowed_responders: ensureArray(session.allowed_responders),
|
|
5786
|
-
conversation_intent_mode: String(session.intent_mode || "").trim().toLowerCase(),
|
|
5738
|
+
if (
|
|
5739
|
+
fallbackRequestKey
|
|
5740
|
+
&& String(session.status || "").trim().toLowerCase() === "open"
|
|
5741
|
+
) {
|
|
5742
|
+
const fallbackRequest = safeObject(normalizeBotRunnerRequests(currentState.requests)[fallbackRequestKey]);
|
|
5743
|
+
const fallbackSourceMessageID = intFromRawAllowZero(
|
|
5744
|
+
fallbackRequest.source_message_id
|
|
5745
|
+
|| safeObject(sessionMatch.routeState).last_source_message_id
|
|
5746
|
+
|| safeObject(sessionMatch.routeState).source_message_id
|
|
5747
|
+
|| safeObject(safeObject(sessionMatch.routeState).last_followup_source_message_envelope).message_id,
|
|
5748
|
+
0,
|
|
5749
|
+
);
|
|
5750
|
+
const fallbackLocalSourceEnvelope = normalizeRunnerTelegramMessageEnvelope(
|
|
5751
|
+
findRunnerRouteLocalInboundEnvelopeByMessage(sessionMatch.routeState, {
|
|
5752
|
+
chatID: String(parsed.chatID || parsed.chatId || "").trim(),
|
|
5753
|
+
messageID: fallbackSourceMessageID,
|
|
5754
|
+
}),
|
|
5755
|
+
);
|
|
5756
|
+
const fallbackSourceEnvelope = mergeRunnerSourceMessageEnvelopes(
|
|
5757
|
+
safeObject(sessionMatch.routeState).last_followup_source_message_envelope,
|
|
5758
|
+
fallbackLocalSourceEnvelope,
|
|
5759
|
+
);
|
|
5760
|
+
const nowISO = new Date().toISOString();
|
|
5761
|
+
const seedRequest = Object.keys(fallbackRequest).length
|
|
5762
|
+
? fallbackRequest
|
|
5763
|
+
: {
|
|
5764
|
+
request_key: fallbackRequestKey,
|
|
5765
|
+
project_id: String(normalizedRoute?.projectID || "").trim(),
|
|
5766
|
+
provider: String(normalizedRoute?.provider || "").trim(),
|
|
5767
|
+
chat_id: String(parsed.chatID || parsed.chatId || "").trim(),
|
|
5768
|
+
source_message_id: intFromRawAllowZero(fallbackSourceEnvelope.message_id, 0) || undefined,
|
|
5769
|
+
source_message_thread_id: intFromRawAllowZero(fallbackSourceEnvelope.message_thread_id, 0) || undefined,
|
|
5770
|
+
source_message_body: String(fallbackSourceEnvelope.body || "").trim(),
|
|
5771
|
+
source_message_origin: String(fallbackSourceEnvelope.source_origin || "").trim().toLowerCase(),
|
|
5772
|
+
source_message_route_key: String(fallbackSourceEnvelope.source_route_key || "").trim(),
|
|
5773
|
+
source_message_bot_username: normalizeTelegramMentionUsername(
|
|
5774
|
+
fallbackSourceEnvelope.source_bot_username,
|
|
5775
|
+
),
|
|
5776
|
+
source_message_envelope: fallbackSourceEnvelope,
|
|
5777
|
+
conversation_id: conversationID,
|
|
5778
|
+
selected_bot_usernames: ensureArray(session.participants),
|
|
5779
|
+
conversation_allowed_responders: ensureArray(session.allowed_responders),
|
|
5780
|
+
conversation_intent_mode: String(session.intent_mode || "").trim().toLowerCase(),
|
|
5787
5781
|
conversation_lead_bot: normalizeTelegramMentionUsername(session.lead_bot_username),
|
|
5788
5782
|
conversation_summary_bot: normalizeTelegramMentionUsername(session.summary_bot_username),
|
|
5789
5783
|
conversation_participants: ensureArray(session.participants),
|
|
@@ -5845,16 +5839,16 @@ function peekRunnerContinuationRequestForBotReply({
|
|
|
5845
5839
|
};
|
|
5846
5840
|
}
|
|
5847
5841
|
|
|
5848
|
-
function resolveRunnerContinuationRequestForBotReply({
|
|
5849
|
-
normalizedRoute,
|
|
5850
|
-
routeKey,
|
|
5851
|
-
selectedRecord,
|
|
5852
|
-
}) {
|
|
5853
|
-
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
5854
|
-
const continuation = peekRunnerContinuationRequestForBotReply({
|
|
5855
|
-
normalizedRoute,
|
|
5856
|
-
selectedRecord,
|
|
5857
|
-
});
|
|
5842
|
+
function resolveRunnerContinuationRequestForBotReply({
|
|
5843
|
+
normalizedRoute,
|
|
5844
|
+
routeKey,
|
|
5845
|
+
selectedRecord,
|
|
5846
|
+
}) {
|
|
5847
|
+
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
5848
|
+
const continuation = peekRunnerContinuationRequestForBotReply({
|
|
5849
|
+
normalizedRoute,
|
|
5850
|
+
selectedRecord,
|
|
5851
|
+
});
|
|
5858
5852
|
if (!continuation.ok) {
|
|
5859
5853
|
return continuation;
|
|
5860
5854
|
}
|
|
@@ -5874,12 +5868,12 @@ function resolveRunnerContinuationRequestForBotReply({
|
|
|
5874
5868
|
comment_kind: commentKind,
|
|
5875
5869
|
request_status: request.status,
|
|
5876
5870
|
});
|
|
5877
|
-
const { requests: nextRequests, request: nextRequest } = upsertRunnerRequest(currentState, request.request_key, {
|
|
5878
|
-
last_comment_id: String(selectedRecord?.id || "").trim(),
|
|
5879
|
-
last_comment_kind: commentKind,
|
|
5880
|
-
last_source_message_id: intFromRawAllowZero(parsed.messageID, 0) || undefined,
|
|
5881
|
-
last_source_message_thread_id: intFromRawAllowZero(parsed.messageThreadID, 0) || undefined,
|
|
5882
|
-
});
|
|
5871
|
+
const { requests: nextRequests, request: nextRequest } = upsertRunnerRequest(currentState, request.request_key, {
|
|
5872
|
+
last_comment_id: String(selectedRecord?.id || "").trim(),
|
|
5873
|
+
last_comment_kind: commentKind,
|
|
5874
|
+
last_source_message_id: intFromRawAllowZero(parsed.messageID, 0) || undefined,
|
|
5875
|
+
last_source_message_thread_id: intFromRawAllowZero(parsed.messageThreadID, 0) || undefined,
|
|
5876
|
+
});
|
|
5883
5877
|
saveBotRunnerState({
|
|
5884
5878
|
routes: currentState.routes,
|
|
5885
5879
|
sharedInboxes: currentState.sharedInboxes || currentState.shared_inboxes,
|
|
@@ -5894,11 +5888,11 @@ function resolveRunnerContinuationRequestForBotReply({
|
|
|
5894
5888
|
};
|
|
5895
5889
|
}
|
|
5896
5890
|
|
|
5897
|
-
function markRunnerRequestLifecycle({
|
|
5898
|
-
normalizedRoute,
|
|
5899
|
-
requestKey,
|
|
5900
|
-
selectedRecord,
|
|
5901
|
-
routeKey,
|
|
5891
|
+
function markRunnerRequestLifecycle({
|
|
5892
|
+
normalizedRoute,
|
|
5893
|
+
requestKey,
|
|
5894
|
+
selectedRecord,
|
|
5895
|
+
routeKey,
|
|
5902
5896
|
outcome,
|
|
5903
5897
|
conversationIDRaw = "",
|
|
5904
5898
|
allowedResponders = [],
|
|
@@ -5928,77 +5922,77 @@ function markRunnerRequestLifecycle({
|
|
|
5928
5922
|
assignmentValidationStatus = "",
|
|
5929
5923
|
assignmentValidationReason = "",
|
|
5930
5924
|
assignmentValidationModes = [],
|
|
5931
|
-
deliveryStatus = "",
|
|
5932
|
-
archiveStatus = "",
|
|
5933
|
-
transportError = "",
|
|
5934
|
-
archiveError = "",
|
|
5935
|
-
lastReplyMessageID = 0,
|
|
5936
|
-
lastReplyMessageThreadID = 0,
|
|
5937
|
-
replyToMessageID = 0,
|
|
5938
|
-
replyFallbackUsed = false,
|
|
5939
|
-
authoritativeSourceMessageEnvelope = {},
|
|
5940
|
-
}) {
|
|
5925
|
+
deliveryStatus = "",
|
|
5926
|
+
archiveStatus = "",
|
|
5927
|
+
transportError = "",
|
|
5928
|
+
archiveError = "",
|
|
5929
|
+
lastReplyMessageID = 0,
|
|
5930
|
+
lastReplyMessageThreadID = 0,
|
|
5931
|
+
replyToMessageID = 0,
|
|
5932
|
+
replyFallbackUsed = false,
|
|
5933
|
+
authoritativeSourceMessageEnvelope = {},
|
|
5934
|
+
}) {
|
|
5941
5935
|
const key = String(requestKey || "").trim();
|
|
5942
5936
|
if (!key) return null;
|
|
5943
|
-
const currentState = loadBotRunnerState();
|
|
5944
|
-
const existing = safeObject(normalizeBotRunnerRequests(currentState.requests)[key]);
|
|
5945
|
-
if (!Object.keys(existing).length) return null;
|
|
5946
|
-
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
5947
|
-
const parsedKind = String(parsed.kind || "").trim().toLowerCase();
|
|
5948
|
-
const conversationID = String(conversationIDRaw || existing.conversation_id || parsed.conversationID || "").trim();
|
|
5949
|
-
const normalizedCurrentBotSelector = normalizeTelegramMentionUsername(
|
|
5950
|
-
currentBotSelector
|
|
5951
|
-
|| safeObject(currentState.routes)[String(routeKey || "").trim()]?.last_speaker_bot_username
|
|
5952
|
-
|| "",
|
|
5953
|
-
);
|
|
5954
|
-
const sourceMessageEnvelope = selectAuthoritativeRunnerSourceMessageEnvelope(
|
|
5955
|
-
selectAuthoritativeRunnerSourceMessageEnvelope(
|
|
5956
|
-
authoritativeSourceMessageEnvelope,
|
|
5957
|
-
safeObject(existing.source_message_envelope),
|
|
5958
|
-
),
|
|
5959
|
-
buildRunnerSourceMessageEnvelope({
|
|
5960
|
-
routeState: safeObject(safeObject(currentState.routes)[String(routeKey || "").trim()]),
|
|
5961
|
-
routeKey,
|
|
5962
|
-
normalizedRoute,
|
|
5963
|
-
parsedArchive: parsed,
|
|
5964
|
-
}),
|
|
5965
|
-
);
|
|
5966
|
-
const effectiveReplyToMessageID = intFromRawAllowZero(
|
|
5967
|
-
replyToMessageID,
|
|
5968
|
-
intFromRawAllowZero(existing.last_reply_to_message_id, 0),
|
|
5969
|
-
);
|
|
5970
|
-
const lastReplyMessageEnvelope = buildTelegramBotReplyEnvelope({
|
|
5971
|
-
sourceEnvelope: sourceMessageEnvelope,
|
|
5972
|
-
chatID: existing.chat_id,
|
|
5973
|
-
messageID: lastReplyMessageID,
|
|
5974
|
-
messageThreadID: lastReplyMessageThreadID,
|
|
5975
|
-
replyToMessageID: effectiveReplyToMessageID,
|
|
5976
|
-
senderUsername: normalizedCurrentBotSelector,
|
|
5977
|
-
body: aiReplyPreview,
|
|
5978
|
-
});
|
|
5979
|
-
const normalizedDeliveryStatus = String(deliveryStatus || "").trim().toLowerCase();
|
|
5980
|
-
const persistSuccessfulReplyEnvelope = ["delivered", "dry_run"].includes(normalizedDeliveryStatus)
|
|
5981
|
-
&& intFromRawAllowZero(lastReplyMessageEnvelope.message_id, 0) > 0;
|
|
5982
|
-
const attemptedDeliveryEnvelope = buildTelegramBotReplyEnvelope({
|
|
5983
|
-
sourceEnvelope: sourceMessageEnvelope,
|
|
5984
|
-
chatID: existing.chat_id,
|
|
5985
|
-
messageThreadID: lastReplyMessageThreadID,
|
|
5986
|
-
replyToMessageID: effectiveReplyToMessageID,
|
|
5987
|
-
senderUsername: normalizedCurrentBotSelector,
|
|
5988
|
-
body: aiReplyPreview,
|
|
5989
|
-
});
|
|
5990
|
-
const shouldRefreshAttemptedDeliveryEnvelope = (
|
|
5991
|
-
aiReplyGenerated === true
|
|
5992
|
-
|| String(aiReplyPreview || "").trim().length > 0
|
|
5993
|
-
|| String(deliveryStatus || "").trim().length > 0
|
|
5994
|
-
|| String(transportError || "").trim().length > 0
|
|
5995
|
-
|| intFromRawAllowZero(replyToMessageID, 0) > 0
|
|
5996
|
-
|| intFromRawAllowZero(lastReplyMessageThreadID, 0) > 0
|
|
5997
|
-
);
|
|
5998
|
-
const rootEffectiveExecutionContractTargets = uniqueOrderedStrings(
|
|
5999
|
-
[
|
|
6000
|
-
...ensureArray(executionContractTargets),
|
|
6001
|
-
...ensureArray(normalizedExecutionContractTargets),
|
|
5937
|
+
const currentState = loadBotRunnerState();
|
|
5938
|
+
const existing = safeObject(normalizeBotRunnerRequests(currentState.requests)[key]);
|
|
5939
|
+
if (!Object.keys(existing).length) return null;
|
|
5940
|
+
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
5941
|
+
const parsedKind = String(parsed.kind || "").trim().toLowerCase();
|
|
5942
|
+
const conversationID = String(conversationIDRaw || existing.conversation_id || parsed.conversationID || "").trim();
|
|
5943
|
+
const normalizedCurrentBotSelector = normalizeTelegramMentionUsername(
|
|
5944
|
+
currentBotSelector
|
|
5945
|
+
|| safeObject(currentState.routes)[String(routeKey || "").trim()]?.last_speaker_bot_username
|
|
5946
|
+
|| "",
|
|
5947
|
+
);
|
|
5948
|
+
const sourceMessageEnvelope = selectAuthoritativeRunnerSourceMessageEnvelope(
|
|
5949
|
+
selectAuthoritativeRunnerSourceMessageEnvelope(
|
|
5950
|
+
authoritativeSourceMessageEnvelope,
|
|
5951
|
+
safeObject(existing.source_message_envelope),
|
|
5952
|
+
),
|
|
5953
|
+
buildRunnerSourceMessageEnvelope({
|
|
5954
|
+
routeState: safeObject(safeObject(currentState.routes)[String(routeKey || "").trim()]),
|
|
5955
|
+
routeKey,
|
|
5956
|
+
normalizedRoute,
|
|
5957
|
+
parsedArchive: parsed,
|
|
5958
|
+
}),
|
|
5959
|
+
);
|
|
5960
|
+
const effectiveReplyToMessageID = intFromRawAllowZero(
|
|
5961
|
+
replyToMessageID,
|
|
5962
|
+
intFromRawAllowZero(existing.last_reply_to_message_id, 0),
|
|
5963
|
+
);
|
|
5964
|
+
const lastReplyMessageEnvelope = buildTelegramBotReplyEnvelope({
|
|
5965
|
+
sourceEnvelope: sourceMessageEnvelope,
|
|
5966
|
+
chatID: existing.chat_id,
|
|
5967
|
+
messageID: lastReplyMessageID,
|
|
5968
|
+
messageThreadID: lastReplyMessageThreadID,
|
|
5969
|
+
replyToMessageID: effectiveReplyToMessageID,
|
|
5970
|
+
senderUsername: normalizedCurrentBotSelector,
|
|
5971
|
+
body: aiReplyPreview,
|
|
5972
|
+
});
|
|
5973
|
+
const normalizedDeliveryStatus = String(deliveryStatus || "").trim().toLowerCase();
|
|
5974
|
+
const persistSuccessfulReplyEnvelope = ["delivered", "dry_run"].includes(normalizedDeliveryStatus)
|
|
5975
|
+
&& intFromRawAllowZero(lastReplyMessageEnvelope.message_id, 0) > 0;
|
|
5976
|
+
const attemptedDeliveryEnvelope = buildTelegramBotReplyEnvelope({
|
|
5977
|
+
sourceEnvelope: sourceMessageEnvelope,
|
|
5978
|
+
chatID: existing.chat_id,
|
|
5979
|
+
messageThreadID: lastReplyMessageThreadID,
|
|
5980
|
+
replyToMessageID: effectiveReplyToMessageID,
|
|
5981
|
+
senderUsername: normalizedCurrentBotSelector,
|
|
5982
|
+
body: aiReplyPreview,
|
|
5983
|
+
});
|
|
5984
|
+
const shouldRefreshAttemptedDeliveryEnvelope = (
|
|
5985
|
+
aiReplyGenerated === true
|
|
5986
|
+
|| String(aiReplyPreview || "").trim().length > 0
|
|
5987
|
+
|| String(deliveryStatus || "").trim().length > 0
|
|
5988
|
+
|| String(transportError || "").trim().length > 0
|
|
5989
|
+
|| intFromRawAllowZero(replyToMessageID, 0) > 0
|
|
5990
|
+
|| intFromRawAllowZero(lastReplyMessageThreadID, 0) > 0
|
|
5991
|
+
);
|
|
5992
|
+
const rootEffectiveExecutionContractTargets = uniqueOrderedStrings(
|
|
5993
|
+
[
|
|
5994
|
+
...ensureArray(executionContractTargets),
|
|
5995
|
+
...ensureArray(normalizedExecutionContractTargets),
|
|
6002
5996
|
...ensureArray(responseContractValidationTargets),
|
|
6003
5997
|
],
|
|
6004
5998
|
normalizeTelegramMentionUsername,
|
|
@@ -6321,11 +6315,11 @@ function markRunnerRequestLifecycle({
|
|
|
6321
6315
|
? transportError || existing.followup_transport_error || ""
|
|
6322
6316
|
: existing.followup_transport_error || "",
|
|
6323
6317
|
).trim(),
|
|
6324
|
-
followup_archive_error: String(
|
|
6325
|
-
isFollowupComment
|
|
6326
|
-
? archiveError || existing.followup_archive_error || ""
|
|
6327
|
-
: existing.followup_archive_error || "",
|
|
6328
|
-
).trim(),
|
|
6318
|
+
followup_archive_error: String(
|
|
6319
|
+
isFollowupComment
|
|
6320
|
+
? archiveError || existing.followup_archive_error || ""
|
|
6321
|
+
: existing.followup_archive_error || "",
|
|
6322
|
+
).trim(),
|
|
6329
6323
|
normalized_intent: nextNormalizedIntent,
|
|
6330
6324
|
status: nextStatus,
|
|
6331
6325
|
started_at: firstNonEmptyString([existing.started_at, nowISO]),
|
|
@@ -6333,45 +6327,45 @@ function markRunnerRequestLifecycle({
|
|
|
6333
6327
|
closed_at: (nextStatus === "closed" || nextStatus === "expired" || nextStatus === "loop_closed")
|
|
6334
6328
|
? nowISO
|
|
6335
6329
|
: String(existing.closed_at || "").trim(),
|
|
6336
|
-
closed_reason: (nextStatus === "closed" || nextStatus === "expired" || nextStatus === "loop_closed")
|
|
6337
|
-
? String(closedReason || existing.closed_reason || normalizedOutcome).trim()
|
|
6338
|
-
: String(existing.closed_reason || "").trim(),
|
|
6339
|
-
source_message_body: parsedKind === "bot_reply"
|
|
6340
|
-
? String(existing.source_message_body || "").trim()
|
|
6341
|
-
: String(parsed.body || existing.source_message_body || "").trim(),
|
|
6342
|
-
source_message_origin: parsedKind === "bot_reply"
|
|
6343
|
-
? String(existing.source_message_origin || "").trim().toLowerCase()
|
|
6344
|
-
: String(sourceMessageEnvelope.source_origin || existing.source_message_origin || "").trim().toLowerCase(),
|
|
6345
|
-
source_message_route_key: parsedKind === "bot_reply"
|
|
6346
|
-
? String(existing.source_message_route_key || "").trim()
|
|
6347
|
-
: String(sourceMessageEnvelope.source_route_key || existing.source_message_route_key || "").trim(),
|
|
6348
|
-
source_message_bot_username: parsedKind === "bot_reply"
|
|
6349
|
-
? normalizeTelegramMentionUsername(existing.source_message_bot_username)
|
|
6350
|
-
: normalizeTelegramMentionUsername(
|
|
6351
|
-
sourceMessageEnvelope.source_bot_username || existing.source_message_bot_username,
|
|
6352
|
-
),
|
|
6353
|
-
source_message_envelope: parsedKind === "bot_reply"
|
|
6354
|
-
? safeObject(existing.source_message_envelope)
|
|
6355
|
-
: Object.keys(sourceMessageEnvelope).length
|
|
6356
|
-
? sourceMessageEnvelope
|
|
6357
|
-
: safeObject(existing.source_message_envelope),
|
|
6358
|
-
last_comment_id: String(selectedRecord?.id || existing.last_comment_id || "").trim(),
|
|
6359
|
-
last_comment_kind: String(parsed.kind || existing.last_comment_kind || "").trim().toLowerCase(),
|
|
6360
|
-
last_source_message_id: intFromRawAllowZero(parsed.messageID, 0) || existing.last_source_message_id,
|
|
6361
|
-
last_source_message_thread_id: intFromRawAllowZero(parsed.messageThreadID, 0) || existing.last_source_message_thread_id,
|
|
6362
|
-
last_reply_message_id: intFromRawAllowZero(lastReplyMessageID, 0) || existing.last_reply_message_id,
|
|
6363
|
-
last_reply_message_thread_id: intFromRawAllowZero(lastReplyMessageThreadID, 0) || existing.last_reply_message_thread_id,
|
|
6364
|
-
last_reply_to_message_id: intFromRawAllowZero(replyToMessageID, 0) || existing.last_reply_to_message_id,
|
|
6365
|
-
last_reply_message_envelope: persistSuccessfulReplyEnvelope
|
|
6366
|
-
? lastReplyMessageEnvelope
|
|
6367
|
-
: safeObject(existing.last_reply_message_envelope),
|
|
6368
|
-
attempted_delivery_envelope: shouldRefreshAttemptedDeliveryEnvelope
|
|
6369
|
-
? attemptedDeliveryEnvelope
|
|
6370
|
-
: safeObject(existing.attempted_delivery_envelope),
|
|
6371
|
-
last_reply_fallback_used: replyFallbackUsed === true
|
|
6372
|
-
? true
|
|
6373
|
-
: existing.last_reply_fallback_used === true,
|
|
6374
|
-
};
|
|
6330
|
+
closed_reason: (nextStatus === "closed" || nextStatus === "expired" || nextStatus === "loop_closed")
|
|
6331
|
+
? String(closedReason || existing.closed_reason || normalizedOutcome).trim()
|
|
6332
|
+
: String(existing.closed_reason || "").trim(),
|
|
6333
|
+
source_message_body: parsedKind === "bot_reply"
|
|
6334
|
+
? String(existing.source_message_body || "").trim()
|
|
6335
|
+
: String(parsed.body || existing.source_message_body || "").trim(),
|
|
6336
|
+
source_message_origin: parsedKind === "bot_reply"
|
|
6337
|
+
? String(existing.source_message_origin || "").trim().toLowerCase()
|
|
6338
|
+
: String(sourceMessageEnvelope.source_origin || existing.source_message_origin || "").trim().toLowerCase(),
|
|
6339
|
+
source_message_route_key: parsedKind === "bot_reply"
|
|
6340
|
+
? String(existing.source_message_route_key || "").trim()
|
|
6341
|
+
: String(sourceMessageEnvelope.source_route_key || existing.source_message_route_key || "").trim(),
|
|
6342
|
+
source_message_bot_username: parsedKind === "bot_reply"
|
|
6343
|
+
? normalizeTelegramMentionUsername(existing.source_message_bot_username)
|
|
6344
|
+
: normalizeTelegramMentionUsername(
|
|
6345
|
+
sourceMessageEnvelope.source_bot_username || existing.source_message_bot_username,
|
|
6346
|
+
),
|
|
6347
|
+
source_message_envelope: parsedKind === "bot_reply"
|
|
6348
|
+
? safeObject(existing.source_message_envelope)
|
|
6349
|
+
: Object.keys(sourceMessageEnvelope).length
|
|
6350
|
+
? sourceMessageEnvelope
|
|
6351
|
+
: safeObject(existing.source_message_envelope),
|
|
6352
|
+
last_comment_id: String(selectedRecord?.id || existing.last_comment_id || "").trim(),
|
|
6353
|
+
last_comment_kind: String(parsed.kind || existing.last_comment_kind || "").trim().toLowerCase(),
|
|
6354
|
+
last_source_message_id: intFromRawAllowZero(parsed.messageID, 0) || existing.last_source_message_id,
|
|
6355
|
+
last_source_message_thread_id: intFromRawAllowZero(parsed.messageThreadID, 0) || existing.last_source_message_thread_id,
|
|
6356
|
+
last_reply_message_id: intFromRawAllowZero(lastReplyMessageID, 0) || existing.last_reply_message_id,
|
|
6357
|
+
last_reply_message_thread_id: intFromRawAllowZero(lastReplyMessageThreadID, 0) || existing.last_reply_message_thread_id,
|
|
6358
|
+
last_reply_to_message_id: intFromRawAllowZero(replyToMessageID, 0) || existing.last_reply_to_message_id,
|
|
6359
|
+
last_reply_message_envelope: persistSuccessfulReplyEnvelope
|
|
6360
|
+
? lastReplyMessageEnvelope
|
|
6361
|
+
: safeObject(existing.last_reply_message_envelope),
|
|
6362
|
+
attempted_delivery_envelope: shouldRefreshAttemptedDeliveryEnvelope
|
|
6363
|
+
? attemptedDeliveryEnvelope
|
|
6364
|
+
: safeObject(existing.attempted_delivery_envelope),
|
|
6365
|
+
last_reply_fallback_used: replyFallbackUsed === true
|
|
6366
|
+
? true
|
|
6367
|
+
: existing.last_reply_fallback_used === true,
|
|
6368
|
+
};
|
|
6375
6369
|
const { requests: nextRequests, request } = upsertRunnerRequest(currentState, key, patch);
|
|
6376
6370
|
const commentID = String(selectedRecord?.id || "").trim();
|
|
6377
6371
|
let nextConsumedComments = currentState.consumedComments || currentState.consumed_comments;
|
|
@@ -6547,55 +6541,55 @@ function runnerLedgerEntryMatchesProject(entryRaw, normalizedRoute, requestIndex
|
|
|
6547
6541
|
);
|
|
6548
6542
|
}
|
|
6549
6543
|
|
|
6550
|
-
function mergeRunnerRequestForServerHydration(localEntryRaw, serverEntryRaw) {
|
|
6551
|
-
const localEntry = safeObject(localEntryRaw);
|
|
6552
|
-
const serverEntry = safeObject(serverEntryRaw);
|
|
6553
|
-
const merged = {
|
|
6554
|
-
...localEntry,
|
|
6555
|
-
...serverEntry,
|
|
6556
|
-
};
|
|
6557
|
-
const preserveLocalNumberWhenServerMissing = (fieldName) => {
|
|
6558
|
-
const serverValue = intFromRawAllowZero(serverEntry[fieldName], 0);
|
|
6559
|
-
const localValue = intFromRawAllowZero(localEntry[fieldName], 0);
|
|
6560
|
-
if (!(serverValue > 0) && localValue > 0) {
|
|
6561
|
-
merged[fieldName] = localValue;
|
|
6562
|
-
}
|
|
6563
|
-
};
|
|
6564
|
-
const preserveLocalStringWhenServerBlank = (fieldName) => {
|
|
6565
|
-
const serverValue = String(serverEntry[fieldName] || "").trim();
|
|
6566
|
-
const localValue = String(localEntry[fieldName] || "").trim();
|
|
6567
|
-
if (!serverValue && localValue) {
|
|
6568
|
-
merged[fieldName] = localValue;
|
|
6544
|
+
function mergeRunnerRequestForServerHydration(localEntryRaw, serverEntryRaw) {
|
|
6545
|
+
const localEntry = safeObject(localEntryRaw);
|
|
6546
|
+
const serverEntry = safeObject(serverEntryRaw);
|
|
6547
|
+
const merged = {
|
|
6548
|
+
...localEntry,
|
|
6549
|
+
...serverEntry,
|
|
6550
|
+
};
|
|
6551
|
+
const preserveLocalNumberWhenServerMissing = (fieldName) => {
|
|
6552
|
+
const serverValue = intFromRawAllowZero(serverEntry[fieldName], 0);
|
|
6553
|
+
const localValue = intFromRawAllowZero(localEntry[fieldName], 0);
|
|
6554
|
+
if (!(serverValue > 0) && localValue > 0) {
|
|
6555
|
+
merged[fieldName] = localValue;
|
|
6556
|
+
}
|
|
6557
|
+
};
|
|
6558
|
+
const preserveLocalStringWhenServerBlank = (fieldName) => {
|
|
6559
|
+
const serverValue = String(serverEntry[fieldName] || "").trim();
|
|
6560
|
+
const localValue = String(localEntry[fieldName] || "").trim();
|
|
6561
|
+
if (!serverValue && localValue) {
|
|
6562
|
+
merged[fieldName] = localValue;
|
|
6569
6563
|
}
|
|
6570
6564
|
};
|
|
6571
6565
|
const preserveLocalArrayWhenServerEmpty = (fieldName) => {
|
|
6572
6566
|
const serverValues = ensureArray(serverEntry[fieldName]).filter(Boolean);
|
|
6573
6567
|
const localValues = ensureArray(localEntry[fieldName]).filter(Boolean);
|
|
6574
|
-
if (serverValues.length === 0 && localValues.length > 0) {
|
|
6575
|
-
merged[fieldName] = localValues;
|
|
6576
|
-
}
|
|
6577
|
-
};
|
|
6578
|
-
const preserveLocalObjectWhenServerBlank = (fieldName) => {
|
|
6579
|
-
const serverValue = safeObject(serverEntry[fieldName]);
|
|
6580
|
-
const localValue = safeObject(localEntry[fieldName]);
|
|
6581
|
-
if (!Object.keys(serverValue).length && Object.keys(localValue).length) {
|
|
6582
|
-
merged[fieldName] = localValue;
|
|
6583
|
-
}
|
|
6584
|
-
};
|
|
6585
|
-
preserveLocalNumberWhenServerMissing("source_message_id");
|
|
6586
|
-
preserveLocalNumberWhenServerMissing("source_message_thread_id");
|
|
6587
|
-
preserveLocalStringWhenServerBlank("source_message_body");
|
|
6588
|
-
preserveLocalStringWhenServerBlank("source_message_origin");
|
|
6589
|
-
preserveLocalStringWhenServerBlank("source_message_route_key");
|
|
6590
|
-
preserveLocalStringWhenServerBlank("source_message_bot_username");
|
|
6591
|
-
preserveLocalObjectWhenServerBlank("source_message_envelope");
|
|
6592
|
-
preserveLocalObjectWhenServerBlank("last_reply_message_envelope");
|
|
6593
|
-
preserveLocalObjectWhenServerBlank("attempted_delivery_envelope");
|
|
6594
|
-
preserveLocalStringWhenServerBlank("conversation_id");
|
|
6595
|
-
preserveLocalStringWhenServerBlank("conversation_intent_mode");
|
|
6596
|
-
preserveLocalStringWhenServerBlank("conversation_lead_bot");
|
|
6597
|
-
preserveLocalStringWhenServerBlank("conversation_summary_bot");
|
|
6598
|
-
preserveLocalStringWhenServerBlank("conversation_reply_expectation");
|
|
6568
|
+
if (serverValues.length === 0 && localValues.length > 0) {
|
|
6569
|
+
merged[fieldName] = localValues;
|
|
6570
|
+
}
|
|
6571
|
+
};
|
|
6572
|
+
const preserveLocalObjectWhenServerBlank = (fieldName) => {
|
|
6573
|
+
const serverValue = safeObject(serverEntry[fieldName]);
|
|
6574
|
+
const localValue = safeObject(localEntry[fieldName]);
|
|
6575
|
+
if (!Object.keys(serverValue).length && Object.keys(localValue).length) {
|
|
6576
|
+
merged[fieldName] = localValue;
|
|
6577
|
+
}
|
|
6578
|
+
};
|
|
6579
|
+
preserveLocalNumberWhenServerMissing("source_message_id");
|
|
6580
|
+
preserveLocalNumberWhenServerMissing("source_message_thread_id");
|
|
6581
|
+
preserveLocalStringWhenServerBlank("source_message_body");
|
|
6582
|
+
preserveLocalStringWhenServerBlank("source_message_origin");
|
|
6583
|
+
preserveLocalStringWhenServerBlank("source_message_route_key");
|
|
6584
|
+
preserveLocalStringWhenServerBlank("source_message_bot_username");
|
|
6585
|
+
preserveLocalObjectWhenServerBlank("source_message_envelope");
|
|
6586
|
+
preserveLocalObjectWhenServerBlank("last_reply_message_envelope");
|
|
6587
|
+
preserveLocalObjectWhenServerBlank("attempted_delivery_envelope");
|
|
6588
|
+
preserveLocalStringWhenServerBlank("conversation_id");
|
|
6589
|
+
preserveLocalStringWhenServerBlank("conversation_intent_mode");
|
|
6590
|
+
preserveLocalStringWhenServerBlank("conversation_lead_bot");
|
|
6591
|
+
preserveLocalStringWhenServerBlank("conversation_summary_bot");
|
|
6592
|
+
preserveLocalStringWhenServerBlank("conversation_reply_expectation");
|
|
6599
6593
|
preserveLocalStringWhenServerBlank("execution_contract_type");
|
|
6600
6594
|
preserveLocalStringWhenServerBlank("normalized_execution_contract_type");
|
|
6601
6595
|
preserveLocalStringWhenServerBlank("ai_reply_generated_at");
|
|
@@ -6631,16 +6625,16 @@ function mergeRunnerRequestForServerHydration(localEntryRaw, serverEntryRaw) {
|
|
|
6631
6625
|
preserveLocalArrayWhenServerEmpty("root_execution_contract_targets");
|
|
6632
6626
|
preserveLocalArrayWhenServerEmpty("root_next_expected_responders");
|
|
6633
6627
|
preserveLocalArrayWhenServerEmpty("root_response_contract_validation_targets");
|
|
6634
|
-
preserveLocalArrayWhenServerEmpty("followup_execution_contract_targets");
|
|
6635
|
-
preserveLocalArrayWhenServerEmpty("followup_next_expected_responders");
|
|
6636
|
-
preserveLocalArrayWhenServerEmpty("followup_normalized_execution_contract_targets");
|
|
6637
|
-
preserveLocalArrayWhenServerEmpty("followup_normalized_execution_next_responders");
|
|
6638
|
-
preserveLocalArrayWhenServerEmpty("followup_response_contract_validation_targets");
|
|
6639
|
-
preserveLocalArrayWhenServerEmpty("followup_assignment_validation_modes");
|
|
6640
|
-
preserveLocalObjectWhenServerBlank("reply_chain_context");
|
|
6641
|
-
if (serverEntry.conversation_allow_bot_to_bot !== true && localEntry.conversation_allow_bot_to_bot === true) {
|
|
6642
|
-
merged.conversation_allow_bot_to_bot = true;
|
|
6643
|
-
}
|
|
6628
|
+
preserveLocalArrayWhenServerEmpty("followup_execution_contract_targets");
|
|
6629
|
+
preserveLocalArrayWhenServerEmpty("followup_next_expected_responders");
|
|
6630
|
+
preserveLocalArrayWhenServerEmpty("followup_normalized_execution_contract_targets");
|
|
6631
|
+
preserveLocalArrayWhenServerEmpty("followup_normalized_execution_next_responders");
|
|
6632
|
+
preserveLocalArrayWhenServerEmpty("followup_response_contract_validation_targets");
|
|
6633
|
+
preserveLocalArrayWhenServerEmpty("followup_assignment_validation_modes");
|
|
6634
|
+
preserveLocalObjectWhenServerBlank("reply_chain_context");
|
|
6635
|
+
if (serverEntry.conversation_allow_bot_to_bot !== true && localEntry.conversation_allow_bot_to_bot === true) {
|
|
6636
|
+
merged.conversation_allow_bot_to_bot = true;
|
|
6637
|
+
}
|
|
6644
6638
|
if (serverEntry.execution_contract_actionable !== true && localEntry.execution_contract_actionable === true) {
|
|
6645
6639
|
merged.execution_contract_actionable = true;
|
|
6646
6640
|
}
|
|
@@ -7895,16 +7889,16 @@ function parseArchivedChatComment(rawBody) {
|
|
|
7895
7889
|
.filter(Boolean),
|
|
7896
7890
|
}
|
|
7897
7891
|
: null;
|
|
7898
|
-
return {
|
|
7899
|
-
kind,
|
|
7900
|
-
header,
|
|
7901
|
-
metadata,
|
|
7902
|
-
body,
|
|
7903
|
-
chatID: String(metadata.chat_id || "").trim(),
|
|
7904
|
-
chatType: String(metadata.chat_type || "").trim().toLowerCase(),
|
|
7905
|
-
messageID: intFromRawAllowZero(metadata.message_id, 0),
|
|
7906
|
-
messageThreadID: intFromRawAllowZero(metadata.message_thread_id, 0),
|
|
7907
|
-
senderID: String(metadata.sender_id || "").trim(),
|
|
7892
|
+
return {
|
|
7893
|
+
kind,
|
|
7894
|
+
header,
|
|
7895
|
+
metadata,
|
|
7896
|
+
body,
|
|
7897
|
+
chatID: String(metadata.chat_id || "").trim(),
|
|
7898
|
+
chatType: String(metadata.chat_type || "").trim().toLowerCase(),
|
|
7899
|
+
messageID: intFromRawAllowZero(metadata.message_id, 0),
|
|
7900
|
+
messageThreadID: intFromRawAllowZero(metadata.message_thread_id, 0),
|
|
7901
|
+
senderID: String(metadata.sender_id || "").trim(),
|
|
7908
7902
|
sender: String(metadata.sender || metadata.bot_username || metadata.bot_name || "").trim(),
|
|
7909
7903
|
senderIsBot: kind === "bot_reply" ? true : boolFromRaw(metadata.sender_is_bot, false),
|
|
7910
7904
|
username: String(metadata.telegram_username || metadata.bot_username || metadata.bot_name || "").trim(),
|
|
@@ -7912,11 +7906,11 @@ function parseArchivedChatComment(rawBody) {
|
|
|
7912
7906
|
.split(",")
|
|
7913
7907
|
.map((value) => normalizeTelegramMentionUsername(value))
|
|
7914
7908
|
.filter(Boolean),
|
|
7915
|
-
occurredAt: String(metadata.occurred_at || "").trim(),
|
|
7916
|
-
sourceOrigin: String(metadata.source_origin || "").trim().toLowerCase(),
|
|
7917
|
-
sourceRouteKey: String(metadata.source_route_key || "").trim(),
|
|
7918
|
-
sourceBotUsername: normalizeTelegramMentionUsername(metadata.source_bot_username || ""),
|
|
7919
|
-
replyToMessageID: intFromRawAllowZero(metadata.reply_to_message_id, 0),
|
|
7909
|
+
occurredAt: String(metadata.occurred_at || "").trim(),
|
|
7910
|
+
sourceOrigin: String(metadata.source_origin || "").trim().toLowerCase(),
|
|
7911
|
+
sourceRouteKey: String(metadata.source_route_key || "").trim(),
|
|
7912
|
+
sourceBotUsername: normalizeTelegramMentionUsername(metadata.source_bot_username || ""),
|
|
7913
|
+
replyToMessageID: intFromRawAllowZero(metadata.reply_to_message_id, 0),
|
|
7920
7914
|
replyToSender: String(metadata.reply_to_sender || "").trim(),
|
|
7921
7915
|
replyToUsername: String(metadata.reply_to_telegram_username || "").trim(),
|
|
7922
7916
|
replyToSenderIsBot: boolFromRaw(metadata.reply_to_sender_is_bot, false),
|
|
@@ -8163,23 +8157,23 @@ function extractTelegramEntityText(text, entity) {
|
|
|
8163
8157
|
return body.slice(offset, offset + length);
|
|
8164
8158
|
}
|
|
8165
8159
|
|
|
8166
|
-
function extractTelegramMentionUsernames(text, entities) {
|
|
8167
|
-
const set = new Set();
|
|
8168
|
-
for (const entityRaw of ensureArray(entities)) {
|
|
8169
|
-
const entity = safeObject(entityRaw);
|
|
8160
|
+
function extractTelegramMentionUsernames(text, entities) {
|
|
8161
|
+
const set = new Set();
|
|
8162
|
+
for (const entityRaw of ensureArray(entities)) {
|
|
8163
|
+
const entity = safeObject(entityRaw);
|
|
8170
8164
|
const type = String(entity.type || "").trim().toLowerCase();
|
|
8171
8165
|
if (type === "mention") {
|
|
8172
8166
|
const username = normalizeTelegramMentionUsername(extractTelegramEntityText(text, entity));
|
|
8173
8167
|
if (username) set.add(username);
|
|
8174
8168
|
continue;
|
|
8175
8169
|
}
|
|
8176
|
-
if (type === "text_mention") {
|
|
8177
|
-
const username = normalizeTelegramMentionUsername(entity.user?.username);
|
|
8178
|
-
if (username) set.add(username);
|
|
8179
|
-
}
|
|
8180
|
-
}
|
|
8181
|
-
return Array.from(set);
|
|
8182
|
-
}
|
|
8170
|
+
if (type === "text_mention") {
|
|
8171
|
+
const username = normalizeTelegramMentionUsername(entity.user?.username);
|
|
8172
|
+
if (username) set.add(username);
|
|
8173
|
+
}
|
|
8174
|
+
}
|
|
8175
|
+
return Array.from(set);
|
|
8176
|
+
}
|
|
8183
8177
|
|
|
8184
8178
|
function normalizeLocalTelegramUpdate(rawUpdate) {
|
|
8185
8179
|
const update = safeObject(rawUpdate);
|
|
@@ -8225,47 +8219,47 @@ function buildArchivedInboundMessageKey(chatID, messageID) {
|
|
|
8225
8219
|
return `${String(chatID || "").trim()}:${intFromRawAllowZero(messageID, 0)}`;
|
|
8226
8220
|
}
|
|
8227
8221
|
|
|
8228
|
-
function formatTelegramInboundArchiveComment(normalized) {
|
|
8229
|
-
const headerLines = [
|
|
8222
|
+
function formatTelegramInboundArchiveComment(normalized) {
|
|
8223
|
+
const headerLines = [
|
|
8230
8224
|
`[Telegram ${normalized.eventName === "telegram.message.updated" ? "edited" : "message"}]`,
|
|
8231
8225
|
`chat_id: ${normalized.chatID || "<missing>"}`,
|
|
8232
8226
|
`chat_type: ${normalized.chatType || "unknown"}`,
|
|
8233
8227
|
`message_id: ${normalized.messageID || "<missing>"}`,
|
|
8234
8228
|
`occurred_at: ${normalized.occurredAt || new Date().toISOString()}`,
|
|
8235
8229
|
`sender_id: ${normalized.fromID || "<missing>"}`,
|
|
8236
|
-
`sender: ${normalized.fromName || normalized.fromUsername || normalized.fromID || "unknown"}`,
|
|
8237
|
-
`sender_is_bot: ${normalized.fromIsBot ? "true" : "false"}`,
|
|
8238
|
-
];
|
|
8239
|
-
if (String(normalized.sourceOrigin || "").trim()) {
|
|
8240
|
-
headerLines.push(`source_origin: ${String(normalized.sourceOrigin || "").trim()}`);
|
|
8241
|
-
}
|
|
8242
|
-
if (String(normalized.sourceRouteKey || "").trim()) {
|
|
8243
|
-
headerLines.push(`source_route_key: ${String(normalized.sourceRouteKey || "").trim()}`);
|
|
8244
|
-
}
|
|
8245
|
-
if (String(normalized.sourceBotUsername || "").trim()) {
|
|
8246
|
-
headerLines.push(`source_bot_username: @${String(normalized.sourceBotUsername || "").trim().replace(/^@+/, "")}`);
|
|
8247
|
-
}
|
|
8248
|
-
if (normalized.fromUsername) {
|
|
8230
|
+
`sender: ${normalized.fromName || normalized.fromUsername || normalized.fromID || "unknown"}`,
|
|
8231
|
+
`sender_is_bot: ${normalized.fromIsBot ? "true" : "false"}`,
|
|
8232
|
+
];
|
|
8233
|
+
if (String(normalized.sourceOrigin || "").trim()) {
|
|
8234
|
+
headerLines.push(`source_origin: ${String(normalized.sourceOrigin || "").trim()}`);
|
|
8235
|
+
}
|
|
8236
|
+
if (String(normalized.sourceRouteKey || "").trim()) {
|
|
8237
|
+
headerLines.push(`source_route_key: ${String(normalized.sourceRouteKey || "").trim()}`);
|
|
8238
|
+
}
|
|
8239
|
+
if (String(normalized.sourceBotUsername || "").trim()) {
|
|
8240
|
+
headerLines.push(`source_bot_username: @${String(normalized.sourceBotUsername || "").trim().replace(/^@+/, "")}`);
|
|
8241
|
+
}
|
|
8242
|
+
if (normalized.fromUsername) {
|
|
8249
8243
|
headerLines.push(`telegram_username: @${normalized.fromUsername.replace(/^@+/, "")}`);
|
|
8250
8244
|
}
|
|
8251
8245
|
if (normalized.mentionUsernames.length > 0) {
|
|
8252
8246
|
headerLines.push(`mention_usernames: ${normalized.mentionUsernames.map((item) => `@${item}`).join(", ")}`);
|
|
8253
8247
|
}
|
|
8254
|
-
if (normalized.replyToMessageID > 0) {
|
|
8255
|
-
headerLines.push(`reply_to_message_id: ${normalized.replyToMessageID}`);
|
|
8256
|
-
headerLines.push(`reply_to_sender_is_bot: ${normalized.replyToFromIsBot ? "true" : "false"}`);
|
|
8248
|
+
if (normalized.replyToMessageID > 0) {
|
|
8249
|
+
headerLines.push(`reply_to_message_id: ${normalized.replyToMessageID}`);
|
|
8250
|
+
headerLines.push(`reply_to_sender_is_bot: ${normalized.replyToFromIsBot ? "true" : "false"}`);
|
|
8257
8251
|
if (normalized.replyToFromName) {
|
|
8258
8252
|
headerLines.push(`reply_to_sender: ${normalized.replyToFromName}`);
|
|
8259
8253
|
}
|
|
8260
8254
|
if (normalized.replyToFromUsername) {
|
|
8261
|
-
headerLines.push(`reply_to_telegram_username: @${normalized.replyToFromUsername.replace(/^@+/, "")}`);
|
|
8262
|
-
}
|
|
8263
|
-
}
|
|
8264
|
-
if (intFromRawAllowZero(normalized.messageThreadID, 0) > 0) {
|
|
8265
|
-
headerLines.push(`message_thread_id: ${intFromRawAllowZero(normalized.messageThreadID, 0)}`);
|
|
8266
|
-
}
|
|
8267
|
-
return `${headerLines.join("\n")}\n\n${String(normalized.text || "").trim()}`;
|
|
8268
|
-
}
|
|
8255
|
+
headerLines.push(`reply_to_telegram_username: @${normalized.replyToFromUsername.replace(/^@+/, "")}`);
|
|
8256
|
+
}
|
|
8257
|
+
}
|
|
8258
|
+
if (intFromRawAllowZero(normalized.messageThreadID, 0) > 0) {
|
|
8259
|
+
headerLines.push(`message_thread_id: ${intFromRawAllowZero(normalized.messageThreadID, 0)}`);
|
|
8260
|
+
}
|
|
8261
|
+
return `${headerLines.join("\n")}\n\n${String(normalized.text || "").trim()}`;
|
|
8262
|
+
}
|
|
8269
8263
|
|
|
8270
8264
|
async function postJSONWithAuthHeaders(urlText, timeoutSeconds, token, payload, extraHeaders = {}) {
|
|
8271
8265
|
return new Promise((resolve, reject) => {
|
|
@@ -9043,25 +9037,25 @@ function summarizeRunnerRequestForStatusLookup(entryRaw) {
|
|
|
9043
9037
|
updated_at: String(entry.updated_at || "").trim(),
|
|
9044
9038
|
source_message_id: intFromRawAllowZero(entry.source_message_id, 0) || undefined,
|
|
9045
9039
|
last_source_message_id: intFromRawAllowZero(entry.last_source_message_id, 0) || undefined,
|
|
9046
|
-
...buildRunnerValidationAndDeliverySummary({
|
|
9047
|
-
aiReplyPreview: runnerRequestPreferredAIReplyPreview(entry),
|
|
9048
|
-
executionContractType: runnerRequestPreferredExecutionContractType(entry),
|
|
9049
|
-
executionContractTargets: runnerRequestPreferredExecutionContractTargets(entry),
|
|
9050
|
-
nextExpectedResponders: runnerRequestPreferredNextExpectedResponders(entry),
|
|
9040
|
+
...buildRunnerValidationAndDeliverySummary({
|
|
9041
|
+
aiReplyPreview: runnerRequestPreferredAIReplyPreview(entry),
|
|
9042
|
+
executionContractType: runnerRequestPreferredExecutionContractType(entry),
|
|
9043
|
+
executionContractTargets: runnerRequestPreferredExecutionContractTargets(entry),
|
|
9044
|
+
nextExpectedResponders: runnerRequestPreferredNextExpectedResponders(entry),
|
|
9051
9045
|
responseContractValidationStatus: runnerRequestPreferredResponseContractValidationStatus(entry),
|
|
9052
9046
|
responseContractValidationReason: runnerRequestPreferredResponseContractValidationReason(entry),
|
|
9053
9047
|
responseContractValidationTargets: runnerRequestPreferredResponseContractValidationTargets(entry),
|
|
9054
9048
|
assignmentValidationStatus: runnerRequestPreferredAssignmentValidationStatus(entry),
|
|
9055
9049
|
assignmentValidationReason: runnerRequestPreferredAssignmentValidationReason(entry),
|
|
9056
9050
|
assignmentValidationModes: runnerRequestPreferredAssignmentValidationModes(entry),
|
|
9057
|
-
deliveryStatus: runnerRequestPreferredDeliveryStatus(entry),
|
|
9058
|
-
archiveStatus: runnerRequestPreferredArchiveStatus(entry),
|
|
9059
|
-
transportError: runnerRequestPreferredTransportError(entry),
|
|
9060
|
-
archiveError: runnerRequestPreferredArchiveError(entry),
|
|
9061
|
-
sourceMessageEnvelope: entry.source_message_envelope,
|
|
9062
|
-
lastReplyMessageEnvelope: entry.last_reply_message_envelope,
|
|
9063
|
-
attemptedDeliveryEnvelope: entry.attempted_delivery_envelope,
|
|
9064
|
-
}),
|
|
9051
|
+
deliveryStatus: runnerRequestPreferredDeliveryStatus(entry),
|
|
9052
|
+
archiveStatus: runnerRequestPreferredArchiveStatus(entry),
|
|
9053
|
+
transportError: runnerRequestPreferredTransportError(entry),
|
|
9054
|
+
archiveError: runnerRequestPreferredArchiveError(entry),
|
|
9055
|
+
sourceMessageEnvelope: entry.source_message_envelope,
|
|
9056
|
+
lastReplyMessageEnvelope: entry.last_reply_message_envelope,
|
|
9057
|
+
attemptedDeliveryEnvelope: entry.attempted_delivery_envelope,
|
|
9058
|
+
}),
|
|
9065
9059
|
selected_bot_usernames: ensureArray(entry.selected_bot_usernames)
|
|
9066
9060
|
.map((value) => normalizeTelegramMentionUsername(value))
|
|
9067
9061
|
.filter(Boolean),
|
|
@@ -9169,16 +9163,16 @@ function resolveRunnerStatusLookupRequests({
|
|
|
9169
9163
|
};
|
|
9170
9164
|
}
|
|
9171
9165
|
|
|
9172
|
-
function buildRunnerShowLastRunPayload(lastRunSummaryRaw) {
|
|
9173
|
-
const lastRunSummary = safeObject(lastRunSummaryRaw);
|
|
9174
|
-
return {
|
|
9175
|
-
action: lastRunSummary.action || "-",
|
|
9176
|
-
reason: lastRunSummary.reason || "-",
|
|
9177
|
-
visibility_status: lastRunSummary.visibility_status || "-",
|
|
9178
|
-
visibility_reason: lastRunSummary.visibility_reason || "-",
|
|
9179
|
-
visibility_source: lastRunSummary.visibility_source || "-",
|
|
9180
|
-
candidate_bot_usernames: ensureArray(lastRunSummary.candidate_bot_usernames),
|
|
9181
|
-
intent_type: lastRunSummary.intent_type || "-",
|
|
9166
|
+
function buildRunnerShowLastRunPayload(lastRunSummaryRaw) {
|
|
9167
|
+
const lastRunSummary = safeObject(lastRunSummaryRaw);
|
|
9168
|
+
return {
|
|
9169
|
+
action: lastRunSummary.action || "-",
|
|
9170
|
+
reason: lastRunSummary.reason || "-",
|
|
9171
|
+
visibility_status: lastRunSummary.visibility_status || "-",
|
|
9172
|
+
visibility_reason: lastRunSummary.visibility_reason || "-",
|
|
9173
|
+
visibility_source: lastRunSummary.visibility_source || "-",
|
|
9174
|
+
candidate_bot_usernames: ensureArray(lastRunSummary.candidate_bot_usernames),
|
|
9175
|
+
intent_type: lastRunSummary.intent_type || "-",
|
|
9182
9176
|
ai_reply_preview: lastRunSummary.ai_reply_preview || "-",
|
|
9183
9177
|
execution_contract_type: lastRunSummary.execution_contract_type || "-",
|
|
9184
9178
|
execution_contract_targets: ensureArray(lastRunSummary.execution_contract_targets),
|
|
@@ -9191,13 +9185,13 @@ function buildRunnerShowLastRunPayload(lastRunSummaryRaw) {
|
|
|
9191
9185
|
assignment_validation_modes: ensureArray(lastRunSummary.assignment_validation_modes),
|
|
9192
9186
|
delivery_status: lastRunSummary.delivery_status || "-",
|
|
9193
9187
|
archive_status: lastRunSummary.archive_status || "-",
|
|
9194
|
-
transport_error: lastRunSummary.transport_error || "-",
|
|
9195
|
-
archive_error: lastRunSummary.archive_error || "-",
|
|
9196
|
-
source_message_envelope: safeObject(lastRunSummary.source_message_envelope),
|
|
9197
|
-
last_reply_message_envelope: safeObject(lastRunSummary.last_reply_message_envelope),
|
|
9198
|
-
attempted_delivery_envelope: safeObject(lastRunSummary.attempted_delivery_envelope),
|
|
9199
|
-
workspace_dir: lastRunSummary.workspace_dir || "-",
|
|
9200
|
-
artifact_validation: lastRunSummary.artifact_validation || "-",
|
|
9188
|
+
transport_error: lastRunSummary.transport_error || "-",
|
|
9189
|
+
archive_error: lastRunSummary.archive_error || "-",
|
|
9190
|
+
source_message_envelope: safeObject(lastRunSummary.source_message_envelope),
|
|
9191
|
+
last_reply_message_envelope: safeObject(lastRunSummary.last_reply_message_envelope),
|
|
9192
|
+
attempted_delivery_envelope: safeObject(lastRunSummary.attempted_delivery_envelope),
|
|
9193
|
+
workspace_dir: lastRunSummary.workspace_dir || "-",
|
|
9194
|
+
artifact_validation: lastRunSummary.artifact_validation || "-",
|
|
9201
9195
|
artifact_paths: ensureArray(lastRunSummary.artifact_paths),
|
|
9202
9196
|
artifact_errors: ensureArray(lastRunSummary.artifact_errors),
|
|
9203
9197
|
boundary_violations: ensureArray(lastRunSummary.boundary_violations),
|
|
@@ -9513,16 +9507,16 @@ function buildRunnerExecutionDeps() {
|
|
|
9513
9507
|
};
|
|
9514
9508
|
}
|
|
9515
9509
|
|
|
9516
|
-
function buildRunnerRuntimeDeps() {
|
|
9517
|
-
return {
|
|
9518
|
-
loadProviderEnvConfig,
|
|
9519
|
-
loadBotRunnerState,
|
|
9520
|
-
saveBotRunnerState,
|
|
9521
|
-
getTelegramBotMe,
|
|
9522
|
-
getTelegramWebhookInfo,
|
|
9523
|
-
deleteTelegramWebhook,
|
|
9524
|
-
saveRunnerRouteState,
|
|
9525
|
-
getTelegramUpdates,
|
|
9510
|
+
function buildRunnerRuntimeDeps() {
|
|
9511
|
+
return {
|
|
9512
|
+
loadProviderEnvConfig,
|
|
9513
|
+
loadBotRunnerState,
|
|
9514
|
+
saveBotRunnerState,
|
|
9515
|
+
getTelegramBotMe,
|
|
9516
|
+
getTelegramWebhookInfo,
|
|
9517
|
+
deleteTelegramWebhook,
|
|
9518
|
+
saveRunnerRouteState,
|
|
9519
|
+
getTelegramUpdates,
|
|
9526
9520
|
normalizeLocalTelegramUpdate,
|
|
9527
9521
|
listThreadComments,
|
|
9528
9522
|
listThreadCommentsTail,
|
|
@@ -10153,12 +10147,12 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10153
10147
|
role_profile: executionPlan.roleProfileName,
|
|
10154
10148
|
};
|
|
10155
10149
|
};
|
|
10156
|
-
const prepareRunnerRequestClaim = async (
|
|
10157
|
-
selectedRecord,
|
|
10158
|
-
selectedResponderSelectors = [],
|
|
10159
|
-
sharedHumanIntent = null,
|
|
10160
|
-
authoritativeSourceMessageEnvelope = {},
|
|
10161
|
-
) => {
|
|
10150
|
+
const prepareRunnerRequestClaim = async (
|
|
10151
|
+
selectedRecord,
|
|
10152
|
+
selectedResponderSelectors = [],
|
|
10153
|
+
sharedHumanIntent = null,
|
|
10154
|
+
authoritativeSourceMessageEnvelope = {},
|
|
10155
|
+
) => {
|
|
10162
10156
|
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
10163
10157
|
const kind = String(parsed.kind || "").trim().toLowerCase();
|
|
10164
10158
|
if (kind === "bot_reply") {
|
|
@@ -10183,18 +10177,18 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10183
10177
|
}
|
|
10184
10178
|
return continuation;
|
|
10185
10179
|
}
|
|
10186
|
-
return claimRunnerRequestForHumanComment({
|
|
10187
|
-
normalizedRoute,
|
|
10188
|
-
routeKey,
|
|
10189
|
-
selectedRecord,
|
|
10190
|
-
selectedBotUsernames: selectedResponderSelectors,
|
|
10191
|
-
normalizedIntent: String(safeObject(sharedHumanIntent).intentType || "").trim().toLowerCase(),
|
|
10192
|
-
sharedHumanIntent,
|
|
10193
|
-
runtime,
|
|
10194
|
-
archiveThreadID: archiveThread.threadID,
|
|
10195
|
-
authoritativeSourceMessageEnvelope,
|
|
10196
|
-
});
|
|
10197
|
-
};
|
|
10180
|
+
return claimRunnerRequestForHumanComment({
|
|
10181
|
+
normalizedRoute,
|
|
10182
|
+
routeKey,
|
|
10183
|
+
selectedRecord,
|
|
10184
|
+
selectedBotUsernames: selectedResponderSelectors,
|
|
10185
|
+
normalizedIntent: String(safeObject(sharedHumanIntent).intentType || "").trim().toLowerCase(),
|
|
10186
|
+
sharedHumanIntent,
|
|
10187
|
+
runtime,
|
|
10188
|
+
archiveThreadID: archiveThread.threadID,
|
|
10189
|
+
authoritativeSourceMessageEnvelope,
|
|
10190
|
+
});
|
|
10191
|
+
};
|
|
10198
10192
|
const buildContinuationResponderAdjudication = (selectedRecord, requestRaw) => {
|
|
10199
10193
|
const request = safeObject(requestRaw);
|
|
10200
10194
|
const referencedBotUsernames = ensureArray(safeObject(selectedRecord?.parsedArchive).mentionUsernames)
|
|
@@ -10228,11 +10222,11 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10228
10222
|
clarification: "",
|
|
10229
10223
|
};
|
|
10230
10224
|
};
|
|
10231
|
-
const finalizePreparedRunnerRequest = async (
|
|
10232
|
-
selectedRecord,
|
|
10233
|
-
requestClaim,
|
|
10234
|
-
authoritativeSourceMessageEnvelope = {},
|
|
10235
|
-
) => {
|
|
10225
|
+
const finalizePreparedRunnerRequest = async (
|
|
10226
|
+
selectedRecord,
|
|
10227
|
+
requestClaim,
|
|
10228
|
+
authoritativeSourceMessageEnvelope = {},
|
|
10229
|
+
) => {
|
|
10236
10230
|
const inheritedRootReference = await inheritRunnerReferenceRootWorkItemForRequest({
|
|
10237
10231
|
normalizedRoute,
|
|
10238
10232
|
selectedRecord,
|
|
@@ -10259,20 +10253,20 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10259
10253
|
|| rootWorkItemClaim.reason
|
|
10260
10254
|
|| (missingRequiredRootWorkItem ? "root_work_item_missing" : "root_work_item_create_failed"),
|
|
10261
10255
|
).trim() || "root_work_item_create_failed";
|
|
10262
|
-
if (String(requestClaim.requestKey || "").trim()) {
|
|
10263
|
-
markRunnerRequestLifecycle({
|
|
10264
|
-
normalizedRoute,
|
|
10265
|
-
requestKey: requestClaim.requestKey,
|
|
10266
|
-
selectedRecord,
|
|
10267
|
-
routeKey,
|
|
10268
|
-
outcome: "closed",
|
|
10269
|
-
closedReason: rootWorkItemFailure,
|
|
10270
|
-
authoritativeSourceMessageEnvelope,
|
|
10271
|
-
});
|
|
10272
|
-
await syncRunnerRequestLedgerForProjectToServer({
|
|
10273
|
-
normalizedRoute,
|
|
10274
|
-
runtime,
|
|
10275
|
-
});
|
|
10256
|
+
if (String(requestClaim.requestKey || "").trim()) {
|
|
10257
|
+
markRunnerRequestLifecycle({
|
|
10258
|
+
normalizedRoute,
|
|
10259
|
+
requestKey: requestClaim.requestKey,
|
|
10260
|
+
selectedRecord,
|
|
10261
|
+
routeKey,
|
|
10262
|
+
outcome: "closed",
|
|
10263
|
+
closedReason: rootWorkItemFailure,
|
|
10264
|
+
authoritativeSourceMessageEnvelope,
|
|
10265
|
+
});
|
|
10266
|
+
await syncRunnerRequestLedgerForProjectToServer({
|
|
10267
|
+
normalizedRoute,
|
|
10268
|
+
runtime,
|
|
10269
|
+
});
|
|
10276
10270
|
}
|
|
10277
10271
|
return {
|
|
10278
10272
|
ok: false,
|
|
@@ -10292,109 +10286,109 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10292
10286
|
},
|
|
10293
10287
|
};
|
|
10294
10288
|
}
|
|
10295
|
-
return {
|
|
10296
|
-
ok: true,
|
|
10297
|
-
claimedRequest,
|
|
10298
|
-
};
|
|
10299
|
-
};
|
|
10300
|
-
const prepareRunnerBotReplyAuthorityContext = async (selectedRecord, routingExecutionDeps, triggerDecision) => {
|
|
10301
|
-
const requestClaim = await prepareRunnerRequestClaim(selectedRecord);
|
|
10302
|
-
if (!requestClaim.ok) {
|
|
10303
|
-
const requestFailureReason = String(requestClaim.reason || "").trim();
|
|
10304
|
-
if (requestFailureReason === "bot_reply_without_active_request") {
|
|
10305
|
-
const conversationContext = await resolvePublicConversationContext({
|
|
10306
|
-
selectedRecord,
|
|
10307
|
-
pendingOrdered: pending.ordered,
|
|
10308
|
-
normalizedRoute,
|
|
10309
|
-
bot,
|
|
10310
|
-
routeState: safeObject(refreshedState.routes?.[routeKey]),
|
|
10311
|
-
executionPlan,
|
|
10312
|
-
deps: routingExecutionDeps,
|
|
10313
|
-
});
|
|
10314
|
-
const conversationAdjudication = buildRunnerResponderAdjudicationFromConversationContext({
|
|
10315
|
-
selectedRecord,
|
|
10316
|
-
conversationContext,
|
|
10317
|
-
currentBotSelector,
|
|
10318
|
-
});
|
|
10319
|
-
const currentBotSelectedFromConversation = ensureArray(conversationAdjudication?.selected_bot_usernames)
|
|
10320
|
-
.map((value) => String(value || "").trim().replace(/^@+/, "").toLowerCase())
|
|
10321
|
-
.includes(currentBotSelector);
|
|
10322
|
-
if (currentBotSelectedFromConversation) {
|
|
10323
|
-
return {
|
|
10324
|
-
ok: true,
|
|
10325
|
-
triggerDecision,
|
|
10326
|
-
routingExecutionDeps,
|
|
10327
|
-
sharedHumanIntentContext: null,
|
|
10328
|
-
adjudication: conversationAdjudication,
|
|
10329
|
-
requestClaim: {
|
|
10330
|
-
ok: true,
|
|
10331
|
-
requestKey: "",
|
|
10332
|
-
request: {},
|
|
10333
|
-
},
|
|
10334
|
-
claimedRequest: {},
|
|
10335
|
-
};
|
|
10336
|
-
}
|
|
10337
|
-
}
|
|
10338
|
-
await syncRunnerRequestLedgerForProjectToServer({
|
|
10339
|
-
normalizedRoute,
|
|
10340
|
-
runtime,
|
|
10341
|
-
});
|
|
10342
|
-
return {
|
|
10343
|
-
ok: false,
|
|
10344
|
-
skip: {
|
|
10345
|
-
kind: "skip",
|
|
10346
|
-
skipAction: "request_skipped",
|
|
10347
|
-
skipReason: requestFailureReason || "request_unavailable",
|
|
10348
|
-
skipTrigger: "request_ledger",
|
|
10349
|
-
skipRecordPatch: {
|
|
10350
|
-
diagnosticType: "skip",
|
|
10351
|
-
contextExcluded: requestFailureReason === "bot_reply_without_active_request",
|
|
10352
|
-
action: "skip_invalid_request_state",
|
|
10353
|
-
closedReason: requestFailureReason,
|
|
10354
|
-
},
|
|
10355
|
-
},
|
|
10356
|
-
};
|
|
10357
|
-
}
|
|
10358
|
-
const continuationAdjudication = buildContinuationResponderAdjudication(
|
|
10359
|
-
selectedRecord,
|
|
10360
|
-
requestClaim.request,
|
|
10361
|
-
);
|
|
10362
|
-
const currentBotSelected = ensureArray(continuationAdjudication.selected_bot_usernames)
|
|
10363
|
-
.map((value) => String(value || "").trim().replace(/^@+/, "").toLowerCase())
|
|
10364
|
-
.includes(currentBotSelector);
|
|
10365
|
-
if (!currentBotSelected) {
|
|
10366
|
-
return {
|
|
10367
|
-
ok: false,
|
|
10368
|
-
skip: {
|
|
10369
|
-
kind: "skip",
|
|
10370
|
-
skipAction: "adjudication_skipped",
|
|
10371
|
-
skipReason: String(continuationAdjudication.reason_code || "").trim() || "not_selected_by_request_contract",
|
|
10372
|
-
skipTrigger: "request_contract",
|
|
10373
|
-
},
|
|
10374
|
-
};
|
|
10375
|
-
}
|
|
10376
|
-
const finalizedRequest = await finalizePreparedRunnerRequest(
|
|
10377
|
-
selectedRecord,
|
|
10378
|
-
requestClaim,
|
|
10379
|
-
);
|
|
10380
|
-
if (!finalizedRequest.ok) {
|
|
10381
|
-
return {
|
|
10382
|
-
ok: false,
|
|
10383
|
-
skip: finalizedRequest.skip,
|
|
10384
|
-
};
|
|
10385
|
-
}
|
|
10386
|
-
return {
|
|
10387
|
-
ok: true,
|
|
10388
|
-
triggerDecision,
|
|
10389
|
-
routingExecutionDeps,
|
|
10390
|
-
sharedHumanIntentContext: null,
|
|
10391
|
-
adjudication: continuationAdjudication,
|
|
10392
|
-
requestClaim,
|
|
10393
|
-
claimedRequest: finalizedRequest.claimedRequest,
|
|
10394
|
-
};
|
|
10395
|
-
};
|
|
10396
|
-
const prepareRunnerSelectedRecordForExecution = async (selectedRecord) => {
|
|
10397
|
-
const selectedRecordKind = String(safeObject(selectedRecord?.parsedArchive).kind || "").trim().toLowerCase();
|
|
10289
|
+
return {
|
|
10290
|
+
ok: true,
|
|
10291
|
+
claimedRequest,
|
|
10292
|
+
};
|
|
10293
|
+
};
|
|
10294
|
+
const prepareRunnerBotReplyAuthorityContext = async (selectedRecord, routingExecutionDeps, triggerDecision) => {
|
|
10295
|
+
const requestClaim = await prepareRunnerRequestClaim(selectedRecord);
|
|
10296
|
+
if (!requestClaim.ok) {
|
|
10297
|
+
const requestFailureReason = String(requestClaim.reason || "").trim();
|
|
10298
|
+
if (requestFailureReason === "bot_reply_without_active_request") {
|
|
10299
|
+
const conversationContext = await resolvePublicConversationContext({
|
|
10300
|
+
selectedRecord,
|
|
10301
|
+
pendingOrdered: pending.ordered,
|
|
10302
|
+
normalizedRoute,
|
|
10303
|
+
bot,
|
|
10304
|
+
routeState: safeObject(refreshedState.routes?.[routeKey]),
|
|
10305
|
+
executionPlan,
|
|
10306
|
+
deps: routingExecutionDeps,
|
|
10307
|
+
});
|
|
10308
|
+
const conversationAdjudication = buildRunnerResponderAdjudicationFromConversationContext({
|
|
10309
|
+
selectedRecord,
|
|
10310
|
+
conversationContext,
|
|
10311
|
+
currentBotSelector,
|
|
10312
|
+
});
|
|
10313
|
+
const currentBotSelectedFromConversation = ensureArray(conversationAdjudication?.selected_bot_usernames)
|
|
10314
|
+
.map((value) => String(value || "").trim().replace(/^@+/, "").toLowerCase())
|
|
10315
|
+
.includes(currentBotSelector);
|
|
10316
|
+
if (currentBotSelectedFromConversation) {
|
|
10317
|
+
return {
|
|
10318
|
+
ok: true,
|
|
10319
|
+
triggerDecision,
|
|
10320
|
+
routingExecutionDeps,
|
|
10321
|
+
sharedHumanIntentContext: null,
|
|
10322
|
+
adjudication: conversationAdjudication,
|
|
10323
|
+
requestClaim: {
|
|
10324
|
+
ok: true,
|
|
10325
|
+
requestKey: "",
|
|
10326
|
+
request: {},
|
|
10327
|
+
},
|
|
10328
|
+
claimedRequest: {},
|
|
10329
|
+
};
|
|
10330
|
+
}
|
|
10331
|
+
}
|
|
10332
|
+
await syncRunnerRequestLedgerForProjectToServer({
|
|
10333
|
+
normalizedRoute,
|
|
10334
|
+
runtime,
|
|
10335
|
+
});
|
|
10336
|
+
return {
|
|
10337
|
+
ok: false,
|
|
10338
|
+
skip: {
|
|
10339
|
+
kind: "skip",
|
|
10340
|
+
skipAction: "request_skipped",
|
|
10341
|
+
skipReason: requestFailureReason || "request_unavailable",
|
|
10342
|
+
skipTrigger: "request_ledger",
|
|
10343
|
+
skipRecordPatch: {
|
|
10344
|
+
diagnosticType: "skip",
|
|
10345
|
+
contextExcluded: requestFailureReason === "bot_reply_without_active_request",
|
|
10346
|
+
action: "skip_invalid_request_state",
|
|
10347
|
+
closedReason: requestFailureReason,
|
|
10348
|
+
},
|
|
10349
|
+
},
|
|
10350
|
+
};
|
|
10351
|
+
}
|
|
10352
|
+
const continuationAdjudication = buildContinuationResponderAdjudication(
|
|
10353
|
+
selectedRecord,
|
|
10354
|
+
requestClaim.request,
|
|
10355
|
+
);
|
|
10356
|
+
const currentBotSelected = ensureArray(continuationAdjudication.selected_bot_usernames)
|
|
10357
|
+
.map((value) => String(value || "").trim().replace(/^@+/, "").toLowerCase())
|
|
10358
|
+
.includes(currentBotSelector);
|
|
10359
|
+
if (!currentBotSelected) {
|
|
10360
|
+
return {
|
|
10361
|
+
ok: false,
|
|
10362
|
+
skip: {
|
|
10363
|
+
kind: "skip",
|
|
10364
|
+
skipAction: "adjudication_skipped",
|
|
10365
|
+
skipReason: String(continuationAdjudication.reason_code || "").trim() || "not_selected_by_request_contract",
|
|
10366
|
+
skipTrigger: "request_contract",
|
|
10367
|
+
},
|
|
10368
|
+
};
|
|
10369
|
+
}
|
|
10370
|
+
const finalizedRequest = await finalizePreparedRunnerRequest(
|
|
10371
|
+
selectedRecord,
|
|
10372
|
+
requestClaim,
|
|
10373
|
+
);
|
|
10374
|
+
if (!finalizedRequest.ok) {
|
|
10375
|
+
return {
|
|
10376
|
+
ok: false,
|
|
10377
|
+
skip: finalizedRequest.skip,
|
|
10378
|
+
};
|
|
10379
|
+
}
|
|
10380
|
+
return {
|
|
10381
|
+
ok: true,
|
|
10382
|
+
triggerDecision,
|
|
10383
|
+
routingExecutionDeps,
|
|
10384
|
+
sharedHumanIntentContext: null,
|
|
10385
|
+
adjudication: continuationAdjudication,
|
|
10386
|
+
requestClaim,
|
|
10387
|
+
claimedRequest: finalizedRequest.claimedRequest,
|
|
10388
|
+
};
|
|
10389
|
+
};
|
|
10390
|
+
const prepareRunnerSelectedRecordForExecution = async (selectedRecord) => {
|
|
10391
|
+
const selectedRecordKind = String(safeObject(selectedRecord?.parsedArchive).kind || "").trim().toLowerCase();
|
|
10398
10392
|
const duplicateArchivedSkip = maybeBuildDuplicateArchivedSkip(selectedRecord, refreshedState);
|
|
10399
10393
|
if (duplicateArchivedSkip) {
|
|
10400
10394
|
return {
|
|
@@ -10447,68 +10441,68 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10447
10441
|
? currentBotSelector !== representativeBotSelector
|
|
10448
10442
|
: false,
|
|
10449
10443
|
});
|
|
10450
|
-
if (startupLoopSkipped) {
|
|
10451
|
-
return {
|
|
10452
|
-
kind: "startup_loop_skipped",
|
|
10453
|
-
skippedRecord: startupLoopSkipped.skippedRecord,
|
|
10454
|
-
};
|
|
10455
|
-
}
|
|
10456
|
-
const visibilityRouteState = safeObject(loadBotRunnerState().routes[routeKey]);
|
|
10457
|
-
const humanInboundVisibility = resolveRunnerHumanInboundVisibility({
|
|
10458
|
-
routeState: Object.keys(visibilityRouteState).length > 0
|
|
10459
|
-
? visibilityRouteState
|
|
10460
|
-
: refreshedState,
|
|
10461
|
-
persistedRequest: null,
|
|
10462
|
-
selectedRecord,
|
|
10463
|
-
routeKey,
|
|
10464
|
-
currentBotSelector,
|
|
10465
|
-
triggerDecision,
|
|
10466
|
-
});
|
|
10467
|
-
const visibilityStatePatch = humanInboundVisibility.applies
|
|
10468
|
-
? {
|
|
10469
|
-
last_visibility_status: String(humanInboundVisibility.visibilityStatus || "").trim(),
|
|
10470
|
-
last_visibility_reason: String(humanInboundVisibility.visibilityReason || "").trim(),
|
|
10471
|
-
last_visibility_source: String(humanInboundVisibility.visibilitySource || "").trim(),
|
|
10472
|
-
last_candidate_bot_usernames: ensureArray(humanInboundVisibility.candidateBotUsernames),
|
|
10473
|
-
}
|
|
10474
|
-
: {};
|
|
10475
|
-
if (humanInboundVisibility.applies && humanInboundVisibility.executable !== true) {
|
|
10476
|
-
return {
|
|
10477
|
-
kind: "skip",
|
|
10478
|
-
skipAction: "visibility_skipped",
|
|
10479
|
-
skipReason: String(
|
|
10480
|
-
humanInboundVisibility.visibilityReason || "telegram human inbound is not local to this route",
|
|
10481
|
-
).trim() || "telegram human inbound is not local to this route",
|
|
10482
|
-
skipTrigger: "local_inbound_visibility",
|
|
10483
|
-
skipStatePatch: visibilityStatePatch,
|
|
10484
|
-
};
|
|
10485
|
-
}
|
|
10486
|
-
const routingExecutionDeps = {
|
|
10487
|
-
...buildRunnerExecutionDeps(),
|
|
10488
|
-
managedConversationBots,
|
|
10489
|
-
resolveConversationPeerBots: resolveRunnerConversationPeers,
|
|
10490
|
-
};
|
|
10491
|
-
if (selectedRecordKind === "bot_reply") {
|
|
10492
|
-
const botReplyAuthorityContext = await prepareRunnerBotReplyAuthorityContext(
|
|
10493
|
-
selectedRecord,
|
|
10494
|
-
routingExecutionDeps,
|
|
10495
|
-
triggerDecision,
|
|
10496
|
-
);
|
|
10497
|
-
if (!botReplyAuthorityContext.ok) {
|
|
10498
|
-
return botReplyAuthorityContext.skip;
|
|
10499
|
-
}
|
|
10500
|
-
return {
|
|
10501
|
-
kind: "ready",
|
|
10502
|
-
triggerDecision: botReplyAuthorityContext.triggerDecision,
|
|
10503
|
-
routingExecutionDeps: botReplyAuthorityContext.routingExecutionDeps,
|
|
10504
|
-
sharedHumanIntentContext: botReplyAuthorityContext.sharedHumanIntentContext,
|
|
10505
|
-
adjudication: botReplyAuthorityContext.adjudication,
|
|
10506
|
-
requestClaim: botReplyAuthorityContext.requestClaim,
|
|
10507
|
-
claimedRequest: botReplyAuthorityContext.claimedRequest,
|
|
10508
|
-
humanInboundVisibility,
|
|
10509
|
-
visibilityStatePatch,
|
|
10510
|
-
};
|
|
10511
|
-
}
|
|
10444
|
+
if (startupLoopSkipped) {
|
|
10445
|
+
return {
|
|
10446
|
+
kind: "startup_loop_skipped",
|
|
10447
|
+
skippedRecord: startupLoopSkipped.skippedRecord,
|
|
10448
|
+
};
|
|
10449
|
+
}
|
|
10450
|
+
const visibilityRouteState = safeObject(loadBotRunnerState().routes[routeKey]);
|
|
10451
|
+
const humanInboundVisibility = resolveRunnerHumanInboundVisibility({
|
|
10452
|
+
routeState: Object.keys(visibilityRouteState).length > 0
|
|
10453
|
+
? visibilityRouteState
|
|
10454
|
+
: refreshedState,
|
|
10455
|
+
persistedRequest: null,
|
|
10456
|
+
selectedRecord,
|
|
10457
|
+
routeKey,
|
|
10458
|
+
currentBotSelector,
|
|
10459
|
+
triggerDecision,
|
|
10460
|
+
});
|
|
10461
|
+
const visibilityStatePatch = humanInboundVisibility.applies
|
|
10462
|
+
? {
|
|
10463
|
+
last_visibility_status: String(humanInboundVisibility.visibilityStatus || "").trim(),
|
|
10464
|
+
last_visibility_reason: String(humanInboundVisibility.visibilityReason || "").trim(),
|
|
10465
|
+
last_visibility_source: String(humanInboundVisibility.visibilitySource || "").trim(),
|
|
10466
|
+
last_candidate_bot_usernames: ensureArray(humanInboundVisibility.candidateBotUsernames),
|
|
10467
|
+
}
|
|
10468
|
+
: {};
|
|
10469
|
+
if (humanInboundVisibility.applies && humanInboundVisibility.executable !== true) {
|
|
10470
|
+
return {
|
|
10471
|
+
kind: "skip",
|
|
10472
|
+
skipAction: "visibility_skipped",
|
|
10473
|
+
skipReason: String(
|
|
10474
|
+
humanInboundVisibility.visibilityReason || "telegram human inbound is not local to this route",
|
|
10475
|
+
).trim() || "telegram human inbound is not local to this route",
|
|
10476
|
+
skipTrigger: "local_inbound_visibility",
|
|
10477
|
+
skipStatePatch: visibilityStatePatch,
|
|
10478
|
+
};
|
|
10479
|
+
}
|
|
10480
|
+
const routingExecutionDeps = {
|
|
10481
|
+
...buildRunnerExecutionDeps(),
|
|
10482
|
+
managedConversationBots,
|
|
10483
|
+
resolveConversationPeerBots: resolveRunnerConversationPeers,
|
|
10484
|
+
};
|
|
10485
|
+
if (selectedRecordKind === "bot_reply") {
|
|
10486
|
+
const botReplyAuthorityContext = await prepareRunnerBotReplyAuthorityContext(
|
|
10487
|
+
selectedRecord,
|
|
10488
|
+
routingExecutionDeps,
|
|
10489
|
+
triggerDecision,
|
|
10490
|
+
);
|
|
10491
|
+
if (!botReplyAuthorityContext.ok) {
|
|
10492
|
+
return botReplyAuthorityContext.skip;
|
|
10493
|
+
}
|
|
10494
|
+
return {
|
|
10495
|
+
kind: "ready",
|
|
10496
|
+
triggerDecision: botReplyAuthorityContext.triggerDecision,
|
|
10497
|
+
routingExecutionDeps: botReplyAuthorityContext.routingExecutionDeps,
|
|
10498
|
+
sharedHumanIntentContext: botReplyAuthorityContext.sharedHumanIntentContext,
|
|
10499
|
+
adjudication: botReplyAuthorityContext.adjudication,
|
|
10500
|
+
requestClaim: botReplyAuthorityContext.requestClaim,
|
|
10501
|
+
claimedRequest: botReplyAuthorityContext.claimedRequest,
|
|
10502
|
+
humanInboundVisibility,
|
|
10503
|
+
visibilityStatePatch,
|
|
10504
|
+
};
|
|
10505
|
+
}
|
|
10512
10506
|
const sharedHumanIntentContext = await resolveHumanIntentContext({
|
|
10513
10507
|
selectedRecord,
|
|
10514
10508
|
normalizedRoute,
|
|
@@ -10561,12 +10555,12 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10561
10555
|
skipTrigger: "responder_adjudication",
|
|
10562
10556
|
};
|
|
10563
10557
|
}
|
|
10564
|
-
const requestClaim = await prepareRunnerRequestClaim(
|
|
10565
|
-
selectedRecord,
|
|
10566
|
-
adjudication.selected_bot_usernames,
|
|
10567
|
-
safeObject(sharedHumanIntentContext).humanIntent || null,
|
|
10568
|
-
humanInboundVisibility.sourceMessageEnvelope,
|
|
10569
|
-
);
|
|
10558
|
+
const requestClaim = await prepareRunnerRequestClaim(
|
|
10559
|
+
selectedRecord,
|
|
10560
|
+
adjudication.selected_bot_usernames,
|
|
10561
|
+
safeObject(sharedHumanIntentContext).humanIntent || null,
|
|
10562
|
+
humanInboundVisibility.sourceMessageEnvelope,
|
|
10563
|
+
);
|
|
10570
10564
|
if (!requestClaim.ok) {
|
|
10571
10565
|
await syncRunnerRequestLedgerForProjectToServer({
|
|
10572
10566
|
normalizedRoute,
|
|
@@ -10585,26 +10579,26 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10585
10579
|
},
|
|
10586
10580
|
};
|
|
10587
10581
|
}
|
|
10588
|
-
const finalizedRequest = await finalizePreparedRunnerRequest(
|
|
10589
|
-
selectedRecord,
|
|
10590
|
-
requestClaim,
|
|
10591
|
-
humanInboundVisibility.sourceMessageEnvelope,
|
|
10592
|
-
);
|
|
10582
|
+
const finalizedRequest = await finalizePreparedRunnerRequest(
|
|
10583
|
+
selectedRecord,
|
|
10584
|
+
requestClaim,
|
|
10585
|
+
humanInboundVisibility.sourceMessageEnvelope,
|
|
10586
|
+
);
|
|
10593
10587
|
if (!finalizedRequest.ok) {
|
|
10594
10588
|
return finalizedRequest.skip;
|
|
10595
10589
|
}
|
|
10596
|
-
return {
|
|
10597
|
-
kind: "ready",
|
|
10598
|
-
triggerDecision,
|
|
10599
|
-
routingExecutionDeps,
|
|
10600
|
-
sharedHumanIntentContext,
|
|
10601
|
-
adjudication,
|
|
10602
|
-
requestClaim,
|
|
10603
|
-
claimedRequest: finalizedRequest.claimedRequest,
|
|
10604
|
-
humanInboundVisibility,
|
|
10605
|
-
visibilityStatePatch,
|
|
10606
|
-
};
|
|
10607
|
-
};
|
|
10590
|
+
return {
|
|
10591
|
+
kind: "ready",
|
|
10592
|
+
triggerDecision,
|
|
10593
|
+
routingExecutionDeps,
|
|
10594
|
+
sharedHumanIntentContext,
|
|
10595
|
+
adjudication,
|
|
10596
|
+
requestClaim,
|
|
10597
|
+
claimedRequest: finalizedRequest.claimedRequest,
|
|
10598
|
+
humanInboundVisibility,
|
|
10599
|
+
visibilityStatePatch,
|
|
10600
|
+
};
|
|
10601
|
+
};
|
|
10608
10602
|
if (deferExecution) {
|
|
10609
10603
|
const skippedRecords = [];
|
|
10610
10604
|
for (const selectedRecord of pending.pending) {
|
|
@@ -10623,27 +10617,27 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10623
10617
|
skippedRecords.push(preparation.skippedRecord);
|
|
10624
10618
|
continue;
|
|
10625
10619
|
}
|
|
10626
|
-
const {
|
|
10627
|
-
triggerDecision,
|
|
10628
|
-
sharedHumanIntentContext,
|
|
10629
|
-
adjudication,
|
|
10630
|
-
requestClaim,
|
|
10631
|
-
claimedRequest,
|
|
10632
|
-
humanInboundVisibility,
|
|
10633
|
-
visibilityStatePatch,
|
|
10634
|
-
} = preparation;
|
|
10635
|
-
saveRunnerRouteState(routeKey, {
|
|
10636
|
-
...buildRunnerActiveExecutionPatch(selectedRecord, requestClaim.requestKey, {
|
|
10637
|
-
id: String(claimedRequest.root_work_item_id || "").trim(),
|
|
10638
|
-
title: String(claimedRequest.root_work_item_title || "").trim(),
|
|
10620
|
+
const {
|
|
10621
|
+
triggerDecision,
|
|
10622
|
+
sharedHumanIntentContext,
|
|
10623
|
+
adjudication,
|
|
10624
|
+
requestClaim,
|
|
10625
|
+
claimedRequest,
|
|
10626
|
+
humanInboundVisibility,
|
|
10627
|
+
visibilityStatePatch,
|
|
10628
|
+
} = preparation;
|
|
10629
|
+
saveRunnerRouteState(routeKey, {
|
|
10630
|
+
...buildRunnerActiveExecutionPatch(selectedRecord, requestClaim.requestKey, {
|
|
10631
|
+
id: String(claimedRequest.root_work_item_id || "").trim(),
|
|
10632
|
+
title: String(claimedRequest.root_work_item_title || "").trim(),
|
|
10639
10633
|
status: String(claimedRequest.root_work_item_status || "").trim(),
|
|
10640
10634
|
}),
|
|
10641
|
-
last_request_key: String(requestClaim.requestKey || "").trim(),
|
|
10642
|
-
last_root_work_item_id: String(claimedRequest.root_work_item_id || "").trim(),
|
|
10643
|
-
last_root_work_item_title: String(claimedRequest.root_work_item_title || "").trim(),
|
|
10644
|
-
last_root_work_item_status: String(claimedRequest.root_work_item_status || "").trim(),
|
|
10645
|
-
...safeObject(visibilityStatePatch),
|
|
10646
|
-
});
|
|
10635
|
+
last_request_key: String(requestClaim.requestKey || "").trim(),
|
|
10636
|
+
last_root_work_item_id: String(claimedRequest.root_work_item_id || "").trim(),
|
|
10637
|
+
last_root_work_item_title: String(claimedRequest.root_work_item_title || "").trim(),
|
|
10638
|
+
last_root_work_item_status: String(claimedRequest.root_work_item_status || "").trim(),
|
|
10639
|
+
...safeObject(visibilityStatePatch),
|
|
10640
|
+
});
|
|
10647
10641
|
await syncRunnerRequestLedgerForProjectToServer({
|
|
10648
10642
|
normalizedRoute,
|
|
10649
10643
|
runtime,
|
|
@@ -10672,14 +10666,14 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10672
10666
|
executionPlan,
|
|
10673
10667
|
runtime,
|
|
10674
10668
|
managedConversationBots,
|
|
10675
|
-
requestKey: String(requestClaim.requestKey || "").trim(),
|
|
10676
|
-
triggerDecision,
|
|
10677
|
-
responderAdjudication: adjudication,
|
|
10678
|
-
humanIntentContext: sharedHumanIntentContext,
|
|
10679
|
-
humanInboundVisibility,
|
|
10680
|
-
},
|
|
10681
|
-
};
|
|
10682
|
-
}
|
|
10669
|
+
requestKey: String(requestClaim.requestKey || "").trim(),
|
|
10670
|
+
triggerDecision,
|
|
10671
|
+
responderAdjudication: adjudication,
|
|
10672
|
+
humanIntentContext: sharedHumanIntentContext,
|
|
10673
|
+
humanInboundVisibility,
|
|
10674
|
+
},
|
|
10675
|
+
};
|
|
10676
|
+
}
|
|
10683
10677
|
{
|
|
10684
10678
|
const skippedOutcome = await finalizeSkippedPendingRecords(skippedRecords);
|
|
10685
10679
|
if (skippedOutcome) {
|
|
@@ -10705,39 +10699,39 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10705
10699
|
continue;
|
|
10706
10700
|
}
|
|
10707
10701
|
const currentRouteState = safeObject(loadBotRunnerState().routes[routeKey]);
|
|
10708
|
-
const {
|
|
10709
|
-
triggerDecision,
|
|
10710
|
-
sharedHumanIntentContext,
|
|
10711
|
-
adjudication: inlineAdjudication,
|
|
10712
|
-
requestClaim,
|
|
10713
|
-
claimedRequest,
|
|
10714
|
-
humanInboundVisibility,
|
|
10715
|
-
visibilityStatePatch,
|
|
10716
|
-
} = preparation;
|
|
10717
|
-
saveRunnerRouteState(routeKey, {
|
|
10718
|
-
...buildRunnerActiveExecutionPatch(selectedRecord, requestClaim.requestKey, {
|
|
10719
|
-
id: String(claimedRequest.root_work_item_id || "").trim(),
|
|
10720
|
-
title: String(claimedRequest.root_work_item_title || "").trim(),
|
|
10702
|
+
const {
|
|
10703
|
+
triggerDecision,
|
|
10704
|
+
sharedHumanIntentContext,
|
|
10705
|
+
adjudication: inlineAdjudication,
|
|
10706
|
+
requestClaim,
|
|
10707
|
+
claimedRequest,
|
|
10708
|
+
humanInboundVisibility,
|
|
10709
|
+
visibilityStatePatch,
|
|
10710
|
+
} = preparation;
|
|
10711
|
+
saveRunnerRouteState(routeKey, {
|
|
10712
|
+
...buildRunnerActiveExecutionPatch(selectedRecord, requestClaim.requestKey, {
|
|
10713
|
+
id: String(claimedRequest.root_work_item_id || "").trim(),
|
|
10714
|
+
title: String(claimedRequest.root_work_item_title || "").trim(),
|
|
10721
10715
|
status: String(claimedRequest.root_work_item_status || "").trim(),
|
|
10722
10716
|
}),
|
|
10723
|
-
last_request_key: String(requestClaim.requestKey || "").trim(),
|
|
10724
|
-
last_root_work_item_id: String(claimedRequest.root_work_item_id || "").trim(),
|
|
10725
|
-
last_root_work_item_title: String(claimedRequest.root_work_item_title || "").trim(),
|
|
10726
|
-
last_root_work_item_status: String(claimedRequest.root_work_item_status || "").trim(),
|
|
10727
|
-
...safeObject(visibilityStatePatch),
|
|
10728
|
-
});
|
|
10717
|
+
last_request_key: String(requestClaim.requestKey || "").trim(),
|
|
10718
|
+
last_root_work_item_id: String(claimedRequest.root_work_item_id || "").trim(),
|
|
10719
|
+
last_root_work_item_title: String(claimedRequest.root_work_item_title || "").trim(),
|
|
10720
|
+
last_root_work_item_status: String(claimedRequest.root_work_item_status || "").trim(),
|
|
10721
|
+
...safeObject(visibilityStatePatch),
|
|
10722
|
+
});
|
|
10729
10723
|
if (String(requestClaim.requestKey || "").trim()) {
|
|
10730
10724
|
const resolvedIntentType = String(safeObject(loadBotRunnerState().routes[routeKey]).last_intent_type || "").trim();
|
|
10731
|
-
markRunnerRequestLifecycle({
|
|
10732
|
-
normalizedRoute,
|
|
10733
|
-
requestKey: requestClaim.requestKey,
|
|
10734
|
-
selectedRecord,
|
|
10735
|
-
routeKey,
|
|
10736
|
-
outcome: "running",
|
|
10737
|
-
authoritativeSourceMessageEnvelope: safeObject(
|
|
10738
|
-
humanInboundVisibility.sourceMessageEnvelope,
|
|
10739
|
-
),
|
|
10740
|
-
});
|
|
10725
|
+
markRunnerRequestLifecycle({
|
|
10726
|
+
normalizedRoute,
|
|
10727
|
+
requestKey: requestClaim.requestKey,
|
|
10728
|
+
selectedRecord,
|
|
10729
|
+
routeKey,
|
|
10730
|
+
outcome: "running",
|
|
10731
|
+
authoritativeSourceMessageEnvelope: safeObject(
|
|
10732
|
+
humanInboundVisibility.sourceMessageEnvelope,
|
|
10733
|
+
),
|
|
10734
|
+
});
|
|
10741
10735
|
const rootWorkItemSync = await syncRunnerRequestRootWorkItemForOutcome({
|
|
10742
10736
|
normalizedRoute,
|
|
10743
10737
|
runtime,
|
|
@@ -10777,15 +10771,15 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10777
10771
|
archiveThread,
|
|
10778
10772
|
executionPlan,
|
|
10779
10773
|
runtime,
|
|
10780
|
-
triggerDecision,
|
|
10781
|
-
responderAdjudication: inlineAdjudication,
|
|
10782
|
-
persistedHumanIntentRequest: claimedRequest,
|
|
10783
|
-
precomputedHumanIntentContext: sharedHumanIntentContext,
|
|
10784
|
-
precomputedHumanInboundVisibility: humanInboundVisibility,
|
|
10785
|
-
deps: {
|
|
10786
|
-
saveRunnerRouteState,
|
|
10787
|
-
startRunnerTypingHeartbeat,
|
|
10788
|
-
runRunnerAIExecution,
|
|
10774
|
+
triggerDecision,
|
|
10775
|
+
responderAdjudication: inlineAdjudication,
|
|
10776
|
+
persistedHumanIntentRequest: claimedRequest,
|
|
10777
|
+
precomputedHumanIntentContext: sharedHumanIntentContext,
|
|
10778
|
+
precomputedHumanInboundVisibility: humanInboundVisibility,
|
|
10779
|
+
deps: {
|
|
10780
|
+
saveRunnerRouteState,
|
|
10781
|
+
startRunnerTypingHeartbeat,
|
|
10782
|
+
runRunnerAIExecution,
|
|
10789
10783
|
explainExecutionFailureWithAI,
|
|
10790
10784
|
performLocalBotDelivery,
|
|
10791
10785
|
serializeRunnerTriggerPolicy,
|
|
@@ -10799,17 +10793,17 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10799
10793
|
});
|
|
10800
10794
|
if (processed.kind === "skipped") {
|
|
10801
10795
|
if (String(requestClaim.requestKey || "").trim()) {
|
|
10802
|
-
markRunnerRequestLifecycle({
|
|
10803
|
-
normalizedRoute,
|
|
10804
|
-
requestKey: requestClaim.requestKey,
|
|
10805
|
-
selectedRecord,
|
|
10806
|
-
routeKey,
|
|
10807
|
-
outcome: "skipped",
|
|
10808
|
-
closedReason: String(processed.skippedRecord?.reason || "skipped").trim() || "skipped",
|
|
10809
|
-
authoritativeSourceMessageEnvelope: safeObject(
|
|
10810
|
-
humanInboundVisibility.sourceMessageEnvelope,
|
|
10811
|
-
),
|
|
10812
|
-
});
|
|
10796
|
+
markRunnerRequestLifecycle({
|
|
10797
|
+
normalizedRoute,
|
|
10798
|
+
requestKey: requestClaim.requestKey,
|
|
10799
|
+
selectedRecord,
|
|
10800
|
+
routeKey,
|
|
10801
|
+
outcome: "skipped",
|
|
10802
|
+
closedReason: String(processed.skippedRecord?.reason || "skipped").trim() || "skipped",
|
|
10803
|
+
authoritativeSourceMessageEnvelope: safeObject(
|
|
10804
|
+
humanInboundVisibility.sourceMessageEnvelope,
|
|
10805
|
+
),
|
|
10806
|
+
});
|
|
10813
10807
|
const rootWorkItemSync = await syncRunnerRequestRootWorkItemForOutcome({
|
|
10814
10808
|
normalizedRoute,
|
|
10815
10809
|
runtime,
|
|
@@ -10833,11 +10827,11 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10833
10827
|
}
|
|
10834
10828
|
if (String(requestClaim.requestKey || "").trim()) {
|
|
10835
10829
|
const resolvedIntentType = String(safeObject(loadBotRunnerState().routes[routeKey]).last_intent_type || "").trim();
|
|
10836
|
-
markRunnerRequestLifecycle({
|
|
10837
|
-
normalizedRoute,
|
|
10838
|
-
requestKey: requestClaim.requestKey,
|
|
10839
|
-
selectedRecord,
|
|
10840
|
-
routeKey,
|
|
10830
|
+
markRunnerRequestLifecycle({
|
|
10831
|
+
normalizedRoute,
|
|
10832
|
+
requestKey: requestClaim.requestKey,
|
|
10833
|
+
selectedRecord,
|
|
10834
|
+
routeKey,
|
|
10841
10835
|
outcome: processed.kind === "delivery_failed"
|
|
10842
10836
|
? "delivery_failed_after_generation"
|
|
10843
10837
|
: String(processed.result?.outcome || "replied").trim().toLowerCase(),
|
|
@@ -10867,19 +10861,19 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
10867
10861
|
responseContractValidationTargets: ensureArray(processed.result?.response_contract_validation_targets),
|
|
10868
10862
|
assignmentValidationStatus: String(processed.result?.assignment_validation_status || "").trim(),
|
|
10869
10863
|
assignmentValidationReason: String(processed.result?.assignment_validation_reason || "").trim(),
|
|
10870
|
-
assignmentValidationModes: ensureArray(processed.result?.assignment_validation_modes),
|
|
10871
|
-
deliveryStatus: String(processed.result?.delivery_status || "").trim(),
|
|
10872
|
-
archiveStatus: String(processed.result?.archive_status || "").trim(),
|
|
10873
|
-
transportError: String(processed.result?.transport_error || "").trim(),
|
|
10874
|
-
archiveError: String(processed.result?.archive_error || "").trim(),
|
|
10875
|
-
lastReplyMessageID: intFromRawAllowZero(processed.result?.last_reply_message_id, 0),
|
|
10876
|
-
lastReplyMessageThreadID: intFromRawAllowZero(processed.result?.last_reply_message_thread_id, 0),
|
|
10877
|
-
replyToMessageID: intFromRawAllowZero(processed.result?.reply_to_message_id, 0),
|
|
10878
|
-
replyFallbackUsed: processed.result?.reply_fallback_used === true,
|
|
10879
|
-
authoritativeSourceMessageEnvelope: safeObject(
|
|
10880
|
-
humanInboundVisibility.sourceMessageEnvelope,
|
|
10881
|
-
),
|
|
10882
|
-
});
|
|
10864
|
+
assignmentValidationModes: ensureArray(processed.result?.assignment_validation_modes),
|
|
10865
|
+
deliveryStatus: String(processed.result?.delivery_status || "").trim(),
|
|
10866
|
+
archiveStatus: String(processed.result?.archive_status || "").trim(),
|
|
10867
|
+
transportError: String(processed.result?.transport_error || "").trim(),
|
|
10868
|
+
archiveError: String(processed.result?.archive_error || "").trim(),
|
|
10869
|
+
lastReplyMessageID: intFromRawAllowZero(processed.result?.last_reply_message_id, 0),
|
|
10870
|
+
lastReplyMessageThreadID: intFromRawAllowZero(processed.result?.last_reply_message_thread_id, 0),
|
|
10871
|
+
replyToMessageID: intFromRawAllowZero(processed.result?.reply_to_message_id, 0),
|
|
10872
|
+
replyFallbackUsed: processed.result?.reply_fallback_used === true,
|
|
10873
|
+
authoritativeSourceMessageEnvelope: safeObject(
|
|
10874
|
+
humanInboundVisibility.sourceMessageEnvelope,
|
|
10875
|
+
),
|
|
10876
|
+
});
|
|
10883
10877
|
if (processed.kind !== "delivery_failed") {
|
|
10884
10878
|
await ensureRunnerRootWorkItemForRequest({
|
|
10885
10879
|
normalizedRoute,
|
|
@@ -11831,11 +11825,24 @@ function resolveRunnerProjectUpRoutes({
|
|
|
11831
11825
|
server_bot_name: botName,
|
|
11832
11826
|
server_bot_id: botID,
|
|
11833
11827
|
});
|
|
11834
|
-
|
|
11828
|
+
const matched = ensureArray(config.routes)
|
|
11835
11829
|
.map((rawRoute) => normalizeRunnerRoute(rawRoute))
|
|
11836
11830
|
.filter((route) => route.enabled)
|
|
11837
11831
|
.filter((route) => configuredRunnerRouteMatchesInlineSelection(route, selectionRoute, selectionFlags, { telegramEntries }))
|
|
11838
11832
|
.filter((route) => !normalizedRoles.length || normalizedRoles.includes(normalizeBotRole(route.role)));
|
|
11833
|
+
if (normalizedRoles.length) {
|
|
11834
|
+
return matched;
|
|
11835
|
+
}
|
|
11836
|
+
const seenBotDestinations = new Map();
|
|
11837
|
+
return matched.filter((route) => {
|
|
11838
|
+
const botIdentity = String(route.serverBotID || route.botID || route.botName || route.serverBotName || "").trim().toLowerCase();
|
|
11839
|
+
const destIdentity = String(route.destinationID || route.destinationLabel || "").trim().toLowerCase();
|
|
11840
|
+
const dedupeKey = `${botIdentity}::${destIdentity}`;
|
|
11841
|
+
if (!dedupeKey || dedupeKey === "::") return true;
|
|
11842
|
+
if (seenBotDestinations.has(dedupeKey)) return false;
|
|
11843
|
+
seenBotDestinations.set(dedupeKey, true);
|
|
11844
|
+
return true;
|
|
11845
|
+
});
|
|
11839
11846
|
}
|
|
11840
11847
|
|
|
11841
11848
|
async function runRunnerProjectUp(flags) {
|
|
@@ -13158,16 +13165,16 @@ async function syncRunnerDeferredExecutionRunningState(deferredExecution) {
|
|
|
13158
13165
|
if (!String(deferredExecution?.requestKey || "").trim()) {
|
|
13159
13166
|
return;
|
|
13160
13167
|
}
|
|
13161
|
-
markRunnerRequestLifecycle({
|
|
13162
|
-
normalizedRoute: deferredExecution.normalizedRoute,
|
|
13163
|
-
requestKey: deferredExecution.requestKey,
|
|
13164
|
-
selectedRecord: deferredExecution.selectedRecord,
|
|
13165
|
-
routeKey: deferredExecution.routeKey,
|
|
13166
|
-
outcome: "running",
|
|
13167
|
-
authoritativeSourceMessageEnvelope: safeObject(
|
|
13168
|
-
safeObject(deferredExecution.humanInboundVisibility).sourceMessageEnvelope,
|
|
13169
|
-
),
|
|
13170
|
-
});
|
|
13168
|
+
markRunnerRequestLifecycle({
|
|
13169
|
+
normalizedRoute: deferredExecution.normalizedRoute,
|
|
13170
|
+
requestKey: deferredExecution.requestKey,
|
|
13171
|
+
selectedRecord: deferredExecution.selectedRecord,
|
|
13172
|
+
routeKey: deferredExecution.routeKey,
|
|
13173
|
+
outcome: "running",
|
|
13174
|
+
authoritativeSourceMessageEnvelope: safeObject(
|
|
13175
|
+
safeObject(deferredExecution.humanInboundVisibility).sourceMessageEnvelope,
|
|
13176
|
+
),
|
|
13177
|
+
});
|
|
13171
13178
|
const rootWorkItemSync = await syncRunnerRequestRootWorkItemForOutcome({
|
|
13172
13179
|
normalizedRoute: deferredExecution.normalizedRoute,
|
|
13173
13180
|
runtime: deferredExecution.runtime,
|
|
@@ -13192,17 +13199,17 @@ async function syncRunnerDeferredExecutionRunningState(deferredExecution) {
|
|
|
13192
13199
|
|
|
13193
13200
|
async function finalizeRunnerDeferredExecutionSkipped(deferredExecution, processed) {
|
|
13194
13201
|
if (String(deferredExecution?.requestKey || "").trim()) {
|
|
13195
|
-
markRunnerRequestLifecycle({
|
|
13196
|
-
normalizedRoute: deferredExecution.normalizedRoute,
|
|
13197
|
-
requestKey: deferredExecution.requestKey,
|
|
13198
|
-
selectedRecord: deferredExecution.selectedRecord,
|
|
13199
|
-
routeKey: deferredExecution.routeKey,
|
|
13200
|
-
outcome: "skipped",
|
|
13201
|
-
closedReason: String(processed?.skippedRecord?.reason || "skipped").trim() || "skipped",
|
|
13202
|
-
authoritativeSourceMessageEnvelope: safeObject(
|
|
13203
|
-
safeObject(deferredExecution.humanInboundVisibility).sourceMessageEnvelope,
|
|
13204
|
-
),
|
|
13205
|
-
});
|
|
13202
|
+
markRunnerRequestLifecycle({
|
|
13203
|
+
normalizedRoute: deferredExecution.normalizedRoute,
|
|
13204
|
+
requestKey: deferredExecution.requestKey,
|
|
13205
|
+
selectedRecord: deferredExecution.selectedRecord,
|
|
13206
|
+
routeKey: deferredExecution.routeKey,
|
|
13207
|
+
outcome: "skipped",
|
|
13208
|
+
closedReason: String(processed?.skippedRecord?.reason || "skipped").trim() || "skipped",
|
|
13209
|
+
authoritativeSourceMessageEnvelope: safeObject(
|
|
13210
|
+
safeObject(deferredExecution.humanInboundVisibility).sourceMessageEnvelope,
|
|
13211
|
+
),
|
|
13212
|
+
});
|
|
13206
13213
|
const rootWorkItemSync = await syncRunnerRequestRootWorkItemForOutcome({
|
|
13207
13214
|
normalizedRoute: deferredExecution.normalizedRoute,
|
|
13208
13215
|
runtime: deferredExecution.runtime,
|
|
@@ -13241,11 +13248,11 @@ async function finalizeRunnerDeferredExecutionProcessed(deferredExecution, proce
|
|
|
13241
13248
|
const resolvedIntentType = String(
|
|
13242
13249
|
safeObject(loadBotRunnerState().routes[deferredExecution.routeKey]).last_intent_type || "",
|
|
13243
13250
|
).trim();
|
|
13244
|
-
markRunnerRequestLifecycle({
|
|
13245
|
-
normalizedRoute: deferredExecution.normalizedRoute,
|
|
13246
|
-
requestKey: deferredExecution.requestKey,
|
|
13247
|
-
selectedRecord: deferredExecution.selectedRecord,
|
|
13248
|
-
routeKey: deferredExecution.routeKey,
|
|
13251
|
+
markRunnerRequestLifecycle({
|
|
13252
|
+
normalizedRoute: deferredExecution.normalizedRoute,
|
|
13253
|
+
requestKey: deferredExecution.requestKey,
|
|
13254
|
+
selectedRecord: deferredExecution.selectedRecord,
|
|
13255
|
+
routeKey: deferredExecution.routeKey,
|
|
13249
13256
|
outcome: processed.kind === "delivery_failed"
|
|
13250
13257
|
? "delivery_failed_after_generation"
|
|
13251
13258
|
: String(processed.result?.outcome || "replied").trim().toLowerCase(),
|
|
@@ -13277,19 +13284,19 @@ async function finalizeRunnerDeferredExecutionProcessed(deferredExecution, proce
|
|
|
13277
13284
|
responseContractValidationTargets: ensureArray(processed.result?.response_contract_validation_targets),
|
|
13278
13285
|
assignmentValidationStatus: String(processed.result?.assignment_validation_status || "").trim(),
|
|
13279
13286
|
assignmentValidationReason: String(processed.result?.assignment_validation_reason || "").trim(),
|
|
13280
|
-
assignmentValidationModes: ensureArray(processed.result?.assignment_validation_modes),
|
|
13281
|
-
deliveryStatus: String(processed.result?.delivery_status || "").trim(),
|
|
13282
|
-
archiveStatus: String(processed.result?.archive_status || "").trim(),
|
|
13283
|
-
transportError: String(processed.result?.transport_error || "").trim(),
|
|
13284
|
-
archiveError: String(processed.result?.archive_error || "").trim(),
|
|
13285
|
-
lastReplyMessageID: intFromRawAllowZero(processed.result?.last_reply_message_id, 0),
|
|
13286
|
-
lastReplyMessageThreadID: intFromRawAllowZero(processed.result?.last_reply_message_thread_id, 0),
|
|
13287
|
-
replyToMessageID: intFromRawAllowZero(processed.result?.reply_to_message_id, 0),
|
|
13288
|
-
replyFallbackUsed: processed.result?.reply_fallback_used === true,
|
|
13289
|
-
authoritativeSourceMessageEnvelope: safeObject(
|
|
13290
|
-
safeObject(deferredExecution.humanInboundVisibility).sourceMessageEnvelope,
|
|
13291
|
-
),
|
|
13292
|
-
});
|
|
13287
|
+
assignmentValidationModes: ensureArray(processed.result?.assignment_validation_modes),
|
|
13288
|
+
deliveryStatus: String(processed.result?.delivery_status || "").trim(),
|
|
13289
|
+
archiveStatus: String(processed.result?.archive_status || "").trim(),
|
|
13290
|
+
transportError: String(processed.result?.transport_error || "").trim(),
|
|
13291
|
+
archiveError: String(processed.result?.archive_error || "").trim(),
|
|
13292
|
+
lastReplyMessageID: intFromRawAllowZero(processed.result?.last_reply_message_id, 0),
|
|
13293
|
+
lastReplyMessageThreadID: intFromRawAllowZero(processed.result?.last_reply_message_thread_id, 0),
|
|
13294
|
+
replyToMessageID: intFromRawAllowZero(processed.result?.reply_to_message_id, 0),
|
|
13295
|
+
replyFallbackUsed: processed.result?.reply_fallback_used === true,
|
|
13296
|
+
authoritativeSourceMessageEnvelope: safeObject(
|
|
13297
|
+
safeObject(deferredExecution.humanInboundVisibility).sourceMessageEnvelope,
|
|
13298
|
+
),
|
|
13299
|
+
});
|
|
13293
13300
|
if (processed.kind !== "delivery_failed") {
|
|
13294
13301
|
await ensureRunnerRootWorkItemForRequest({
|
|
13295
13302
|
normalizedRoute: deferredExecution.normalizedRoute,
|
|
@@ -13346,18 +13353,18 @@ async function finalizeRunnerDeferredExecutionError(deferredExecution, errorText
|
|
|
13346
13353
|
|| currentRequest.normalized_intent
|
|
13347
13354
|
|| "",
|
|
13348
13355
|
).trim();
|
|
13349
|
-
markRunnerRequestLifecycle({
|
|
13350
|
-
normalizedRoute: deferredExecution.normalizedRoute,
|
|
13351
|
-
requestKey: deferredExecution.requestKey,
|
|
13352
|
-
selectedRecord: deferredExecution.selectedRecord,
|
|
13353
|
-
routeKey: deferredExecution.routeKey,
|
|
13354
|
-
outcome: "error",
|
|
13355
|
-
closedReason: errorText || "execution_error",
|
|
13356
|
-
normalizedIntent: resolvedIntentType,
|
|
13357
|
-
authoritativeSourceMessageEnvelope: safeObject(
|
|
13358
|
-
safeObject(deferredExecution.humanInboundVisibility).sourceMessageEnvelope,
|
|
13359
|
-
),
|
|
13360
|
-
});
|
|
13356
|
+
markRunnerRequestLifecycle({
|
|
13357
|
+
normalizedRoute: deferredExecution.normalizedRoute,
|
|
13358
|
+
requestKey: deferredExecution.requestKey,
|
|
13359
|
+
selectedRecord: deferredExecution.selectedRecord,
|
|
13360
|
+
routeKey: deferredExecution.routeKey,
|
|
13361
|
+
outcome: "error",
|
|
13362
|
+
closedReason: errorText || "execution_error",
|
|
13363
|
+
normalizedIntent: resolvedIntentType,
|
|
13364
|
+
authoritativeSourceMessageEnvelope: safeObject(
|
|
13365
|
+
safeObject(deferredExecution.humanInboundVisibility).sourceMessageEnvelope,
|
|
13366
|
+
),
|
|
13367
|
+
});
|
|
13361
13368
|
await ensureRunnerRootWorkItemForRequest({
|
|
13362
13369
|
normalizedRoute: deferredExecution.normalizedRoute,
|
|
13363
13370
|
routeKey: deferredExecution.routeKey,
|
|
@@ -13572,10 +13579,10 @@ function createRunnerDeferredExecutionPromise({
|
|
|
13572
13579
|
}) {
|
|
13573
13580
|
return (async () => {
|
|
13574
13581
|
try {
|
|
13575
|
-
const processed = await processRunnerSelectedRecord({
|
|
13576
|
-
routeKey: deferredExecution.routeKey,
|
|
13577
|
-
normalizedRoute: deferredExecution.normalizedRoute,
|
|
13578
|
-
routeState: deferredExecution.routeState,
|
|
13582
|
+
const processed = await processRunnerSelectedRecord({
|
|
13583
|
+
routeKey: deferredExecution.routeKey,
|
|
13584
|
+
normalizedRoute: deferredExecution.normalizedRoute,
|
|
13585
|
+
routeState: deferredExecution.routeState,
|
|
13579
13586
|
selectedRecord: deferredExecution.selectedRecord,
|
|
13580
13587
|
pendingOrdered: deferredExecution.pendingOrdered,
|
|
13581
13588
|
bot: deferredExecution.bot,
|
|
@@ -13583,14 +13590,14 @@ function createRunnerDeferredExecutionPromise({
|
|
|
13583
13590
|
archiveThread: deferredExecution.archiveThread,
|
|
13584
13591
|
executionPlan: deferredExecution.executionPlan,
|
|
13585
13592
|
runtime: deferredExecution.runtime,
|
|
13586
|
-
triggerDecision: deferredExecution.triggerDecision,
|
|
13587
|
-
responderAdjudication: deferredExecution.responderAdjudication,
|
|
13588
|
-
persistedHumanIntentRequest: loadRunnerRequestByKey(deferredExecution.requestKey),
|
|
13589
|
-
precomputedHumanIntentContext: safeObject(deferredExecution.humanIntentContext),
|
|
13590
|
-
precomputedHumanInboundVisibility: safeObject(deferredExecution.humanInboundVisibility),
|
|
13591
|
-
deps: {
|
|
13592
|
-
saveRunnerRouteState,
|
|
13593
|
-
startRunnerTypingHeartbeat,
|
|
13593
|
+
triggerDecision: deferredExecution.triggerDecision,
|
|
13594
|
+
responderAdjudication: deferredExecution.responderAdjudication,
|
|
13595
|
+
persistedHumanIntentRequest: loadRunnerRequestByKey(deferredExecution.requestKey),
|
|
13596
|
+
precomputedHumanIntentContext: safeObject(deferredExecution.humanIntentContext),
|
|
13597
|
+
precomputedHumanInboundVisibility: safeObject(deferredExecution.humanInboundVisibility),
|
|
13598
|
+
deps: {
|
|
13599
|
+
saveRunnerRouteState,
|
|
13600
|
+
startRunnerTypingHeartbeat,
|
|
13594
13601
|
runRunnerAIExecution,
|
|
13595
13602
|
explainExecutionFailureWithAI,
|
|
13596
13603
|
performLocalBotDelivery,
|
|
@@ -17918,25 +17925,25 @@ TELEGRAM_BOT_REVIEW_TOKEN=review-token
|
|
|
17918
17925
|
mergeServerRunnerRequestLedgerIntoLocalState,
|
|
17919
17926
|
buildRunnerStatusQueryLookup,
|
|
17920
17927
|
tryJsonParse,
|
|
17921
|
-
safeObject,
|
|
17922
|
-
normalizeRunnerTriggerPolicy,
|
|
17923
|
-
evaluateTelegramRunnerTrigger,
|
|
17924
|
-
resolveHumanIntentContext,
|
|
17925
|
-
resolveRunnerResponderAdjudication,
|
|
17926
|
-
selectPendingArchiveComments,
|
|
17928
|
+
safeObject,
|
|
17929
|
+
normalizeRunnerTriggerPolicy,
|
|
17930
|
+
evaluateTelegramRunnerTrigger,
|
|
17931
|
+
resolveHumanIntentContext,
|
|
17932
|
+
resolveRunnerResponderAdjudication,
|
|
17933
|
+
selectPendingArchiveComments,
|
|
17927
17934
|
selectRunnerPendingWork,
|
|
17928
17935
|
processRunnerSelectedRecord,
|
|
17929
|
-
resolveRunnerStartupLoopAdjudication,
|
|
17930
|
-
shouldBypassRunnerStartupLoopForContractFollowup,
|
|
17931
|
-
claimRunnerRequestForHumanComment,
|
|
17932
|
-
markRunnerRequestLifecycle,
|
|
17933
|
-
resolveRunnerContinuationRequestForBotReply,
|
|
17934
|
-
normalizeBotRunnerRequests,
|
|
17935
|
-
buildRunnerRequestRecoveryPatchFromRouteState,
|
|
17936
|
-
peekRunnerContinuationRequestForBotReply,
|
|
17937
|
-
cleanupBotRunnerRequestState,
|
|
17938
|
-
runRunnerAIExecution,
|
|
17939
|
-
buildLocalBotPrompt,
|
|
17936
|
+
resolveRunnerStartupLoopAdjudication,
|
|
17937
|
+
shouldBypassRunnerStartupLoopForContractFollowup,
|
|
17938
|
+
claimRunnerRequestForHumanComment,
|
|
17939
|
+
markRunnerRequestLifecycle,
|
|
17940
|
+
resolveRunnerContinuationRequestForBotReply,
|
|
17941
|
+
normalizeBotRunnerRequests,
|
|
17942
|
+
buildRunnerRequestRecoveryPatchFromRouteState,
|
|
17943
|
+
peekRunnerContinuationRequestForBotReply,
|
|
17944
|
+
cleanupBotRunnerRequestState,
|
|
17945
|
+
runRunnerAIExecution,
|
|
17946
|
+
buildLocalBotPrompt,
|
|
17940
17947
|
formatBotReplyArchiveComment,
|
|
17941
17948
|
findArchivedBotReplyRecord,
|
|
17942
17949
|
parseArchivedChatComment,
|