@clawchatsai/connector 0.0.10 → 0.0.11
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/package.json +4 -2
- package/server.js +29 -41
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clawchatsai/connector",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
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 });
|