@archipelagolab/lobi 1.0.0

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.
Files changed (315) hide show
  1. package/CHANGELOG.md +164 -0
  2. package/ENDOFFILE +0 -0
  3. package/EOF +0 -0
  4. package/LICENSE +21 -0
  5. package/SPEC-SUPPORT.md +116 -0
  6. package/YAMLEND +0 -0
  7. package/api.ts +18 -0
  8. package/archipelagolab-lobi-1.0.0.tgz +0 -0
  9. package/auth-presence.ts +56 -0
  10. package/channel-plugin-api.ts +3 -0
  11. package/cli-metadata.ts +11 -0
  12. package/contract-api.ts +17 -0
  13. package/docs/CHECKLIST.md +83 -0
  14. package/docs/FORK_SDK_GUIDE.md +279 -0
  15. package/helper-api.ts +3 -0
  16. package/index.test.ts +61 -0
  17. package/index.ts +65 -0
  18. package/openclaw.plugin.json +23 -0
  19. package/package.json +52 -0
  20. package/plugin-entry.handlers.runtime.ts +1 -0
  21. package/runtime-api.ts +54 -0
  22. package/runtime-heavy-api.ts +1 -0
  23. package/scripts/migrate-to-lobi.sh +72 -0
  24. package/secret-contract-api.ts +5 -0
  25. package/setup-entry.ts +13 -0
  26. package/src/account-selection.test.ts +124 -0
  27. package/src/account-selection.ts +226 -0
  28. package/src/actions.account-propagation.test.ts +251 -0
  29. package/src/actions.test.ts +251 -0
  30. package/src/actions.ts +336 -0
  31. package/src/approval-auth.test.ts +23 -0
  32. package/src/approval-auth.ts +25 -0
  33. package/src/approval-handler.runtime.test.ts +46 -0
  34. package/src/approval-handler.runtime.ts +400 -0
  35. package/src/approval-ids.ts +6 -0
  36. package/src/approval-native.test.ts +329 -0
  37. package/src/approval-native.ts +336 -0
  38. package/src/approval-reactions.test.ts +107 -0
  39. package/src/approval-reactions.ts +158 -0
  40. package/src/auth-precedence.ts +61 -0
  41. package/src/channel-account-paths.ts +92 -0
  42. package/src/channel.account-paths.test.ts +102 -0
  43. package/src/channel.directory.test.ts +601 -0
  44. package/src/channel.resolve.test.ts +38 -0
  45. package/src/channel.runtime.ts +16 -0
  46. package/src/channel.setup.test.ts +269 -0
  47. package/src/channel.ts +570 -0
  48. package/src/cli-metadata.ts +19 -0
  49. package/src/cli.test.ts +1015 -0
  50. package/src/cli.ts +1198 -0
  51. package/src/config-adapter.ts +41 -0
  52. package/src/config-schema.test.ts +90 -0
  53. package/src/config-schema.ts +114 -0
  54. package/src/directory-live.test.ts +200 -0
  55. package/src/directory-live.ts +238 -0
  56. package/src/doctor-contract.ts +287 -0
  57. package/src/doctor.test.ts +440 -0
  58. package/src/doctor.ts +262 -0
  59. package/src/env-vars.ts +92 -0
  60. package/src/exec-approval-resolver.test.ts +68 -0
  61. package/src/exec-approval-resolver.ts +23 -0
  62. package/src/exec-approvals.test.ts +483 -0
  63. package/src/exec-approvals.ts +290 -0
  64. package/src/group-mentions.ts +41 -0
  65. package/src/legacy-crypto-inspector-availability.test.ts +81 -0
  66. package/src/legacy-crypto-inspector-availability.ts +60 -0
  67. package/src/legacy-crypto.test.ts +234 -0
  68. package/src/legacy-crypto.ts +549 -0
  69. package/src/legacy-state.test.ts +86 -0
  70. package/src/legacy-state.ts +156 -0
  71. package/src/matrix/account-config.ts +150 -0
  72. package/src/matrix/accounts.readiness.test.ts +27 -0
  73. package/src/matrix/accounts.test.ts +757 -0
  74. package/src/matrix/accounts.ts +194 -0
  75. package/src/matrix/actions/client.test.ts +215 -0
  76. package/src/matrix/actions/client.ts +31 -0
  77. package/src/matrix/actions/devices.test.ts +114 -0
  78. package/src/matrix/actions/devices.ts +34 -0
  79. package/src/matrix/actions/limits.test.ts +15 -0
  80. package/src/matrix/actions/limits.ts +6 -0
  81. package/src/matrix/actions/messages.test.ts +289 -0
  82. package/src/matrix/actions/messages.ts +123 -0
  83. package/src/matrix/actions/pins.test.ts +74 -0
  84. package/src/matrix/actions/pins.ts +64 -0
  85. package/src/matrix/actions/polls.test.ts +71 -0
  86. package/src/matrix/actions/polls.ts +109 -0
  87. package/src/matrix/actions/profile.test.ts +109 -0
  88. package/src/matrix/actions/profile.ts +37 -0
  89. package/src/matrix/actions/reactions.test.ts +135 -0
  90. package/src/matrix/actions/reactions.ts +59 -0
  91. package/src/matrix/actions/room.test.ts +79 -0
  92. package/src/matrix/actions/room.ts +71 -0
  93. package/src/matrix/actions/summary.test.ts +87 -0
  94. package/src/matrix/actions/summary.ts +88 -0
  95. package/src/matrix/actions/types.ts +82 -0
  96. package/src/matrix/actions/verification.test.ts +105 -0
  97. package/src/matrix/actions/verification.ts +237 -0
  98. package/src/matrix/actions.ts +37 -0
  99. package/src/matrix/active-client.ts +26 -0
  100. package/src/matrix/async-lock.ts +18 -0
  101. package/src/matrix/backup-health.ts +115 -0
  102. package/src/matrix/client/config-runtime-api.ts +14 -0
  103. package/src/matrix/client/config-secret-input.runtime.ts +1 -0
  104. package/src/matrix/client/config.ts +982 -0
  105. package/src/matrix/client/create-client.test.ts +115 -0
  106. package/src/matrix/client/create-client.ts +101 -0
  107. package/src/matrix/client/env-auth.ts +6 -0
  108. package/src/matrix/client/file-sync-store.test.ts +265 -0
  109. package/src/matrix/client/file-sync-store.ts +289 -0
  110. package/src/matrix/client/logging.ts +123 -0
  111. package/src/matrix/client/migration-snapshot.runtime.ts +1 -0
  112. package/src/matrix/client/private-network-host.ts +56 -0
  113. package/src/matrix/client/runtime.ts +4 -0
  114. package/src/matrix/client/shared.test.ts +344 -0
  115. package/src/matrix/client/shared.ts +306 -0
  116. package/src/matrix/client/storage.test.ts +634 -0
  117. package/src/matrix/client/storage.ts +544 -0
  118. package/src/matrix/client/types.ts +50 -0
  119. package/src/matrix/client-bootstrap.test.ts +84 -0
  120. package/src/matrix/client-bootstrap.ts +164 -0
  121. package/src/matrix/client-resolver.test-helpers.ts +147 -0
  122. package/src/matrix/client.test.ts +1521 -0
  123. package/src/matrix/client.ts +23 -0
  124. package/src/matrix/config-paths.ts +31 -0
  125. package/src/matrix/config-update.test.ts +237 -0
  126. package/src/matrix/config-update.ts +291 -0
  127. package/src/matrix/credentials-read.ts +206 -0
  128. package/src/matrix/credentials-write.runtime.ts +26 -0
  129. package/src/matrix/credentials.test.ts +501 -0
  130. package/src/matrix/credentials.ts +95 -0
  131. package/src/matrix/deps.test.ts +74 -0
  132. package/src/matrix/deps.ts +225 -0
  133. package/src/matrix/device-health.test.ts +45 -0
  134. package/src/matrix/device-health.ts +31 -0
  135. package/src/matrix/direct-management.test.ts +350 -0
  136. package/src/matrix/direct-management.ts +347 -0
  137. package/src/matrix/direct-room.test.ts +61 -0
  138. package/src/matrix/direct-room.ts +128 -0
  139. package/src/matrix/draft-stream.test.ts +406 -0
  140. package/src/matrix/draft-stream.ts +216 -0
  141. package/src/matrix/encryption-guidance.ts +27 -0
  142. package/src/matrix/errors.ts +21 -0
  143. package/src/matrix/format.test.ts +340 -0
  144. package/src/matrix/format.ts +428 -0
  145. package/src/matrix/legacy-crypto-inspector.ts +95 -0
  146. package/src/matrix/media-errors.ts +20 -0
  147. package/src/matrix/media-text.ts +169 -0
  148. package/src/matrix/monitor/access-state.test.ts +45 -0
  149. package/src/matrix/monitor/access-state.ts +77 -0
  150. package/src/matrix/monitor/ack-config.test.ts +57 -0
  151. package/src/matrix/monitor/ack-config.ts +26 -0
  152. package/src/matrix/monitor/allowlist.test.ts +45 -0
  153. package/src/matrix/monitor/allowlist.ts +94 -0
  154. package/src/matrix/monitor/auto-join.test.ts +203 -0
  155. package/src/matrix/monitor/auto-join.ts +86 -0
  156. package/src/matrix/monitor/config.test.ts +197 -0
  157. package/src/matrix/monitor/config.ts +303 -0
  158. package/src/matrix/monitor/context-summary.ts +43 -0
  159. package/src/matrix/monitor/direct.test.ts +529 -0
  160. package/src/matrix/monitor/direct.ts +270 -0
  161. package/src/matrix/monitor/events.test.ts +1524 -0
  162. package/src/matrix/monitor/events.ts +213 -0
  163. package/src/matrix/monitor/handler.body-for-agent.test.ts +396 -0
  164. package/src/matrix/monitor/handler.group-history.test.ts +648 -0
  165. package/src/matrix/monitor/handler.media-failure.test.ts +267 -0
  166. package/src/matrix/monitor/handler.test-helpers.ts +308 -0
  167. package/src/matrix/monitor/handler.test.ts +2952 -0
  168. package/src/matrix/monitor/handler.thread-root-media.test.ts +82 -0
  169. package/src/matrix/monitor/handler.ts +1679 -0
  170. package/src/matrix/monitor/inbound-dedupe.test.ts +146 -0
  171. package/src/matrix/monitor/inbound-dedupe.ts +267 -0
  172. package/src/matrix/monitor/index.test.ts +920 -0
  173. package/src/matrix/monitor/index.ts +434 -0
  174. package/src/matrix/monitor/legacy-crypto-restore.test.ts +206 -0
  175. package/src/matrix/monitor/legacy-crypto-restore.ts +139 -0
  176. package/src/matrix/monitor/location.ts +100 -0
  177. package/src/matrix/monitor/media.test.ts +159 -0
  178. package/src/matrix/monitor/media.ts +119 -0
  179. package/src/matrix/monitor/mentions.test.ts +289 -0
  180. package/src/matrix/monitor/mentions.ts +177 -0
  181. package/src/matrix/monitor/reaction-events.test.ts +326 -0
  182. package/src/matrix/monitor/reaction-events.ts +187 -0
  183. package/src/matrix/monitor/recent-invite.test.ts +92 -0
  184. package/src/matrix/monitor/recent-invite.ts +30 -0
  185. package/src/matrix/monitor/replies.test.ts +265 -0
  186. package/src/matrix/monitor/replies.ts +136 -0
  187. package/src/matrix/monitor/reply-context.test.ts +276 -0
  188. package/src/matrix/monitor/reply-context.ts +92 -0
  189. package/src/matrix/monitor/room-history.test.ts +258 -0
  190. package/src/matrix/monitor/room-history.ts +301 -0
  191. package/src/matrix/monitor/room-info.test.ts +201 -0
  192. package/src/matrix/monitor/room-info.ts +126 -0
  193. package/src/matrix/monitor/rooms.test.ts +121 -0
  194. package/src/matrix/monitor/rooms.ts +52 -0
  195. package/src/matrix/monitor/route.test.ts +255 -0
  196. package/src/matrix/monitor/route.ts +178 -0
  197. package/src/matrix/monitor/runtime-api.ts +31 -0
  198. package/src/matrix/monitor/startup-verification.test.ts +294 -0
  199. package/src/matrix/monitor/startup-verification.ts +237 -0
  200. package/src/matrix/monitor/startup.test.ts +257 -0
  201. package/src/matrix/monitor/startup.ts +218 -0
  202. package/src/matrix/monitor/status.ts +111 -0
  203. package/src/matrix/monitor/sync-lifecycle.test.ts +224 -0
  204. package/src/matrix/monitor/sync-lifecycle.ts +91 -0
  205. package/src/matrix/monitor/task-runner.ts +38 -0
  206. package/src/matrix/monitor/thread-context.test.ts +149 -0
  207. package/src/matrix/monitor/thread-context.ts +108 -0
  208. package/src/matrix/monitor/threads.test.ts +68 -0
  209. package/src/matrix/monitor/threads.ts +85 -0
  210. package/src/matrix/monitor/types.ts +30 -0
  211. package/src/matrix/monitor/verification-events.ts +627 -0
  212. package/src/matrix/monitor/verification-utils.test.ts +47 -0
  213. package/src/matrix/monitor/verification-utils.ts +46 -0
  214. package/src/matrix/outbound-media-runtime.ts +1 -0
  215. package/src/matrix/poll-summary.ts +110 -0
  216. package/src/matrix/poll-types.test.ts +205 -0
  217. package/src/matrix/poll-types.ts +433 -0
  218. package/src/matrix/probe.runtime.ts +4 -0
  219. package/src/matrix/probe.test.ts +154 -0
  220. package/src/matrix/probe.ts +96 -0
  221. package/src/matrix/profile.test.ts +154 -0
  222. package/src/matrix/profile.ts +184 -0
  223. package/src/matrix/reaction-common.test.ts +96 -0
  224. package/src/matrix/reaction-common.ts +147 -0
  225. package/src/matrix/sdk/crypto-bootstrap.test.ts +505 -0
  226. package/src/matrix/sdk/crypto-bootstrap.ts +341 -0
  227. package/src/matrix/sdk/crypto-facade.test.ts +197 -0
  228. package/src/matrix/sdk/crypto-facade.ts +207 -0
  229. package/src/matrix/sdk/crypto-node.runtime.test.ts +27 -0
  230. package/src/matrix/sdk/crypto-node.runtime.ts +9 -0
  231. package/src/matrix/sdk/crypto-runtime.ts +11 -0
  232. package/src/matrix/sdk/decrypt-bridge.ts +356 -0
  233. package/src/matrix/sdk/event-helpers.test.ts +60 -0
  234. package/src/matrix/sdk/event-helpers.ts +71 -0
  235. package/src/matrix/sdk/http-client.test.ts +134 -0
  236. package/src/matrix/sdk/http-client.ts +87 -0
  237. package/src/matrix/sdk/idb-persistence-lock.ts +51 -0
  238. package/src/matrix/sdk/idb-persistence.lock-order.test.ts +108 -0
  239. package/src/matrix/sdk/idb-persistence.test-helpers.ts +88 -0
  240. package/src/matrix/sdk/idb-persistence.test.ts +149 -0
  241. package/src/matrix/sdk/idb-persistence.ts +283 -0
  242. package/src/matrix/sdk/logger.test.ts +25 -0
  243. package/src/matrix/sdk/logger.ts +108 -0
  244. package/src/matrix/sdk/read-response-with-limit.ts +19 -0
  245. package/src/matrix/sdk/recovery-key-store.test.ts +385 -0
  246. package/src/matrix/sdk/recovery-key-store.ts +430 -0
  247. package/src/matrix/sdk/transport.test.ts +161 -0
  248. package/src/matrix/sdk/transport.ts +344 -0
  249. package/src/matrix/sdk/types.ts +236 -0
  250. package/src/matrix/sdk/verification-manager.test.ts +509 -0
  251. package/src/matrix/sdk/verification-manager.ts +694 -0
  252. package/src/matrix/sdk/verification-status.ts +23 -0
  253. package/src/matrix/sdk.test.ts +2568 -0
  254. package/src/matrix/sdk.ts +1789 -0
  255. package/src/matrix/send/client.test.ts +174 -0
  256. package/src/matrix/send/client.ts +90 -0
  257. package/src/matrix/send/formatting.ts +189 -0
  258. package/src/matrix/send/media.ts +244 -0
  259. package/src/matrix/send/targets.test.ts +254 -0
  260. package/src/matrix/send/targets.ts +104 -0
  261. package/src/matrix/send/types.ts +134 -0
  262. package/src/matrix/send.test.ts +958 -0
  263. package/src/matrix/send.ts +609 -0
  264. package/src/matrix/session-store-metadata.ts +108 -0
  265. package/src/matrix/startup-abort.ts +44 -0
  266. package/src/matrix/sync-state.ts +27 -0
  267. package/src/matrix/target-ids.ts +102 -0
  268. package/src/matrix/thread-bindings-shared.ts +201 -0
  269. package/src/matrix/thread-bindings.test.ts +673 -0
  270. package/src/matrix/thread-bindings.ts +577 -0
  271. package/src/matrix-migration.runtime.ts +9 -0
  272. package/src/migration-config.test.ts +228 -0
  273. package/src/migration-config.ts +243 -0
  274. package/src/migration-snapshot-backup.ts +117 -0
  275. package/src/migration-snapshot.test.ts +184 -0
  276. package/src/migration-snapshot.ts +55 -0
  277. package/src/onboarding.resolve.test.ts +55 -0
  278. package/src/onboarding.test-harness.ts +158 -0
  279. package/src/onboarding.test.ts +665 -0
  280. package/src/onboarding.ts +773 -0
  281. package/src/outbound.test.ts +173 -0
  282. package/src/outbound.ts +78 -0
  283. package/src/plugin-entry.runtime.js +159 -0
  284. package/src/plugin-entry.runtime.test.ts +108 -0
  285. package/src/plugin-entry.runtime.ts +68 -0
  286. package/src/profile-update.ts +68 -0
  287. package/src/record-shared.ts +3 -0
  288. package/src/resolve-targets.test.ts +178 -0
  289. package/src/resolve-targets.ts +175 -0
  290. package/src/resolver.ts +21 -0
  291. package/src/runtime-api.ts +144 -0
  292. package/src/runtime.ts +7 -0
  293. package/src/secret-contract.ts +174 -0
  294. package/src/session-route.test.ts +315 -0
  295. package/src/session-route.ts +113 -0
  296. package/src/setup-bootstrap.ts +94 -0
  297. package/src/setup-config.ts +222 -0
  298. package/src/setup-contract.ts +89 -0
  299. package/src/setup-core.test.ts +326 -0
  300. package/src/setup-core.ts +50 -0
  301. package/src/setup-surface.ts +4 -0
  302. package/src/startup-maintenance.test.ts +227 -0
  303. package/src/startup-maintenance.ts +114 -0
  304. package/src/storage-paths.ts +92 -0
  305. package/src/test-helpers.ts +42 -0
  306. package/src/test-mocks.ts +55 -0
  307. package/src/test-runtime.ts +72 -0
  308. package/src/test-support/monitor-route-test-support.ts +8 -0
  309. package/src/tool-actions.runtime.ts +1 -0
  310. package/src/tool-actions.test.ts +422 -0
  311. package/src/tool-actions.ts +498 -0
  312. package/src/types.ts +230 -0
  313. package/test-api.ts +2 -0
  314. package/thread-bindings-runtime.ts +4 -0
  315. package/tsconfig.json +16 -0
@@ -0,0 +1,88 @@
1
+ import { isMatrixNotFoundError } from "../errors.js";
2
+ import { resolveMatrixMessageAttachment, resolveMatrixMessageBody } from "../media-text.js";
3
+ import { fetchMatrixPollMessageSummary } from "../poll-summary.js";
4
+ import type { MatrixClient } from "../sdk.js";
5
+ import {
6
+ EventType,
7
+ type MatrixMessageSummary,
8
+ type MatrixRawEvent,
9
+ type RoomMessageEventContent,
10
+ type RoomPinnedEventsEventContent,
11
+ } from "./types.js";
12
+
13
+ export function summarizeMatrixRawEvent(event: MatrixRawEvent): MatrixMessageSummary {
14
+ const content = event.content as RoomMessageEventContent;
15
+ const relates = content["m.relates_to"];
16
+ let relType: string | undefined;
17
+ let eventId: string | undefined;
18
+ if (relates) {
19
+ if ("rel_type" in relates) {
20
+ relType = relates.rel_type;
21
+ eventId = relates.event_id;
22
+ } else if ("m.in_reply_to" in relates) {
23
+ eventId = relates["m.in_reply_to"]?.event_id;
24
+ }
25
+ }
26
+ const relatesTo =
27
+ relType || eventId
28
+ ? {
29
+ relType,
30
+ eventId,
31
+ }
32
+ : undefined;
33
+ return {
34
+ eventId: event.event_id,
35
+ sender: event.sender,
36
+ body: resolveMatrixMessageBody({
37
+ body: content.body,
38
+ filename: content.filename,
39
+ msgtype: content.msgtype,
40
+ }),
41
+ msgtype: content.msgtype,
42
+ attachment: resolveMatrixMessageAttachment({
43
+ body: content.body,
44
+ filename: content.filename,
45
+ msgtype: content.msgtype,
46
+ }),
47
+ timestamp: event.origin_server_ts,
48
+ relatesTo,
49
+ };
50
+ }
51
+
52
+ export async function readPinnedEvents(client: MatrixClient, roomId: string): Promise<string[]> {
53
+ try {
54
+ const content = (await client.getRoomStateEvent(
55
+ roomId,
56
+ EventType.RoomPinnedEvents,
57
+ "",
58
+ )) as RoomPinnedEventsEventContent;
59
+ const pinned = content.pinned;
60
+ return pinned.filter((id) => id.trim().length > 0);
61
+ } catch (err: unknown) {
62
+ if (isMatrixNotFoundError(err)) {
63
+ return [];
64
+ }
65
+ throw err;
66
+ }
67
+ }
68
+
69
+ export async function fetchEventSummary(
70
+ client: MatrixClient,
71
+ roomId: string,
72
+ eventId: string,
73
+ ): Promise<MatrixMessageSummary | null> {
74
+ try {
75
+ const raw = (await client.getEvent(roomId, eventId)) as unknown as MatrixRawEvent;
76
+ if (raw.unsigned?.redacted_because) {
77
+ return null;
78
+ }
79
+ const pollSummary = await fetchMatrixPollMessageSummary(client, roomId, raw);
80
+ if (pollSummary) {
81
+ return pollSummary;
82
+ }
83
+ return summarizeMatrixRawEvent(raw);
84
+ } catch {
85
+ // Event not found, redacted, or inaccessible - return null
86
+ return null;
87
+ }
88
+ }
@@ -0,0 +1,82 @@
1
+ import type { CoreConfig } from "../../types.js";
2
+ import {
3
+ MATRIX_ANNOTATION_RELATION_TYPE,
4
+ MATRIX_REACTION_EVENT_TYPE,
5
+ type MatrixReactionEventContent,
6
+ } from "../reaction-common.js";
7
+ import type { MatrixClient, MessageEventContent } from "../sdk.js";
8
+ export type { MatrixRawEvent } from "../sdk.js";
9
+ export type { MatrixReactionSummary } from "../reaction-common.js";
10
+
11
+ export const MsgType = {
12
+ Text: "m.text",
13
+ } as const;
14
+
15
+ export const RelationType = {
16
+ Replace: "m.replace",
17
+ Annotation: MATRIX_ANNOTATION_RELATION_TYPE,
18
+ } as const;
19
+
20
+ export const EventType = {
21
+ RoomMessage: "m.room.message",
22
+ RoomPinnedEvents: "m.room.pinned_events",
23
+ RoomTopic: "m.room.topic",
24
+ Reaction: MATRIX_REACTION_EVENT_TYPE,
25
+ } as const;
26
+
27
+ export type RoomMessageEventContent = MessageEventContent & {
28
+ msgtype: string;
29
+ body: string;
30
+ "m.new_content"?: RoomMessageEventContent;
31
+ "m.relates_to"?: {
32
+ rel_type?: string;
33
+ event_id?: string;
34
+ "m.in_reply_to"?: { event_id?: string };
35
+ };
36
+ };
37
+
38
+ export type ReactionEventContent = MatrixReactionEventContent;
39
+
40
+ export type RoomPinnedEventsEventContent = {
41
+ pinned: string[];
42
+ };
43
+
44
+ export type RoomTopicEventContent = {
45
+ topic?: string;
46
+ };
47
+
48
+ export type MatrixActionClientOpts = {
49
+ client?: MatrixClient;
50
+ cfg?: CoreConfig;
51
+ mediaLocalRoots?: readonly string[];
52
+ timeoutMs?: number;
53
+ accountId?: string | null;
54
+ readiness?: "none" | "prepared" | "started";
55
+ };
56
+
57
+ export type MatrixMessageSummary = {
58
+ eventId?: string;
59
+ sender?: string;
60
+ body?: string;
61
+ msgtype?: string;
62
+ attachment?: MatrixMessageAttachmentSummary;
63
+ timestamp?: number;
64
+ relatesTo?: {
65
+ relType?: string;
66
+ eventId?: string;
67
+ key?: string;
68
+ };
69
+ };
70
+
71
+ export type MatrixMessageAttachmentKind = "audio" | "file" | "image" | "sticker" | "video";
72
+
73
+ export type MatrixMessageAttachmentSummary = {
74
+ kind: MatrixMessageAttachmentKind;
75
+ caption?: string;
76
+ filename?: string;
77
+ };
78
+
79
+ export type MatrixActionClient = {
80
+ client: MatrixClient;
81
+ stopOnDone: boolean;
82
+ };
@@ -0,0 +1,105 @@
1
+ import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
2
+
3
+ const withStartedActionClientMock = vi.fn();
4
+ const loadConfigMock = vi.fn(() => ({
5
+ channels: {
6
+ matrix: {},
7
+ },
8
+ }));
9
+
10
+ vi.mock("../../runtime.js", () => ({
11
+ getMatrixRuntime: () => ({
12
+ config: {
13
+ loadConfig: loadConfigMock,
14
+ },
15
+ }),
16
+ }));
17
+
18
+ vi.mock("./client.js", () => ({
19
+ withStartedActionClient: (...args: unknown[]) => withStartedActionClientMock(...args),
20
+ }));
21
+
22
+ let listMatrixVerifications: typeof import("./verification.js").listMatrixVerifications;
23
+
24
+ describe("matrix verification actions", () => {
25
+ beforeAll(async () => {
26
+ ({ listMatrixVerifications } = await import("./verification.js"));
27
+ });
28
+
29
+ beforeEach(() => {
30
+ vi.clearAllMocks();
31
+ loadConfigMock.mockReturnValue({
32
+ channels: {
33
+ matrix: {},
34
+ },
35
+ });
36
+ });
37
+
38
+ it("points encryption guidance at the selected Matrix account", async () => {
39
+ loadConfigMock.mockReturnValue({
40
+ channels: {
41
+ matrix: {
42
+ accounts: {
43
+ ops: {
44
+ encryption: false,
45
+ },
46
+ },
47
+ },
48
+ },
49
+ });
50
+ withStartedActionClientMock.mockImplementation(async (_opts, run) => {
51
+ return await run({ crypto: null });
52
+ });
53
+
54
+ await expect(listMatrixVerifications({ accountId: "ops" })).rejects.toThrow(
55
+ "Matrix encryption is not available (enable channels.lobi.accounts.ops.encryption=true)",
56
+ );
57
+ });
58
+
59
+ it("uses the resolved default Matrix account when accountId is omitted", async () => {
60
+ loadConfigMock.mockReturnValue({
61
+ channels: {
62
+ matrix: {
63
+ defaultAccount: "ops",
64
+ accounts: {
65
+ ops: {
66
+ encryption: false,
67
+ },
68
+ },
69
+ },
70
+ },
71
+ });
72
+ withStartedActionClientMock.mockImplementation(async (_opts, run) => {
73
+ return await run({ crypto: null });
74
+ });
75
+
76
+ await expect(listMatrixVerifications()).rejects.toThrow(
77
+ "Matrix encryption is not available (enable channels.lobi.accounts.ops.encryption=true)",
78
+ );
79
+ });
80
+
81
+ it("uses explicit cfg instead of runtime config when crypto is unavailable", async () => {
82
+ const explicitCfg = {
83
+ channels: {
84
+ matrix: {
85
+ accounts: {
86
+ ops: {
87
+ encryption: false,
88
+ },
89
+ },
90
+ },
91
+ },
92
+ };
93
+ loadConfigMock.mockImplementation(() => {
94
+ throw new Error("verification actions should not reload runtime config when cfg is provided");
95
+ });
96
+ withStartedActionClientMock.mockImplementation(async (_opts, run) => {
97
+ return await run({ crypto: null });
98
+ });
99
+
100
+ await expect(listMatrixVerifications({ cfg: explicitCfg, accountId: "ops" })).rejects.toThrow(
101
+ "Matrix encryption is not available (enable channels.lobi.accounts.ops.encryption=true)",
102
+ );
103
+ expect(loadConfigMock).not.toHaveBeenCalled();
104
+ });
105
+ });
@@ -0,0 +1,237 @@
1
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
2
+ import { getMatrixRuntime } from "../../runtime.js";
3
+ import type { CoreConfig } from "../../types.js";
4
+ import { formatMatrixEncryptionUnavailableError } from "../encryption-guidance.js";
5
+ import { withStartedActionClient } from "./client.js";
6
+ import type { MatrixActionClientOpts } from "./types.js";
7
+
8
+ function requireCrypto(
9
+ client: import("../sdk.js").MatrixClient,
10
+ opts: MatrixActionClientOpts,
11
+ ): NonNullable<import("../sdk.js").MatrixClient["crypto"]> {
12
+ if (!client.crypto) {
13
+ const cfg = opts.cfg ?? (getMatrixRuntime().config.loadConfig() as CoreConfig);
14
+ throw new Error(formatMatrixEncryptionUnavailableError(cfg, opts.accountId));
15
+ }
16
+ return client.crypto;
17
+ }
18
+
19
+ function resolveVerificationId(input: string): string {
20
+ const normalized = input.trim();
21
+ if (!normalized) {
22
+ throw new Error("Matrix verification request id is required");
23
+ }
24
+ return normalized;
25
+ }
26
+
27
+ export async function listMatrixVerifications(opts: MatrixActionClientOpts = {}) {
28
+ return await withStartedActionClient(opts, async (client) => {
29
+ const crypto = requireCrypto(client, opts);
30
+ return await crypto.listVerifications();
31
+ });
32
+ }
33
+
34
+ export async function requestMatrixVerification(
35
+ params: MatrixActionClientOpts & {
36
+ ownUser?: boolean;
37
+ userId?: string;
38
+ deviceId?: string;
39
+ roomId?: string;
40
+ } = {},
41
+ ) {
42
+ return await withStartedActionClient(params, async (client) => {
43
+ const crypto = requireCrypto(client, params);
44
+ const ownUser = params.ownUser ?? (!params.userId && !params.deviceId && !params.roomId);
45
+ return await crypto.requestVerification({
46
+ ownUser,
47
+ userId: normalizeOptionalString(params.userId),
48
+ deviceId: normalizeOptionalString(params.deviceId),
49
+ roomId: normalizeOptionalString(params.roomId),
50
+ });
51
+ });
52
+ }
53
+
54
+ export async function acceptMatrixVerification(
55
+ requestId: string,
56
+ opts: MatrixActionClientOpts = {},
57
+ ) {
58
+ return await withStartedActionClient(opts, async (client) => {
59
+ const crypto = requireCrypto(client, opts);
60
+ return await crypto.acceptVerification(resolveVerificationId(requestId));
61
+ });
62
+ }
63
+
64
+ export async function cancelMatrixVerification(
65
+ requestId: string,
66
+ opts: MatrixActionClientOpts & { reason?: string; code?: string } = {},
67
+ ) {
68
+ return await withStartedActionClient(opts, async (client) => {
69
+ const crypto = requireCrypto(client, opts);
70
+ return await crypto.cancelVerification(resolveVerificationId(requestId), {
71
+ reason: normalizeOptionalString(opts.reason),
72
+ code: normalizeOptionalString(opts.code),
73
+ });
74
+ });
75
+ }
76
+
77
+ export async function startMatrixVerification(
78
+ requestId: string,
79
+ opts: MatrixActionClientOpts & { method?: "sas" } = {},
80
+ ) {
81
+ return await withStartedActionClient(opts, async (client) => {
82
+ const crypto = requireCrypto(client, opts);
83
+ return await crypto.startVerification(resolveVerificationId(requestId), opts.method ?? "sas");
84
+ });
85
+ }
86
+
87
+ export async function generateMatrixVerificationQr(
88
+ requestId: string,
89
+ opts: MatrixActionClientOpts = {},
90
+ ) {
91
+ return await withStartedActionClient(opts, async (client) => {
92
+ const crypto = requireCrypto(client, opts);
93
+ return await crypto.generateVerificationQr(resolveVerificationId(requestId));
94
+ });
95
+ }
96
+
97
+ export async function scanMatrixVerificationQr(
98
+ requestId: string,
99
+ qrDataBase64: string,
100
+ opts: MatrixActionClientOpts = {},
101
+ ) {
102
+ return await withStartedActionClient(opts, async (client) => {
103
+ const crypto = requireCrypto(client, opts);
104
+ const payload = qrDataBase64.trim();
105
+ if (!payload) {
106
+ throw new Error("Matrix QR data is required");
107
+ }
108
+ return await crypto.scanVerificationQr(resolveVerificationId(requestId), payload);
109
+ });
110
+ }
111
+
112
+ export async function getMatrixVerificationSas(
113
+ requestId: string,
114
+ opts: MatrixActionClientOpts = {},
115
+ ) {
116
+ return await withStartedActionClient(opts, async (client) => {
117
+ const crypto = requireCrypto(client, opts);
118
+ return await crypto.getVerificationSas(resolveVerificationId(requestId));
119
+ });
120
+ }
121
+
122
+ export async function confirmMatrixVerificationSas(
123
+ requestId: string,
124
+ opts: MatrixActionClientOpts = {},
125
+ ) {
126
+ return await withStartedActionClient(opts, async (client) => {
127
+ const crypto = requireCrypto(client, opts);
128
+ return await crypto.confirmVerificationSas(resolveVerificationId(requestId));
129
+ });
130
+ }
131
+
132
+ export async function mismatchMatrixVerificationSas(
133
+ requestId: string,
134
+ opts: MatrixActionClientOpts = {},
135
+ ) {
136
+ return await withStartedActionClient(opts, async (client) => {
137
+ const crypto = requireCrypto(client, opts);
138
+ return await crypto.mismatchVerificationSas(resolveVerificationId(requestId));
139
+ });
140
+ }
141
+
142
+ export async function confirmMatrixVerificationReciprocateQr(
143
+ requestId: string,
144
+ opts: MatrixActionClientOpts = {},
145
+ ) {
146
+ return await withStartedActionClient(opts, async (client) => {
147
+ const crypto = requireCrypto(client, opts);
148
+ return await crypto.confirmVerificationReciprocateQr(resolveVerificationId(requestId));
149
+ });
150
+ }
151
+
152
+ export async function getMatrixEncryptionStatus(
153
+ opts: MatrixActionClientOpts & { includeRecoveryKey?: boolean } = {},
154
+ ) {
155
+ return await withStartedActionClient(opts, async (client) => {
156
+ const crypto = requireCrypto(client, opts);
157
+ const recoveryKey = await crypto.getRecoveryKey();
158
+ return {
159
+ encryptionEnabled: true,
160
+ recoveryKeyStored: Boolean(recoveryKey),
161
+ recoveryKeyCreatedAt: recoveryKey?.createdAt ?? null,
162
+ ...(opts.includeRecoveryKey ? { recoveryKey: recoveryKey?.encodedPrivateKey ?? null } : {}),
163
+ pendingVerifications: (await crypto.listVerifications()).length,
164
+ };
165
+ });
166
+ }
167
+
168
+ export async function getMatrixVerificationStatus(
169
+ opts: MatrixActionClientOpts & { includeRecoveryKey?: boolean } = {},
170
+ ) {
171
+ return await withStartedActionClient(opts, async (client) => {
172
+ const status = await client.getOwnDeviceVerificationStatus();
173
+ const payload = {
174
+ ...status,
175
+ pendingVerifications: client.crypto ? (await client.crypto.listVerifications()).length : 0,
176
+ };
177
+ if (!opts.includeRecoveryKey) {
178
+ return payload;
179
+ }
180
+ const recoveryKey = client.crypto ? await client.crypto.getRecoveryKey() : null;
181
+ return {
182
+ ...payload,
183
+ recoveryKey: recoveryKey?.encodedPrivateKey ?? null,
184
+ };
185
+ });
186
+ }
187
+
188
+ export async function getMatrixRoomKeyBackupStatus(opts: MatrixActionClientOpts = {}) {
189
+ return await withStartedActionClient(
190
+ opts,
191
+ async (client) => await client.getRoomKeyBackupStatus(),
192
+ );
193
+ }
194
+
195
+ export async function verifyMatrixRecoveryKey(
196
+ recoveryKey: string,
197
+ opts: MatrixActionClientOpts = {},
198
+ ) {
199
+ return await withStartedActionClient(
200
+ opts,
201
+ async (client) => await client.verifyWithRecoveryKey(recoveryKey),
202
+ );
203
+ }
204
+
205
+ export async function restoreMatrixRoomKeyBackup(
206
+ opts: MatrixActionClientOpts & {
207
+ recoveryKey?: string;
208
+ } = {},
209
+ ) {
210
+ return await withStartedActionClient(
211
+ opts,
212
+ async (client) =>
213
+ await client.restoreRoomKeyBackup({
214
+ recoveryKey: normalizeOptionalString(opts.recoveryKey),
215
+ }),
216
+ );
217
+ }
218
+
219
+ export async function resetMatrixRoomKeyBackup(opts: MatrixActionClientOpts = {}) {
220
+ return await withStartedActionClient(opts, async (client) => await client.resetRoomKeyBackup());
221
+ }
222
+
223
+ export async function bootstrapMatrixVerification(
224
+ opts: MatrixActionClientOpts & {
225
+ recoveryKey?: string;
226
+ forceResetCrossSigning?: boolean;
227
+ } = {},
228
+ ) {
229
+ return await withStartedActionClient(
230
+ opts,
231
+ async (client) =>
232
+ await client.bootstrapOwnDeviceVerification({
233
+ recoveryKey: normalizeOptionalString(opts.recoveryKey),
234
+ forceResetCrossSigning: opts.forceResetCrossSigning === true,
235
+ }),
236
+ );
237
+ }
@@ -0,0 +1,37 @@
1
+ export type {
2
+ MatrixActionClientOpts,
3
+ MatrixMessageSummary,
4
+ MatrixReactionSummary,
5
+ } from "./actions/types.js";
6
+ export {
7
+ sendMatrixMessage,
8
+ editMatrixMessage,
9
+ deleteMatrixMessage,
10
+ readMatrixMessages,
11
+ } from "./actions/messages.js";
12
+ export { voteMatrixPoll } from "./actions/polls.js";
13
+ export { listMatrixReactions, removeMatrixReactions } from "./actions/reactions.js";
14
+ export { pinMatrixMessage, unpinMatrixMessage, listMatrixPins } from "./actions/pins.js";
15
+ export { getMatrixMemberInfo, getMatrixRoomInfo } from "./actions/room.js";
16
+ export { updateMatrixOwnProfile } from "./actions/profile.js";
17
+ export {
18
+ bootstrapMatrixVerification,
19
+ acceptMatrixVerification,
20
+ cancelMatrixVerification,
21
+ confirmMatrixVerificationReciprocateQr,
22
+ confirmMatrixVerificationSas,
23
+ generateMatrixVerificationQr,
24
+ getMatrixEncryptionStatus,
25
+ getMatrixRoomKeyBackupStatus,
26
+ getMatrixVerificationStatus,
27
+ getMatrixVerificationSas,
28
+ listMatrixVerifications,
29
+ mismatchMatrixVerificationSas,
30
+ requestMatrixVerification,
31
+ resetMatrixRoomKeyBackup,
32
+ restoreMatrixRoomKeyBackup,
33
+ scanMatrixVerificationQr,
34
+ startMatrixVerification,
35
+ verifyMatrixRecoveryKey,
36
+ } from "./actions/verification.js";
37
+ export { reactMatrixMessage } from "./send.js";
@@ -0,0 +1,26 @@
1
+ import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
2
+ import type { MatrixClient } from "./sdk.js";
3
+
4
+ const activeClients = new Map<string, MatrixClient>();
5
+
6
+ function resolveAccountKey(accountId?: string | null): string {
7
+ const normalized = normalizeAccountId(accountId);
8
+ return normalized || DEFAULT_ACCOUNT_ID;
9
+ }
10
+
11
+ export function setActiveMatrixClient(
12
+ client: MatrixClient | null,
13
+ accountId?: string | null,
14
+ ): void {
15
+ const key = resolveAccountKey(accountId);
16
+ if (!client) {
17
+ activeClients.delete(key);
18
+ return;
19
+ }
20
+ activeClients.set(key, client);
21
+ }
22
+
23
+ export function getActiveMatrixClient(accountId?: string | null): MatrixClient | null {
24
+ const key = resolveAccountKey(accountId);
25
+ return activeClients.get(key) ?? null;
26
+ }
@@ -0,0 +1,18 @@
1
+ export type AsyncLock = <T>(fn: () => Promise<T>) => Promise<T>;
2
+
3
+ export function createAsyncLock(): AsyncLock {
4
+ let lock: Promise<void> = Promise.resolve();
5
+ return async function withLock<T>(fn: () => Promise<T>): Promise<T> {
6
+ const previous = lock;
7
+ let release: (() => void) | undefined;
8
+ lock = new Promise<void>((resolve) => {
9
+ release = resolve;
10
+ });
11
+ await previous;
12
+ try {
13
+ return await fn();
14
+ } finally {
15
+ release?.();
16
+ }
17
+ };
18
+ }