chrome-openclaw-sider 1.0.2 → 1.0.26

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 (58) hide show
  1. package/README.md +11 -1
  2. package/README.zh_CN.md +8 -6
  3. package/dist/index.d.ts +12 -0
  4. package/{index.ts → dist/index.js} +24 -17
  5. package/dist/setup-entry.d.ts +18 -0
  6. package/dist/setup-entry.js +8 -0
  7. package/dist/src/account.d.ts +54 -0
  8. package/{src/account.ts → dist/src/account.js} +70 -160
  9. package/dist/src/auth.d.ts +30 -0
  10. package/{src/auth.ts → dist/src/auth.js} +61 -128
  11. package/dist/src/auto-title.d.ts +20 -0
  12. package/dist/src/auto-title.js +22 -0
  13. package/dist/src/channel-auto-title.d.ts +23 -0
  14. package/dist/src/channel-auto-title.js +77 -0
  15. package/dist/src/channel-builders.d.ts +105 -0
  16. package/dist/src/channel-builders.js +238 -0
  17. package/dist/src/channel-hooks.d.ts +30 -0
  18. package/dist/src/channel-hooks.js +331 -0
  19. package/dist/src/channel-monitor.d.ts +34 -0
  20. package/dist/src/channel-monitor.js +341 -0
  21. package/dist/src/channel-relay.d.ts +117 -0
  22. package/dist/src/channel-relay.js +573 -0
  23. package/dist/src/channel-runtime.d.ts +32 -0
  24. package/dist/src/channel-runtime.js +85 -0
  25. package/dist/src/channel-send-result.d.ts +19 -0
  26. package/dist/src/channel-send-result.js +126 -0
  27. package/dist/src/channel-session-model.d.ts +19 -0
  28. package/dist/src/channel-session-model.js +244 -0
  29. package/dist/src/channel-state.d.ts +92 -0
  30. package/dist/src/channel-state.js +471 -0
  31. package/dist/src/channel-streaming.d.ts +117 -0
  32. package/dist/src/channel-streaming.js +645 -0
  33. package/dist/src/channel-types.d.ts +207 -0
  34. package/dist/src/channel-types.js +40 -0
  35. package/dist/src/channel-typing.d.ts +17 -0
  36. package/dist/src/channel-typing.js +79 -0
  37. package/dist/src/channel-util.d.ts +78 -0
  38. package/dist/src/channel-util.js +524 -0
  39. package/dist/src/channel.d.ts +14 -0
  40. package/dist/src/channel.js +1023 -0
  41. package/dist/src/config.d.ts +18 -0
  42. package/dist/src/config.js +38 -0
  43. package/dist/src/inbound-media.d.ts +37 -0
  44. package/{src/inbound-media.ts → dist/src/inbound-media.js} +33 -81
  45. package/dist/src/media-upload.d.ts +86 -0
  46. package/dist/src/media-upload.js +1222 -0
  47. package/dist/src/setup-core.d.ts +72 -0
  48. package/{src/setup-core.ts → dist/src/setup-core.js} +106 -194
  49. package/dist/src/user-agent.d.ts +4 -0
  50. package/dist/src/user-agent.js +6 -0
  51. package/openclaw.plugin.json +86 -0
  52. package/package.json +9 -13
  53. package/setup-entry.ts +0 -6
  54. package/src/channel.ts +0 -3862
  55. package/src/config.ts +0 -29
  56. package/src/media-upload.ts +0 -983
  57. package/src/remote-browser-support.ts +0 -64
  58. package/src/user-agent.ts +0 -17
@@ -0,0 +1,341 @@
1
+ import { WebSocket } from "ws";
2
+ import {
3
+ DEFAULT_MONITOR_KEEPALIVE_MS,
4
+ DEFAULT_MONITOR_PONG_TIMEOUT_MS
5
+ } from "./channel-types.js";
6
+ import {
7
+ logDebug,
8
+ createMonitorLogger,
9
+ siderRelayMonitors,
10
+ sleep
11
+ } from "./channel-runtime.js";
12
+ import {
13
+ connectRelaySocket,
14
+ setRelaySocketConnected,
15
+ clearRelaySocketState,
16
+ closeSocketQuietly,
17
+ wsDataToText,
18
+ parseInboundFrame,
19
+ resolveAckSessionId,
20
+ resolveAckId,
21
+ resolveAckClientReqId,
22
+ resolveManagedAck,
23
+ describeSocketClose,
24
+ getSocketCloseInfo,
25
+ waitForAbortSignal,
26
+ buildRelayMonitorAccountSignature
27
+ } from "./channel-relay.js";
28
+ import { toRecord } from "./channel-util.js";
29
+ async function monitorSiderSession(params) {
30
+ const { cfg, account, abortSignal, log } = params;
31
+ let currentCfg = cfg;
32
+ let currentAccount = account;
33
+ const monitorLog = createMonitorLogger(log);
34
+ while (!abortSignal.aborted) {
35
+ let ws = null;
36
+ let skipSleep = false;
37
+ try {
38
+ monitorLog.info(`[${currentAccount.accountId}] opening sider relay websocket`, {
39
+ accountId: currentAccount.accountId,
40
+ relayId: currentAccount.relayId
41
+ });
42
+ ws = await connectRelaySocket({
43
+ account: currentAccount,
44
+ relayId: currentAccount.relayId
45
+ });
46
+ setRelaySocketConnected({
47
+ account: currentAccount,
48
+ ws,
49
+ relayId: currentAccount.relayId
50
+ });
51
+ monitorLog.info(`[${currentAccount.accountId}] sider relay connected`, {
52
+ accountId: currentAccount.accountId,
53
+ relayId: currentAccount.relayId
54
+ });
55
+ await new Promise((resolve) => {
56
+ const socket = ws;
57
+ if (!socket) {
58
+ resolve();
59
+ return;
60
+ }
61
+ let settled = false;
62
+ let pendingPingSince = 0;
63
+ const finish = (params2) => {
64
+ if (settled) {
65
+ return;
66
+ }
67
+ settled = true;
68
+ if (params2.logMessage) {
69
+ const data = {
70
+ accountId: currentAccount.accountId,
71
+ relayId: currentAccount.relayId
72
+ };
73
+ const writeLog = params2.warn ? monitorLog.warn : monitorLog.info;
74
+ writeLog(params2.logMessage, data);
75
+ }
76
+ if (params2.closeSocket) {
77
+ closeSocketQuietly(socket);
78
+ }
79
+ cleanup();
80
+ clearRelaySocketState({
81
+ accountId: currentAccount.accountId,
82
+ expectedWs: socket,
83
+ closeSocket: false,
84
+ reason: params2.reason
85
+ });
86
+ resolve();
87
+ };
88
+ const keepalive = setInterval(() => {
89
+ if (socket.readyState !== WebSocket.OPEN) {
90
+ return;
91
+ }
92
+ const now = Date.now();
93
+ if (pendingPingSince > 0 && now - pendingPingSince >= DEFAULT_MONITOR_PONG_TIMEOUT_MS) {
94
+ finish({
95
+ reason: `relay keepalive timeout after ${DEFAULT_MONITOR_PONG_TIMEOUT_MS}ms`,
96
+ closeSocket: true,
97
+ logMessage: `[${currentAccount.accountId}] sider relay keepalive timeout; reconnecting`,
98
+ warn: true
99
+ });
100
+ return;
101
+ }
102
+ try {
103
+ socket.send(JSON.stringify({ type: "ping" }));
104
+ if (pendingPingSince === 0) {
105
+ pendingPingSince = now;
106
+ }
107
+ logDebug("sent sider relay keepalive ping", {
108
+ accountId: currentAccount.accountId,
109
+ relayId: currentAccount.relayId
110
+ });
111
+ } catch (err) {
112
+ monitorLog.warn(`[${currentAccount.accountId}] sider relay keepalive failed: ${String(err)}`, {
113
+ accountId: currentAccount.accountId,
114
+ relayId: currentAccount.relayId,
115
+ error: String(err)
116
+ });
117
+ closeSocketQuietly(socket);
118
+ }
119
+ }, DEFAULT_MONITOR_KEEPALIVE_MS);
120
+ const cleanup = () => {
121
+ clearInterval(keepalive);
122
+ socket.off("message", onMessage);
123
+ socket.off("close", onClose);
124
+ socket.off("error", onError);
125
+ abortSignal.removeEventListener("abort", onAbort);
126
+ };
127
+ const onMessage = (data) => {
128
+ void (async () => {
129
+ const text = await wsDataToText(data);
130
+ const frame = parseInboundFrame(text);
131
+ if (!frame) {
132
+ return;
133
+ }
134
+ if (frame.type === "event") {
135
+ return;
136
+ }
137
+ pendingPingSince = 0;
138
+ const frameRecord = toRecord(frame);
139
+ monitorLog.info("ws frame message", {
140
+ type: frame.type,
141
+ sessionId: typeof frameRecord?.session_id === "string" ? frameRecord.session_id : void 0,
142
+ messageId: typeof frameRecord?.message_id === "string" ? frameRecord.message_id : void 0,
143
+ eventId: typeof frameRecord?.event_id === "string" ? frameRecord.event_id : void 0
144
+ });
145
+ if (frame.type === "ping") {
146
+ socket.send(JSON.stringify({ type: "pong" }));
147
+ return;
148
+ }
149
+ if (frame.type === "pong") {
150
+ logDebug("received sider relay keepalive pong", {
151
+ accountId: currentAccount.accountId,
152
+ relayId: currentAccount.relayId
153
+ });
154
+ return;
155
+ }
156
+ if (frame.type === "replaced") {
157
+ monitorLog.warn(`[${currentAccount.accountId}] sider relay replaced by a newer connection`, {
158
+ accountId: currentAccount.accountId,
159
+ relayId: currentAccount.relayId
160
+ });
161
+ closeSocketQuietly(socket);
162
+ return;
163
+ }
164
+ if (frame.type === "ack") {
165
+ const ackFrame = frame;
166
+ const resolved = resolveManagedAck({
167
+ accountId: currentAccount.accountId,
168
+ frame: ackFrame
169
+ });
170
+ logDebug("received sider ack on monitor socket", {
171
+ accountId: currentAccount.accountId,
172
+ sessionId: resolveAckSessionId(ackFrame),
173
+ id: resolveAckId(ackFrame),
174
+ clientReqId: resolveAckClientReqId(ackFrame),
175
+ resolved
176
+ });
177
+ return;
178
+ }
179
+ if (frame.type !== "message") {
180
+ return;
181
+ }
182
+ await params.onInboundMessage({
183
+ cfg: currentCfg,
184
+ account: currentAccount,
185
+ event: frame
186
+ });
187
+ })().catch((err) => {
188
+ log?.error(`[${currentAccount.accountId}] sider inbound handling failed: ${String(err)}`);
189
+ });
190
+ };
191
+ const onClose = (code, reason) => {
192
+ const closeInfo = getSocketCloseInfo({ code, reason });
193
+ if (closeInfo.code === 1008 && closeInfo.reason === "relay replaced") {
194
+ finish({
195
+ reason: `relay socket closed${describeSocketClose(closeInfo)}`,
196
+ logMessage: `[${currentAccount.accountId}] sider relay closed by gateway: relay replaced`,
197
+ warn: true
198
+ });
199
+ } else {
200
+ finish({
201
+ reason: `relay socket closed${describeSocketClose(closeInfo)}`,
202
+ logMessage: `[${currentAccount.accountId}] sider relay socket closed${describeSocketClose(closeInfo)}`
203
+ });
204
+ }
205
+ };
206
+ const onError = () => {
207
+ finish({
208
+ reason: "relay socket error",
209
+ logMessage: `[${currentAccount.accountId}] sider relay socket error`,
210
+ warn: true
211
+ });
212
+ };
213
+ const onAbort = () => {
214
+ finish({
215
+ reason: "relay monitor aborted",
216
+ closeSocket: true
217
+ });
218
+ };
219
+ socket.on("message", onMessage);
220
+ socket.on("close", onClose);
221
+ socket.on("error", onError);
222
+ abortSignal.addEventListener("abort", onAbort, { once: true });
223
+ if (abortSignal.aborted) {
224
+ onAbort();
225
+ }
226
+ });
227
+ } catch (err) {
228
+ monitorLog.warn(`[${currentAccount.accountId}] sider relay loop error: ${String(err)}`, {
229
+ accountId: currentAccount.accountId,
230
+ relayId: currentAccount.relayId,
231
+ error: String(err)
232
+ });
233
+ } finally {
234
+ if (ws) {
235
+ clearRelaySocketState({
236
+ accountId: currentAccount.accountId,
237
+ expectedWs: ws,
238
+ closeSocket: false,
239
+ reason: "relay reconnecting"
240
+ });
241
+ closeSocketQuietly(ws);
242
+ }
243
+ }
244
+ if (!abortSignal.aborted && !skipSleep) {
245
+ await sleep(currentAccount.reconnectDelayMs);
246
+ }
247
+ }
248
+ clearRelaySocketState({
249
+ accountId: currentAccount.accountId,
250
+ closeSocket: true
251
+ });
252
+ }
253
+ function launchManagedRelayMonitor(registration) {
254
+ const controller = new AbortController();
255
+ registration.controller = controller;
256
+ const runCfg = registration.cfg;
257
+ const runAccount = registration.account;
258
+ const runLog = registration.log;
259
+ registration.runner = (async () => {
260
+ try {
261
+ await monitorSiderSession({
262
+ cfg: runCfg,
263
+ account: runAccount,
264
+ abortSignal: controller.signal,
265
+ log: runLog,
266
+ onInboundMessage: registration.onInboundMessage
267
+ });
268
+ } finally {
269
+ const current = siderRelayMonitors.get(runAccount.accountId);
270
+ if (current !== registration || current.controller !== controller) {
271
+ return;
272
+ }
273
+ if (current.restartRequested && current.subscribers.size > 0) {
274
+ current.restartRequested = false;
275
+ launchManagedRelayMonitor(current);
276
+ return;
277
+ }
278
+ if (current.subscribers.size > 0) {
279
+ current.log?.warn(
280
+ `[${current.account.accountId}] managed sider relay monitor stopped unexpectedly; restarting`
281
+ );
282
+ launchManagedRelayMonitor(current);
283
+ return;
284
+ }
285
+ siderRelayMonitors.delete(runAccount.accountId);
286
+ }
287
+ })();
288
+ }
289
+ async function runManagedSiderRelayMonitor(params) {
290
+ const { account, abortSignal, log } = params;
291
+ const subscriberId = crypto.randomUUID();
292
+ const monitorSignature = buildRelayMonitorAccountSignature(account);
293
+ let registration = siderRelayMonitors.get(account.accountId);
294
+ if (!registration) {
295
+ registration = {
296
+ cfg: params.cfg,
297
+ account,
298
+ monitorSignature,
299
+ subscribers: /* @__PURE__ */ new Set([subscriberId]),
300
+ controller: new AbortController(),
301
+ runner: Promise.resolve(),
302
+ restartRequested: false,
303
+ log,
304
+ onInboundMessage: params.onInboundMessage
305
+ };
306
+ siderRelayMonitors.set(account.accountId, registration);
307
+ launchManagedRelayMonitor(registration);
308
+ } else {
309
+ registration.subscribers.add(subscriberId);
310
+ registration.log = log ?? registration.log;
311
+ if (registration.monitorSignature !== monitorSignature) {
312
+ registration.cfg = params.cfg;
313
+ registration.account = account;
314
+ registration.monitorSignature = monitorSignature;
315
+ registration.restartRequested = true;
316
+ log?.info(`[${account.accountId}] restarting sider relay monitor with updated settings`);
317
+ registration.controller.abort();
318
+ } else {
319
+ log?.info(`[${account.accountId}] reusing existing sider relay monitor`);
320
+ }
321
+ }
322
+ try {
323
+ await waitForAbortSignal(abortSignal);
324
+ } finally {
325
+ const current = siderRelayMonitors.get(account.accountId);
326
+ if (!current) {
327
+ return;
328
+ }
329
+ current.subscribers.delete(subscriberId);
330
+ if (current.subscribers.size > 0) {
331
+ return;
332
+ }
333
+ current.controller.abort();
334
+ await current.runner;
335
+ }
336
+ }
337
+ export {
338
+ launchManagedRelayMonitor,
339
+ monitorSiderSession,
340
+ runManagedSiderRelayMonitor
341
+ };
@@ -0,0 +1,117 @@
1
+ import { WebSocket } from 'ws';
2
+ import { SiderRelaySocketState, SiderPendingAck, SiderInboundFrame, SiderInboundAck, SiderPart, SiderAggregation, SiderSampleEvent } from './channel-types.js';
3
+ import { ResolvedSiderAccount } from './account.js';
4
+ import 'openclaw/plugin-sdk';
5
+ import 'openclaw/plugin-sdk/setup';
6
+ import './auth.js';
7
+ import 'openclaw/plugin-sdk/plugin-entry';
8
+ import './auto-title.js';
9
+
10
+ declare function getSocketCloseInfo(closeInfo?: {
11
+ code?: number;
12
+ reason?: string | Buffer;
13
+ wasClean?: boolean;
14
+ }): {
15
+ code?: number;
16
+ reason?: string;
17
+ wasClean?: boolean;
18
+ };
19
+ declare function describeSocketClose(closeInfo?: {
20
+ code?: number;
21
+ reason?: string | Buffer;
22
+ wasClean?: boolean;
23
+ }): string;
24
+ declare function resolveRelayWsUrl(gatewayUrl: string): string;
25
+ declare function wsDataToText(data: unknown): Promise<string>;
26
+ declare function parseInboundFrame(rawText: string): SiderInboundFrame | null;
27
+ declare function waitForSocketOpen(params: {
28
+ ws: WebSocket;
29
+ timeoutMs: number;
30
+ accountId: string;
31
+ }): Promise<void>;
32
+ declare function closeSocketQuietly(ws: WebSocket): void;
33
+ declare function normalizeRelaySocketToken(token?: string): string | undefined;
34
+ declare function getOrCreateRelaySocketState(accountId: string): SiderRelaySocketState;
35
+ declare function buildRelaySocketAccountSignature(account: ResolvedSiderAccount): string;
36
+ declare function buildRelayMonitorAccountSignature(account: ResolvedSiderAccount): string;
37
+ declare function waitForAbortSignal(signal: AbortSignal): Promise<void>;
38
+ declare function clearRelaySocketState(params: {
39
+ accountId: string;
40
+ expectedWs?: WebSocket;
41
+ closeSocket?: boolean;
42
+ reason?: string;
43
+ }): void;
44
+ declare function setRelaySocketConnected(params: {
45
+ account: ResolvedSiderAccount;
46
+ ws: WebSocket;
47
+ relayId: string;
48
+ }): void;
49
+ declare function waitForRelaySocketReady(params: {
50
+ account: ResolvedSiderAccount;
51
+ timeoutMs: number;
52
+ }): Promise<{
53
+ ws: WebSocket;
54
+ state: SiderRelaySocketState;
55
+ }>;
56
+ declare function waitForManagedAck(params: {
57
+ state: SiderRelaySocketState;
58
+ accountId: string;
59
+ sessionId: string;
60
+ timeoutMs: number;
61
+ clientReqId?: string;
62
+ }): Promise<string>;
63
+ declare function readAckToken(value: unknown): string | undefined;
64
+ declare function resolveAckSessionId(frame: SiderInboundAck): string | undefined;
65
+ declare function resolveAckClientReqId(frame: SiderInboundAck): string | undefined;
66
+ declare function resolveAckId(frame: SiderInboundAck): string | undefined;
67
+ declare function countPendingAcks(state: SiderRelaySocketState): number;
68
+ declare function detachPendingAck(state: SiderRelaySocketState, pendingAck: SiderPendingAck): void;
69
+ declare function settlePendingAck(params: {
70
+ accountId: string;
71
+ state: SiderRelaySocketState;
72
+ pendingAck: SiderPendingAck;
73
+ ackId?: string;
74
+ ackClientReqId?: string;
75
+ }): boolean;
76
+ declare function resolveManagedAck(params: {
77
+ accountId: string;
78
+ frame: SiderInboundAck;
79
+ }): boolean;
80
+ declare function resolveFrameClientReqId(frame: Record<string, unknown>): string | undefined;
81
+ declare function isAckTimeoutError(error: unknown): boolean;
82
+ declare function sendRelayFrameWithAck(params: {
83
+ account: ResolvedSiderAccount;
84
+ sessionId: string;
85
+ frame: Record<string, unknown>;
86
+ timeoutMs: number;
87
+ }): Promise<string>;
88
+ declare function connectRelaySocket(params: {
89
+ account: ResolvedSiderAccount;
90
+ relayId: string;
91
+ }): Promise<WebSocket>;
92
+ declare function sendMessageToSider(params: {
93
+ account: ResolvedSiderAccount;
94
+ sessionId: string;
95
+ parts: SiderPart[];
96
+ aggregation?: SiderAggregation;
97
+ meta?: Record<string, unknown>;
98
+ }): Promise<{
99
+ messageId: string;
100
+ conversationId: string;
101
+ }>;
102
+ declare function sendSiderEventBestEffort(params: {
103
+ account: ResolvedSiderAccount;
104
+ sessionId: string;
105
+ event: SiderSampleEvent;
106
+ context: string;
107
+ }): Promise<void>;
108
+ declare function sendSiderMessageBestEffort(params: {
109
+ account: ResolvedSiderAccount;
110
+ sessionId: string;
111
+ parts: SiderPart[];
112
+ aggregation?: SiderAggregation;
113
+ meta?: Record<string, unknown>;
114
+ context: string;
115
+ }): Promise<void>;
116
+
117
+ export { buildRelayMonitorAccountSignature, buildRelaySocketAccountSignature, clearRelaySocketState, closeSocketQuietly, connectRelaySocket, countPendingAcks, describeSocketClose, detachPendingAck, getOrCreateRelaySocketState, getSocketCloseInfo, isAckTimeoutError, normalizeRelaySocketToken, parseInboundFrame, readAckToken, resolveAckClientReqId, resolveAckId, resolveAckSessionId, resolveFrameClientReqId, resolveManagedAck, resolveRelayWsUrl, sendMessageToSider, sendRelayFrameWithAck, sendSiderEventBestEffort, sendSiderMessageBestEffort, setRelaySocketConnected, settlePendingAck, waitForAbortSignal, waitForManagedAck, waitForRelaySocketReady, waitForSocketOpen, wsDataToText };