@openclaw/imessage 2026.9.6 → 2026.9.8
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/assets/icon.png +0 -0
- package/dist/.setup/{accounts-CUxZrTcY.mjs → accounts-nzcU0cq2.mjs} +3 -6
- package/dist/.setup/{actions.runtime-D0zG_96v.mjs → actions.runtime-DdBN29zj.mjs} +3 -5
- package/dist/.setup/{api-RZv6yXul.mjs → api-B9Qx21G-.mjs} +6 -5
- package/dist/.setup/{api-VLVcFh7r.mjs → api-D2S6FhGw.mjs} +7 -7
- package/dist/.setup/{approval-handler.runtime-Bv5_XgNr.mjs → approval-handler.runtime-DKSq0DWq.mjs} +8 -8
- package/dist/.setup/{approval-reactions-D6RFg6lU.mjs → approval-reactions-Bp33xc83.mjs} +5 -5
- package/dist/.setup/{channel-BLTaKdSK.mjs → channel-9fyvuN_p.mjs} +97 -152
- package/dist/.setup/channel.runtime-n-MPKL8k.mjs +92 -0
- package/dist/.setup/{config-schema-CCbTcJEV.mjs → config-schema-4Q3_EqYt.mjs} +9 -1
- package/dist/.setup/{group-policy-Cjztkquv.mjs → group-policy-90pw4tyG.mjs} +48 -334
- package/dist/.setup/{media-contract-DKJK7rh3.mjs → media-contract-CagwSMvo.mjs} +1 -1
- package/dist/.setup/{message-tool-api-pvlcOJPG.mjs → message-tool-api-D032l82H.mjs} +3 -18
- package/dist/.setup/{monitor-BJ3Ozi6I.mjs → monitor-fv9nRuTH.mjs} +211 -280
- package/dist/.setup/{question-reactions-lm8OxWbb.mjs → question-reactions-Cy-dmU_j.mjs} +1 -1
- package/dist/.setup/{remote-file-Bye99O-C.mjs → remote-file-DRPCaVmg.mjs} +70 -21
- package/dist/.setup/rolldown-runtime-BBjsoOtd.mjs +27 -0
- package/dist/.setup/{sanitize-outbound-sJPF2DVM.mjs → sanitize-outbound-3MLljgtY.mjs} +86 -24
- package/dist/.setup/{send-odAfTQ2J.mjs → send-Cu9nl757.mjs} +28 -112
- package/dist/.setup/setup-core-8MDdYHj5.mjs +226 -0
- package/dist/.setup/{channel.runtime---s2k4YN.mjs → setup-surface-tGXFDdWh.mjs} +6 -103
- package/dist/.setup/state-migrations-B-Q7bO0Y.mjs +47 -0
- package/dist/.setup/{targets-Cc9vthzI.mjs → targets-BicBiYsM.mjs} +10 -16
- package/dist/api.js +7 -7
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/contract-api.js +1 -1
- package/dist/doctor-contract-api.js +168 -7
- package/dist/media-contract-api.js +1 -1
- package/dist/message-tool-api.js +1 -1
- package/dist/runtime-api.js +6 -6
- package/dist/setup-entry.js +1 -1
- package/dist/src/chat-db.worker.js +6 -1
- package/node_modules/typebox/build/compile/code.mjs +1 -2
- package/node_modules/typebox/build/compile/validator.mjs +5 -1
- package/node_modules/typebox/build/format/iri.mjs +16 -9
- package/node_modules/typebox/build/guard/emit.mjs +2 -2
- package/node_modules/typebox/build/guard/guard.d.mts +7 -5
- package/node_modules/typebox/build/guard/guard.mjs +14 -9
- package/node_modules/typebox/build/guard/index.mjs +6 -0
- package/node_modules/typebox/build/guard/unicode/unicode.d.mts +6 -0
- package/node_modules/typebox/build/guard/unicode/unicode.mjs +35 -0
- package/node_modules/typebox/build/guard/{string.mjs → unicode/unicode_segment.mjs} +16 -19
- package/node_modules/typebox/build/schema/build.mjs +2 -3
- package/node_modules/typebox/build/schema/engine/_pathing.d.mts +1 -0
- package/node_modules/typebox/build/schema/engine/_pathing.mjs +11 -0
- package/node_modules/typebox/build/schema/engine/_refine.mjs +13 -5
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dependencies.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dependentSchemas.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/format.mjs +9 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/properties.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/ref.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/ref.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/schema.mjs +24 -24
- package/node_modules/typebox/build/schema/parse.mjs +3 -0
- package/node_modules/typebox/build/schema/pointer/pointer.d.mts +1 -6
- package/node_modules/typebox/build/schema/pointer/pointer.mjs +47 -64
- package/node_modules/typebox/build/system/settings/internal.d.mts +2 -0
- package/node_modules/typebox/build/system/settings/internal.mjs +20 -0
- package/node_modules/typebox/build/system/settings/settings.d.mts +11 -0
- package/node_modules/typebox/build/system/settings/settings.mjs +14 -0
- package/node_modules/typebox/build/type/extends/inference.d.mts +1 -1
- package/node_modules/typebox/build/type/extends/inference.mjs +15 -2
- package/node_modules/typebox/build/type/extends/tuple.d.mts +2 -1
- package/node_modules/typebox/build/type/extends/tuple.mjs +21 -1
- package/node_modules/typebox/build/value/parse/parse.mjs +10 -4
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +3 -1
- package/openclaw.plugin.json +14 -0
- package/package.json +5 -5
- package/dist/.setup/rolldown-runtime-D7D4PA-g.mjs +0 -13
- package/dist/.setup/state-contract-DvahEY4X.mjs +0 -56
- package/dist/.setup/state-migrations-DIDzI99d.mjs +0 -277
- /package/node_modules/typebox/build/guard/{string.d.mts → unicode/unicode_segment.d.mts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-BBjsoOtd.mjs";
|
|
2
2
|
import { n as normalizeIMessageGuid, t as resolveIMessageReactionContext } from "./reaction-context-Br-vAJFp.mjs";
|
|
3
3
|
import { createQuestionReactionTargetStore, questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
|
|
4
4
|
//#region extensions/imessage/src/question-reactions.ts
|
|
@@ -1,13 +1,68 @@
|
|
|
1
|
-
import { p as resolveLocalIMessageChatDbPath } from "./accounts-
|
|
2
|
-
import {
|
|
1
|
+
import { p as resolveLocalIMessageChatDbPath } from "./accounts-nzcU0cq2.mjs";
|
|
2
|
+
import { T as isIMessageEmailChatIdentifier, m as resolveIMessageMessageId, p as resolveIMessageCachedResourceBinding, w as chatContextFromIMessageTarget } from "./sanitize-outbound-3MLljgtY.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";
|
|
6
|
-
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
6
|
+
import { createSubsystemLogger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
7
7
|
import { randomUUID } from "node:crypto";
|
|
8
|
-
import { runCommandWithTimeout } from "openclaw/plugin-sdk/process-runtime";
|
|
9
|
-
import {
|
|
8
|
+
import { resolveRuntimeWorkerUrl, runCommandWithTimeout } from "openclaw/plugin-sdk/process-runtime";
|
|
9
|
+
import { openSqliteWorkerStore } from "openclaw/plugin-sdk/sqlite-runtime";
|
|
10
10
|
import { sanitizeTempFileName } from "openclaw/plugin-sdk/temp-path";
|
|
11
|
+
//#region extensions/imessage/src/chat-db.ts
|
|
12
|
+
function openIMessageChatDbReader(databasePath) {
|
|
13
|
+
return openSqliteWorkerStore({
|
|
14
|
+
moduleUrl: resolveRuntimeWorkerUrl({
|
|
15
|
+
currentModuleUrl: import.meta.url,
|
|
16
|
+
sourceWorkerName: "chat-db.worker",
|
|
17
|
+
distWorkerPath: "extensions/imessage/src/chat-db.worker.js",
|
|
18
|
+
package: {
|
|
19
|
+
name: "@openclaw/imessage",
|
|
20
|
+
distWorkerPath: "src/chat-db.worker.js"
|
|
21
|
+
}
|
|
22
|
+
}),
|
|
23
|
+
databasePath,
|
|
24
|
+
existingOnly: true,
|
|
25
|
+
input: void 0
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async function resolveIMessageStartupRowidWatermark(dbPath) {
|
|
29
|
+
let store;
|
|
30
|
+
try {
|
|
31
|
+
store = await openIMessageChatDbReader(dbPath);
|
|
32
|
+
if (!store) throw new Error("Messages database is unavailable");
|
|
33
|
+
return await store.execute({
|
|
34
|
+
type: "startupWatermark",
|
|
35
|
+
input: void 0
|
|
36
|
+
});
|
|
37
|
+
} catch (err) {
|
|
38
|
+
logVerbose(`imessage: startup rowid watermark unavailable for db=${dbPath}: ${String(err)}`);
|
|
39
|
+
return null;
|
|
40
|
+
} finally {
|
|
41
|
+
await store?.close();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function withIMessageReceiptGuidReader(databasePath, use) {
|
|
45
|
+
let store;
|
|
46
|
+
let closed = false;
|
|
47
|
+
const read = async (command) => {
|
|
48
|
+
if (closed) throw new Error("iMessage receipt lookup is closed");
|
|
49
|
+
try {
|
|
50
|
+
store ??= await openIMessageChatDbReader(databasePath);
|
|
51
|
+
return store ? await store.execute(command) : null;
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
try {
|
|
57
|
+
return await use(read);
|
|
58
|
+
} finally {
|
|
59
|
+
closed = true;
|
|
60
|
+
try {
|
|
61
|
+
await store?.close();
|
|
62
|
+
} catch {}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
11
66
|
//#region extensions/imessage/src/message-resource-db.ts
|
|
12
67
|
function normalizeIMessageMessageGuidForLookup(messageId) {
|
|
13
68
|
const trimmed = messageId.trim();
|
|
@@ -53,7 +108,7 @@ function matchesAnyChatCandidate(stored, candidates) {
|
|
|
53
108
|
if (typeof stored !== "string") return false;
|
|
54
109
|
return candidates.some((candidate) => matchesChatCandidate(stored, candidate));
|
|
55
110
|
}
|
|
56
|
-
function checkIMessageResourceBinding(params) {
|
|
111
|
+
async function checkIMessageResourceBinding(params) {
|
|
57
112
|
const dbPath = resolveLocalIMessageChatDbPath(params);
|
|
58
113
|
if (!dbPath) return "unavailable";
|
|
59
114
|
const messageGuid = normalizeIMessageMessageGuidForLookup(params.messageId);
|
|
@@ -64,25 +119,19 @@ function checkIMessageResourceBinding(params) {
|
|
|
64
119
|
const chatId = params.chatContext.chatId;
|
|
65
120
|
const hasChatId = typeof chatId === "number" && Number.isSafeInteger(chatId) && chatId > 0;
|
|
66
121
|
if (!hasChatId && expectedChatGuids.length === 0 && expectedChatIdentifiers.length === 0 && identifierChatGuids.length === 0) return "unavailable";
|
|
67
|
-
let
|
|
122
|
+
let store;
|
|
68
123
|
try {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
JOIN chat_message_join cmj ON cmj.message_id = m.ROWID
|
|
75
|
-
JOIN chat c ON c.ROWID = cmj.chat_id
|
|
76
|
-
WHERE m.guid = ?`).all(messageGuid).map((row) => ({
|
|
77
|
-
chatId: row.chatId,
|
|
78
|
-
chatGuid: row.chatGuid,
|
|
79
|
-
chatIdentifier: row.chatIdentifier
|
|
124
|
+
store = await openIMessageChatDbReader(dbPath);
|
|
125
|
+
if (!store) return "unavailable";
|
|
126
|
+
return (await store.execute({
|
|
127
|
+
type: "messageChats",
|
|
128
|
+
input: { messageGuid }
|
|
80
129
|
})).some((row) => (!hasChatId || row.chatId === chatId) && (expectedChatGuids.length === 0 || matchesAnyChatCandidate(row.chatGuid, expectedChatGuids)) && (expectedChatIdentifiers.length === 0 || matchesAnyChatCandidate(row.chatIdentifier, expectedChatIdentifiers)) && (identifierChatGuids.length === 0 || matchesAnyChatCandidate(row.chatGuid, identifierChatGuids))) ? "match" : "mismatch";
|
|
81
130
|
} catch {
|
|
82
131
|
return "unavailable";
|
|
83
132
|
} finally {
|
|
84
133
|
try {
|
|
85
|
-
|
|
134
|
+
await store?.close();
|
|
86
135
|
} catch {}
|
|
87
136
|
}
|
|
88
137
|
}
|
|
@@ -131,7 +180,7 @@ async function authorizeIMessageResourceReference(params) {
|
|
|
131
180
|
if (cacheBinding === "unknown" && normalizedMessageId !== params.messageId.trim()) cacheBinding = await resolveIMessageCachedResourceBinding(normalizedMessageId, cacheContext);
|
|
132
181
|
if (cacheBinding === "match") return;
|
|
133
182
|
if (cacheBinding === "mismatch") throw new Error("iMessage message reference belongs to a different account or conversation.");
|
|
134
|
-
const providerBinding = params.hasExclusiveLocalDatabase ? checkIMessageResourceBinding(params) : "unavailable";
|
|
183
|
+
const providerBinding = params.hasExclusiveLocalDatabase ? await checkIMessageResourceBinding(params) : "unavailable";
|
|
135
184
|
if (providerBinding === "match") return;
|
|
136
185
|
if (providerBinding === "mismatch") throw new Error("iMessage message reference does not belong to the selected conversation.");
|
|
137
186
|
if (params.conversationReadOrigin === "direct-operator") return;
|
|
@@ -245,4 +294,4 @@ rm -rf -- ${remoteDir}
|
|
|
245
294
|
}
|
|
246
295
|
}
|
|
247
296
|
//#endregion
|
|
248
|
-
export { authorizeIMessageResourceReference as n, resolveAuthorizedIMessageReplyReference as r, withIMessageRemoteFile as t };
|
|
297
|
+
export { withIMessageReceiptGuidReader as a, resolveIMessageStartupRowidWatermark as i, authorizeIMessageResourceReference as n, resolveAuthorizedIMessageReplyReference as r, withIMessageRemoteFile as t };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __exportAll = (all, no_symbols) => {
|
|
7
|
+
let target = {};
|
|
8
|
+
for (var name in all) __defProp(target, name, {
|
|
9
|
+
get: all[name],
|
|
10
|
+
enumerable: true
|
|
11
|
+
});
|
|
12
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
13
|
+
return target;
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
17
|
+
key = keys[i];
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
19
|
+
get: ((k) => from[k]).bind(null, key),
|
|
20
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return to;
|
|
24
|
+
};
|
|
25
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
26
|
+
//#endregion
|
|
27
|
+
export { __reExport as n, __exportAll as t };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { u as expandIMessageUserPath } from "./accounts-
|
|
2
|
-
import { i as invalidateCachedIMessagePrivateApiStatus } from "./message-tool-api-
|
|
1
|
+
import { u as expandIMessageUserPath } from "./accounts-nzcU0cq2.mjs";
|
|
2
|
+
import { i as invalidateCachedIMessagePrivateApiStatus } from "./message-tool-api-D032l82H.mjs";
|
|
3
3
|
import { t as getIMessageRuntime } from "./runtime-Cza4CY5T.mjs";
|
|
4
|
-
import { a as IMESSAGE_REPLY_CACHE_NAMESPACE, f as resolveIMessageReplyCacheEntryKey, i as IMESSAGE_REPLY_CACHE_MAX_ENTRIES, n as IMESSAGE_REPLY_CACHE_COUNTER_KEY, o as IMESSAGE_REPLY_CACHE_TTL_MS, r as IMESSAGE_REPLY_CACHE_COUNTER_NAMESPACE } from "./state-contract-DvahEY4X.mjs";
|
|
5
4
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
5
|
import { normalizeE164 } from "openclaw/plugin-sdk/account-resolution";
|
|
7
6
|
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
8
|
import { runCommandWithTimeout } from "openclaw/plugin-sdk/process-runtime";
|
|
9
9
|
import { resolveUserPath } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
10
10
|
import { spawn } from "node:child_process";
|
|
@@ -98,6 +98,60 @@ function isPositiveIMessageChatMatch(cached, current) {
|
|
|
98
98
|
const DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS = 1e4;
|
|
99
99
|
const DEFAULT_IMESSAGE_SEND_TIMEOUT_MS = 18e4;
|
|
100
100
|
//#endregion
|
|
101
|
+
//#region extensions/imessage/src/state-contract.ts
|
|
102
|
+
const IMESSAGE_REPLY_CACHE_NAMESPACE = "imessage.reply-cache";
|
|
103
|
+
const IMESSAGE_REPLY_CACHE_MAX_ENTRIES = 2e3;
|
|
104
|
+
const IMESSAGE_REPLY_CACHE_COUNTER_NAMESPACE = "imessage.reply-cache-counter";
|
|
105
|
+
const IMESSAGE_REPLY_CACHE_COUNTER_KEY = "short-id-counter";
|
|
106
|
+
const IMESSAGE_REPLY_CACHE_TTL_MS = 216e5;
|
|
107
|
+
function resolveIMessageReplyCacheEntryKey(messageId) {
|
|
108
|
+
return createHash("sha256").update(messageId, "utf8").digest("hex").slice(0, 32);
|
|
109
|
+
}
|
|
110
|
+
const MAX_FAILURE_RETRY_MAP_SIZE = 512;
|
|
111
|
+
const MAX_FAILURE_RETRY_MAP_JSON_BYTES = 48e3;
|
|
112
|
+
const textEncoder = new TextEncoder();
|
|
113
|
+
const IMESSAGE_CATCHUP_CURSOR_NAMESPACE = "imessage.catchup-cursors";
|
|
114
|
+
function resolveIMessageCatchupCursorKey(accountId) {
|
|
115
|
+
return createHash("sha256").update(accountId, "utf8").digest("hex").slice(0, 32);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Bound the retry map so a pathological storm of unique failing GUIDs
|
|
119
|
+
* cannot grow the cursor value without limit. Keeps the `maxSize` entries
|
|
120
|
+
* with the highest counts (closest to give-up) when over the bound.
|
|
121
|
+
*/
|
|
122
|
+
function capFailureRetriesMap(map, maxSize = MAX_FAILURE_RETRY_MAP_SIZE, maxBytes = MAX_FAILURE_RETRY_MAP_JSON_BYTES) {
|
|
123
|
+
const entries = Object.entries(map);
|
|
124
|
+
if (entries.length <= maxSize && textEncoder.encode(JSON.stringify(map)).byteLength <= maxBytes) return map;
|
|
125
|
+
entries.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
|
|
126
|
+
const capped = {};
|
|
127
|
+
for (const [guid, count] of entries.slice(0, maxSize)) {
|
|
128
|
+
capped[guid] = count;
|
|
129
|
+
if (textEncoder.encode(JSON.stringify(capped)).byteLength > maxBytes) {
|
|
130
|
+
delete capped[guid];
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return capped;
|
|
135
|
+
}
|
|
136
|
+
const IMESSAGE_SENT_ECHOES_TTL_MS = 432e5;
|
|
137
|
+
const IMESSAGE_SENT_ECHOES_NAMESPACE = "imessage.sent-echoes";
|
|
138
|
+
function resolveIMessageSentEchoEntryKey(entry) {
|
|
139
|
+
return createHash("sha256").update(JSON.stringify([
|
|
140
|
+
entry.scope,
|
|
141
|
+
entry.text ?? "",
|
|
142
|
+
resolveIMessageEchoMediaKey(entry.media) ?? "",
|
|
143
|
+
entry.messageId ?? "",
|
|
144
|
+
entry.timestamp
|
|
145
|
+
])).digest("hex").slice(0, 32);
|
|
146
|
+
}
|
|
147
|
+
function resolveIMessageEchoMediaKey(media) {
|
|
148
|
+
const contentType = media?.contentType?.trim().toLowerCase() || void 0;
|
|
149
|
+
const kind = media?.kind && media.kind !== "unknown" ? media.kind : void 0;
|
|
150
|
+
if (kind) return `kind:${kind}`;
|
|
151
|
+
const normalizedContentType = contentType?.split(";", 1)[0]?.trim();
|
|
152
|
+
return normalizedContentType ? `mime:${normalizedContentType}` : void 0;
|
|
153
|
+
}
|
|
154
|
+
//#endregion
|
|
101
155
|
//#region extensions/imessage/src/monitor-reply-cache.ts
|
|
102
156
|
/** Recency window for the "react to the latest message" fallback. */
|
|
103
157
|
const LATEST_FALLBACK_MS = 6e5;
|
|
@@ -109,7 +163,6 @@ function reportPersistenceFailure(scope, err) {
|
|
|
109
163
|
}
|
|
110
164
|
const imessageReplyCacheByMessageId = /* @__PURE__ */ new Map();
|
|
111
165
|
const imessageShortIdToUuid = /* @__PURE__ */ new Map();
|
|
112
|
-
const imessageUuidToShortId = /* @__PURE__ */ new Map();
|
|
113
166
|
let imessageShortIdCounter = 0;
|
|
114
167
|
function openReplyCacheStore() {
|
|
115
168
|
return getIMessageRuntime().state.openKeyedStore({
|
|
@@ -135,12 +188,11 @@ function hydrateCounter(counter) {
|
|
|
135
188
|
}
|
|
136
189
|
function hydrateRows(entries) {
|
|
137
190
|
const cutoff = Date.now() - IMESSAGE_REPLY_CACHE_TTL_MS;
|
|
138
|
-
for (const entry of entries.filter((cached) => cached.timestamp >= cutoff).toSorted((a, b) => a.timestamp - b.timestamp).slice(-
|
|
191
|
+
for (const entry of entries.filter((cached) => cached.timestamp >= cutoff).toSorted((a, b) => a.timestamp - b.timestamp).slice(-2e3)) {
|
|
139
192
|
const numeric = Number.parseInt(entry.shortId, 10);
|
|
140
193
|
if (Number.isFinite(numeric) && numeric > imessageShortIdCounter) imessageShortIdCounter = numeric;
|
|
141
194
|
imessageReplyCacheByMessageId.set(entry.messageId, entry);
|
|
142
195
|
imessageShortIdToUuid.set(entry.shortId, entry.messageId);
|
|
143
|
-
imessageUuidToShortId.set(entry.messageId, entry.shortId);
|
|
144
196
|
}
|
|
145
197
|
}
|
|
146
198
|
async function hydrateFromStoreOnce() {
|
|
@@ -221,12 +273,11 @@ async function rememberIMessageReplyCache(entry) {
|
|
|
221
273
|
...entry,
|
|
222
274
|
shortId: ""
|
|
223
275
|
};
|
|
224
|
-
let shortId =
|
|
276
|
+
let shortId = imessageReplyCacheByMessageId.get(messageId)?.shortId;
|
|
225
277
|
const isNewMessage = !shortId;
|
|
226
278
|
if (!shortId) {
|
|
227
279
|
shortId = generateShortId();
|
|
228
280
|
imessageShortIdToUuid.set(shortId, messageId);
|
|
229
|
-
imessageUuidToShortId.set(messageId, shortId);
|
|
230
281
|
}
|
|
231
282
|
const fullEntry = buildReplyCacheEntry(entry, messageId, shortId);
|
|
232
283
|
imessageReplyCacheByMessageId.delete(messageId);
|
|
@@ -237,10 +288,7 @@ async function rememberIMessageReplyCache(entry) {
|
|
|
237
288
|
if (value.timestamp >= cutoff) break;
|
|
238
289
|
imessageReplyCacheByMessageId.delete(key);
|
|
239
290
|
deletedMessageIds.push(key);
|
|
240
|
-
if (value.shortId)
|
|
241
|
-
imessageShortIdToUuid.delete(value.shortId);
|
|
242
|
-
imessageUuidToShortId.delete(key);
|
|
243
|
-
}
|
|
291
|
+
if (value.shortId) imessageShortIdToUuid.delete(value.shortId);
|
|
244
292
|
}
|
|
245
293
|
while (imessageReplyCacheByMessageId.size > IMESSAGE_REPLY_CACHE_MAX_ENTRIES) {
|
|
246
294
|
const oldest = imessageReplyCacheByMessageId.keys().next().value;
|
|
@@ -248,10 +296,7 @@ async function rememberIMessageReplyCache(entry) {
|
|
|
248
296
|
const oldEntry = imessageReplyCacheByMessageId.get(oldest);
|
|
249
297
|
imessageReplyCacheByMessageId.delete(oldest);
|
|
250
298
|
deletedMessageIds.push(oldest);
|
|
251
|
-
if (oldEntry?.shortId)
|
|
252
|
-
imessageShortIdToUuid.delete(oldEntry.shortId);
|
|
253
|
-
imessageUuidToShortId.delete(oldest);
|
|
254
|
-
}
|
|
299
|
+
if (oldEntry?.shortId) imessageShortIdToUuid.delete(oldEntry.shortId);
|
|
255
300
|
}
|
|
256
301
|
const counter = imessageShortIdCounter;
|
|
257
302
|
persistence = persistence.then(async () => {
|
|
@@ -314,8 +359,23 @@ async function isKnownFromMeIMessageMessageId(messageId, ctx) {
|
|
|
314
359
|
if (!trimmed || !ctx.accountId || !hasChatScope(ctx)) return false;
|
|
315
360
|
await hydrateFromStoreOnce();
|
|
316
361
|
const cached = imessageReplyCacheByMessageId.get(trimmed);
|
|
317
|
-
if (!cached || cached.isFromMe !== true
|
|
318
|
-
return
|
|
362
|
+
if (!cached || cached.isFromMe !== true) return false;
|
|
363
|
+
return resolveCachedResourceBinding(trimmed, {
|
|
364
|
+
...ctx,
|
|
365
|
+
accountId: ctx.accountId
|
|
366
|
+
}) === "match";
|
|
367
|
+
}
|
|
368
|
+
async function isKnownFromMeIMessageTarget(params) {
|
|
369
|
+
const { accountId, chatId, chatGuid, chatIdentifier } = params;
|
|
370
|
+
const ctx = {
|
|
371
|
+
accountId,
|
|
372
|
+
chatId,
|
|
373
|
+
chatGuid,
|
|
374
|
+
chatIdentifier
|
|
375
|
+
};
|
|
376
|
+
const isKnownFromMe = params.isKnownFromMeMessageId ?? isKnownFromMeIMessageMessageId;
|
|
377
|
+
for (const messageId of params.messageIds) if (await isKnownFromMe(messageId, ctx)) return true;
|
|
378
|
+
return false;
|
|
319
379
|
}
|
|
320
380
|
function buildFromMeError(inputId, inputKind) {
|
|
321
381
|
return /* @__PURE__ */ new Error(`iMessage message id ${describeMessageIdForError(inputId, inputKind)} is not one this agent sent. edit and unsend can only target messages the gateway delivered itself; messages received from other participants cannot be modified.`);
|
|
@@ -360,9 +420,7 @@ function resolveCachedResourceBinding(messageId, ctx) {
|
|
|
360
420
|
if (!entry) return "unknown";
|
|
361
421
|
if (Date.now() - entry.timestamp > 216e5) return "unknown";
|
|
362
422
|
if (entry.accountId !== ctx.accountId) return "mismatch";
|
|
363
|
-
|
|
364
|
-
if (chatMatch !== "match") return chatMatch;
|
|
365
|
-
return "match";
|
|
423
|
+
return resolveIMessageChatMatch(entry, ctx);
|
|
366
424
|
}
|
|
367
425
|
/** @deprecated Used only by hosts without asynchronous conversation matching. */
|
|
368
426
|
function isIMessageCurrentMessageInChat(params) {
|
|
@@ -457,6 +515,7 @@ function recoverIMessageBridge(cliPath) {
|
|
|
457
515
|
}
|
|
458
516
|
//#endregion
|
|
459
517
|
//#region extensions/imessage/src/client.ts
|
|
518
|
+
const IMSG_APPLE_FRAMEWORK_STDERR_PATTERN = /^(?:\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ imsg\[\d+:\d+\] )?Could not fetch group for change type \d+ with identifier [^:]+:ABGroup, making it a delete change type\.$/u;
|
|
460
519
|
var IMessageRpcRequestError = class extends Error {
|
|
461
520
|
constructor(message, code, data) {
|
|
462
521
|
super(message);
|
|
@@ -466,8 +525,7 @@ var IMessageRpcRequestError = class extends Error {
|
|
|
466
525
|
}
|
|
467
526
|
};
|
|
468
527
|
function isIMessageBridgeStall(error) {
|
|
469
|
-
|
|
470
|
-
return error.message.includes("Timed out waiting for response");
|
|
528
|
+
return error instanceof Error && error.message.includes("Timed out waiting for response");
|
|
471
529
|
}
|
|
472
530
|
const BRIDGE_STALL_GUIDANCE = "The imsg private API bridge stopped responding. Run `imsg launch` to re-inject the dylib, then `openclaw channels status --probe` to refresh capability detection.";
|
|
473
531
|
function describeIMessageBridgeStall(error) {
|
|
@@ -671,6 +729,10 @@ var IMessageRpcClient = class {
|
|
|
671
729
|
const trimmed = line.trim();
|
|
672
730
|
if (!trimmed) return;
|
|
673
731
|
this.recordProcessDiagnostic(trimmed);
|
|
732
|
+
if (IMSG_APPLE_FRAMEWORK_STDERR_PATTERN.test(trimmed)) {
|
|
733
|
+
logVerbose(`imsg rpc: ${trimmed}`);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
674
736
|
this.runtime?.error?.(`imsg rpc: ${trimmed}`);
|
|
675
737
|
}
|
|
676
738
|
handleLine(line) {
|
|
@@ -1313,4 +1375,4 @@ function sanitizeOutboundText(text) {
|
|
|
1313
1375
|
return cleaned;
|
|
1314
1376
|
}
|
|
1315
1377
|
//#endregion
|
|
1316
|
-
export {
|
|
1378
|
+
export { DEFAULT_IMESSAGE_SEND_TIMEOUT_MS as C, resolveIMessageDirectChatService as D, normalizeDirectChatIdentifier as E, DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS as S, isIMessageEmailChatIdentifier as T, IMESSAGE_SENT_ECHOES_TTL_MS as _, IMessageRpcRequestError as a, resolveIMessageEchoMediaKey as b, findLatestIMessageEntryForChat as c, isKnownFromMeIMessageTarget as d, rememberIMessageReplyCache as f, IMESSAGE_SENT_ECHOES_NAMESPACE as g, IMESSAGE_CATCHUP_CURSOR_NAMESPACE as h, extractMarkdownFormatRuns as i, isIMessageCurrentMessageInChat as l, resolveIMessageMessageId as m, sanitizeIMessageFinalOutboundText as n, createIMessageRpcClient as o, resolveIMessageCachedResourceBinding as p, sanitizeOutboundText as r, runIMessageCliJsonCommand as s, protectIMessageFencedRoleMarkers as t, isIMessageCurrentMessageInChatAsync as u, capFailureRetriesMap as v, chatContextFromIMessageTarget as w, resolveIMessageSentEchoEntryKey as x, resolveIMessageCatchupCursorKey as y };
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { c as parseIMessageTarget, o as normalizeIMessageHandle, t as formatIMessageChatTarget } from "./targets-
|
|
2
|
-
import { d as resolveIMessageChatDbLookupPath, l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount } from "./accounts-
|
|
3
|
-
import { _ as
|
|
4
|
-
import { c as getIMessageApprovalApprovers, l as imessageApprovalAuth } from "./group-policy-
|
|
1
|
+
import { c as parseIMessageTarget, o as normalizeIMessageHandle, t as formatIMessageChatTarget } from "./targets-BicBiYsM.mjs";
|
|
2
|
+
import { d as resolveIMessageChatDbLookupPath, l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount } from "./accounts-nzcU0cq2.mjs";
|
|
3
|
+
import { D as resolveIMessageDirectChatService, _ as IMESSAGE_SENT_ECHOES_TTL_MS, a as IMessageRpcRequestError, b as resolveIMessageEchoMediaKey, f as rememberIMessageReplyCache, g as IMESSAGE_SENT_ECHOES_NAMESPACE, n as sanitizeIMessageFinalOutboundText, o as createIMessageRpcClient, s as runIMessageCliJsonCommand, t as protectIMessageFencedRoleMarkers, w as chatContextFromIMessageTarget, x as resolveIMessageSentEchoEntryKey } from "./sanitize-outbound-3MLljgtY.mjs";
|
|
4
|
+
import { c as getIMessageApprovalApprovers, l as imessageApprovalAuth } from "./group-policy-90pw4tyG.mjs";
|
|
5
5
|
import { n as getOptionalIMessageRuntime, t as getIMessageRuntime } from "./runtime-Cza4CY5T.mjs";
|
|
6
|
-
import {
|
|
7
|
-
import { d as normalizeConversationKey, i as registerIMessageApprovalReactionTarget, l as enumerateApprovalTargetKeys, s as buildIMessageApprovalConversationKeyForInbound, u as enumerateConversationKeyForms } from "./approval-reactions-D6RFg6lU.mjs";
|
|
6
|
+
import { d as normalizeConversationKey, i as registerIMessageApprovalReactionTarget, l as enumerateApprovalTargetKeys, s as buildIMessageApprovalConversationKeyForInbound, u as enumerateConversationKeyForms } from "./approval-reactions-Bp33xc83.mjs";
|
|
8
7
|
import { n as normalizeIMessageGuid } from "./reaction-context-Br-vAJFp.mjs";
|
|
9
|
-
import { r as resolveAuthorizedIMessageReplyReference, t as withIMessageRemoteFile } from "./remote-file-
|
|
8
|
+
import { a as withIMessageReceiptGuidReader, r as resolveAuthorizedIMessageReplyReference, t as withIMessageRemoteFile } from "./remote-file-DRPCaVmg.mjs";
|
|
10
9
|
import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
11
10
|
import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
|
|
12
11
|
import { createLazyRuntimeSurface } from "openclaw/plugin-sdk/lazy-runtime";
|
|
@@ -15,13 +14,11 @@ import { basename } from "node:path";
|
|
|
15
14
|
import { extractOriginalFilename, kindFromMime, resolveOutboundAttachmentFromUrl } from "openclaw/plugin-sdk/media-runtime";
|
|
16
15
|
import { logVerbose, sleep } from "openclaw/plugin-sdk/runtime-env";
|
|
17
16
|
import { asDateTimestampMs } from "openclaw/plugin-sdk/number-runtime";
|
|
18
|
-
import { resolveRuntimeWorkerUrl } from "openclaw/plugin-sdk/process-runtime";
|
|
19
17
|
import { PlatformMessageNotDispatchedError, isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
|
|
20
18
|
import { addApprovalReactionHintToText, createApprovalReactionTargetStore, listApprovalReactionBindings } from "openclaw/plugin-sdk/approval-reaction-runtime";
|
|
21
19
|
import { convertMarkdownTables, stripInlineDirectiveTagsForDelivery } from "openclaw/plugin-sdk/text-chunking";
|
|
22
20
|
import { createChannelPartialDeliveryError } from "openclaw/plugin-sdk/channel-inbound";
|
|
23
21
|
import { createPluginStateErrorReporter } from "openclaw/plugin-sdk/plugin-state-runtime";
|
|
24
|
-
import { openSqliteWorkerStore } from "openclaw/plugin-sdk/sqlite-runtime";
|
|
25
22
|
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
26
23
|
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
27
24
|
import { resolvePreferredOpenClawTmpDir, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
|
|
@@ -113,7 +110,7 @@ const loadResolveApprovalOverGateway = createLazyRuntimeSurface(() => import("op
|
|
|
113
110
|
const reportPersistentError = createPluginStateErrorReporter(getOptionalIMessageRuntime, "imessage", "approval-poll-state", "iMessage persistent approval poll state failed");
|
|
114
111
|
function readPersistedTarget(value) {
|
|
115
112
|
const target = value;
|
|
116
|
-
if (!target || typeof target.approvalId !== "string" || target.approvalKind !== "exec" && target.approvalKind !== "plugin" || !Array.isArray(target.optionDecisions)) return null;
|
|
113
|
+
if (!target || typeof target.approvalId !== "string" || target.approvalKind !== "exec" && target.approvalKind !== "plugin" && target.approvalKind !== "system-agent" || !Array.isArray(target.optionDecisions)) return null;
|
|
117
114
|
const optionDecisions = target.optionDecisions.flatMap((pair) => {
|
|
118
115
|
if (!Array.isArray(pair) || pair.length !== 2) return [];
|
|
119
116
|
const [optionId, decision] = pair;
|
|
@@ -275,27 +272,18 @@ function readPollVoteEvent(message) {
|
|
|
275
272
|
malformedVotes
|
|
276
273
|
};
|
|
277
274
|
}
|
|
278
|
-
async function
|
|
275
|
+
async function lookupPollRecord(store, params) {
|
|
279
276
|
for (const key of enumeratePollTargetKeys({
|
|
280
277
|
accountId: params.accountId,
|
|
281
278
|
conversation: params.conversation,
|
|
282
279
|
pollGuid: params.pollGuid,
|
|
283
280
|
optionIds: params.optionIds
|
|
284
281
|
})) {
|
|
285
|
-
const target = await
|
|
282
|
+
const target = await store.lookup(key);
|
|
286
283
|
if (target) return target;
|
|
287
284
|
}
|
|
288
285
|
return null;
|
|
289
286
|
}
|
|
290
|
-
async function hasTombstone(params) {
|
|
291
|
-
for (const key of enumeratePollTargetKeys({
|
|
292
|
-
accountId: params.accountId,
|
|
293
|
-
conversation: params.conversation,
|
|
294
|
-
pollGuid: params.pollGuid,
|
|
295
|
-
optionIds: params.optionIds
|
|
296
|
-
})) if (await pollTombstones.lookup(key)) return true;
|
|
297
|
-
return false;
|
|
298
|
-
}
|
|
299
287
|
/**
|
|
300
288
|
* Outcomes for votes we own are logged at info, not verbose: an approval
|
|
301
289
|
* decision is security-relevant, and diagnosing "the tap did nothing" must not
|
|
@@ -331,8 +319,8 @@ async function maybeResolveIMessageApprovalPollVote(params) {
|
|
|
331
319
|
pollGuid: event.pollGuid,
|
|
332
320
|
optionIds: event.votes.map((vote) => vote.optionId)
|
|
333
321
|
};
|
|
334
|
-
const target = await
|
|
335
|
-
if (!target) return await
|
|
322
|
+
const target = await lookupPollRecord(pollTargets, lookupKey);
|
|
323
|
+
if (!target) return Boolean(await lookupPollRecord(pollTombstones, lookupKey));
|
|
336
324
|
if (event.malformedVotes) {
|
|
337
325
|
warn$1("approval poll vote ignored: malformed complete vote set", {
|
|
338
326
|
approvalId: target.approvalId,
|
|
@@ -450,76 +438,19 @@ const iMessageApprovalPollTargets = {
|
|
|
450
438
|
clearForTest: clearIMessageApprovalPollTargetsForTest
|
|
451
439
|
};
|
|
452
440
|
//#endregion
|
|
453
|
-
//#region extensions/imessage/src/chat-db.ts
|
|
454
|
-
function openIMessageChatDbReader(databasePath) {
|
|
455
|
-
return openSqliteWorkerStore({
|
|
456
|
-
moduleUrl: resolveRuntimeWorkerUrl({
|
|
457
|
-
currentModuleUrl: import.meta.url,
|
|
458
|
-
sourceWorkerName: "chat-db.worker",
|
|
459
|
-
distWorkerPath: "extensions/imessage/src/chat-db.worker.js",
|
|
460
|
-
package: {
|
|
461
|
-
name: "@openclaw/imessage",
|
|
462
|
-
distWorkerPath: "src/chat-db.worker.js"
|
|
463
|
-
}
|
|
464
|
-
}),
|
|
465
|
-
databasePath,
|
|
466
|
-
existingOnly: true,
|
|
467
|
-
input: void 0
|
|
468
|
-
});
|
|
469
|
-
}
|
|
470
|
-
async function resolveIMessageStartupRowidWatermark(dbPath) {
|
|
471
|
-
let store;
|
|
472
|
-
try {
|
|
473
|
-
store = await openIMessageChatDbReader(dbPath);
|
|
474
|
-
if (!store) throw new Error("Messages database is unavailable");
|
|
475
|
-
return await store.execute({
|
|
476
|
-
type: "startupWatermark",
|
|
477
|
-
input: void 0
|
|
478
|
-
});
|
|
479
|
-
} catch (err) {
|
|
480
|
-
logVerbose(`imessage: startup rowid watermark unavailable for db=${dbPath}: ${String(err)}`);
|
|
481
|
-
return null;
|
|
482
|
-
} finally {
|
|
483
|
-
await store?.close();
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
async function withIMessageReceiptGuidReader(databasePath, use) {
|
|
487
|
-
let store;
|
|
488
|
-
let closed = false;
|
|
489
|
-
const read = async (command) => {
|
|
490
|
-
if (closed) throw new Error("iMessage receipt lookup is closed");
|
|
491
|
-
try {
|
|
492
|
-
store ??= await openIMessageChatDbReader(databasePath);
|
|
493
|
-
return store ? await store.execute(command) : null;
|
|
494
|
-
} catch {
|
|
495
|
-
return null;
|
|
496
|
-
}
|
|
497
|
-
};
|
|
498
|
-
try {
|
|
499
|
-
return await use(read);
|
|
500
|
-
} finally {
|
|
501
|
-
closed = true;
|
|
502
|
-
try {
|
|
503
|
-
await store?.close();
|
|
504
|
-
} catch {}
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
//#endregion
|
|
508
441
|
//#region extensions/imessage/src/monitor/echo-text-corruption.ts
|
|
509
442
|
function isLeadingEchoTextCorruptionMarker(code) {
|
|
510
443
|
return code === 0 || code === 65279 || code === 65533 || code === 65534 || code === 65535;
|
|
511
444
|
}
|
|
512
|
-
function
|
|
445
|
+
function normalizeIMessageEchoText(text) {
|
|
446
|
+
if (!text) return;
|
|
447
|
+
const normalized = text.replace(/\r\n?/g, "\n").trim();
|
|
513
448
|
let offset = 0;
|
|
514
|
-
while (offset <
|
|
515
|
-
return
|
|
449
|
+
while (offset < normalized.length && isLeadingEchoTextCorruptionMarker(normalized.charCodeAt(offset))) offset += 1;
|
|
450
|
+
return normalized.slice(offset).trim() || void 0;
|
|
516
451
|
}
|
|
517
452
|
//#endregion
|
|
518
453
|
//#region extensions/imessage/src/monitor/persisted-echo-cache.ts
|
|
519
|
-
function normalizeText(text) {
|
|
520
|
-
if (!text) return;
|
|
521
|
-
return stripLeadingEchoTextCorruptionMarkers(text.replace(/\r\n?/g, "\n").trim()).trim() || void 0;
|
|
522
|
-
}
|
|
523
454
|
function normalizeMessageId(messageId) {
|
|
524
455
|
const normalized = messageId?.trim();
|
|
525
456
|
if (!normalized || normalized === "ok" || normalized === "unknown") return;
|
|
@@ -579,7 +510,7 @@ async function persistEntry(entry, ttlMs) {
|
|
|
579
510
|
return key;
|
|
580
511
|
}
|
|
581
512
|
async function rememberPersistedIMessageEcho(params) {
|
|
582
|
-
const text =
|
|
513
|
+
const text = normalizeIMessageEchoText(params.text);
|
|
583
514
|
const media = normalizeMedia(params.media);
|
|
584
515
|
const messageId = normalizeMessageId(params.messageId);
|
|
585
516
|
const entry = {
|
|
@@ -603,7 +534,7 @@ async function forgetPersistedIMessageEchoKey(key) {
|
|
|
603
534
|
}
|
|
604
535
|
}
|
|
605
536
|
async function hasPersistedIMessageEcho(params) {
|
|
606
|
-
const text =
|
|
537
|
+
const text = normalizeIMessageEchoText(params.text);
|
|
607
538
|
const mediaKey = resolveIMessageEchoMediaKey(params.media);
|
|
608
539
|
const messageId = normalizeMessageId(params.messageId);
|
|
609
540
|
if (!text && !mediaKey && !messageId) return false;
|
|
@@ -659,10 +590,6 @@ function resolveOutboundMessageGuid(result) {
|
|
|
659
590
|
function isNumericMessageRowId(value) {
|
|
660
591
|
return typeof value === "string" && /^\d+$/.test(value.trim());
|
|
661
592
|
}
|
|
662
|
-
function resolveTargetService(target) {
|
|
663
|
-
if (target.kind !== "handle") return;
|
|
664
|
-
if (target.serviceExplicit || target.service !== "auto") return target.service;
|
|
665
|
-
}
|
|
666
593
|
function normalizeResolvedMessageGuid(value) {
|
|
667
594
|
if (typeof value !== "string") return null;
|
|
668
595
|
const trimmed = value.trim();
|
|
@@ -732,9 +659,6 @@ function shouldRecoverApprovalPromptGuid(params) {
|
|
|
732
659
|
function canCheckSentMessageAfterRpcTimeout(params) {
|
|
733
660
|
return Boolean(params.resolveSentMessageGuidImpl) || canResolveLatestSentMessageGuidFromChatDb(params.dbPath);
|
|
734
661
|
}
|
|
735
|
-
function resolveOutboundEchoText(text) {
|
|
736
|
-
return text.trim() || void 0;
|
|
737
|
-
}
|
|
738
662
|
function resolveOutboundEchoMedia(mediaContentType) {
|
|
739
663
|
if (!mediaContentType) return;
|
|
740
664
|
return {
|
|
@@ -862,7 +786,7 @@ async function trySendAttachmentForTarget(params) {
|
|
|
862
786
|
let result;
|
|
863
787
|
let pendingEchoKey;
|
|
864
788
|
try {
|
|
865
|
-
|
|
789
|
+
pendingEchoKey = await rememberPersistedIMessageEcho({
|
|
866
790
|
scope: echoScope,
|
|
867
791
|
text: params.echoText,
|
|
868
792
|
media: params.echoMedia,
|
|
@@ -926,7 +850,7 @@ async function trySendAttachmentForTarget(params) {
|
|
|
926
850
|
resolveMessageGuidImpl: params.resolveMessageGuidImpl
|
|
927
851
|
});
|
|
928
852
|
const messageId = resolvedId ?? (result.ok || result.success ? "ok" : "unknown");
|
|
929
|
-
|
|
853
|
+
await rememberPersistedIMessageEcho({
|
|
930
854
|
scope: echoScope,
|
|
931
855
|
text: params.echoText,
|
|
932
856
|
media: params.echoMedia,
|
|
@@ -975,7 +899,7 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
975
899
|
remoteHost
|
|
976
900
|
});
|
|
977
901
|
const target = parseIMessageTarget(opts.chatId ? formatIMessageChatTarget(opts.chatId) : to);
|
|
978
|
-
const service = opts.service ??
|
|
902
|
+
const service = opts.service ?? (target.kind === "handle" && (target.serviceExplicit || target.service !== "auto") ? target.service : void 0) ?? account.config.service;
|
|
979
903
|
const sendTransport = account.config.sendTransport ?? "auto";
|
|
980
904
|
const resolvedReplyToId = await resolveAuthorizedIMessageReplyReference({
|
|
981
905
|
account,
|
|
@@ -1038,7 +962,7 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
1038
962
|
});
|
|
1039
963
|
message = formatted.text;
|
|
1040
964
|
if (!message.trim() && !filePath) throw new Error("iMessage send requires text or media");
|
|
1041
|
-
const echoText =
|
|
965
|
+
const echoText = message.trim() || void 0;
|
|
1042
966
|
const echoMedia = filePath ? resolveOutboundEchoMedia(mediaContentType) : void 0;
|
|
1043
967
|
let effectiveReplyToId = resolvedReplyToId;
|
|
1044
968
|
const runCli = opts.runCliJson ?? ((args) => runIMessageCliJsonCommand({
|
|
@@ -1053,11 +977,7 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
1053
977
|
};
|
|
1054
978
|
const requestOwnedRpc = async (method, rpcParams) => {
|
|
1055
979
|
opts.assertDirectAdapterHandoff?.();
|
|
1056
|
-
const rpcClient = opts.createClient
|
|
1057
|
-
cliPath,
|
|
1058
|
-
dbPath,
|
|
1059
|
-
remoteHost
|
|
1060
|
-
}) : await createIMessageRpcClient({
|
|
980
|
+
const rpcClient = await (opts.createClient ?? createIMessageRpcClient)({
|
|
1061
981
|
cliPath,
|
|
1062
982
|
dbPath,
|
|
1063
983
|
remoteHost
|
|
@@ -1146,15 +1066,11 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
1146
1066
|
target
|
|
1147
1067
|
});
|
|
1148
1068
|
opts.assertDirectAdapterHandoff?.();
|
|
1149
|
-
const client = opts.client ?? (opts.createClient
|
|
1069
|
+
const client = opts.client ?? await (opts.createClient ?? createIMessageRpcClient)({
|
|
1150
1070
|
cliPath,
|
|
1151
1071
|
dbPath,
|
|
1152
1072
|
remoteHost
|
|
1153
|
-
})
|
|
1154
|
-
cliPath,
|
|
1155
|
-
dbPath,
|
|
1156
|
-
remoteHost
|
|
1157
|
-
}));
|
|
1073
|
+
});
|
|
1158
1074
|
const shouldClose = !opts.client;
|
|
1159
1075
|
const requestSuccessfulSend = async (sendParams) => {
|
|
1160
1076
|
const request = async (nativeParams) => await requestIMessageRpcSend(client, "send", nativeParams, timeoutMs, opts);
|
|
@@ -1183,7 +1099,7 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
1183
1099
|
let pendingEchoKey;
|
|
1184
1100
|
try {
|
|
1185
1101
|
try {
|
|
1186
|
-
|
|
1102
|
+
pendingEchoKey = await rememberPersistedIMessageEcho({
|
|
1187
1103
|
scope: echoScope,
|
|
1188
1104
|
text: echoText,
|
|
1189
1105
|
media: echoMedia,
|
|
@@ -1240,7 +1156,7 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
1240
1156
|
sentAfterMs: sendStartedAtMs,
|
|
1241
1157
|
resolveSentMessageGuidImpl: opts.resolveSentMessageGuidImpl
|
|
1242
1158
|
});
|
|
1243
|
-
|
|
1159
|
+
await rememberPersistedIMessageEcho({
|
|
1244
1160
|
scope: echoScope,
|
|
1245
1161
|
text: echoText,
|
|
1246
1162
|
media: echoMedia,
|
|
@@ -1299,4 +1215,4 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
1299
1215
|
}
|
|
1300
1216
|
}
|
|
1301
1217
|
//#endregion
|
|
1302
|
-
export {
|
|
1218
|
+
export { iMessageApprovalPollTargets as a, iMessageApprovalControlBindings as c, buildApprovalPollOptions as i, hasPersistedIMessageEcho as n, mapSentPollOptionsToDecisions as o, normalizeIMessageEchoText as r, maybeResolveIMessageApprovalPollVote as s, sendMessageIMessage as t };
|