@openclaw/imessage 2026.10.5-beta.4 → 2026.10.10-beta.1
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/dist/.setup/{actions-Hxh12myO.mjs → actions-CZHoxlpi.mjs} +6 -10
- package/dist/.setup/{actions.runtime-DOIX6Fkf.mjs → actions.runtime-B-OHCffC.mjs} +7 -9
- package/dist/.setup/{api-BV8qHfLl.mjs → api-BifRABgX.mjs} +6 -6
- package/dist/.setup/{api-DC1yHVGj.mjs → api-dHebtZYA.mjs} +4 -4
- package/dist/.setup/{approval-handler.runtime-Dc3KzakG.mjs → approval-handler.runtime-jO19jL0F.mjs} +68 -76
- package/dist/.setup/{approval-reactions-JvzJCJ4a.mjs → approval-reactions-DFgEJMz2.mjs} +11 -15
- package/dist/.setup/{channel-9TWBUDkP.mjs → channel-D-E9DvQL.mjs} +17 -17
- package/dist/.setup/{channel.runtime-DrLDEY4R.mjs → channel.runtime-Cx_lRd-J.mjs} +63 -121
- package/dist/.setup/{client-HixFQQWY.mjs → client-BEZ_gLk-.mjs} +4 -27
- package/dist/.setup/{conversation-bindings-GDQ_Laxj.mjs → conversation-bindings-DR-dbHjs.mjs} +14 -2
- package/dist/.setup/{question-reactions-9jrqVZgE.mjs → question-reactions-BUSvdHlF.mjs} +2 -2
- package/dist/.setup/{reaction-context-CRXpeYAr.mjs → reaction-context-DbYCapmR.mjs} +1 -1
- package/dist/.setup/{remote-file-Dq5Asi_F.mjs → remote-file-vdoCnZze.mjs} +1 -1
- package/dist/.setup/{sanitize-outbound-DpdQERYJ.mjs → sanitize-outbound-BtEY324R.mjs} +14 -14
- package/dist/.setup/{send-BZZzMbdi.mjs → send-Jaf5eIJS.mjs} +10 -63
- package/dist/.setup/{setup-core-CaRGbZOL.mjs → setup-core-BHyLkAEJ.mjs} +1 -1
- package/dist/.setup/{setup-surface-BMWS7VuY.mjs → setup-surface-DPqiLGy0.mjs} +1 -1
- package/dist/api.js +6 -6
- package/dist/channel-config-api.js +1 -2
- package/dist/channel-plugin-api.js +1 -2
- package/dist/contract-api.js +1 -2
- package/dist/media-contract-api.js +1 -2
- package/dist/message-tool-api.js +1 -2
- package/dist/runtime-api.js +1 -1
- package/dist/session-binding-contract-api.js +1 -2
- package/dist/setup-entry.js +1 -1
- package/node_modules/typebox/build/value/clean/from_object.mjs +1 -1
- package/node_modules/typebox/package.json +1 -1
- package/package.json +5 -5
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { c as parseIMessageTarget, o as normalizeIMessageHandle, r as isAllowedIMessageReplyContextSender, s as parseIMessageAllowTarget, t as formatIMessageChatTarget } from "./targets-B4oU7n-v.mjs";
|
|
2
2
|
import { d as resolveIMessageChatDbLookupPath, f as resolveIMessageHomeDir, l as resolveIMessageRemoteHost, o as resolveIMessageAccount, r as listEnabledIMessageAccounts, s as resolveIMessageDuplicateSourceOwner } from "./accounts-DacCvDBt.mjs";
|
|
3
3
|
import { r as imessageRpcSupportsMethod } from "./message-tool-api-B5NfPnFL.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { a as normalizeIMessageMessageId, i as normalizeIMessageGuid, n as probeIMessage, r as probeIMessagePrivateApi } from "./actions-
|
|
4
|
+
import { S as resolveIMessageDirectChatService, h as resolveIMessageEchoMediaKey, m as resolveIMessageCatchupCursorKey, n as createIMessageRpcClient, o as isKnownFromMeIMessageTarget, p as capFailureRetriesMap, s as rememberIMessageReplyCache, u as IMESSAGE_CATCHUP_CURSOR_NAMESPACE } from "./client-BEZ_gLk-.mjs";
|
|
5
|
+
import { a as normalizeIMessageMessageId, i as normalizeIMessageGuid, n as probeIMessage, r as probeIMessagePrivateApi } from "./actions-CZHoxlpi.mjs";
|
|
6
6
|
import { t as getIMessageRuntime } from "./runtime-Cza4CY5T.mjs";
|
|
7
|
-
import { a as resolveIMessageGroupSystemPrompt, s as resolveIMessageInboundConversationId } from "./channel-
|
|
8
|
-
import { r as sanitizeOutboundText } from "./sanitize-outbound-
|
|
7
|
+
import { a as resolveIMessageGroupSystemPrompt, s as resolveIMessageInboundConversationId } from "./channel-D-E9DvQL.mjs";
|
|
8
|
+
import { r as sanitizeOutboundText } from "./sanitize-outbound-BtEY324R.mjs";
|
|
9
9
|
import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots } from "./media-contract-BwWs5PM7.mjs";
|
|
10
10
|
import { t as IMESSAGE_LEGACY_OUTBOUND_SEND_DEP_KEYS } from "./outbound-send-deps-B-QEsLSM.mjs";
|
|
11
|
-
import { i as resolveIMessageStartupRowidWatermark } from "./remote-file-
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { t as resolveIMessageReactionContext } from "./reaction-context-
|
|
15
|
-
import { n as maybeResolveIMessageQuestionReaction, t as hasIMessageQuestionReactionTarget } from "./question-reactions-
|
|
16
|
-
import { imessageSetupWizard } from "./setup-surface-
|
|
11
|
+
import { i as resolveIMessageStartupRowidWatermark } from "./remote-file-vdoCnZze.mjs";
|
|
12
|
+
import { i as registerIMessageApprovalReactionTarget, n as handleIMessageApprovalReaction, o as listPendingIMessageApprovalReactionPollTargets, r as maybeResolveIMessageApprovalReaction } from "./approval-reactions-DFgEJMz2.mjs";
|
|
13
|
+
import { n as hasPersistedIMessageEcho, r as normalizeIMessageEchoText, s as maybeResolveIMessageApprovalPollVote, t as sendMessageIMessage } from "./send-Jaf5eIJS.mjs";
|
|
14
|
+
import { t as resolveIMessageReactionContext } from "./reaction-context-DbYCapmR.mjs";
|
|
15
|
+
import { n as maybeResolveIMessageQuestionReaction, t as hasIMessageQuestionReactionTarget } from "./question-reactions-BUSvdHlF.mjs";
|
|
16
|
+
import { imessageSetupWizard } from "./setup-surface-DPqiLGy0.mjs";
|
|
17
17
|
import { asSafeIntegerInRange, hasNonEmptyString, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeStringEntries, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
18
18
|
import { normalizeChannelDmPolicy } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
19
19
|
import { bindIngressLifecycleToReplyOptions, createAccountStatusSink, createChannelDeliveryAccumulator, createChannelIngressError, createChannelIngressMonitor, createChannelMessageReplyPipeline, resolveChannelStreamingBlockEnabled, resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
|
|
@@ -27,7 +27,7 @@ import { isInboundPathAllowed, kindFromMime } from "openclaw/plugin-sdk/media-ru
|
|
|
27
27
|
import { createNonExitingRuntime, danger, logVerbose, shouldLogVerbose, sleepWithAbort, waitForAbortSignal, warn } from "openclaw/plugin-sdk/runtime-env";
|
|
28
28
|
import { asDateTimestampMs, asPositiveFiniteNumber, parseDateStringTimestampMs, resolveIntegerOption, resolvePromptHistoryLimit, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
|
|
29
29
|
import { createHash } from "node:crypto";
|
|
30
|
-
import {
|
|
30
|
+
import { captureRuntimeConfigAsyncReader, createRuntimeConfigReader } from "openclaw/plugin-sdk/runtime-config-snapshot";
|
|
31
31
|
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
32
32
|
import { collectErrorGraphCandidates, formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
33
33
|
import { resolveChannelGroupPolicy, resolveChannelGroups, resolveChannelGroupsConfigPath, resolveScopeRequireMention } from "openclaw/plugin-sdk/channel-policy";
|
|
@@ -47,7 +47,7 @@ import { ensureConfiguredBindingRouteReady, readChannelAllowFromStore, upsertCha
|
|
|
47
47
|
import { channelReadyPatch } from "openclaw/plugin-sdk/gateway-runtime";
|
|
48
48
|
import { redactIdentifier } from "openclaw/plugin-sdk/logging-core";
|
|
49
49
|
import { resolveDefaultGroupPolicy, resolveOpenProviderRuntimeGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
50
|
-
import {
|
|
50
|
+
import { getSessionEntryAsync, readSessionUpdatedAtAsync, resolveSendPolicy, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
51
51
|
import { waitForTransportReady } from "openclaw/plugin-sdk/transport-ready-runtime";
|
|
52
52
|
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
|
53
53
|
import { chunkMarkdownTextWithMode, resolveChunkMode } from "openclaw/plugin-sdk/reply-chunking";
|
|
@@ -266,7 +266,7 @@ const DEFAULT_MAX_FAILURE_RETRIES = 10;
|
|
|
266
266
|
const MAX_MAX_FAILURE_RETRIES = 1e3;
|
|
267
267
|
const cursorWriteQueue = new KeyedAsyncQueue();
|
|
268
268
|
function openCatchupCursorStore() {
|
|
269
|
-
return getIMessageRuntime().state.
|
|
269
|
+
return getIMessageRuntime().state.openKeyedStoreV2({
|
|
270
270
|
namespace: IMESSAGE_CATCHUP_CURSOR_NAMESPACE,
|
|
271
271
|
maxEntries: 256
|
|
272
272
|
});
|
|
@@ -308,40 +308,27 @@ function buildIMessageCatchupCursor(next, updatedAt) {
|
|
|
308
308
|
function decideCatchupCursorSave(existingValue, cursor, allowCursorRewindForRetries) {
|
|
309
309
|
const existing = normalizeIMessageCatchupCursor(existingValue);
|
|
310
310
|
if (existing && cursor.lastSeenRowid < existing.lastSeenRowid) {
|
|
311
|
-
if (!allowCursorRewindForRetries) return
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
lastSeenRowid: cursor.lastSeenRowid,
|
|
321
|
-
failureRetries: {
|
|
322
|
-
...existing.failureRetries,
|
|
323
|
-
...cursor.failureRetries
|
|
324
|
-
}
|
|
325
|
-
}, cursor.updatedAt)
|
|
326
|
-
};
|
|
311
|
+
if (!allowCursorRewindForRetries) return;
|
|
312
|
+
return buildIMessageCatchupCursor({
|
|
313
|
+
lastSeenMs: cursor.lastSeenMs,
|
|
314
|
+
lastSeenRowid: cursor.lastSeenRowid,
|
|
315
|
+
failureRetries: {
|
|
316
|
+
...existing.failureRetries,
|
|
317
|
+
...cursor.failureRetries
|
|
318
|
+
}
|
|
319
|
+
}, cursor.updatedAt);
|
|
327
320
|
}
|
|
328
|
-
return
|
|
329
|
-
operation: "update",
|
|
330
|
-
action: "set",
|
|
331
|
-
value: cursor
|
|
332
|
-
};
|
|
321
|
+
return cursor;
|
|
333
322
|
}
|
|
334
323
|
async function updateIMessageCatchupCursor(accountId, decide) {
|
|
335
|
-
const store = openCatchupCursorStore();
|
|
336
|
-
if (!store.observe || !store.compareAndApply) throw new Error("iMessage catchup cursor persistence requires plugin-state comparison support.");
|
|
337
324
|
const key = resolveIMessageCatchupCursorKey(accountId);
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}
|
|
325
|
+
return await cursorWriteQueue.enqueue(key, async () => {
|
|
326
|
+
const store = openCatchupCursorStore();
|
|
327
|
+
const next = decide(await store.lookup(key));
|
|
328
|
+
if (!next) return false;
|
|
329
|
+
await store.register(key, next);
|
|
330
|
+
return true;
|
|
331
|
+
});
|
|
345
332
|
}
|
|
346
333
|
function clampInt(value, min, max, fallback) {
|
|
347
334
|
return resolveIntegerOption(value, fallback, {
|
|
@@ -360,31 +347,18 @@ function resolveCatchupConfig(raw) {
|
|
|
360
347
|
}
|
|
361
348
|
function decideLiveCatchupCursorAdvance(existingValue, next, maxFailureRetries) {
|
|
362
349
|
const cursor = normalizeIMessageCatchupCursor(existingValue);
|
|
363
|
-
if (cursor && next.lastSeenRowid <= cursor.lastSeenRowid) return
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
};
|
|
371
|
-
return {
|
|
372
|
-
operation: "update",
|
|
373
|
-
action: "set",
|
|
374
|
-
value: buildIMessageCatchupCursor({
|
|
375
|
-
lastSeenMs: Math.max(cursor?.lastSeenMs ?? next.lastSeenMs, next.lastSeenMs),
|
|
376
|
-
lastSeenRowid: next.lastSeenRowid,
|
|
377
|
-
failureRetries: cursor?.failureRetries
|
|
378
|
-
}, next.updatedAt)
|
|
379
|
-
};
|
|
350
|
+
if (cursor && next.lastSeenRowid <= cursor.lastSeenRowid) return;
|
|
351
|
+
if (Object.values(cursor?.failureRetries ?? {}).some((count) => count < maxFailureRetries)) return;
|
|
352
|
+
return buildIMessageCatchupCursor({
|
|
353
|
+
lastSeenMs: Math.max(cursor?.lastSeenMs ?? next.lastSeenMs, next.lastSeenMs),
|
|
354
|
+
lastSeenRowid: next.lastSeenRowid,
|
|
355
|
+
failureRetries: cursor?.failureRetries
|
|
356
|
+
}, next.updatedAt);
|
|
380
357
|
}
|
|
381
358
|
async function advanceIMessageCatchupCursor(accountId, next, config) {
|
|
382
359
|
if (!Number.isFinite(next.lastSeenMs) || !Number.isFinite(next.lastSeenRowid)) return false;
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const maxFailureRetries = config.maxFailureRetries;
|
|
386
|
-
return updateIMessageCatchupCursor(accountId, (existing) => decideLiveCatchupCursorAdvance(existing, cursor, maxFailureRetries));
|
|
387
|
-
});
|
|
360
|
+
const cursor = buildIMessageCatchupCursor(next, Date.now());
|
|
361
|
+
return await updateIMessageCatchupCursor(accountId, (existing) => decideLiveCatchupCursorAdvance(existing, cursor, config.maxFailureRetries));
|
|
388
362
|
}
|
|
389
363
|
async function performIMessageCatchup(params) {
|
|
390
364
|
const now = params.now ?? Date.now();
|
|
@@ -1665,8 +1639,7 @@ async function resolveIMessageInboundDecision(params) {
|
|
|
1665
1639
|
...selfChatLookup,
|
|
1666
1640
|
text: bodyText
|
|
1667
1641
|
})) {
|
|
1668
|
-
|
|
1669
|
-
params.logVerbose?.(`imessage: dropping self-chat reflected duplicate: "${preview}"`);
|
|
1642
|
+
params.logVerbose?.("imessage: dropping self-chat reflected duplicate");
|
|
1670
1643
|
return {
|
|
1671
1644
|
kind: "drop",
|
|
1672
1645
|
reason: "self-chat echo"
|
|
@@ -1681,7 +1654,7 @@ async function resolveIMessageInboundDecision(params) {
|
|
|
1681
1654
|
messageIds: inboundMessageIds,
|
|
1682
1655
|
includePendingText: isSelfChat
|
|
1683
1656
|
})) {
|
|
1684
|
-
params.logVerbose?.(`imessage: skipping echo message${inboundMessageId ? ` id=${inboundMessageId}` : ""}
|
|
1657
|
+
params.logVerbose?.(`imessage: skipping echo message${inboundMessageId ? ` id=${inboundMessageId}` : ""}`);
|
|
1685
1658
|
return {
|
|
1686
1659
|
kind: "drop",
|
|
1687
1660
|
reason: "echo"
|
|
@@ -2165,7 +2138,7 @@ function isHeicAttachment(attachmentPath, mimeType) {
|
|
|
2165
2138
|
return ext === ".heic" || ext === ".heif";
|
|
2166
2139
|
}
|
|
2167
2140
|
async function readAttachmentBuffer(params) {
|
|
2168
|
-
await using opened = await
|
|
2141
|
+
await using opened = await openLocalFileSafely({ filePath: params.attachmentPath });
|
|
2169
2142
|
if (opened.stat.size > params.maxBytes) throw new Error(`attachment exceeds ${Math.round(params.maxBytes / 1048576)}MB limit`);
|
|
2170
2143
|
if (params.allowedRoots) {
|
|
2171
2144
|
const canonicalRoots = [];
|
|
@@ -2185,14 +2158,13 @@ async function readAttachmentBuffer(params) {
|
|
|
2185
2158
|
throw error;
|
|
2186
2159
|
});
|
|
2187
2160
|
if (isHeicAttachment(params.attachmentPath, params.mimeType)) try {
|
|
2188
|
-
const convert = params.deps.convertHeicToJpeg;
|
|
2189
2161
|
return {
|
|
2190
2162
|
buffer: (await withTempWorkspace({
|
|
2191
2163
|
rootDir: resolvePreferredOpenClawTmpDir(),
|
|
2192
2164
|
prefix: "openclaw-imessage-heic-"
|
|
2193
2165
|
}, async (workspace) => {
|
|
2194
2166
|
const pinnedPath = await workspace.write("attachment.heic", buffer);
|
|
2195
|
-
return
|
|
2167
|
+
return await loadWebMedia(pinnedPath, {
|
|
2196
2168
|
maxBytes: params.maxBytes,
|
|
2197
2169
|
localRoots: [workspace.dir]
|
|
2198
2170
|
});
|
|
@@ -2211,7 +2183,6 @@ async function readAttachmentBuffer(params) {
|
|
|
2211
2183
|
}
|
|
2212
2184
|
async function stageIMessageAttachments(attachments, params) {
|
|
2213
2185
|
const deps = params.deps ?? {};
|
|
2214
|
-
const save = deps.saveMediaBuffer ?? saveMediaBuffer;
|
|
2215
2186
|
const staged = [];
|
|
2216
2187
|
let unavailableCount = 0;
|
|
2217
2188
|
for (const attachment of attachments) {
|
|
@@ -2229,7 +2200,7 @@ async function stageIMessageAttachments(attachments, params) {
|
|
|
2229
2200
|
allowedRoots: params.allowedRoots,
|
|
2230
2201
|
deps
|
|
2231
2202
|
});
|
|
2232
|
-
const saved = await
|
|
2203
|
+
const saved = await saveMediaBuffer(media.buffer, media.contentType, "inbound", params.maxBytes, media.originalFilename);
|
|
2233
2204
|
const contentType = saved.contentType ?? media.contentType;
|
|
2234
2205
|
staged.push({
|
|
2235
2206
|
path: saved.path,
|
|
@@ -2324,7 +2295,7 @@ function enqueueIMessageReactionSystemEvent(params) {
|
|
|
2324
2295
|
const { decision, runtime } = params;
|
|
2325
2296
|
const queued = enqueueRoutedSystemEvent(decision.text, decision.route, { contextKey: decision.contextKey });
|
|
2326
2297
|
runtime.log?.(`imessage: reaction system event ${queued ? "queued" : "deduped"} session=${decision.route.sessionKey} target=${decision.reaction.targetGuid ?? "unknown"} action=${decision.reaction.action} emoji=${decision.reaction.emoji}`);
|
|
2327
|
-
params.logVerbose?.(
|
|
2298
|
+
params.logVerbose?.("imessage: reaction event enqueued");
|
|
2328
2299
|
return queued;
|
|
2329
2300
|
}
|
|
2330
2301
|
//#endregion
|
|
@@ -2335,8 +2306,9 @@ const RECOVERY_CURSOR_STORE_OPTIONS = {
|
|
|
2335
2306
|
};
|
|
2336
2307
|
const LEGACY_CATCHUP_CURSOR_NAMESPACE = "imessage.catchup-cursors";
|
|
2337
2308
|
const LEGACY_CATCHUP_CURSOR_MAX_ENTRIES = 256;
|
|
2309
|
+
let cursorWrites = Promise.resolve();
|
|
2338
2310
|
function openRecoveryCursorStore() {
|
|
2339
|
-
return getIMessageRuntime().state.
|
|
2311
|
+
return getIMessageRuntime().state.openKeyedStoreV2(RECOVERY_CURSOR_STORE_OPTIONS);
|
|
2340
2312
|
}
|
|
2341
2313
|
function normalizeLocalDbPath(dbPath) {
|
|
2342
2314
|
let resolved = dbPath.trim();
|
|
@@ -2374,34 +2346,17 @@ function decideRecoveryCursorUpdate(current, update) {
|
|
|
2374
2346
|
} else if (current && current.lastRowid >= update.rowid) return;
|
|
2375
2347
|
return { lastRowid: update.rowid };
|
|
2376
2348
|
}
|
|
2377
|
-
|
|
2378
|
-
const
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
const
|
|
2382
|
-
if (!
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
});
|
|
2389
|
-
return result;
|
|
2390
|
-
}
|
|
2391
|
-
const observe = store.observe.bind(store);
|
|
2392
|
-
const compareAndApply = store.compareAndApply.bind(store);
|
|
2393
|
-
let observation = await observe(key);
|
|
2394
|
-
for (;;) {
|
|
2395
|
-
const next = decideRecoveryCursorUpdate(observation.value, update);
|
|
2396
|
-
if (!next) return observation.value;
|
|
2397
|
-
const result = await compareAndApply(key, observation.comparison, {
|
|
2398
|
-
operation: "update",
|
|
2399
|
-
action: "set",
|
|
2400
|
-
value: next
|
|
2401
|
-
});
|
|
2402
|
-
if (result.status !== "conflict") return next;
|
|
2403
|
-
observation = result.current;
|
|
2404
|
-
}
|
|
2349
|
+
function applyRecoveryCursorUpdate(key, update) {
|
|
2350
|
+
const write = cursorWrites.then(async () => {
|
|
2351
|
+
const store = openRecoveryCursorStore();
|
|
2352
|
+
const current = await store.lookup(key);
|
|
2353
|
+
const next = decideRecoveryCursorUpdate(current, update);
|
|
2354
|
+
if (!next) return current;
|
|
2355
|
+
await store.register(key, next);
|
|
2356
|
+
return next;
|
|
2357
|
+
});
|
|
2358
|
+
cursorWrites = write.catch(() => {});
|
|
2359
|
+
return write;
|
|
2405
2360
|
}
|
|
2406
2361
|
async function readRecoveryCursor(accountId, dbIdentity) {
|
|
2407
2362
|
try {
|
|
@@ -2422,7 +2377,7 @@ async function readRecoveryCursor(accountId, dbIdentity) {
|
|
|
2422
2377
|
}
|
|
2423
2378
|
async function migrateLegacyCatchupCursor(accountId, dbIdentity) {
|
|
2424
2379
|
try {
|
|
2425
|
-
const legacy = getIMessageRuntime().state.
|
|
2380
|
+
const legacy = getIMessageRuntime().state.openKeyedStoreV2({
|
|
2426
2381
|
namespace: LEGACY_CATCHUP_CURSOR_NAMESPACE,
|
|
2427
2382
|
maxEntries: LEGACY_CATCHUP_CURSOR_MAX_ENTRIES
|
|
2428
2383
|
});
|
|
@@ -2601,7 +2556,7 @@ const IMESSAGE_THROTTLED_DIAGNOSTIC_DROP_REASONS = /* @__PURE__ */ new Set(["fro
|
|
|
2601
2556
|
async function monitorIMessageProvider(opts) {
|
|
2602
2557
|
const { scheduler } = opts;
|
|
2603
2558
|
const runtime = opts.runtime ?? createNonExitingRuntime();
|
|
2604
|
-
const cfg = opts.config ??
|
|
2559
|
+
const cfg = opts.config ?? await captureRuntimeConfigAsyncReader()();
|
|
2605
2560
|
const readConfig = createRuntimeConfigReader(cfg);
|
|
2606
2561
|
const accountInfo = resolveIMessageAccount({
|
|
2607
2562
|
cfg,
|
|
@@ -3004,7 +2959,7 @@ async function monitorIMessageProvider(opts) {
|
|
|
3004
2959
|
const configuredTypingMode = resolveAgentConfig(cfg, decision.route.agentId)?.typingMode ?? cfg.agents?.defaults?.typingMode;
|
|
3005
2960
|
const sendPolicy = resolveSendPolicy({
|
|
3006
2961
|
cfg,
|
|
3007
|
-
entry:
|
|
2962
|
+
entry: await getSessionEntryAsync({
|
|
3008
2963
|
storePath,
|
|
3009
2964
|
sessionKey: decision.route.sessionKey
|
|
3010
2965
|
}),
|
|
@@ -3266,14 +3221,10 @@ async function monitorIMessageProvider(opts) {
|
|
|
3266
3221
|
logVerboseMessage: logVerbose
|
|
3267
3222
|
});
|
|
3268
3223
|
};
|
|
3269
|
-
const resolveApprovalControlConversation = (message) => {
|
|
3270
|
-
const actorHandle = resolveIMessageApprovalControlActor(message);
|
|
3271
|
-
return actorHandle ? buildIMessageApprovalConversationKeyForInbound(message, actorHandle) : null;
|
|
3272
|
-
};
|
|
3273
3224
|
const ingress = createIMessageDurableIngress({
|
|
3274
3225
|
accountId: accountInfo.accountId,
|
|
3275
3226
|
runtime,
|
|
3276
|
-
dispatchPriority: async (message,
|
|
3227
|
+
dispatchPriority: async (message, _lifecycle, receivedAt, provenance) => {
|
|
3277
3228
|
const bodyText = (message.text ?? "").trim();
|
|
3278
3229
|
const isApprovalCommand = /^\/approve(?:@[^\s]+)?(?:\s|$)/i.test(bodyText);
|
|
3279
3230
|
if (!(isApprovalCommand || message.poll?.kind === "vote" || Boolean(resolveIMessageReactionContext(message, bodyText)))) return;
|
|
@@ -3284,16 +3235,7 @@ async function monitorIMessageProvider(opts) {
|
|
|
3284
3235
|
await handleMessageNow(repairedMessage);
|
|
3285
3236
|
return { kind: "completed" };
|
|
3286
3237
|
}
|
|
3287
|
-
|
|
3288
|
-
while (true) {
|
|
3289
|
-
if (await maybeHandleApprovalControl(repairedMessage)) return { kind: "completed" };
|
|
3290
|
-
if (!conversation) return;
|
|
3291
|
-
if (!await iMessageApprovalControlBindings.wait({
|
|
3292
|
-
accountId: accountInfo.accountId,
|
|
3293
|
-
conversation,
|
|
3294
|
-
abortSignal: lifecycle.abortSignal
|
|
3295
|
-
})) return await maybeHandleApprovalControl(repairedMessage) ? { kind: "completed" } : void 0;
|
|
3296
|
-
}
|
|
3238
|
+
return await maybeHandleApprovalControl(repairedMessage) ? { kind: "completed" } : void 0;
|
|
3297
3239
|
},
|
|
3298
3240
|
dispatch: async (message, ingressLifecycle, receivedAt, provenance) => {
|
|
3299
3241
|
if (suppressStaleIngress(message, receivedAt, provenance)) return { kind: "completed" };
|
|
@@ -158,13 +158,13 @@ const imessageReplyCacheByMessageId = /* @__PURE__ */ new Map();
|
|
|
158
158
|
const imessageShortIdToUuid = /* @__PURE__ */ new Map();
|
|
159
159
|
let imessageShortIdCounter = 0;
|
|
160
160
|
function openReplyCacheStore() {
|
|
161
|
-
return getIMessageRuntime().state.
|
|
161
|
+
return getIMessageRuntime().state.openKeyedStoreV2({
|
|
162
162
|
namespace: IMESSAGE_REPLY_CACHE_NAMESPACE,
|
|
163
163
|
maxEntries: IMESSAGE_REPLY_CACHE_MAX_ENTRIES
|
|
164
164
|
});
|
|
165
165
|
}
|
|
166
166
|
function openReplyCacheCounterStore() {
|
|
167
|
-
return getIMessageRuntime().state.
|
|
167
|
+
return getIMessageRuntime().state.openKeyedStoreV2({
|
|
168
168
|
namespace: IMESSAGE_REPLY_CACHE_COUNTER_NAMESPACE,
|
|
169
169
|
maxEntries: 1
|
|
170
170
|
});
|
|
@@ -193,8 +193,7 @@ async function hydrateFromStoreOnce() {
|
|
|
193
193
|
hydration ??= (async () => {
|
|
194
194
|
try {
|
|
195
195
|
hydrateCounter(await openReplyCacheCounterStore().lookup(IMESSAGE_REPLY_CACHE_COUNTER_KEY));
|
|
196
|
-
|
|
197
|
-
if (!hydrated) hydrateRows(entries.map(({ value }) => value));
|
|
196
|
+
hydrateRows((await openReplyCacheStore().entries()).map(({ value }) => value));
|
|
198
197
|
} catch (err) {
|
|
199
198
|
reportPersistenceFailure("read", err);
|
|
200
199
|
} finally {
|
|
@@ -203,23 +202,6 @@ async function hydrateFromStoreOnce() {
|
|
|
203
202
|
})();
|
|
204
203
|
await hydration;
|
|
205
204
|
}
|
|
206
|
-
function hydrateFromStoreOnceSync() {
|
|
207
|
-
if (hydrated) return;
|
|
208
|
-
hydrated = true;
|
|
209
|
-
try {
|
|
210
|
-
const state = getIMessageRuntime().state;
|
|
211
|
-
hydrateCounter(state.openSyncKeyedStore({
|
|
212
|
-
namespace: IMESSAGE_REPLY_CACHE_COUNTER_NAMESPACE,
|
|
213
|
-
maxEntries: 1
|
|
214
|
-
}).lookup(IMESSAGE_REPLY_CACHE_COUNTER_KEY));
|
|
215
|
-
hydrateRows(state.openSyncKeyedStore({
|
|
216
|
-
namespace: IMESSAGE_REPLY_CACHE_NAMESPACE,
|
|
217
|
-
maxEntries: IMESSAGE_REPLY_CACHE_MAX_ENTRIES
|
|
218
|
-
}).entries().map(({ value }) => value));
|
|
219
|
-
} catch (err) {
|
|
220
|
-
reportPersistenceFailure("read", err);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
205
|
async function persistReplyCacheEntry(entry) {
|
|
224
206
|
const ttlMs = remainingTtlMs(entry.timestamp);
|
|
225
207
|
if (!ttlMs) return;
|
|
@@ -379,11 +361,6 @@ function resolveCachedResourceBinding(messageId, ctx) {
|
|
|
379
361
|
if (entry.accountId !== ctx.accountId) return "mismatch";
|
|
380
362
|
return resolveIMessageChatMatch(entry, ctx);
|
|
381
363
|
}
|
|
382
|
-
/** @deprecated Used only by hosts without asynchronous conversation matching. */
|
|
383
|
-
function isIMessageCurrentMessageInChat(params) {
|
|
384
|
-
hydrateFromStoreOnceSync();
|
|
385
|
-
return isCurrentMessageInChat(params);
|
|
386
|
-
}
|
|
387
364
|
async function isIMessageCurrentMessageInChatAsync(params) {
|
|
388
365
|
await hydrateFromStoreOnce();
|
|
389
366
|
return isCurrentMessageInChat(params);
|
|
@@ -762,4 +739,4 @@ async function createIMessageRpcClient(opts = {}) {
|
|
|
762
739
|
return client;
|
|
763
740
|
}
|
|
764
741
|
//#endregion
|
|
765
|
-
export { resolveIMessageDirectChatService as
|
|
742
|
+
export { resolveIMessageDirectChatService as S, DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS as _, isIMessageCurrentMessageInChatAsync as a, isIMessageEmailChatIdentifier as b, resolveIMessageCachedResourceBinding as c, IMESSAGE_SENT_ECHOES_NAMESPACE as d, IMESSAGE_SENT_ECHOES_TTL_MS as f, resolveIMessageSentEchoEntryKey as g, resolveIMessageEchoMediaKey as h, findLatestIMessageEntryForChat as i, resolveIMessageMessageId as l, resolveIMessageCatchupCursorKey as m, createIMessageRpcClient as n, isKnownFromMeIMessageTarget as o, capFailureRetriesMap as p, runIMessageCliJsonCommand as r, rememberIMessageReplyCache as s, IMessageRpcRequestError as t, IMESSAGE_CATCHUP_CURSOR_NAMESPACE as u, DEFAULT_IMESSAGE_SEND_TIMEOUT_MS as v, normalizeDirectChatIdentifier as x, chatContextFromIMessageTarget as y };
|
package/dist/.setup/{conversation-bindings-GDQ_Laxj.mjs → conversation-bindings-DR-dbHjs.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAccountScopedConversationBindingManager, resetAccountScopedConversationBindingsForTests } from "openclaw/plugin-sdk/thread-bindings-runtime";
|
|
1
|
+
import { createAccountScopedConversationBindingManager, createAccountScopedConversationBindingManagerV2, resetAccountScopedConversationBindingsForTests } from "openclaw/plugin-sdk/thread-bindings-runtime";
|
|
2
2
|
//#region extensions/imessage/src/conversation-bindings.ts
|
|
3
3
|
const IMESSAGE_CONVERSATION_BINDINGS_STATE_KEY = Symbol.for("openclaw.imessageConversationBindingsState");
|
|
4
4
|
function toSessionBindingTargetKind(raw) {
|
|
@@ -7,6 +7,7 @@ function toSessionBindingTargetKind(raw) {
|
|
|
7
7
|
function toIMessageTargetKind(raw) {
|
|
8
8
|
return raw === "subagent" ? "subagent" : "acp";
|
|
9
9
|
}
|
|
10
|
+
/** @deprecated Use createIMessageConversationBindingManagerV2; final compatibility day: 2026-12-31. */
|
|
10
11
|
function createIMessageConversationBindingManager(params) {
|
|
11
12
|
return createAccountScopedConversationBindingManager({
|
|
12
13
|
channel: "imessage",
|
|
@@ -17,8 +18,19 @@ function createIMessageConversationBindingManager(params) {
|
|
|
17
18
|
toSessionBindingTargetKind
|
|
18
19
|
});
|
|
19
20
|
}
|
|
21
|
+
/** Worker-owned manager used by bundled channel startup. */
|
|
22
|
+
function createIMessageConversationBindingManagerV2(params) {
|
|
23
|
+
return createAccountScopedConversationBindingManagerV2({
|
|
24
|
+
channel: "imessage",
|
|
25
|
+
cfg: params.cfg,
|
|
26
|
+
accountId: params.accountId,
|
|
27
|
+
stateKey: IMESSAGE_CONVERSATION_BINDINGS_STATE_KEY,
|
|
28
|
+
toStoredTargetKind: toIMessageTargetKind,
|
|
29
|
+
toSessionBindingTargetKind
|
|
30
|
+
});
|
|
31
|
+
}
|
|
20
32
|
const testing = { resetIMessageConversationBindingsForTests() {
|
|
21
33
|
resetAccountScopedConversationBindingsForTests({ stateKey: IMESSAGE_CONVERSATION_BINDINGS_STATE_KEY });
|
|
22
34
|
} };
|
|
23
35
|
//#endregion
|
|
24
|
-
export {
|
|
36
|
+
export { createIMessageConversationBindingManagerV2 as n, testing as r, createIMessageConversationBindingManager as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-BBjsoOtd.mjs";
|
|
2
|
-
import { i as normalizeIMessageGuid } from "./actions-
|
|
3
|
-
import { t as resolveIMessageReactionContext } from "./reaction-context-
|
|
2
|
+
import { i as normalizeIMessageGuid } from "./actions-CZHoxlpi.mjs";
|
|
3
|
+
import { t as resolveIMessageReactionContext } from "./reaction-context-DbYCapmR.mjs";
|
|
4
4
|
import { createQuestionReactionTargetStore, questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
|
|
5
5
|
//#region extensions/imessage/src/question-reactions.ts
|
|
6
6
|
var question_reactions_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { p as resolveLocalIMessageChatDbPath } from "./accounts-DacCvDBt.mjs";
|
|
2
|
-
import { b as
|
|
2
|
+
import { b as isIMessageEmailChatIdentifier, c as resolveIMessageCachedResourceBinding, l as resolveIMessageMessageId, y as chatContextFromIMessageTarget } from "./client-BEZ_gLk-.mjs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { normalizeScpRemoteHost } from "openclaw/plugin-sdk/host-runtime";
|
|
5
5
|
import { createActionGate } from "openclaw/plugin-sdk/channel-actions";
|
|
@@ -157,7 +157,7 @@ function assertSafeIMessageOutboundMarkup(text) {
|
|
|
157
157
|
cursor += suffix.length;
|
|
158
158
|
if (PRIVATE_PROVIDER_TAG_NAME_SET.has(candidate) && /[\s/>]/.test(text.charAt(cursor))) throw new Error("iMessage outbound ambiguous nested HTML is not allowed");
|
|
159
159
|
if (!PRIVATE_PROVIDER_TAG_NAMES.some((name) => name.startsWith(candidate))) break;
|
|
160
|
-
if (depth + 1 >= MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES && (OPAQUE_PRIVATE_RUNTIME_CONTEXT_BLOCK_RE.test(text.slice(cursor)) || REMOVABLE_PRIVATE_MARKUP_TAG_RE.test(text.slice(cursor)))) throw new Error("iMessage outbound runtime
|
|
160
|
+
if (depth + 1 >= MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES && (OPAQUE_PRIVATE_RUNTIME_CONTEXT_BLOCK_RE.test(text.slice(cursor)) || REMOVABLE_PRIVATE_MARKUP_TAG_RE.test(text.slice(cursor)))) throw new Error("iMessage outbound runtime markup exceeded its limit");
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
}
|
|
@@ -166,14 +166,14 @@ function findIMessageMarkupEnd(text, start, kind, contentOffset = 2) {
|
|
|
166
166
|
let quote;
|
|
167
167
|
let bracketDepth = 0;
|
|
168
168
|
for (let index = start + contentOffset; index <= text.length - terminator.length; index += 1) {
|
|
169
|
-
if (kind === "private" && index - start > MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES ** 2) throw new Error("iMessage outbound runtime
|
|
169
|
+
if (kind === "private" && index - start > MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES ** 2) throw new Error("iMessage outbound runtime markup exceeded its limit");
|
|
170
170
|
const character = text[index];
|
|
171
171
|
if (quote) {
|
|
172
172
|
if (character === quote) quote = void 0;
|
|
173
173
|
} else if (character === "'" || character === "\"") quote = character;
|
|
174
174
|
else if (kind === "declaration" && character === "[") bracketDepth += 1;
|
|
175
175
|
else if (kind === "declaration" && character === "]" && bracketDepth > 0) bracketDepth -= 1;
|
|
176
|
-
else if (kind === "private" && character === "<") throw new Error("iMessage outbound runtime
|
|
176
|
+
else if (kind === "private" && character === "<") throw new Error("iMessage outbound runtime markup is malformed");
|
|
177
177
|
else if (bracketDepth === 0 && text.startsWith(terminator, index)) return index + terminator.length;
|
|
178
178
|
}
|
|
179
179
|
return -1;
|
|
@@ -211,7 +211,7 @@ function stripIMessageBalancedPrivateRuntimeBlocks(text, verifyProtectedRoles) {
|
|
|
211
211
|
end: closing?.end ?? text.length,
|
|
212
212
|
terminated: Boolean(closing)
|
|
213
213
|
});
|
|
214
|
-
if (rawTextHtml.length > MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES ** 2) throw new Error("iMessage outbound runtime
|
|
214
|
+
if (rawTextHtml.length > MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES ** 2) throw new Error("iMessage outbound runtime markup exceeded its limit");
|
|
215
215
|
}
|
|
216
216
|
const opaqueHtml = [];
|
|
217
217
|
for (let cursor = 0; cursor < text.length;) {
|
|
@@ -239,7 +239,7 @@ function stripIMessageBalancedPrivateRuntimeBlocks(text, verifyProtectedRoles) {
|
|
|
239
239
|
cursor = start + 1;
|
|
240
240
|
continue;
|
|
241
241
|
}
|
|
242
|
-
if (opaqueHtml.length >= MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES ** 2) throw new Error("iMessage outbound runtime
|
|
242
|
+
if (opaqueHtml.length >= MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES ** 2) throw new Error("iMessage outbound runtime markup exceeded its limit");
|
|
243
243
|
const terminated = end >= 0;
|
|
244
244
|
const regionEnd = terminated ? end + delimiterLength : text.length;
|
|
245
245
|
opaqueHtml.push({
|
|
@@ -273,15 +273,15 @@ function stripIMessageBalancedPrivateRuntimeBlocks(text, verifyProtectedRoles) {
|
|
|
273
273
|
enclosingBlock.sawNested = true;
|
|
274
274
|
continue;
|
|
275
275
|
}
|
|
276
|
-
if (enclosingBlock?.codeRegion && enclosingBlock.codeRegion !== codeRegion) throw new Error("iMessage outbound runtime
|
|
277
|
-
if (++scannedTags > MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES ** 2) throw new Error("iMessage outbound runtime
|
|
276
|
+
if (enclosingBlock?.codeRegion && enclosingBlock.codeRegion !== codeRegion) throw new Error("iMessage outbound runtime markup is malformed");
|
|
277
|
+
if (++scannedTags > MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES ** 2) throw new Error("iMessage outbound runtime markup exceeded its limit");
|
|
278
278
|
const end = findIMessageMarkupEnd(text, start, "private", token[0].length);
|
|
279
|
-
if (end < 0) throw new Error("iMessage outbound runtime
|
|
279
|
+
if (end < 0) throw new Error("iMessage outbound runtime markup is malformed");
|
|
280
280
|
if (enclosingBlock?.codeRegion && enclosingBlock.codeRegion === codeRegion) {
|
|
281
281
|
if (!enclosingBlock.nestedCodeRegions) {
|
|
282
|
-
if (codeRegion.end - enclosingBlock.end > MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES ** 3) throw new Error("iMessage outbound runtime
|
|
282
|
+
if (codeRegion.end - enclosingBlock.end > MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES ** 3) throw new Error("iMessage outbound runtime markup exceeded its limit");
|
|
283
283
|
enclosingBlock.nestedCodeRegions = findCodeRegions(text.slice(enclosingBlock.end, codeRegion.end));
|
|
284
|
-
if (enclosingBlock.nestedCodeRegions.length > MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES ** 2) throw new Error("iMessage outbound runtime
|
|
284
|
+
if (enclosingBlock.nestedCodeRegions.length > MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES ** 2) throw new Error("iMessage outbound runtime markup exceeded its limit");
|
|
285
285
|
}
|
|
286
286
|
if (isInsideCode(start - enclosingBlock.end, enclosingBlock.nestedCodeRegions)) {
|
|
287
287
|
enclosingBlock.sawNested = true;
|
|
@@ -302,7 +302,7 @@ function stripIMessageBalancedPrivateRuntimeBlocks(text, verifyProtectedRoles) {
|
|
|
302
302
|
}
|
|
303
303
|
const name = (token[2] ?? "").toLowerCase();
|
|
304
304
|
if (!closing) {
|
|
305
|
-
if (openBlocks.length >= MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES) throw new Error("iMessage outbound runtime
|
|
305
|
+
if (openBlocks.length >= MAX_PRIVATE_MARKDOWN_UNWRAP_PASSES) throw new Error("iMessage outbound runtime markup exceeded its limit");
|
|
306
306
|
const parent = openBlocks.at(-1);
|
|
307
307
|
if (parent) parent.sawNested = true;
|
|
308
308
|
openBlocks.push({
|
|
@@ -322,14 +322,14 @@ function stripIMessageBalancedPrivateRuntimeBlocks(text, verifyProtectedRoles) {
|
|
|
322
322
|
});
|
|
323
323
|
continue;
|
|
324
324
|
}
|
|
325
|
-
if (opening.name !== name) throw new Error("iMessage outbound runtime
|
|
325
|
+
if (opening.name !== name) throw new Error("iMessage outbound runtime markup is malformed");
|
|
326
326
|
openBlocks.pop();
|
|
327
327
|
completedBlocks.push({
|
|
328
328
|
start: opening.start,
|
|
329
329
|
end
|
|
330
330
|
});
|
|
331
331
|
}
|
|
332
|
-
if (openBlocks.length > 1 || openBlocks[0]?.sawNested || openBlocks[0] && [...opaqueHtml, ...rawTextHtml].some((region) => !region.terminated && openBlocks[0].start < region.start)) throw new Error("iMessage outbound runtime
|
|
332
|
+
if (openBlocks.length > 1 || openBlocks[0]?.sawNested || openBlocks[0] && [...opaqueHtml, ...rawTextHtml].some((region) => !region.terminated && openBlocks[0].start < region.start)) throw new Error("iMessage outbound runtime markup is malformed");
|
|
333
333
|
const orphan = openBlocks[0];
|
|
334
334
|
if (orphan) completedBlocks.push({
|
|
335
335
|
start: orphan.start,
|
|
@@ -368,7 +368,7 @@ function stripIMessagePrivateRuntimeScaffolding(text, verifyProtectedRoles) {
|
|
|
368
368
|
}
|
|
369
369
|
if (!changed) return current;
|
|
370
370
|
}
|
|
371
|
-
throw new Error("iMessage outbound runtime
|
|
371
|
+
throw new Error("iMessage outbound runtime markup exceeded its limit");
|
|
372
372
|
}
|
|
373
373
|
function sanitizeIMessageAssistantVisibleText(text, verifyProtectedRoles) {
|
|
374
374
|
const cleaned = stripIMessagePrivateRuntimeScaffolding(text, verifyProtectedRoles);
|