@clawchatsai/connector 0.0.10 → 0.0.12
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/index.d.ts +1 -1
- package/dist/index.js +2 -4
- package/dist/signaling-client.d.ts +1 -2
- package/dist/signaling-client.js +3 -11
- package/package.json +4 -2
- package/server.js +29 -41
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* Spec: specs/multitenant-p2p.md sections 6.1-6.2
|
|
11
11
|
*/
|
|
12
12
|
export declare const PLUGIN_ID = "connector";
|
|
13
|
-
export declare const PLUGIN_VERSION = "0.0.
|
|
13
|
+
export declare const PLUGIN_VERSION = "0.0.12";
|
|
14
14
|
interface PluginServiceContext {
|
|
15
15
|
stateDir: string;
|
|
16
16
|
logger: {
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ import { checkForUpdates, performUpdate } from './updater.js';
|
|
|
19
19
|
// Inline from shared/api-version.ts to avoid rootDir conflict
|
|
20
20
|
const CURRENT_API_VERSION = 1;
|
|
21
21
|
export const PLUGIN_ID = 'connector';
|
|
22
|
-
export const PLUGIN_VERSION = '0.0.
|
|
22
|
+
export const PLUGIN_VERSION = '0.0.12';
|
|
23
23
|
/** Max DataChannel message size (~256KB, leave room for envelope) */
|
|
24
24
|
const MAX_DC_MESSAGE_SIZE = 256 * 1024;
|
|
25
25
|
/** Active DataChannel connections: connectionId → send function */
|
|
@@ -147,9 +147,7 @@ async function startShellChat(ctx, api) {
|
|
|
147
147
|
signaling.on('auth-rejected', (reason) => {
|
|
148
148
|
ctx.logger.error(`Signaling auth rejected: ${reason}`);
|
|
149
149
|
});
|
|
150
|
-
|
|
151
|
-
ctx.logger.error(`Plugin version ${current} rejected, minimum: ${minimum}`);
|
|
152
|
-
});
|
|
150
|
+
// version-rejected listener removed — version check is now client-side
|
|
153
151
|
signaling.on('force-update', async (targetVersion) => {
|
|
154
152
|
ctx.logger.info(`Force update to ${targetVersion} requested`);
|
|
155
153
|
try {
|
|
@@ -37,8 +37,7 @@ export declare class SignalingClient extends EventEmitter {
|
|
|
37
37
|
/**
|
|
38
38
|
* Open the WebSocket connection and perform the gateway-auth handshake.
|
|
39
39
|
* Resolves once the socket is open (not necessarily authenticated yet).
|
|
40
|
-
* Authentication outcome is signalled via 'connected' / 'auth-rejected'
|
|
41
|
-
* 'version-rejected' events.
|
|
40
|
+
* Authentication outcome is signalled via 'connected' / 'auth-rejected' events.
|
|
42
41
|
*/
|
|
43
42
|
connect(): Promise<void>;
|
|
44
43
|
/**
|
package/dist/signaling-client.js
CHANGED
|
@@ -63,8 +63,7 @@ export class SignalingClient extends EventEmitter {
|
|
|
63
63
|
/**
|
|
64
64
|
* Open the WebSocket connection and perform the gateway-auth handshake.
|
|
65
65
|
* Resolves once the socket is open (not necessarily authenticated yet).
|
|
66
|
-
* Authentication outcome is signalled via 'connected' / 'auth-rejected'
|
|
67
|
-
* 'version-rejected' events.
|
|
66
|
+
* Authentication outcome is signalled via 'connected' / 'auth-rejected' events.
|
|
68
67
|
*/
|
|
69
68
|
connect() {
|
|
70
69
|
this.intentionalClose = false;
|
|
@@ -198,15 +197,8 @@ export class SignalingClient extends EventEmitter {
|
|
|
198
197
|
this.emit('auth-rejected', reason);
|
|
199
198
|
break;
|
|
200
199
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const minimum = msg['minimum'] ?? '';
|
|
204
|
-
console.error(`[SignalingClient] Version rejected: current=${current}, minimum=${minimum}`);
|
|
205
|
-
// Do not reconnect — must upgrade first; auto-update logic is in updater.ts
|
|
206
|
-
this.intentionalClose = true;
|
|
207
|
-
this.emit('version-rejected', current, minimum);
|
|
208
|
-
break;
|
|
209
|
-
}
|
|
200
|
+
// version-rejected removed — version compatibility is now checked
|
|
201
|
+
// client-side via pluginVersion in connect-ready
|
|
210
202
|
case 'ice-offer': {
|
|
211
203
|
const offer = {
|
|
212
204
|
connectionId: msg['connectionId'] ?? '',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clawchatsai/connector",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "ShellChat OpenClaw plugin — P2P tunnel + local API bridge",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
"ws": "^8.0.0"
|
|
30
30
|
},
|
|
31
31
|
"openclaw": {
|
|
32
|
-
"extensions": [
|
|
32
|
+
"extensions": [
|
|
33
|
+
"./dist/index.js"
|
|
34
|
+
]
|
|
33
35
|
},
|
|
34
36
|
"devDependencies": {
|
|
35
37
|
"@types/ws": "^8.0.0",
|
package/server.js
CHANGED
|
@@ -2357,17 +2357,11 @@ class GatewayClient {
|
|
|
2357
2357
|
// Update thread updated_at
|
|
2358
2358
|
db.prepare('UPDATE threads SET updated_at = ? WHERE id = ?').run(now, parsed.threadId);
|
|
2359
2359
|
|
|
2360
|
-
//
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
);
|
|
2364
|
-
|
|
2365
|
-
// Track unread message if thread not active in any browser
|
|
2366
|
-
if (!isActive) {
|
|
2367
|
-
db.prepare('INSERT OR IGNORE INTO unread_messages (thread_id, message_id, created_at) VALUES (?, ?, ?)').run(parsed.threadId, messageId, now);
|
|
2368
|
-
// Recount from table (always accurate)
|
|
2369
|
-
syncThreadUnreadCount(db, parsed.threadId);
|
|
2370
|
-
}
|
|
2360
|
+
// Always mark as unread server-side. The browser client is responsible
|
|
2361
|
+
// for sending read receipts (active-thread) to clear unreads — same
|
|
2362
|
+
// pattern as Slack/Discord. Server doesn't track viewport state.
|
|
2363
|
+
db.prepare('INSERT OR IGNORE INTO unread_messages (thread_id, message_id, created_at) VALUES (?, ?, ?)').run(parsed.threadId, messageId, now);
|
|
2364
|
+
syncThreadUnreadCount(db, parsed.threadId);
|
|
2371
2365
|
|
|
2372
2366
|
// Get thread title and unread info for notification
|
|
2373
2367
|
const threadInfo = db.prepare('SELECT title FROM threads WHERE id = ?').get(parsed.threadId);
|
|
@@ -2387,23 +2381,21 @@ class GatewayClient {
|
|
|
2387
2381
|
unreadCount
|
|
2388
2382
|
}));
|
|
2389
2383
|
|
|
2390
|
-
//
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
}));
|
|
2406
|
-
}
|
|
2384
|
+
// Always broadcast unread-update — browser sends read receipts to clear
|
|
2385
|
+
const workspaceUnreadTotal = db.prepare('SELECT COALESCE(SUM(unread_count), 0) as total FROM threads').get().total;
|
|
2386
|
+
this.broadcastToBrowsers(JSON.stringify({
|
|
2387
|
+
type: 'shellchat',
|
|
2388
|
+
event: 'unread-update',
|
|
2389
|
+
workspace: parsed.workspace,
|
|
2390
|
+
threadId: parsed.threadId,
|
|
2391
|
+
messageId,
|
|
2392
|
+
action: 'new',
|
|
2393
|
+
unreadCount,
|
|
2394
|
+
workspaceUnreadTotal,
|
|
2395
|
+
title: threadInfo?.title || 'Chat',
|
|
2396
|
+
preview,
|
|
2397
|
+
timestamp: now
|
|
2398
|
+
}));
|
|
2407
2399
|
|
|
2408
2400
|
console.log(`Saved assistant message to ${parsed.workspace}/${parsed.threadId} (seq: ${seq})`);
|
|
2409
2401
|
} catch (e) {
|
|
@@ -2854,13 +2846,13 @@ class GatewayClient {
|
|
|
2854
2846
|
}
|
|
2855
2847
|
|
|
2856
2848
|
setActiveThread(ws, workspace, threadId) {
|
|
2857
|
-
const client = this.browserClients.get(ws);
|
|
2849
|
+
const client = ws ? this.browserClients.get(ws) : null;
|
|
2858
2850
|
if (client) {
|
|
2859
2851
|
client.activeWorkspace = workspace;
|
|
2860
2852
|
client.activeThreadId = threadId;
|
|
2861
2853
|
}
|
|
2862
2854
|
|
|
2863
|
-
// Auto-clear unreads: opening a thread = reading it
|
|
2855
|
+
// Auto-clear unreads: opening a thread = reading it (read receipt)
|
|
2864
2856
|
if (workspace && threadId) {
|
|
2865
2857
|
try {
|
|
2866
2858
|
const wsData = getWorkspaces();
|
|
@@ -3620,19 +3612,15 @@ export function createApp(config = {}) {
|
|
|
3620
3612
|
try {
|
|
3621
3613
|
db.prepare(`INSERT INTO messages (id, thread_id, role, content, status, timestamp, created_at) VALUES (?, ?, 'assistant', ?, 'sent', ?, ?) ON CONFLICT(id) DO UPDATE SET content = excluded.content, timestamp = excluded.timestamp`).run(messageId, parsed.threadId, content, now, now);
|
|
3622
3614
|
db.prepare('UPDATE threads SET updated_at = ? WHERE id = ?').run(now, parsed.threadId);
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
syncThreadUnreadCount(db, parsed.threadId);
|
|
3627
|
-
}
|
|
3615
|
+
// Always mark as unread — browser sends read receipts to clear
|
|
3616
|
+
db.prepare('INSERT OR IGNORE INTO unread_messages (thread_id, message_id, created_at) VALUES (?, ?, ?)').run(parsed.threadId, messageId, now);
|
|
3617
|
+
syncThreadUnreadCount(db, parsed.threadId);
|
|
3628
3618
|
const threadInfo = db.prepare('SELECT title FROM threads WHERE id = ?').get(parsed.threadId);
|
|
3629
3619
|
const unreadCount = db.prepare('SELECT COUNT(*) as c FROM unread_messages WHERE thread_id = ?').get(parsed.threadId).c;
|
|
3630
3620
|
const preview = content.length > 120 ? content.substring(0, 120) + '...' : content;
|
|
3631
3621
|
this.broadcastToBrowsers(JSON.stringify({ type: 'shellchat', event: 'message-saved', threadId: parsed.threadId, workspace: parsed.workspace, messageId, timestamp: now, title: threadInfo?.title || 'Chat', preview, unreadCount }));
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
this.broadcastToBrowsers(JSON.stringify({ type: 'shellchat', event: 'unread-update', workspace: parsed.workspace, threadId: parsed.threadId, messageId, action: 'new', unreadCount, workspaceUnreadTotal, title: threadInfo?.title || 'Chat', preview, timestamp: now }));
|
|
3635
|
-
}
|
|
3622
|
+
const workspaceUnreadTotal = db.prepare('SELECT COALESCE(SUM(unread_count), 0) as total FROM threads').get().total;
|
|
3623
|
+
this.broadcastToBrowsers(JSON.stringify({ type: 'shellchat', event: 'unread-update', workspace: parsed.workspace, threadId: parsed.threadId, messageId, action: 'new', unreadCount, workspaceUnreadTotal, title: threadInfo?.title || 'Chat', preview, timestamp: now }));
|
|
3636
3624
|
console.log(`Saved assistant message to ${parsed.workspace}/${parsed.threadId} (seq: ${seq})`);
|
|
3637
3625
|
} catch (e) { console.error(`Failed to save assistant message:`, e.message); }
|
|
3638
3626
|
}
|
|
@@ -3846,7 +3834,7 @@ export function createApp(config = {}) {
|
|
|
3846
3834
|
removeBrowserClient(ws) { this.browserClients.delete(ws); }
|
|
3847
3835
|
|
|
3848
3836
|
setActiveThread(ws, workspace, threadId) {
|
|
3849
|
-
const client = this.browserClients.get(ws);
|
|
3837
|
+
const client = ws ? this.browserClients.get(ws) : null;
|
|
3850
3838
|
if (client) { client.activeWorkspace = workspace; client.activeThreadId = threadId; }
|
|
3851
3839
|
if (workspace && threadId) {
|
|
3852
3840
|
try {
|
|
@@ -3944,7 +3932,7 @@ export function createApp(config = {}) {
|
|
|
3944
3932
|
if (method === 'GET' && urlPath === '/api/export') return _handleExport(req, res);
|
|
3945
3933
|
if (method === 'POST' && urlPath === '/api/import') return await _handleImport(req, res);
|
|
3946
3934
|
if (method === 'POST' && urlPath === '/api/active-thread') {
|
|
3947
|
-
const body =
|
|
3935
|
+
const body = await parseBody(req);
|
|
3948
3936
|
const { threadId, workspace } = body;
|
|
3949
3937
|
if (threadId && workspace) _gatewayClient.setActiveThread(null, workspace, threadId);
|
|
3950
3938
|
return send(res, 200, { ok: true });
|