@openclaw/imessage 2026.10.10 → 2026.11.5-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/{accounts-BH0coL46.mjs → accounts-C1Ypv3Wn.mjs} +6 -7
- package/dist/.setup/{actions-CW7XYYF4.mjs → actions-qOuKy8To.mjs} +360 -108
- package/dist/.setup/{actions.runtime-B2ZHQ3TJ.mjs → actions.runtime-Ccg9CARL.mjs} +10 -56
- package/dist/.setup/{api-6xi-NBrt.mjs → api-BXXuQQCS.mjs} +7 -7
- package/dist/.setup/{api-B0ih8Iof.mjs → api-DTbxSOPc.mjs} +8 -8
- package/dist/.setup/{approval-handler.runtime-BKmqba3L.mjs → approval-handler.runtime-B6vrFfZx.mjs} +112 -131
- package/dist/.setup/{approval-reactions-B9CJS0NT.mjs → approval-reactions-DBBsqbRC.mjs} +152 -72
- package/dist/.setup/{channel-6kcKpSRw.mjs → channel-CLaN4mQn.mjs} +142 -119
- package/dist/.setup/{channel.runtime-BW4A0m4h.mjs → channel.runtime-XJGx1MIH.mjs} +205 -363
- package/dist/.setup/chat-context-fTfJVqAi.mjs +77 -0
- package/dist/.setup/chat-lookup-xtPsOBkl.mjs +50 -0
- package/dist/.setup/client-D_BaG8sC.mjs +367 -0
- package/dist/.setup/{config-schema-DRkdRC21.mjs → config-schema-BjkQV5P5.mjs} +1 -2
- package/dist/.setup/{conversation-bindings-vZFn6sN2.mjs → conversation-bindings-8DjxoIYU.mjs} +9 -6
- package/dist/.setup/{media-contract-CoixpXRX.mjs → media-contract-BErFBKV9.mjs} +1 -1
- package/dist/.setup/{message-tool-api-CxSY_rh7.mjs → message-tool-api-DtZ1wKbT.mjs} +3 -6
- package/dist/.setup/{remote-file-CCgMYZ-u.mjs → remote-file-DpK3GQFD.mjs} +8 -22
- package/dist/.setup/{sanitize-outbound-C02fJrn6.mjs → sanitize-outbound-Dhjhz0a-.mjs} +23 -27
- package/dist/.setup/{send-D98hQFdv.mjs → send-DhEW0gfe.mjs} +150 -226
- package/dist/.setup/{setup-core-BWnW0czE.mjs → setup-core-B1_P_t4T.mjs} +2 -2
- package/dist/.setup/{setup-surface-aRZhAzzQ.mjs → setup-surface-CD28mXWK.mjs} +11 -25
- package/dist/.setup/{targets-CIx4BKqL.mjs → targets-C7CIWJ0k.mjs} +12 -3
- package/dist/.source-module-urls/929c518fa2986b0f85f66bceefead22868db0ab452dee914dc6a2bb86b2e60ad.json +1 -1
- package/dist/api.js +8 -8
- 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/media-contract-api.js +1 -1
- package/dist/message-tool-api.js +1 -1
- package/dist/runtime-api.js +1 -3
- package/dist/session-binding-contract-api.js +1 -1
- package/dist/setup-entry.js +1 -1
- package/dist/src/chat-db.worker.js +1 -1
- package/node_modules/typebox/build/format/duration.d.mts +2 -2
- package/node_modules/typebox/build/format/duration.mjs +2 -2
- package/node_modules/typebox/build/format/idn_email.d.mts +1 -0
- package/node_modules/typebox/build/format/idn_email.mjs +1 -0
- package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -1
- package/node_modules/typebox/build/format/idn_hostname.mjs +1 -1
- package/node_modules/typebox/build/format/ipv4.d.mts +2 -2
- package/node_modules/typebox/build/format/ipv4.mjs +2 -2
- package/node_modules/typebox/build/format/ipv6.d.mts +1 -1
- package/node_modules/typebox/build/format/ipv6.mjs +1 -1
- package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
- package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
- package/node_modules/typebox/build/schema/build.mjs +1 -0
- package/node_modules/typebox/build/schema/engine/_unique.d.mts +4 -2
- package/node_modules/typebox/build/schema/engine/_unique.mjs +7 -3
- package/node_modules/typebox/build/schema/engine/additionalItems.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +0 -3
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +15 -17
- package/node_modules/typebox/build/schema/engine/contains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/index.d.mts +1 -0
- package/node_modules/typebox/build/schema/engine/index.mjs +1 -0
- package/node_modules/typebox/build/schema/engine/items.mjs +7 -4
- package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/minContains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/oneOf.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +2 -2
- package/node_modules/typebox/build/system/hashing/hash.mjs +63 -34
- package/node_modules/typebox/build/system/locale/en_US.mjs +2 -1
- package/node_modules/typebox/build/system/memory/assign.d.mts +2 -8
- package/node_modules/typebox/build/system/memory/assign.mjs +13 -6
- package/node_modules/typebox/build/system/memory/clone.d.mts +4 -5
- package/node_modules/typebox/build/system/memory/clone.mjs +8 -96
- package/node_modules/typebox/build/system/memory/create.d.mts +1 -5
- package/node_modules/typebox/build/system/memory/create.mjs +18 -13
- package/node_modules/typebox/build/system/memory/deep.d.mts +2 -0
- package/node_modules/typebox/build/system/memory/deep.mjs +108 -0
- package/node_modules/typebox/build/system/memory/discard.d.mts +1 -1
- package/node_modules/typebox/build/system/memory/discard.mjs +9 -8
- package/node_modules/typebox/build/system/memory/finalize.d.mts +4 -0
- package/node_modules/typebox/build/system/memory/finalize.mjs +30 -0
- package/node_modules/typebox/build/system/memory/keys.d.mts +2 -0
- package/node_modules/typebox/build/system/memory/keys.mjs +8 -0
- package/node_modules/typebox/build/system/memory/update.d.mts +1 -4
- package/node_modules/typebox/build/system/memory/update.mjs +43 -16
- package/node_modules/typebox/build/type/engine/call/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/call/index.mjs +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +2 -24
- package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +2 -29
- package/node_modules/typebox/build/type/engine/evaluate/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/index.mjs +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +5 -1
- package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +6 -1
- package/node_modules/typebox/build/type/engine/evaluate/property.d.mts +30 -0
- package/node_modules/typebox/build/type/engine/evaluate/property.mjs +29 -0
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/object/from_intersect.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/object/from_intersect.mjs +2 -2
- package/node_modules/typebox/build/type/engine/object/from_union.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/this/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/this/index.mjs +1 -0
- package/node_modules/typebox/build/value/clone/clone.d.mts +4 -3
- package/node_modules/typebox/build/value/clone/clone.mjs +5 -7
- package/node_modules/typebox/build/value/repair/from_cyclic.d.mts +2 -0
- package/node_modules/typebox/build/value/repair/from_cyclic.mjs +6 -0
- package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +25 -14
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +1 -1
- package/node_modules/zod/package.json +1 -1
- package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
- package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
- package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
- package/node_modules/zod/src/v4/core/compile.ts +9 -0
- package/node_modules/zod/src/v4/core/schemas.ts +35 -1
- package/node_modules/zod/src/v4/core/util.ts +13 -0
- package/node_modules/zod/src/v4/core/versions.ts +1 -1
- package/node_modules/zod/v4/core/compile.cjs +8 -0
- package/node_modules/zod/v4/core/compile.js +8 -0
- package/node_modules/zod/v4/core/schemas.cjs +30 -0
- package/node_modules/zod/v4/core/schemas.d.cts +3 -1
- package/node_modules/zod/v4/core/schemas.d.ts +3 -1
- package/node_modules/zod/v4/core/schemas.js +30 -0
- package/node_modules/zod/v4/core/util.cjs +15 -0
- package/node_modules/zod/v4/core/util.d.cts +2 -0
- package/node_modules/zod/v4/core/util.d.ts +2 -0
- package/node_modules/zod/v4/core/util.js +14 -0
- package/node_modules/zod/v4/core/versions.cjs +1 -1
- package/node_modules/zod/v4/core/versions.js +1 -1
- package/openclaw.plugin.json +0 -30
- package/package.json +6 -6
- package/dist/.setup/client-C3e7ZLqA.mjs +0 -739
- package/dist/.setup/question-reactions-DTj-VH3N.mjs +0 -67
- package/dist/.setup/reaction-context-Bw00FkmU.mjs +0 -105
- package/dist/.setup/runtime-BRQCPuAD.mjs +0 -7
- package/node_modules/typebox/build/system/memory/freeze.d.mts +0 -4
- package/node_modules/typebox/build/system/memory/freeze.mjs +0 -6
|
@@ -35,11 +35,23 @@ const IMESSAGE_STYLE_MAP = {
|
|
|
35
35
|
underline: "underline",
|
|
36
36
|
strikethrough: "strikethrough"
|
|
37
37
|
};
|
|
38
|
-
function
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
function extractMarkdownFormatRuns(input) {
|
|
39
|
+
const ir = markdownToIR(input, {
|
|
40
|
+
autolink: false,
|
|
41
|
+
enableHtmlUnderline: true,
|
|
42
|
+
headingStyle: "rich",
|
|
43
|
+
linkify: false,
|
|
44
|
+
preserveDunderIdentifiers: true,
|
|
45
|
+
preserveSourceBlockSpacing: true
|
|
46
|
+
});
|
|
47
|
+
const rendered = renderMarkdownWithAttributedRanges(ir, { styleMap: IMESSAGE_STYLE_MAP }, IMESSAGE_FORMAT_PROFILE);
|
|
48
|
+
const codeRanges = ir.styles.some((span) => span.style === "code") ? renderMarkdownWithAttributedRanges(ir, { styleMap: { code: "code" } }, IMESSAGE_CODE_PROFILE).ranges : [];
|
|
49
|
+
const text = rendered.text;
|
|
50
|
+
const ranges = rendered.ranges.map(({ start, length, style }) => ({
|
|
51
|
+
start,
|
|
52
|
+
length,
|
|
53
|
+
styles: [style]
|
|
54
|
+
}));
|
|
43
55
|
if (codeRanges.length === 0) return {
|
|
44
56
|
text,
|
|
45
57
|
ranges
|
|
@@ -47,7 +59,8 @@ function restoreCodeMarkers(text, ranges, codeRanges) {
|
|
|
47
59
|
const edits = codeRanges.map((range) => {
|
|
48
60
|
const end = range.start + range.length;
|
|
49
61
|
const content = text.slice(range.start, end);
|
|
50
|
-
const
|
|
62
|
+
const longestRun = Math.max(0, ...[...content.matchAll(/`+/gu)].map((match) => match[0].length));
|
|
63
|
+
const marker = "`".repeat(longestRun + 1);
|
|
51
64
|
const padding = content.startsWith("`") || content.endsWith("`") ? " " : "";
|
|
52
65
|
return {
|
|
53
66
|
start: range.start,
|
|
@@ -55,36 +68,19 @@ function restoreCodeMarkers(text, ranges, codeRanges) {
|
|
|
55
68
|
text: `${marker}${padding}${content}${padding}${marker}`
|
|
56
69
|
};
|
|
57
70
|
});
|
|
58
|
-
const { text:
|
|
71
|
+
const { text: restoredText, mapOffset } = applyMarkdownTextEdits(text, edits);
|
|
59
72
|
return {
|
|
60
|
-
text:
|
|
73
|
+
text: restoredText,
|
|
61
74
|
ranges: ranges.map((range) => {
|
|
62
75
|
const start = mapOffset(range.start);
|
|
63
76
|
return {
|
|
64
|
-
...range,
|
|
65
77
|
start,
|
|
66
|
-
length: mapOffset(range.start + range.length) - start
|
|
78
|
+
length: mapOffset(range.start + range.length) - start,
|
|
79
|
+
styles: range.styles
|
|
67
80
|
};
|
|
68
81
|
})
|
|
69
82
|
};
|
|
70
83
|
}
|
|
71
|
-
function extractMarkdownFormatRuns(input) {
|
|
72
|
-
const ir = markdownToIR(input, {
|
|
73
|
-
autolink: false,
|
|
74
|
-
enableHtmlUnderline: true,
|
|
75
|
-
headingStyle: "rich",
|
|
76
|
-
linkify: false,
|
|
77
|
-
preserveDunderIdentifiers: true,
|
|
78
|
-
preserveSourceBlockSpacing: true
|
|
79
|
-
});
|
|
80
|
-
const rendered = renderMarkdownWithAttributedRanges(ir, { styleMap: IMESSAGE_STYLE_MAP }, IMESSAGE_FORMAT_PROFILE);
|
|
81
|
-
const codeRanges = ir.styles.some((span) => span.style === "code") ? renderMarkdownWithAttributedRanges(ir, { styleMap: { code: "code" } }, IMESSAGE_CODE_PROFILE).ranges : [];
|
|
82
|
-
return restoreCodeMarkers(rendered.text, rendered.ranges.map(({ start, length, style }) => ({
|
|
83
|
-
start,
|
|
84
|
-
length,
|
|
85
|
-
styles: [style]
|
|
86
|
-
})), codeRanges);
|
|
87
|
-
}
|
|
88
84
|
// extensions/imessage/src/monitor/sanitize-outbound.ts
|
|
89
85
|
/**
|
|
90
86
|
* Patterns that indicate assistant-internal metadata leaked into text.
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { d as resolveIMessageChatDbLookupPath, l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount } from "./accounts-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { d as getIMessageApprovalApprovers, f as imessageApprovalAuth } from "./channel-
|
|
7
|
-
import { n as sanitizeIMessageFinalOutboundText, t as protectIMessageFencedRoleMarkers } from "./sanitize-outbound-
|
|
8
|
-
import { a as withIMessageReceiptGuidReader, r as resolveAuthorizedIMessageReplyReference, t as withIMessageRemoteFile } from "./remote-file-
|
|
9
|
-
import { d as resolveIMessageApprovalControlActor,
|
|
1
|
+
import { l as parseIMessageTarget, n as iMessageTargetRpcParams, s as normalizeIMessageHandle, t as formatIMessageChatTarget } from "./targets-C7CIWJ0k.mjs";
|
|
2
|
+
import { d as resolveIMessageChatDbLookupPath, l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount } from "./accounts-C1Ypv3Wn.mjs";
|
|
3
|
+
import { a as resolveIMessageDirectChatService, t as chatContextFromIMessageTarget } from "./chat-context-fTfJVqAi.mjs";
|
|
4
|
+
import { i as runIMessageCliJsonCommand, n as createIMessageRpcClient, t as IMessageRpcRequestError } from "./client-D_BaG8sC.mjs";
|
|
5
|
+
import { a as rememberIMessageReplyCache, b as normalizeIMessageMessageId, g as getOptionalIMessageRuntime, h as getIMessageRuntime, l as IMESSAGE_SENT_ECHOES_NAMESPACE, m as resolveIMessageSentEchoEntryKey, p as resolveIMessageEchoMediaKey, u as IMESSAGE_SENT_ECHOES_TTL_MS, v as createPersistenceFailureReporter, y as normalizeIMessageGuid } from "./actions-qOuKy8To.mjs";
|
|
6
|
+
import { d as getIMessageApprovalApprovers, f as imessageApprovalAuth } from "./channel-CLaN4mQn.mjs";
|
|
7
|
+
import { n as sanitizeIMessageFinalOutboundText, t as protectIMessageFencedRoleMarkers } from "./sanitize-outbound-Dhjhz0a-.mjs";
|
|
8
|
+
import { a as withIMessageReceiptGuidReader, r as resolveAuthorizedIMessageReplyReference, t as withIMessageRemoteFile } from "./remote-file-DpK3GQFD.mjs";
|
|
9
|
+
import { d as resolveIMessageApprovalControlActor, l as enumerateApprovalTargetKeys, r as registerIMessageApprovalReactionTarget, s as buildIMessageApprovalConversationKeyForInbound, u as normalizeConversationKey } from "./approval-reactions-DBBsqbRC.mjs";
|
|
10
10
|
import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
11
11
|
import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
|
|
12
12
|
import { createLazyRuntimeSurface } from "openclaw/plugin-sdk/lazy-runtime";
|
|
13
13
|
import { accessSync, constants } from "node:fs";
|
|
14
14
|
import { basename } from "node:path";
|
|
15
15
|
import { extractOriginalFilename, kindFromMime, resolveOutboundAttachmentFromUrl } from "openclaw/plugin-sdk/media-runtime";
|
|
16
|
-
import {
|
|
17
|
-
import { asDateTimestampMs } from "openclaw/plugin-sdk/number-runtime";
|
|
16
|
+
import { sleep } from "openclaw/plugin-sdk/runtime-env";
|
|
18
17
|
import { PlatformMessageNotDispatchedError, isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
|
|
19
18
|
import { captureChannelReadAuthority, captureEffectAuthority } from "openclaw/plugin-sdk/fetch-runtime";
|
|
20
19
|
import { addApprovalReactionHintToText, createApprovalReactionTargetStore, listApprovalReactionBindings } from "openclaw/plugin-sdk/approval-reaction-runtime";
|
|
21
20
|
import { convertMarkdownTables, stripInlineDirectiveTagsForDelivery } from "openclaw/plugin-sdk/text-chunking";
|
|
22
21
|
import { createChannelPartialDeliveryError } from "openclaw/plugin-sdk/channel-inbound";
|
|
23
22
|
import { resolvePreferredOpenClawTmpDir, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
|
|
23
|
+
import { asDateTimestampMs } from "openclaw/plugin-sdk/number-runtime";
|
|
24
24
|
import { createPluginStateErrorReporter } from "openclaw/plugin-sdk/plugin-state-runtime";
|
|
25
25
|
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
26
26
|
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
@@ -313,7 +313,6 @@ async function maybeResolveIMessageApprovalPollVote(params) {
|
|
|
313
313
|
channel: "imessage",
|
|
314
314
|
accountId: params.accountId,
|
|
315
315
|
senderId: event.actorHandle,
|
|
316
|
-
gatewayUrl: params.gatewayUrl,
|
|
317
316
|
...params.gatewayRuntime ? { gatewayRuntime: params.gatewayRuntime } : {}
|
|
318
317
|
});
|
|
319
318
|
await unregisterIMessageApprovalPollTarget({
|
|
@@ -345,16 +344,10 @@ async function maybeResolveIMessageApprovalPollVote(params) {
|
|
|
345
344
|
throw error;
|
|
346
345
|
}
|
|
347
346
|
}
|
|
348
|
-
function clearIMessageApprovalPollTargetsForTest() {
|
|
349
|
-
pollTargets.clearForTest();
|
|
350
|
-
pollTombstones.clearForTest();
|
|
351
|
-
loadResolveApprovalOverGateway.clear();
|
|
352
|
-
}
|
|
353
347
|
const iMessageApprovalPollTargets = {
|
|
354
348
|
register: registerIMessageApprovalPollTarget,
|
|
355
349
|
unregister: unregisterIMessageApprovalPollTarget,
|
|
356
|
-
registerTombstone: registerIMessageApprovalPollTombstone
|
|
357
|
-
clearForTest: clearIMessageApprovalPollTargetsForTest
|
|
350
|
+
registerTombstone: registerIMessageApprovalPollTombstone
|
|
358
351
|
};
|
|
359
352
|
// extensions/imessage/src/monitor/echo-text-corruption.ts
|
|
360
353
|
function isLeadingEchoTextCorruptionMarker(code) {
|
|
@@ -368,12 +361,7 @@ function normalizeIMessageEchoText(text) {
|
|
|
368
361
|
return normalized.slice(offset).trim() || void 0;
|
|
369
362
|
}
|
|
370
363
|
// extensions/imessage/src/monitor/persisted-echo-cache.ts
|
|
371
|
-
|
|
372
|
-
function reportFailure(scope, err) {
|
|
373
|
-
if (persistenceFailureLogged) return;
|
|
374
|
-
persistenceFailureLogged = true;
|
|
375
|
-
logVerbose(`imessage echo-cache: ${scope} disabled after first failure: ${String(err)}`);
|
|
376
|
-
}
|
|
364
|
+
const reportFailure = createPersistenceFailureReporter("echo-cache");
|
|
377
365
|
function normalizeMedia(media) {
|
|
378
366
|
if (!resolveIMessageEchoMediaKey(media)) return;
|
|
379
367
|
const contentType = media?.contentType?.trim().toLowerCase() || void 0;
|
|
@@ -393,28 +381,23 @@ function remainingTtlMs(timestamp) {
|
|
|
393
381
|
const remaining = IMESSAGE_SENT_ECHOES_TTL_MS - Math.max(0, Date.now() - timestamp);
|
|
394
382
|
return remaining > 0 ? remaining : void 0;
|
|
395
383
|
}
|
|
396
|
-
function resolveEntryTtlMs(entry, ttlMs) {
|
|
397
|
-
if (typeof ttlMs === "number" && Number.isFinite(ttlMs) && ttlMs > 0) return ttlMs;
|
|
398
|
-
return remainingTtlMs(entry.timestamp);
|
|
399
|
-
}
|
|
400
384
|
function isLiveEntry(entry, now = Date.now()) {
|
|
401
385
|
const cutoff = now - IMESSAGE_SENT_ECHOES_TTL_MS;
|
|
402
386
|
return entry.timestamp >= cutoff && (entry.expiresAt == null || entry.expiresAt > now);
|
|
403
387
|
}
|
|
404
388
|
async function readRecentEntries() {
|
|
405
389
|
try {
|
|
406
|
-
return (await openPersistedEchoStore().entries()).map(({ value }) => value).filter((entry) => isLiveEntry(entry))
|
|
390
|
+
return (await openPersistedEchoStore().entries()).map(({ value }) => value).filter((entry) => isLiveEntry(entry));
|
|
407
391
|
} catch (err) {
|
|
408
392
|
reportFailure("read", err);
|
|
409
393
|
return [];
|
|
410
394
|
}
|
|
411
395
|
}
|
|
412
396
|
async function persistEntry(entry, ttlMs) {
|
|
413
|
-
|
|
414
|
-
if (!effectiveTtlMs) return;
|
|
397
|
+
if (!ttlMs) return;
|
|
415
398
|
const key = resolveIMessageSentEchoEntryKey(entry);
|
|
416
399
|
try {
|
|
417
|
-
await openPersistedEchoStore().register(key, entry, { ttlMs
|
|
400
|
+
await openPersistedEchoStore().register(key, entry, { ttlMs });
|
|
418
401
|
} catch (err) {
|
|
419
402
|
reportFailure("write", err);
|
|
420
403
|
return;
|
|
@@ -433,9 +416,10 @@ async function rememberPersistedIMessageEcho(params) {
|
|
|
433
416
|
...messageId ? { messageId } : {},
|
|
434
417
|
...params.pending ? { pending: true } : {}
|
|
435
418
|
};
|
|
436
|
-
|
|
419
|
+
const ttlMs = typeof params.ttlMs === "number" && Number.isFinite(params.ttlMs) && params.ttlMs > 0 ? params.ttlMs : void 0;
|
|
420
|
+
if (ttlMs !== void 0) entry.expiresAt = entry.timestamp + ttlMs;
|
|
437
421
|
if (!entry.text && !entry.media && !entry.messageId) return;
|
|
438
|
-
return await persistEntry(entry,
|
|
422
|
+
return await persistEntry(entry, ttlMs ?? remainingTtlMs(entry.timestamp));
|
|
439
423
|
}
|
|
440
424
|
async function forgetPersistedIMessageEchoKey(key) {
|
|
441
425
|
if (!key) return;
|
|
@@ -463,14 +447,13 @@ async function hasPersistedIMessageEcho(params) {
|
|
|
463
447
|
function bindIMessageCliSend(handoff, options) {
|
|
464
448
|
const effect = captureEffectAuthority();
|
|
465
449
|
const assertReadAuthority = captureChannelReadAuthority();
|
|
466
|
-
const runCli = handoff.runCliJson ?? ((args) => runIMessageCliJsonCommand({
|
|
467
|
-
...options,
|
|
468
|
-
args
|
|
469
|
-
}));
|
|
470
450
|
return (args) => effect.initiate(() => {
|
|
471
451
|
assertReadAuthority?.();
|
|
472
452
|
handoff.assertDirectAdapterHandoff?.();
|
|
473
|
-
return
|
|
453
|
+
return runIMessageCliJsonCommand({
|
|
454
|
+
...options,
|
|
455
|
+
args
|
|
456
|
+
});
|
|
474
457
|
});
|
|
475
458
|
}
|
|
476
459
|
function normalizeIMessageRpcSendError(error) {
|
|
@@ -517,74 +500,25 @@ function canResolveLatestSentMessageGuidFromChatDb(dbPath) {
|
|
|
517
500
|
return false;
|
|
518
501
|
}
|
|
519
502
|
}
|
|
520
|
-
async function resolveApprovalBindingMessageGuid(params) {
|
|
521
|
-
for (const key of [
|
|
522
|
-
"messageGuid",
|
|
523
|
-
"guid",
|
|
524
|
-
"messageId",
|
|
525
|
-
"message_id",
|
|
526
|
-
"id"
|
|
527
|
-
]) {
|
|
528
|
-
const guid = normalizeResolvedMessageGuid(params.result?.[key]);
|
|
529
|
-
if (guid) return guid;
|
|
530
|
-
}
|
|
531
|
-
const messageId = params.messageId?.trim();
|
|
532
|
-
if (!messageId || !isNumericMessageRowId(messageId)) return null;
|
|
533
|
-
if (params.resolveMessageGuidImpl) return normalizeResolvedMessageGuid(await params.resolveMessageGuidImpl({
|
|
534
|
-
dbPath: params.dbPath,
|
|
535
|
-
messageId
|
|
536
|
-
}));
|
|
537
|
-
const dbPath = params.dbPath?.trim();
|
|
538
|
-
return dbPath ? normalizeResolvedMessageGuid(await withIMessageReceiptGuidReader(dbPath, (read) => read({
|
|
539
|
-
type: "messageGuid",
|
|
540
|
-
input: { messageId }
|
|
541
|
-
}))) : null;
|
|
542
|
-
}
|
|
543
503
|
async function resolveFallbackSentMessageGuid(params) {
|
|
544
504
|
const dbPath = params.dbPath?.trim();
|
|
545
|
-
if (!
|
|
505
|
+
if (!dbPath || !canResolveLatestSentMessageGuidFromChatDb(dbPath)) return null;
|
|
546
506
|
const deadlineMs = Date.now() + 5e3;
|
|
547
|
-
|
|
507
|
+
return await withIMessageReceiptGuidReader(dbPath, async (read) => {
|
|
548
508
|
while (Date.now() <= deadlineMs) {
|
|
549
|
-
const resolved = normalizeResolvedMessageGuid(await
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
509
|
+
const resolved = normalizeResolvedMessageGuid(await read({
|
|
510
|
+
type: "latestSentGuid",
|
|
511
|
+
input: {
|
|
512
|
+
target: params.target,
|
|
513
|
+
text: params.text,
|
|
514
|
+
sentAfterMs: params.sentAfterMs
|
|
515
|
+
}
|
|
554
516
|
}));
|
|
555
517
|
if (resolved) return resolved;
|
|
556
518
|
if (Date.now() >= deadlineMs) return null;
|
|
557
519
|
await sleep(250);
|
|
558
520
|
}
|
|
559
521
|
return null;
|
|
560
|
-
};
|
|
561
|
-
if (params.resolveSentMessageGuidImpl) return await poll(params.resolveSentMessageGuidImpl);
|
|
562
|
-
if (!dbPath) return null;
|
|
563
|
-
return await withIMessageReceiptGuidReader(dbPath, (read) => poll(({ target, text, sentAfterMs }) => read({
|
|
564
|
-
type: "latestSentGuid",
|
|
565
|
-
input: {
|
|
566
|
-
target,
|
|
567
|
-
text,
|
|
568
|
-
sentAfterMs
|
|
569
|
-
}
|
|
570
|
-
})));
|
|
571
|
-
}
|
|
572
|
-
function createIMessageSendReceipt(params) {
|
|
573
|
-
const messageId = params.messageId.trim();
|
|
574
|
-
const results = normalizeIMessageMessageId(messageId) ? [{
|
|
575
|
-
channel: "imessage",
|
|
576
|
-
messageId,
|
|
577
|
-
meta: { targetKind: params.target.kind }
|
|
578
|
-
}] : [];
|
|
579
|
-
if (results[0]) {
|
|
580
|
-
if (params.target.kind === "chat_id") results[0].chatId = String(params.target.chatId);
|
|
581
|
-
else if (params.target.kind === "chat_guid") results[0].conversationId = params.target.chatGuid;
|
|
582
|
-
else if (params.target.kind === "chat_identifier") results[0].conversationId = params.target.chatIdentifier;
|
|
583
|
-
}
|
|
584
|
-
return createMessageReceiptFromOutboundResults({
|
|
585
|
-
results,
|
|
586
|
-
kind: params.kind,
|
|
587
|
-
...params.replyToId ? { replyToId: params.replyToId } : {}
|
|
588
522
|
});
|
|
589
523
|
}
|
|
590
524
|
async function withOriginalIMessageAttachmentPath(filePath, send) {
|
|
@@ -595,12 +529,6 @@ async function withOriginalIMessageAttachmentPath(filePath, send) {
|
|
|
595
529
|
prefix: "openclaw-imessage-outbound-"
|
|
596
530
|
}, async (workspace) => await send(await workspace.copyIn(filename, filePath)));
|
|
597
531
|
}
|
|
598
|
-
function resolveOutboundEchoScope(params) {
|
|
599
|
-
if (params.target.kind === "chat_id") return `${params.accountId}:${formatIMessageChatTarget(params.target.chatId)}`;
|
|
600
|
-
if (params.target.kind === "chat_guid") return `${params.accountId}:chat_guid:${params.target.chatGuid}`;
|
|
601
|
-
if (params.target.kind === "chat_identifier") return `${params.accountId}:chat_identifier:${params.target.chatIdentifier}`;
|
|
602
|
-
return `${params.accountId}:imessage:${params.target.to}`;
|
|
603
|
-
}
|
|
604
532
|
function resolveIMessageSendFailure(result) {
|
|
605
533
|
if (result.success !== false) return null;
|
|
606
534
|
return typeof result.error === "string" && result.error.trim() ? result.error.trim() : "iMessage action failed";
|
|
@@ -664,7 +592,7 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
664
592
|
const timeoutMs = opts.timeoutMs ?? Math.max(account.config.probeTimeoutMs ?? 0, 18e4);
|
|
665
593
|
const pendingEchoTtlMs = Math.max(MIN_PENDING_PERSISTED_ECHO_TTL_MS, Math.max(0, timeoutMs) + PENDING_PERSISTED_ECHO_GRACE_MS);
|
|
666
594
|
const region = opts.region?.trim() || account.config.region?.trim() || "US";
|
|
667
|
-
const maxBytes =
|
|
595
|
+
const maxBytes = opts.maxBytes ?? (account.config.mediaMaxMb ?? 16) * 1024 * 1024;
|
|
668
596
|
let message = opts.approvalPrompt ? addApprovalReactionHintToText({
|
|
669
597
|
text,
|
|
670
598
|
allowedDecisions: opts.approvalPrompt.allowedDecisions
|
|
@@ -674,7 +602,7 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
674
602
|
let filePath;
|
|
675
603
|
let mediaContentType;
|
|
676
604
|
if (opts.mediaUrl?.trim()) {
|
|
677
|
-
const resolved = await
|
|
605
|
+
const resolved = await resolveOutboundAttachmentFromUrl(opts.mediaUrl.trim(), maxBytes, {
|
|
678
606
|
mediaAccess: opts.mediaAccess,
|
|
679
607
|
localRoots: opts.mediaLocalRoots,
|
|
680
608
|
readFile: opts.mediaReadFile
|
|
@@ -717,7 +645,7 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
717
645
|
});
|
|
718
646
|
const requestOwnedRpc = async (method, rpcParams) => {
|
|
719
647
|
opts.assertDirectAdapterHandoff?.();
|
|
720
|
-
const rpcClient = await
|
|
648
|
+
const rpcClient = await createIMessageRpcClient({
|
|
721
649
|
cliPath,
|
|
722
650
|
dbPath,
|
|
723
651
|
remoteHost
|
|
@@ -728,10 +656,109 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
728
656
|
await rpcClient.stop();
|
|
729
657
|
}
|
|
730
658
|
};
|
|
731
|
-
const
|
|
659
|
+
const echoScope = target.kind === "chat_id" ? `${account.accountId}:${formatIMessageChatTarget(target.chatId)}` : target.kind === "chat_guid" ? `${account.accountId}:chat_guid:${target.chatGuid}` : target.kind === "chat_identifier" ? `${account.accountId}:chat_identifier:${target.chatIdentifier}` : `${account.accountId}:imessage:${target.to}`;
|
|
660
|
+
async function recordAcceptedSend(result, delivery) {
|
|
661
|
+
const isMessage = delivery.kind === "message";
|
|
662
|
+
const resolvedId = resolveMessageId(result);
|
|
663
|
+
const messageId = resolvedId ?? (result.ok || result.success || isMessage && result.status === "sent" ? "ok" : "unknown");
|
|
664
|
+
let guid = null;
|
|
665
|
+
for (const key of [
|
|
666
|
+
"messageGuid",
|
|
667
|
+
"guid",
|
|
668
|
+
"messageId",
|
|
669
|
+
"message_id",
|
|
670
|
+
"id"
|
|
671
|
+
]) {
|
|
672
|
+
guid = normalizeResolvedMessageGuid(result[key]);
|
|
673
|
+
if (guid) break;
|
|
674
|
+
}
|
|
675
|
+
if (!guid) {
|
|
676
|
+
const rowId = resolvedId?.trim();
|
|
677
|
+
if (rowId && isNumericMessageRowId(rowId)) {
|
|
678
|
+
const lookupPath = chatDbLookupPath?.trim();
|
|
679
|
+
if (lookupPath) guid = normalizeResolvedMessageGuid(await withIMessageReceiptGuidReader(lookupPath, (read) => read({
|
|
680
|
+
type: "messageGuid",
|
|
681
|
+
input: { messageId: rowId }
|
|
682
|
+
})));
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
if (!guid && isMessage && opts.approvalPrompt && !filePath && !effectiveReplyToId) guid = await resolveFallbackSentMessageGuid({
|
|
686
|
+
dbPath: chatDbLookupPath,
|
|
687
|
+
target,
|
|
688
|
+
text: message,
|
|
689
|
+
sentAfterMs: delivery.startedAtMs
|
|
690
|
+
});
|
|
691
|
+
await rememberPersistedIMessageEcho({
|
|
692
|
+
scope: echoScope,
|
|
693
|
+
text: isMessage ? echoText : void 0,
|
|
694
|
+
media: echoMedia,
|
|
695
|
+
messageId: resolvedId ?? void 0
|
|
696
|
+
});
|
|
697
|
+
const providerChatGuid = isMessage ? normalizeOptionalString(result.chat_guid) ?? normalizeOptionalString(result.chatGuid) : void 0;
|
|
698
|
+
const confirmedService = isMessage ? resolveIMessageDirectChatService(resultService(result.service) ?? service, providerChatGuid) : void 0;
|
|
699
|
+
if (resolvedId && normalizeIMessageMessageId(resolvedId)) {
|
|
700
|
+
const chatContext = isMessage ? {
|
|
701
|
+
...chatContextFromIMessageTarget(target, confirmedService ?? service),
|
|
702
|
+
...providerChatGuid ? { chatGuid: providerChatGuid } : {}
|
|
703
|
+
} : {
|
|
704
|
+
chatGuid: target.kind === "chat_guid" ? target.chatGuid : target.kind === "chat_id" ? delivery.chatTarget : void 0,
|
|
705
|
+
chatIdentifier: target.kind === "chat_identifier" || target.kind === "handle" ? delivery.chatTarget : void 0,
|
|
706
|
+
chatId: target.kind === "chat_id" ? target.chatId : void 0
|
|
707
|
+
};
|
|
708
|
+
await rememberIMessageReplyCache({
|
|
709
|
+
accountId: account.accountId,
|
|
710
|
+
messageId: resolvedId,
|
|
711
|
+
...chatContext,
|
|
712
|
+
timestamp: Date.now(),
|
|
713
|
+
isFromMe: true
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
if (isMessage && message && guid && opts.approvalPrompt) {
|
|
717
|
+
const handle = target.kind === "handle" ? normalizeIMessageHandle(target.to) : void 0;
|
|
718
|
+
const conversation = {
|
|
719
|
+
...target.kind === "chat_guid" ? { chatGuid: target.chatGuid } : {},
|
|
720
|
+
...target.kind === "chat_identifier" ? { chatIdentifier: target.chatIdentifier } : {},
|
|
721
|
+
...target.kind === "chat_id" ? { chatId: target.chatId } : {},
|
|
722
|
+
...handle ? { handle } : {}
|
|
723
|
+
};
|
|
724
|
+
await registerIMessageApprovalReactionTarget({
|
|
725
|
+
accountId: account.accountId,
|
|
726
|
+
conversation,
|
|
727
|
+
messageId: guid,
|
|
728
|
+
approvalId: opts.approvalPrompt.approvalId,
|
|
729
|
+
approvalKind: opts.approvalPrompt.approvalKind,
|
|
730
|
+
allowedDecisions: opts.approvalPrompt.allowedDecisions
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
const replyToId = isMessage ? effectiveReplyToId : resolvedReplyToId;
|
|
734
|
+
const receiptMessageId = messageId.trim();
|
|
735
|
+
const results = normalizeIMessageMessageId(receiptMessageId) ? [{
|
|
736
|
+
channel: "imessage",
|
|
737
|
+
messageId: receiptMessageId,
|
|
738
|
+
meta: { targetKind: target.kind }
|
|
739
|
+
}] : [];
|
|
740
|
+
if (results[0]) {
|
|
741
|
+
if (target.kind === "chat_id") results[0].chatId = String(target.chatId);
|
|
742
|
+
else if (target.kind === "chat_guid") results[0].conversationId = target.chatGuid;
|
|
743
|
+
else if (target.kind === "chat_identifier") results[0].conversationId = target.chatIdentifier;
|
|
744
|
+
}
|
|
745
|
+
return {
|
|
746
|
+
messageId,
|
|
747
|
+
...guid ? { guid } : {},
|
|
748
|
+
...confirmedService ? { service: confirmedService } : {},
|
|
749
|
+
...providerChatGuid ? { chatGuid: providerChatGuid } : {},
|
|
750
|
+
sentText: isMessage ? message : "",
|
|
751
|
+
...isMessage && echoText ? { echoText } : {},
|
|
752
|
+
...echoMedia ? { echoMedia } : {},
|
|
753
|
+
receipt: createMessageReceiptFromOutboundResults({
|
|
754
|
+
results,
|
|
755
|
+
kind: isMessage ? filePath ? "media" : "text" : delivery.audioAsVoice ? "voice" : "media",
|
|
756
|
+
...replyToId ? { replyToId } : {}
|
|
757
|
+
})
|
|
758
|
+
};
|
|
759
|
+
}
|
|
732
760
|
async function trySendAttachment(attachmentFilePath) {
|
|
733
|
-
const { audioAsVoice,
|
|
734
|
-
const accountId = account.accountId;
|
|
761
|
+
const { audioAsVoice, assertDirectAdapterHandoff, onPlatformSendDispatch } = opts;
|
|
735
762
|
if (audioAsVoice && sendTransport === "applescript") throw new Error("iMessage voice messages require bridge transport; AppleScript cannot send native voice notes. Set sendTransport to bridge or auto.");
|
|
736
763
|
if (target.kind === "handle" && !audioAsVoice && sendTransport !== "bridge" && (service === "sms" || service === "imessage")) return null;
|
|
737
764
|
if (remoteHost && sendTransport === "applescript") return null;
|
|
@@ -763,10 +790,6 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
763
790
|
return null;
|
|
764
791
|
}
|
|
765
792
|
assertDirectAdapterHandoff?.();
|
|
766
|
-
const echoScope = resolveOutboundEchoScope({
|
|
767
|
-
accountId,
|
|
768
|
-
target
|
|
769
|
-
});
|
|
770
793
|
let result;
|
|
771
794
|
let pendingEchoKey;
|
|
772
795
|
try {
|
|
@@ -777,7 +800,7 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
777
800
|
pending: true
|
|
778
801
|
});
|
|
779
802
|
result = await withOriginalIMessageAttachmentPath(attachmentFilePath, async (attachmentPath) => {
|
|
780
|
-
if (remoteHost) return await
|
|
803
|
+
if (remoteHost) return await withIMessageRemoteFile({
|
|
781
804
|
remoteHost,
|
|
782
805
|
localPath: attachmentPath,
|
|
783
806
|
timeoutMs,
|
|
@@ -816,40 +839,11 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
816
839
|
if (!audioAsVoice && isAttachmentCommandFallbackError(error)) return null;
|
|
817
840
|
throw error;
|
|
818
841
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
result,
|
|
824
|
-
resolveMessageGuidImpl
|
|
842
|
+
return await recordAcceptedSend(result, {
|
|
843
|
+
kind: "attachment",
|
|
844
|
+
chatTarget: attachmentChatTarget,
|
|
845
|
+
audioAsVoice
|
|
825
846
|
});
|
|
826
|
-
const messageId = resolvedId ?? (result.ok || result.success ? "ok" : "unknown");
|
|
827
|
-
await rememberPersistedIMessageEcho({
|
|
828
|
-
scope: echoScope,
|
|
829
|
-
media: echoMedia,
|
|
830
|
-
messageId: resolvedId ?? void 0
|
|
831
|
-
});
|
|
832
|
-
if (resolvedId && normalizeIMessageMessageId(resolvedId)) await rememberIMessageReplyCache({
|
|
833
|
-
accountId,
|
|
834
|
-
messageId: resolvedId,
|
|
835
|
-
chatGuid: target.kind === "chat_guid" ? target.chatGuid : target.kind === "chat_id" ? attachmentChatTarget : void 0,
|
|
836
|
-
chatIdentifier: target.kind === "chat_identifier" || target.kind === "handle" ? attachmentChatTarget : void 0,
|
|
837
|
-
chatId: target.kind === "chat_id" ? target.chatId : void 0,
|
|
838
|
-
timestamp: Date.now(),
|
|
839
|
-
isFromMe: true
|
|
840
|
-
});
|
|
841
|
-
return {
|
|
842
|
-
messageId,
|
|
843
|
-
...approvalBindingMessageId ? { guid: approvalBindingMessageId } : {},
|
|
844
|
-
sentText: "",
|
|
845
|
-
...echoMedia ? { echoMedia } : {},
|
|
846
|
-
receipt: createIMessageSendReceipt({
|
|
847
|
-
messageId,
|
|
848
|
-
target,
|
|
849
|
-
kind: audioAsVoice ? "voice" : "media",
|
|
850
|
-
...resolvedReplyToId ? { replyToId: resolvedReplyToId } : {}
|
|
851
|
-
})
|
|
852
|
-
};
|
|
853
847
|
}
|
|
854
848
|
if (filePath && (!resolvedReplyToId || opts.audioAsVoice)) {
|
|
855
849
|
const attachmentResult = await trySendAttachment(filePath);
|
|
@@ -891,6 +885,7 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
891
885
|
}
|
|
892
886
|
}
|
|
893
887
|
const params = {
|
|
888
|
+
...iMessageTargetRpcParams(target),
|
|
894
889
|
text: message,
|
|
895
890
|
service: service || "auto",
|
|
896
891
|
region,
|
|
@@ -899,16 +894,8 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
899
894
|
if (resolvedReplyToId) params.reply_to = resolvedReplyToId;
|
|
900
895
|
if (formatted.ranges.length > 0) params.formatting = formatted.ranges;
|
|
901
896
|
if (filePath) params.file = filePath;
|
|
902
|
-
if (target.kind === "chat_id") params.chat_id = target.chatId;
|
|
903
|
-
else if (target.kind === "chat_guid") params.chat_guid = target.chatGuid;
|
|
904
|
-
else if (target.kind === "chat_identifier") params.chat_identifier = target.chatIdentifier;
|
|
905
|
-
else params.to = target.to;
|
|
906
|
-
const echoScope = resolveOutboundEchoScope({
|
|
907
|
-
accountId: account.accountId,
|
|
908
|
-
target
|
|
909
|
-
});
|
|
910
897
|
opts.assertDirectAdapterHandoff?.();
|
|
911
|
-
const client = opts.client ?? await
|
|
898
|
+
const client = opts.client ?? await createIMessageRpcClient({
|
|
912
899
|
cliPath,
|
|
913
900
|
dbPath,
|
|
914
901
|
remoteHost
|
|
@@ -917,7 +904,7 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
917
904
|
const requestSuccessfulSend = async (sendParams) => {
|
|
918
905
|
const request = async (nativeParams) => await requestIMessageRpcSend(client, "send", nativeParams, timeoutMs, opts);
|
|
919
906
|
const response = filePath ? await withOriginalIMessageAttachmentPath(filePath, async (attachmentPath) => {
|
|
920
|
-
if (remoteHost) return await
|
|
907
|
+
if (remoteHost) return await withIMessageRemoteFile({
|
|
921
908
|
remoteHost,
|
|
922
909
|
localPath: attachmentPath,
|
|
923
910
|
timeoutMs,
|
|
@@ -956,14 +943,13 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
956
943
|
result = await requestSuccessfulSend(plainParams);
|
|
957
944
|
effectiveReplyToId = void 0;
|
|
958
945
|
} else if (filePath || !isIMessageRpcSendTimeout(error)) throw error;
|
|
959
|
-
else if (!opts.approvalPrompt || resolvedReplyToId || !
|
|
946
|
+
else if (!opts.approvalPrompt || resolvedReplyToId || !canResolveLatestSentMessageGuidFromChatDb(chatDbLookupPath)) throw error;
|
|
960
947
|
else {
|
|
961
948
|
const recoveredGuid = await resolveFallbackSentMessageGuid({
|
|
962
949
|
dbPath: chatDbLookupPath,
|
|
963
950
|
target,
|
|
964
951
|
text: message,
|
|
965
|
-
sentAfterMs: sendStartedAtMs
|
|
966
|
-
resolveSentMessageGuidImpl: opts.resolveSentMessageGuidImpl
|
|
952
|
+
sentAfterMs: sendStartedAtMs
|
|
967
953
|
});
|
|
968
954
|
if (recoveredGuid) result = {
|
|
969
955
|
guid: recoveredGuid,
|
|
@@ -972,72 +958,10 @@ async function sendMessageIMessage(to, text, opts) {
|
|
|
972
958
|
else throw error;
|
|
973
959
|
}
|
|
974
960
|
}
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
dbPath: chatDbLookupPath,
|
|
979
|
-
messageId: resolvedId,
|
|
980
|
-
result,
|
|
981
|
-
resolveMessageGuidImpl: opts.resolveMessageGuidImpl
|
|
982
|
-
});
|
|
983
|
-
if (!approvalBindingMessageId && opts.approvalPrompt && !filePath && !effectiveReplyToId) approvalBindingMessageId = await resolveFallbackSentMessageGuid({
|
|
984
|
-
dbPath: chatDbLookupPath,
|
|
985
|
-
target,
|
|
986
|
-
text: message,
|
|
987
|
-
sentAfterMs: sendStartedAtMs,
|
|
988
|
-
resolveSentMessageGuidImpl: opts.resolveSentMessageGuidImpl
|
|
989
|
-
});
|
|
990
|
-
await rememberPersistedIMessageEcho({
|
|
991
|
-
scope: echoScope,
|
|
992
|
-
text: echoText,
|
|
993
|
-
media: echoMedia,
|
|
994
|
-
messageId: resolvedId ?? void 0
|
|
961
|
+
return await recordAcceptedSend(result, {
|
|
962
|
+
kind: "message",
|
|
963
|
+
startedAtMs: sendStartedAtMs
|
|
995
964
|
});
|
|
996
|
-
const providerChatGuid = normalizeOptionalString(result.chat_guid) ?? normalizeOptionalString(result.chatGuid);
|
|
997
|
-
const confirmedService = resolveIMessageDirectChatService(resultService(result.service) ?? service, providerChatGuid);
|
|
998
|
-
if (resolvedId && normalizeIMessageMessageId(resolvedId)) {
|
|
999
|
-
const chatContext = chatContextFromIMessageTarget(target, confirmedService ?? service);
|
|
1000
|
-
await rememberIMessageReplyCache({
|
|
1001
|
-
accountId: account.accountId,
|
|
1002
|
-
messageId: resolvedId,
|
|
1003
|
-
...chatContext,
|
|
1004
|
-
...providerChatGuid ? { chatGuid: providerChatGuid } : {},
|
|
1005
|
-
timestamp: Date.now(),
|
|
1006
|
-
isFromMe: true
|
|
1007
|
-
});
|
|
1008
|
-
}
|
|
1009
|
-
if (message && approvalBindingMessageId && opts.approvalPrompt) {
|
|
1010
|
-
const handleForKey = target.kind === "handle" ? normalizeIMessageHandle(target.to) : void 0;
|
|
1011
|
-
const conversation = {
|
|
1012
|
-
...target.kind === "chat_guid" ? { chatGuid: target.chatGuid } : {},
|
|
1013
|
-
...target.kind === "chat_identifier" ? { chatIdentifier: target.chatIdentifier } : {},
|
|
1014
|
-
...target.kind === "chat_id" ? { chatId: target.chatId } : {},
|
|
1015
|
-
...handleForKey ? { handle: handleForKey } : {}
|
|
1016
|
-
};
|
|
1017
|
-
await registerIMessageApprovalReactionTarget({
|
|
1018
|
-
accountId: account.accountId,
|
|
1019
|
-
conversation,
|
|
1020
|
-
messageId: approvalBindingMessageId,
|
|
1021
|
-
approvalId: opts.approvalPrompt.approvalId,
|
|
1022
|
-
approvalKind: opts.approvalPrompt.approvalKind,
|
|
1023
|
-
allowedDecisions: opts.approvalPrompt.allowedDecisions
|
|
1024
|
-
});
|
|
1025
|
-
}
|
|
1026
|
-
return {
|
|
1027
|
-
messageId,
|
|
1028
|
-
...approvalBindingMessageId ? { guid: approvalBindingMessageId } : {},
|
|
1029
|
-
...confirmedService ? { service: confirmedService } : {},
|
|
1030
|
-
...providerChatGuid ? { chatGuid: providerChatGuid } : {},
|
|
1031
|
-
sentText: message,
|
|
1032
|
-
...echoText ? { echoText } : {},
|
|
1033
|
-
...echoMedia ? { echoMedia } : {},
|
|
1034
|
-
receipt: createIMessageSendReceipt({
|
|
1035
|
-
messageId,
|
|
1036
|
-
target,
|
|
1037
|
-
kind: filePath ? "media" : "text",
|
|
1038
|
-
...effectiveReplyToId ? { replyToId: effectiveReplyToId } : {}
|
|
1039
|
-
})
|
|
1040
|
-
};
|
|
1041
965
|
} catch (error) {
|
|
1042
966
|
await forgetPersistedIMessageEchoKey(pendingEchoKey);
|
|
1043
967
|
throw error;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as resolveDefaultIMessageAccountId, o as resolveIMessageAccount } from "./accounts-
|
|
1
|
+
import { s as normalizeIMessageHandle, u as IMESSAGE_CHAT_TARGET_PREFIX_RE } from "./targets-C7CIWJ0k.mjs";
|
|
2
|
+
import { a as resolveDefaultIMessageAccountId, o as resolveIMessageAccount } from "./accounts-C1Ypv3Wn.mjs";
|
|
3
3
|
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
import { parseAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
|
|
5
5
|
import { createChannelDmPolicy } from "openclaw/plugin-sdk/channel-dm-policy";
|