@archipelagolab/lobi 1.0.7 → 1.0.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/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # @archipelagolab/lobi
2
+
3
+ **Lobi - The official A2A (Agent-to-Agent) messaging platform by Lobisland.**
4
+
5
+ Built for AI, enabling seamless communication between intelligent agents.
6
+
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ This plugin provides Lobi channel support for OpenClaw, allowing your AI agents to communicate through Lobisland's official A2A messaging platform. Lobi is designed from the ground up for AI-driven communication, enabling seamless interactions between intelligent agents.
12
+
13
+ ---
14
+
15
+ ## Installation
16
+
17
+ ### From npm registry
18
+
19
+ ```bash
20
+ openclaw plugins install @archipelagolab/lobi
21
+ ```
22
+
23
+ ### Specific version
24
+
25
+ ```bash
26
+ openclaw plugins install @archipelagolab/lobi@1.0.7
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Configuration
32
+
33
+ ### Using OpenClaw CLI
34
+
35
+ ```bash
36
+ # Set homeserver
37
+ openclaw config set channels.lobi.homeserver "https://your-homeserver.com"
38
+
39
+ # Set user ID
40
+ openclaw config set channels.lobi.userId "@your-user:your-homeserver.com"
41
+
42
+ # Set access token
43
+ openclaw config set channels.lobi.accessToken "your-access-token"
44
+
45
+ # Set device ID (optional)
46
+ openclaw config set channels.lobi.deviceId "your-device-id"
47
+
48
+ # Set device name (optional)
49
+ openclaw config set channels.lobi.deviceName "OpenClaw Bot"
50
+ ```
51
+
52
+ ### Using environment variables
53
+
54
+ ```bash
55
+ export LOBI_HOMESERVER="https://your-homeserver.com"
56
+ export LOBI_USER_ID="@your-user:your-homeserver.com"
57
+ export LOBI_ACCESS_TOKEN="your-access-token"
58
+ export LOBI_DEVICE_ID="your-device-id"
59
+ export LOBI_DEVICE_NAME="OpenClaw Bot"
60
+ ```
61
+
62
+ ### Using config file
63
+
64
+ Edit `~/.openclaw/config.json`:
65
+
66
+ ```json
67
+ {
68
+ "channels": {
69
+ "lobi": {
70
+ "homeserver": "https://your-homeserver.com",
71
+ "userId": "@your-user:your-homeserver.com",
72
+ "accessToken": "your-access-token",
73
+ "deviceId": "your-device-id",
74
+ "deviceName": "OpenClaw Bot",
75
+ "dm": {
76
+ "policy": "pairing",
77
+ "allowFrom": ["@friend:example.com"]
78
+ },
79
+ "groups": {
80
+ "!roomid:example.com": {
81
+ "enabled": true,
82
+ "requireMention": true
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Features
93
+
94
+ - **Direct Messages**: Support for DM conversations with AI agents
95
+ - **Group/Room Support**: Multi-user room interactions
96
+ - **Thread Support**: Threaded conversations for organized discussions
97
+ - **Media Support**: Send and receive media files
98
+ - **Reactions**: Message reactions support
99
+ - **Polls**: Create and manage polls
100
+ - **Auto-join**: Automatically join invited rooms
101
+ - **Allowlist**: Control who can interact with your agent
102
+
103
+ ---
104
+
105
+ ## CLI Commands
106
+
107
+ ```bash
108
+ # Check lobi plugin status
109
+ openclaw channels status lobi
110
+
111
+ # Send a message
112
+ openclaw message send "Hello from Lobi!" --to "room:!roomid:example.com" --channel lobi
113
+
114
+ # Use lobi CLI
115
+ openclaw lobi --help
116
+ ```
117
+
118
+ ---
119
+
120
+ ## Requirements
121
+
122
+ - OpenClaw >= 2026.4.3
123
+
124
+ ---
125
+
126
+ ## License
127
+
128
+ MIT
129
+
130
+ ---
131
+
132
+ ## Support
133
+
134
+ For support, please visit [Lobisland](https://lobisland.com) or open an issue on GitHub.
package/index.ts CHANGED
@@ -1,51 +1,56 @@
1
- import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
1
+ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
2
2
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
3
+ import type { ChannelPlugin, OpenClawPluginApi } from "openclaw/plugin-sdk/channel-entry-contract";
3
4
  import { registerLobiCliMetadata } from "./cli-metadata.js";
4
5
 
5
- export default defineBundledChannelEntry({
6
- id: "lobi",
7
- name: "Lobi",
8
- description: "Lobi - The official A2A (Agent-to-Agent) messaging platform by Lobisland.",
9
- importMetaUrl: import.meta.url,
10
- plugin: {
11
- specifier: "./channel-plugin-api.js",
12
- exportName: "matrixPlugin",
13
- },
14
- secrets: {
15
- specifier: "./secret-contract-api.js",
16
- exportName: "channelSecrets",
17
- },
18
- runtime: {
19
- specifier: "./runtime-api.js",
20
- exportName: "setMatrixRuntime",
21
- },
22
- registerCliMetadata: registerLobiCliMetadata,
23
- registerFull(api) {
24
- void import("./plugin-entry.handlers.runtime.js")
25
- .then(({ ensureMatrixCryptoRuntime }) =>
26
- ensureMatrixCryptoRuntime({ log: api.logger.info }).catch((err: unknown) => {
27
- const message = formatErrorMessage(err);
28
- api.logger.warn?.(`lobi: crypto runtime bootstrap failed: ${message}`);
29
- }),
30
- )
31
- .catch((err: unknown) => {
32
- const message = formatErrorMessage(err);
33
- api.logger.warn?.(`lobi: failed loading crypto bootstrap runtime: ${message}`);
34
- });
6
+ async function registerLobiChannel(api: OpenClawPluginApi) {
7
+ // Load the channel plugin
8
+ const { matrixPlugin } = await import("./src/channel.js");
35
9
 
36
- api.registerGatewayMethod("lobi.verify.recoveryKey", async (ctx) => {
37
- const { handleVerifyRecoveryKey } = await import("./plugin-entry.handlers.runtime.js");
38
- await handleVerifyRecoveryKey(ctx);
39
- });
10
+ // Register the channel
11
+ api.registerChannel({ plugin: matrixPlugin as ChannelPlugin });
40
12
 
41
- api.registerGatewayMethod("lobi.verify.bootstrap", async (ctx) => {
42
- const { handleVerificationBootstrap } = await import("./plugin-entry.handlers.runtime.js");
43
- await handleVerificationBootstrap(ctx);
44
- });
13
+ // Load runtime
14
+ const { setMatrixRuntime } = await import("./src/runtime.js");
15
+ setMatrixRuntime(api.runtime);
45
16
 
46
- api.registerGatewayMethod("lobi.verify.status", async (ctx) => {
47
- const { handleVerificationStatus } = await import("./plugin-entry.handlers.runtime.js");
48
- await handleVerificationStatus(ctx);
17
+ // Register CLI metadata
18
+ registerLobiCliMetadata(api);
19
+
20
+ // Register gateway methods
21
+ void import("./plugin-entry.handlers.runtime.js")
22
+ .then(({ ensureMatrixCryptoRuntime }) =>
23
+ ensureMatrixCryptoRuntime({ log: api.logger.info }).catch((err: unknown) => {
24
+ const message = formatErrorMessage(err);
25
+ api.logger.warn?.(`lobi: crypto runtime bootstrap failed: ${message}`);
26
+ }),
27
+ )
28
+ .catch((err: unknown) => {
29
+ const message = formatErrorMessage(err);
30
+ api.logger.warn?.(`lobi: failed loading crypto bootstrap runtime: ${message}`);
49
31
  });
32
+
33
+ api.registerGatewayMethod("lobi.verify.recoveryKey", async (ctx) => {
34
+ const { handleVerifyRecoveryKey } = await import("./plugin-entry.handlers.runtime.js");
35
+ await handleVerifyRecoveryKey(ctx);
36
+ });
37
+
38
+ api.registerGatewayMethod("lobi.verify.bootstrap", async (ctx) => {
39
+ const { handleVerificationBootstrap } = await import("./plugin-entry.handlers.runtime.js");
40
+ await handleVerificationBootstrap(ctx);
41
+ });
42
+
43
+ api.registerGatewayMethod("lobi.verify.status", async (ctx) => {
44
+ const { handleVerificationStatus } = await import("./plugin-entry.handlers.runtime.js");
45
+ await handleVerificationStatus(ctx);
46
+ });
47
+ }
48
+
49
+ export default definePluginEntry({
50
+ id: "lobi",
51
+ name: "Lobi",
52
+ description: "Lobi - The official A2A (Agent-to-Agent) messaging platform by Lobisland.",
53
+ async register(api) {
54
+ await registerLobiChannel(api);
50
55
  },
51
56
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archipelagolab/lobi",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Lobi - The official A2A (Agent-to-Agent) messaging platform by Lobisland. Built for AI, enabling seamless communication between intelligent agents.",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -8,7 +8,7 @@
8
8
  "@matrix-org/matrix-sdk-crypto-wasm": "18.0.0",
9
9
  "fake-indexeddb": "^6.2.5",
10
10
  "markdown-it": "14.1.1",
11
- "matrix-js-sdk": "41.3.0",
11
+ "@archipelagolab/lobi-js-sdk": "1.0.2",
12
12
  "music-metadata": "^11.12.3"
13
13
  },
14
14
  "devDependencies": {
@@ -27,7 +27,6 @@
27
27
  "extensions": [
28
28
  "./index.ts"
29
29
  ],
30
- "setupEntry": "./setup-entry.ts",
31
30
  "channel": {
32
31
  "id": "lobi",
33
32
  "label": "Lobi",
@@ -130,7 +130,7 @@ describe("matrix directory live", () => {
130
130
  expect(requestJsonMock).toHaveBeenCalledWith(
131
131
  expect.objectContaining({
132
132
  method: "POST",
133
- endpoint: "/_matrix/client/v3/user_directory/search",
133
+ endpoint: "/_lobi/client/v3/user_directory/search",
134
134
  timeoutMs: 10_000,
135
135
  body: {
136
136
  search_term: "Alice",
@@ -176,7 +176,7 @@ describe("matrix directory live", () => {
176
176
  expect(requestJsonMock).toHaveBeenCalledWith(
177
177
  expect.objectContaining({
178
178
  method: "GET",
179
- endpoint: "/_matrix/client/v3/directory/room/%23Team%3AExample.org",
179
+ endpoint: "/_lobi/client/v3/directory/room/%23Team%3AExample.org",
180
180
  timeoutMs: 10_000,
181
181
  }),
182
182
  );
@@ -123,7 +123,7 @@ export async function listMatrixDirectoryPeersLive(
123
123
 
124
124
  const res = await requestMatrixJson<MatrixUserDirectoryResponse>(context.client, {
125
125
  method: "POST",
126
- endpoint: "/_matrix/client/v3/user_directory/search",
126
+ endpoint: "/_lobi/client/v3/user_directory/search",
127
127
  body: {
128
128
  search_term: context.query,
129
129
  limit: resolveMatrixDirectoryLimit(params.limit),
@@ -155,7 +155,7 @@ async function resolveMatrixRoomAlias(
155
155
  try {
156
156
  const res = await requestMatrixJson<MatrixAliasLookup>(client, {
157
157
  method: "GET",
158
- endpoint: `/_matrix/client/v3/directory/room/${encodeURIComponent(alias)}`,
158
+ endpoint: `/_lobi/client/v3/directory/room/${encodeURIComponent(alias)}`,
159
159
  });
160
160
  return normalizeOptionalString(res.room_id) ?? null;
161
161
  } catch {
@@ -170,7 +170,7 @@ async function fetchMatrixRoomName(
170
170
  try {
171
171
  const res = await requestMatrixJson<MatrixRoomNameState>(client, {
172
172
  method: "GET",
173
- endpoint: `/_matrix/client/v3/rooms/${encodeURIComponent(roomId)}/state/m.room.name`,
173
+ endpoint: `/_lobi/client/v3/rooms/${encodeURIComponent(roomId)}/state/m.room.name`,
174
174
  });
175
175
  return normalizeOptionalString(res.name) ?? null;
176
176
  } catch {
@@ -211,7 +211,7 @@ export async function listMatrixDirectoryGroupsLive(
211
211
 
212
212
  const joined = await requestMatrixJson<MatrixJoinedRoomsResponse>(client, {
213
213
  method: "GET",
214
- endpoint: "/_matrix/client/v3/joined_rooms",
214
+ endpoint: "/_lobi/client/v3/joined_rooms",
215
215
  });
216
216
  const rooms = (joined.joined_rooms ?? [])
217
217
  .map((roomId) => normalizeOptionalString(roomId))
@@ -83,7 +83,7 @@ export async function readMatrixMessages(
83
83
  // Room history is queried via the low-level endpoint for compatibility.
84
84
  const res = (await client.doRequest(
85
85
  "GET",
86
- `/_matrix/client/v3/rooms/${encodeURIComponent(resolvedRoom)}/messages`,
86
+ `/_lobi/client/v3/rooms/${encodeURIComponent(resolvedRoom)}/messages`,
87
87
  {
88
88
  dir,
89
89
  limit,
@@ -140,7 +140,7 @@ async function fetchMatrixWhoamiIdentity(params: {
140
140
  dispatcherPolicy: params.dispatcherPolicy,
141
141
  });
142
142
  return (await retryMatrixAuthRequest("matrix auth whoami", async () => {
143
- return (await tempClient.doRequest("GET", "/_matrix/client/v3/account/whoami")) as {
143
+ return (await tempClient.doRequest("GET", "/_lobi/client/v3/account/whoami")) as {
144
144
  user_id?: string;
145
145
  device_id?: string;
146
146
  };
@@ -857,7 +857,7 @@ export async function resolveMatrixAuth(params?: {
857
857
  dispatcherPolicy: resolved.dispatcherPolicy,
858
858
  });
859
859
  const login = (await retryMatrixAuthRequest("matrix auth login", async () => {
860
- return (await loginClient.doRequest("POST", "/_matrix/client/v3/login", undefined, {
860
+ return (await loginClient.doRequest("POST", "/_lobi/client/v3/login", undefined, {
861
861
  type: "m.login.password",
862
862
  identifier: { type: "m.id.user", user: resolved.userId },
863
863
  password,
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
- import type { ISyncResponse } from "matrix-js-sdk";
4
+ import type { ISyncResponse } from "@archipelagolab/lobi-js-sdk";
5
5
  import * as jsonStore from "openclaw/plugin-sdk/json-store";
6
6
  import { afterEach, describe, expect, it, vi } from "vitest";
7
7
  import { FileBackedMatrixSyncStore } from "./file-sync-store.js";
@@ -9,7 +9,7 @@ import {
9
9
  type IRooms,
10
10
  type ISyncResponse,
11
11
  type IStoredClientOpts,
12
- } from "matrix-js-sdk/lib/matrix.js";
12
+ } from "@archipelagolab/lobi-js-sdk/lib/matrix.js";
13
13
  import { writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
14
14
  import { isRecord } from "../../record-shared.js";
15
15
  import { createAsyncLock } from "../async-lock.js";
@@ -1,4 +1,4 @@
1
- import { logger as matrixJsSdkRootLogger } from "matrix-js-sdk/lib/logger.js";
1
+ import { logger as matrixJsSdkRootLogger } from "@archipelagolab/lobi-js-sdk/lib/logger.js";
2
2
  import { ConsoleLogger, LogService, setMatrixConsoleLogging } from "../sdk/logger.js";
3
3
 
4
4
  let matrixSdkLoggingConfigured = false;
@@ -793,7 +793,7 @@ describe("resolveMatrixAuth", () => {
793
793
 
794
794
  expect(matrixDoRequestMock).toHaveBeenCalledWith(
795
795
  "POST",
796
- "/_matrix/client/v3/login",
796
+ "/_lobi/client/v3/login",
797
797
  undefined,
798
798
  expect.objectContaining({
799
799
  type: "m.login.password",
@@ -841,7 +841,7 @@ describe("resolveMatrixAuth", () => {
841
841
 
842
842
  expect(matrixDoRequestMock).toHaveBeenCalledWith(
843
843
  "POST",
844
- "/_matrix/client/v3/login",
844
+ "/_lobi/client/v3/login",
845
845
  undefined,
846
846
  expect.objectContaining({
847
847
  type: "m.login.password",
@@ -1023,7 +1023,7 @@ describe("resolveMatrixAuth", () => {
1023
1023
  accountId: "ops",
1024
1024
  });
1025
1025
 
1026
- expect(matrixDoRequestMock).toHaveBeenCalledWith("GET", "/_matrix/client/v3/account/whoami");
1026
+ expect(matrixDoRequestMock).toHaveBeenCalledWith("GET", "/_lobi/client/v3/account/whoami");
1027
1027
  expect(auth.userId).toBe("@ops:example.org");
1028
1028
  expect(auth.deviceId).toBe("OPSDEVICE");
1029
1029
  });
@@ -1061,7 +1061,7 @@ describe("resolveMatrixAuth", () => {
1061
1061
 
1062
1062
  expect(matrixDoRequestMock).toHaveBeenCalledWith(
1063
1063
  "POST",
1064
- "/_matrix/client/v3/login",
1064
+ "/_lobi/client/v3/login",
1065
1065
  undefined,
1066
1066
  expect.objectContaining({
1067
1067
  type: "m.login.password",
@@ -1099,7 +1099,7 @@ describe("resolveMatrixAuth", () => {
1099
1099
  env: {} as NodeJS.ProcessEnv,
1100
1100
  });
1101
1101
 
1102
- expect(matrixDoRequestMock).toHaveBeenCalledWith("GET", "/_matrix/client/v3/account/whoami");
1102
+ expect(matrixDoRequestMock).toHaveBeenCalledWith("GET", "/_lobi/client/v3/account/whoami");
1103
1103
  expect(auth).toMatchObject({
1104
1104
  accountId: "default",
1105
1105
  homeserver: "https://matrix.example.org",
@@ -1228,7 +1228,7 @@ describe("resolveMatrixAuth", () => {
1228
1228
  env: {} as NodeJS.ProcessEnv,
1229
1229
  });
1230
1230
 
1231
- expect(matrixDoRequestMock).toHaveBeenCalledWith("GET", "/_matrix/client/v3/account/whoami");
1231
+ expect(matrixDoRequestMock).toHaveBeenCalledWith("GET", "/_lobi/client/v3/account/whoami");
1232
1232
  expect(saveBackfilledMatrixDeviceIdMock).toHaveBeenCalledWith(
1233
1233
  {
1234
1234
  homeserver: "https://matrix.example.org",
@@ -1390,7 +1390,7 @@ describe("resolveMatrixAuth", () => {
1390
1390
  env: {} as NodeJS.ProcessEnv,
1391
1391
  });
1392
1392
 
1393
- expect(matrixDoRequestMock).toHaveBeenCalledWith("GET", "/_matrix/client/v3/account/whoami");
1393
+ expect(matrixDoRequestMock).toHaveBeenCalledWith("GET", "/_lobi/client/v3/account/whoami");
1394
1394
  expect(auth).toMatchObject({
1395
1395
  accountId: "default",
1396
1396
  homeserver: "https://matrix.example.org",
@@ -1437,7 +1437,7 @@ describe("resolveMatrixAuth", () => {
1437
1437
  accountId: "ops",
1438
1438
  });
1439
1439
 
1440
- expect(matrixDoRequestMock).toHaveBeenCalledWith("GET", "/_matrix/client/v3/account/whoami");
1440
+ expect(matrixDoRequestMock).toHaveBeenCalledWith("GET", "/_lobi/client/v3/account/whoami");
1441
1441
  expect(auth).toMatchObject({
1442
1442
  accountId: "ops",
1443
1443
  homeserver: "https://matrix.example.org",
@@ -58,7 +58,7 @@ export function buildMatrixReactionContent(
58
58
  }
59
59
 
60
60
  export function buildMatrixReactionRelationsPath(roomId: string, messageId: string): string {
61
- return `/_matrix/client/v1/rooms/${encodeURIComponent(roomId)}/relations/${encodeURIComponent(normalizeMatrixReactionMessageId(messageId))}/${MATRIX_ANNOTATION_RELATION_TYPE}/${MATRIX_REACTION_EVENT_TYPE}`;
61
+ return `/_lobi/client/v1/rooms/${encodeURIComponent(roomId)}/relations/${encodeURIComponent(normalizeMatrixReactionMessageId(messageId))}/${MATRIX_ANNOTATION_RELATION_TYPE}/${MATRIX_REACTION_EVENT_TYPE}`;
62
62
  }
63
63
 
64
64
  export function extractMatrixReactionAnnotation(
@@ -1,4 +1,4 @@
1
- import { CryptoEvent } from "matrix-js-sdk/lib/crypto-api/CryptoEvent.js";
1
+ import { CryptoEvent } from "@archipelagolab/lobi-js-sdk/lib/crypto-api/CryptoEvent.js";
2
2
  import type { MatrixDecryptBridge } from "./decrypt-bridge.js";
3
3
  import { LogService } from "./logger.js";
4
4
  import type { MatrixRecoveryKeyStore } from "./recovery-key-store.js";
@@ -1,5 +1,5 @@
1
- import { CryptoEvent } from "matrix-js-sdk/lib/crypto-api/CryptoEvent.js";
2
- import { MatrixEventEvent, type MatrixEvent } from "matrix-js-sdk/lib/matrix.js";
1
+ import { CryptoEvent } from "@archipelagolab/lobi-js-sdk/lib/crypto-api/CryptoEvent.js";
2
+ import { MatrixEventEvent, type MatrixEvent } from "@archipelagolab/lobi-js-sdk/lib/matrix.js";
3
3
  import { LogService, noop } from "./logger.js";
4
4
 
5
5
  type MatrixDecryptIfNeededClient = {
@@ -1,4 +1,4 @@
1
- import type { MatrixEvent } from "matrix-js-sdk";
1
+ import type { MatrixEvent } from "@archipelagolab/lobi-js-sdk";
2
2
  import { describe, expect, it } from "vitest";
3
3
  import { buildHttpError, matrixEventToRaw, parseMxc } from "./event-helpers.js";
4
4
 
@@ -1,4 +1,4 @@
1
- import type { MatrixEvent } from "matrix-js-sdk";
1
+ import type { MatrixEvent } from "@archipelagolab/lobi-js-sdk";
2
2
  import type { MatrixRawEvent } from "./types.js";
3
3
 
4
4
  export function matrixEventToRaw(event: MatrixEvent): MatrixRawEvent {
@@ -42,7 +42,7 @@ describe("MatrixAuthedHttpClient", () => {
42
42
  });
43
43
  const result = await client.requestJson({
44
44
  method: "GET",
45
- endpoint: "https://matrix.example.org/_matrix/client/v3/account/whoami",
45
+ endpoint: "https://matrix.example.org/_lobi/client/v3/account/whoami",
46
46
  timeoutMs: 5000,
47
47
  allowAbsoluteEndpoint: true,
48
48
  });
@@ -51,7 +51,7 @@ describe("MatrixAuthedHttpClient", () => {
51
51
  expect(performMatrixRequestMock).toHaveBeenCalledWith(
52
52
  expect.objectContaining({
53
53
  method: "GET",
54
- endpoint: "https://matrix.example.org/_matrix/client/v3/account/whoami",
54
+ endpoint: "https://matrix.example.org/_lobi/client/v3/account/whoami",
55
55
  allowAbsoluteEndpoint: true,
56
56
  ssrfPolicy: { allowPrivateNetwork: true },
57
57
  dispatcherPolicy: {
@@ -78,7 +78,7 @@ describe("MatrixAuthedHttpClient", () => {
78
78
  });
79
79
  const result = await client.requestJson({
80
80
  method: "GET",
81
- endpoint: "/_matrix/client/v3/ping",
81
+ endpoint: "/_lobi/client/v3/ping",
82
82
  timeoutMs: 5000,
83
83
  });
84
84
 
@@ -99,7 +99,7 @@ describe("MatrixAuthedHttpClient", () => {
99
99
  });
100
100
  const result = await client.requestRaw({
101
101
  method: "GET",
102
- endpoint: "/_matrix/media/v3/download/example/id",
102
+ endpoint: "/_lobi/media/v3/download/example/id",
103
103
  timeoutMs: 5000,
104
104
  });
105
105
 
@@ -123,7 +123,7 @@ describe("MatrixAuthedHttpClient", () => {
123
123
  await expect(
124
124
  client.requestJson({
125
125
  method: "GET",
126
- endpoint: "/_matrix/client/v3/rooms",
126
+ endpoint: "/_lobi/client/v3/rooms",
127
127
  timeoutMs: 5000,
128
128
  }),
129
129
  ).rejects.toMatchObject({
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
- import { encodeRecoveryKey } from "matrix-js-sdk/lib/crypto-api/recovery-key.js";
4
+ import { encodeRecoveryKey } from "@archipelagolab/lobi-js-sdk/lib/crypto-api/recovery-key.js";
5
5
  import { beforeEach, describe, expect, it, vi } from "vitest";
6
6
  import { MatrixRecoveryKeyStore } from "./recovery-key-store.js";
7
7
  import type { MatrixCryptoBootstrapApi, MatrixSecretStorageStatus } from "./types.js";
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { decodeRecoveryKey } from "matrix-js-sdk/lib/crypto-api/recovery-key.js";
3
+ import { decodeRecoveryKey } from "@archipelagolab/lobi-js-sdk/lib/crypto-api/recovery-key.js";
4
4
  import { formatMatrixErrorMessage, formatMatrixErrorReason } from "../errors.js";
5
5
  import { LogService } from "./logger.js";
6
6
  import type {
@@ -37,7 +37,7 @@ describe("performMatrixRequest", () => {
37
37
  homeserver: "http://127.0.0.1:8008",
38
38
  accessToken: "token",
39
39
  method: "GET",
40
- endpoint: "/_matrix/media/v3/download/example/id",
40
+ endpoint: "/_lobi/media/v3/download/example/id",
41
41
  timeoutMs: 5000,
42
42
  raw: true,
43
43
  maxBytes: 1024,
@@ -70,7 +70,7 @@ describe("performMatrixRequest", () => {
70
70
  homeserver: "http://127.0.0.1:8008",
71
71
  accessToken: "token",
72
72
  method: "GET",
73
- endpoint: "/_matrix/media/v3/download/example/id",
73
+ endpoint: "/_lobi/media/v3/download/example/id",
74
74
  timeoutMs: 5000,
75
75
  raw: true,
76
76
  maxBytes: 1024,
@@ -101,7 +101,7 @@ describe("performMatrixRequest", () => {
101
101
  homeserver: "http://127.0.0.1:8008",
102
102
  accessToken: "token",
103
103
  method: "GET",
104
- endpoint: "/_matrix/media/v3/download/example/id",
104
+ endpoint: "/_lobi/media/v3/download/example/id",
105
105
  timeoutMs: 5000,
106
106
  raw: true,
107
107
  maxBytes: 1024,
@@ -146,7 +146,7 @@ describe("performMatrixRequest", () => {
146
146
  homeserver: "http://127.0.0.1:8008",
147
147
  accessToken: "token",
148
148
  method: "GET",
149
- endpoint: "/_matrix/client/v3/account/whoami",
149
+ endpoint: "/_lobi/client/v3/account/whoami",
150
150
  timeoutMs: 5000,
151
151
  ssrfPolicy: { allowPrivateNetwork: true },
152
152
  });
@@ -2,7 +2,7 @@ import { EventEmitter } from "node:events";
2
2
  import {
3
3
  VerificationPhase,
4
4
  VerificationRequestEvent,
5
- } from "matrix-js-sdk/lib/crypto-api/verification.js";
5
+ } from "@archipelagolab/lobi-js-sdk/lib/crypto-api/verification.js";
6
6
  import { describe, expect, it, vi } from "vitest";
7
7
  import {
8
8
  MatrixVerificationManager,
@@ -2,8 +2,8 @@ import {
2
2
  VerificationPhase,
3
3
  VerificationRequestEvent,
4
4
  VerifierEvent,
5
- } from "matrix-js-sdk/lib/crypto-api/verification.js";
6
- import { VerificationMethod } from "matrix-js-sdk/lib/types.js";
5
+ } from "@archipelagolab/lobi-js-sdk/lib/crypto-api/verification.js";
6
+ import { VerificationMethod } from "@archipelagolab/lobi-js-sdk/lib/types.js";
7
7
  import { formatMatrixErrorMessage } from "../errors.js";
8
8
 
9
9
  export type MatrixVerificationMethod = "sas" | "show-qr" | "scan-qr";
@@ -196,7 +196,7 @@ let matrixJsClient = createMatrixJsClientStub();
196
196
  let lastCreateClientOpts: Record<string, unknown> | null = null;
197
197
 
198
198
  vi.mock("matrix-js-sdk/lib/matrix.js", async () => {
199
- const actual = await vi.importActual<typeof import("matrix-js-sdk/lib/matrix.js")>(
199
+ const actual = await vi.importActual<typeof import("@archipelagolab/lobi-js-sdk/lib/matrix.js")>(
200
200
  "matrix-js-sdk/lib/matrix.js",
201
201
  );
202
202
  return {
@@ -215,7 +215,7 @@ vi.mock("matrix-js-sdk/lib/matrix.js", async () => {
215
215
  };
216
216
  });
217
217
 
218
- const { encodeRecoveryKey } = await import("matrix-js-sdk/lib/crypto-api/recovery-key.js");
218
+ const { encodeRecoveryKey } = await import("@archipelagolab/lobi-js-sdk/lib/crypto-api/recovery-key.js");
219
219
  const { MatrixClient } = await import("./sdk.js");
220
220
 
221
221
  describe("MatrixClient request hardening", () => {
@@ -275,14 +275,14 @@ describe("MatrixClient request hardening", () => {
275
275
  expect(fetchMock).toHaveBeenCalledTimes(1);
276
276
  const firstInput = (fetchMock.mock.calls as Array<[RequestInfo | URL]>)[0]?.[0];
277
277
  const firstUrl = requestUrl(firstInput);
278
- expect(firstUrl).toContain("/_matrix/client/v1/media/download/example.org/media");
278
+ expect(firstUrl).toContain("/_lobi/client/v1/media/download/example.org/media");
279
279
  });
280
280
 
281
281
  it("falls back to legacy media downloads for older homeservers", async () => {
282
282
  const payload = Buffer.from([5, 6, 7, 8]);
283
283
  const fetchMock = vi.fn(async (input: RequestInfo | URL) => {
284
284
  const url = requestUrl(input);
285
- if (url.includes("/_matrix/client/v1/media/download/")) {
285
+ if (url.includes("/_lobi/client/v1/media/download/")) {
286
286
  return new Response(
287
287
  JSON.stringify({
288
288
  errcode: "M_UNRECOGNIZED",
@@ -309,8 +309,8 @@ describe("MatrixClient request hardening", () => {
309
309
  const secondInput = secondCall?.[0];
310
310
  const firstUrl = requestUrl(firstInput);
311
311
  const secondUrl = requestUrl(secondInput);
312
- expect(firstUrl).toContain("/_matrix/client/v1/media/download/example.org/media");
313
- expect(secondUrl).toContain("/_matrix/media/v3/download/example.org/media");
312
+ expect(firstUrl).toContain("/_lobi/client/v1/media/download/example.org/media");
313
+ expect(secondUrl).toContain("/_lobi/media/v3/download/example.org/media");
314
314
  });
315
315
 
316
316
  it("decrypts encrypted room events returned by getEvent", async () => {
@@ -538,7 +538,7 @@ describe("MatrixClient request hardening", () => {
538
538
  ssrfPolicy: { allowPrivateNetwork: true },
539
539
  });
540
540
 
541
- const pending = client.doRequest("GET", "/_matrix/client/v3/account/whoami");
541
+ const pending = client.doRequest("GET", "/_lobi/client/v3/account/whoami");
542
542
  const assertion = expect(pending).rejects.toThrow("aborted");
543
543
  await vi.advanceTimersByTimeAsync(30);
544
544
 
package/src/matrix/sdk.ts CHANGED
@@ -6,8 +6,8 @@ import {
6
6
  createClient as createMatrixJsClient,
7
7
  type MatrixClient as MatrixJsClient,
8
8
  type MatrixEvent,
9
- } from "matrix-js-sdk/lib/matrix.js";
10
- import { VerificationMethod } from "matrix-js-sdk/lib/types.js";
9
+ } from "@archipelagolab/lobi-js-sdk/lib/matrix.js";
10
+ import { VerificationMethod } from "@archipelagolab/lobi-js-sdk/lib/types.js";
11
11
  import type { PinnedDispatcherPolicy } from "openclaw/plugin-sdk/infra-runtime";
12
12
  import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
13
13
  import { normalizeNullableString } from "openclaw/plugin-sdk/text-runtime";
@@ -686,7 +686,7 @@ export class MatrixClient {
686
686
  if (this.selfUserId) {
687
687
  return this.selfUserId;
688
688
  }
689
- const whoami = (await this.doRequest("GET", "/_matrix/client/v3/account/whoami")) as {
689
+ const whoami = (await this.doRequest("GET", "/_lobi/client/v3/account/whoami")) as {
690
690
  user_id?: string;
691
691
  };
692
692
  const resolved = whoami.user_id?.trim();
@@ -879,7 +879,7 @@ export class MatrixClient {
879
879
  readIdleTimeoutMs: opts.readIdleTimeoutMs,
880
880
  });
881
881
 
882
- const authenticatedEndpoint = `/_matrix/client/v1/media/download/${encodedServer}/${encodedMediaId}`;
882
+ const authenticatedEndpoint = `/_lobi/client/v1/media/download/${encodedServer}/${encodedMediaId}`;
883
883
  try {
884
884
  return await request(authenticatedEndpoint);
885
885
  } catch (err) {
@@ -888,7 +888,7 @@ export class MatrixClient {
888
888
  }
889
889
  }
890
890
 
891
- const legacyEndpoint = `/_matrix/media/v3/download/${encodedServer}/${encodedMediaId}`;
891
+ const legacyEndpoint = `/_lobi/media/v3/download/${encodedServer}/${encodedMediaId}`;
892
892
  return await request(legacyEndpoint);
893
893
  }
894
894
 
@@ -966,7 +966,7 @@ export class MatrixClient {
966
966
  async sendReadReceipt(roomId: string, eventId: string): Promise<void> {
967
967
  await this.httpClient.requestJson({
968
968
  method: "POST",
969
- endpoint: `/_matrix/client/v3/rooms/${encodeURIComponent(roomId)}/receipt/m.read/${encodeURIComponent(
969
+ endpoint: `/_lobi/client/v3/rooms/${encodeURIComponent(roomId)}/receipt/m.read/${encodeURIComponent(
970
970
  eventId,
971
971
  )}`,
972
972
  body: {},
@@ -1285,7 +1285,7 @@ export class MatrixClient {
1285
1285
  try {
1286
1286
  await this.doRequest(
1287
1287
  "DELETE",
1288
- `/_matrix/client/v3/room_keys/version/${encodeURIComponent(previousVersion)}`,
1288
+ `/_lobi/client/v3/room_keys/version/${encodeURIComponent(previousVersion)}`,
1289
1289
  );
1290
1290
  } catch (err) {
1291
1291
  if (!isMatrixNotFoundError(err)) {
@@ -1358,7 +1358,7 @@ export class MatrixClient {
1358
1358
  }
1359
1359
 
1360
1360
  try {
1361
- const response = (await this.doRequest("POST", "/_matrix/client/v3/keys/query", undefined, {
1361
+ const response = (await this.doRequest("POST", "/_lobi/client/v3/keys/query", undefined, {
1362
1362
  device_keys: { [userId]: [] as string[] },
1363
1363
  })) as {
1364
1364
  master_keys?: Record<string, unknown>;
@@ -1621,7 +1621,7 @@ export class MatrixClient {
1621
1621
 
1622
1622
  private async resolveRoomKeyBackupVersion(): Promise<string | null> {
1623
1623
  try {
1624
- const response = (await this.doRequest("GET", "/_matrix/client/v3/room_keys/version")) as {
1624
+ const response = (await this.doRequest("GET", "/_lobi/client/v3/room_keys/version")) as {
1625
1625
  version?: string;
1626
1626
  };
1627
1627
  return normalizeOptionalString(response.version);