@clawchatsai/connector 0.0.13 → 0.0.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
- * @shellchat/tunnel — OpenClaw plugin entry point
2
+ * @clawchatsai/connector — OpenClaw plugin entry point
3
3
  *
4
- * Registers ShellChat as a gateway plugin, providing:
4
+ * Registers ClawChats as a gateway plugin, providing:
5
5
  * - Local HTTP API bridge via createApp()
6
6
  * - WebRTC DataChannel for browser connections
7
7
  * - Signaling client for NAT traversal
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
- * @shellchat/tunnel — OpenClaw plugin entry point
2
+ * @clawchatsai/connector — OpenClaw plugin entry point
3
3
  *
4
- * Registers ShellChat as a gateway plugin, providing:
4
+ * Registers ClawChats as a gateway plugin, providing:
5
5
  * - Local HTTP API bridge via createApp()
6
6
  * - WebRTC DataChannel for browser connections
7
7
  * - Signaling client for NAT traversal
@@ -32,7 +32,7 @@ let _stopRequested = false;
32
32
  // ---------------------------------------------------------------------------
33
33
  // Config helpers
34
34
  // ---------------------------------------------------------------------------
35
- const CONFIG_DIR = path.join(process.env.HOME || '/root', '.openclaw', 'shellchats');
35
+ const CONFIG_DIR = path.join(process.env.HOME || '/root', '.openclaw', 'clawchats');
36
36
  const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
37
37
  const RUNTIME_FILE = path.join(CONFIG_DIR, 'runtime.json');
38
38
  function loadConfig() {
@@ -73,11 +73,11 @@ async function ensureNativeModules(ctx) {
73
73
  ctx.logger.error('Try running manually: cd ~/.openclaw/extensions/connector && npm rebuild better-sqlite3');
74
74
  }
75
75
  }
76
- async function startShellChat(ctx, api) {
76
+ async function startClawChats(ctx, api) {
77
77
  _stopRequested = false;
78
78
  let config = loadConfig();
79
79
  if (!config) {
80
- ctx.logger.info('ShellChats not configured. Waiting for setup...');
80
+ ctx.logger.info('ClawChats not configured. Waiting for setup...');
81
81
  fs.mkdirSync(CONFIG_DIR, { recursive: true });
82
82
  while (!config && !_stopRequested) {
83
83
  await new Promise(r => setTimeout(r, 2000));
@@ -85,7 +85,7 @@ async function startShellChat(ctx, api) {
85
85
  }
86
86
  if (_stopRequested || !config)
87
87
  return;
88
- ctx.logger.info('Setup detected — connecting to ShellChats...');
88
+ ctx.logger.info('Setup detected — connecting to ClawChats...');
89
89
  }
90
90
  // 1. Check for updates
91
91
  const update = await checkForUpdates();
@@ -95,7 +95,7 @@ async function startShellChat(ctx, api) {
95
95
  try {
96
96
  await performUpdate();
97
97
  ctx.logger.info(`Updated to ${update.latest}. Requesting graceful restart...`);
98
- api.runtime.requestRestart?.('shellchats update');
98
+ api.runtime.requestRestart?.('clawchats update');
99
99
  return; // will restart with new version
100
100
  }
101
101
  catch (e) {
@@ -108,14 +108,14 @@ async function startShellChat(ctx, api) {
108
108
  const gwAuth = gwCfg?.['gateway']?.['auth'];
109
109
  const gatewayToken = gwAuth?.['token'] || config.gatewayToken || '';
110
110
  if (!gatewayToken) {
111
- ctx.logger.error('No gateway token available. Re-run: openclaw shellchats setup <token>');
111
+ ctx.logger.error('No gateway token available. Re-run: openclaw clawchats setup <token>');
112
112
  return;
113
113
  }
114
114
  // 3. Ensure native modules are built (OpenClaw installs with --ignore-scripts)
115
115
  await ensureNativeModules(ctx);
116
116
  // 4. Import server.js and create app instance with plugin paths
117
- const dataDir = path.join(ctx.stateDir, 'shellchats', 'data');
118
- const uploadsDir = path.join(ctx.stateDir, 'shellchats', 'uploads');
117
+ const dataDir = path.join(ctx.stateDir, 'clawchats', 'data');
118
+ const uploadsDir = path.join(ctx.stateDir, 'clawchats', 'uploads');
119
119
  // Dynamic import of server.js (plain JS, no type declarations)
120
120
  // @ts-expect-error — server.js is plain JS with no .d.ts
121
121
  const serverModule = await import('../server.js');
@@ -228,11 +228,11 @@ async function startShellChat(ctx, api) {
228
228
  }, null, 2), { mode: 0o600 });
229
229
  ctx.logger.info(`Health endpoint on 127.0.0.1:${addr.port}`);
230
230
  });
231
- ctx.logger.info('ShellChat service started');
231
+ ctx.logger.info('ClawChats service started');
232
232
  }
233
- async function stopShellChat(ctx) {
233
+ async function stopClawChats(ctx) {
234
234
  _stopRequested = true;
235
- ctx.logger.info('ShellChat service stopping...');
235
+ ctx.logger.info('ClawChats service stopping...');
236
236
  // 0. Tear down health endpoint
237
237
  if (healthServer) {
238
238
  healthServer.close();
@@ -259,7 +259,7 @@ async function stopShellChat(ctx) {
259
259
  // 4. Close SQLite databases
260
260
  app?.shutdown();
261
261
  app = null;
262
- ctx.logger.info('ShellChat service stopped');
262
+ ctx.logger.info('ClawChats service stopped');
263
263
  }
264
264
  // ---------------------------------------------------------------------------
265
265
  // DataChannel message handler (spec section 6.4)
@@ -386,7 +386,7 @@ function broadcastToClients(msg) {
386
386
  // ---------------------------------------------------------------------------
387
387
  function formatStatus() {
388
388
  const lines = [];
389
- lines.push(`ShellChat Plugin v${PLUGIN_VERSION}`);
389
+ lines.push(`ClawChats Plugin v${PLUGIN_VERSION}`);
390
390
  lines.push(`Gateway: ${app?.gatewayClient?.connected ? 'connected' : 'disconnected'}`);
391
391
  lines.push(`Signaling: ${signaling?.isConnected ? 'connected' : 'disconnected'}`);
392
392
  lines.push(`Clients: ${connectedClients.size}`);
@@ -410,7 +410,7 @@ async function handleSetup(token) {
410
410
  console.error('Setup token has expired. Generate a new one from clawchats.ai.');
411
411
  return;
412
412
  }
413
- console.log('Setting up ShellChats...');
413
+ console.log('Setting up ClawChats...');
414
414
  console.log(` Server: ${tokenData.serverUrl}`);
415
415
  // Generate API key for signaling server auth
416
416
  const { randomBytes } = await import('node:crypto');
@@ -467,7 +467,7 @@ async function handleSetup(token) {
467
467
  const uploadsDir = path.join(CONFIG_DIR, 'uploads');
468
468
  fs.mkdirSync(dataDir, { recursive: true });
469
469
  fs.mkdirSync(uploadsDir, { recursive: true });
470
- console.log(' ShellChats is ready!');
470
+ console.log(' ClawChats is ready!');
471
471
  console.log(' Open clawchats.ai in your browser to start chatting.');
472
472
  ws.close();
473
473
  resolve();
@@ -497,7 +497,7 @@ async function handleStatus() {
497
497
  runtime = JSON.parse(fs.readFileSync(RUNTIME_FILE, 'utf8'));
498
498
  }
499
499
  catch {
500
- console.log('ShellChats: offline (service not running)');
500
+ console.log('ClawChats: offline (service not running)');
501
501
  return;
502
502
  }
503
503
  // Verify PID is alive
@@ -505,7 +505,7 @@ async function handleStatus() {
505
505
  process.kill(runtime.pid, 0);
506
506
  }
507
507
  catch {
508
- console.log('ShellChats: offline (stale runtime file)');
508
+ console.log('ClawChats: offline (stale runtime file)');
509
509
  try {
510
510
  fs.unlinkSync(RUNTIME_FILE);
511
511
  }
@@ -524,20 +524,20 @@ async function handleStatus() {
524
524
  req.setTimeout(3000, () => { req.destroy(); reject(new Error('timeout')); });
525
525
  });
526
526
  const status = JSON.parse(body);
527
- console.log(`ShellChats Plugin v${status.version}`);
527
+ console.log(`ClawChats Plugin v${status.version}`);
528
528
  console.log(`Uptime: ${Math.floor(status.uptime)}s`);
529
529
  console.log(`Gateway: ${status.gateway.connected ? 'connected' : 'disconnected'}`);
530
530
  console.log(`Signaling: ${status.signaling.connected ? 'connected' : 'disconnected'}`);
531
531
  console.log(`Clients: ${status.clients.active}`);
532
532
  }
533
533
  catch {
534
- console.log('ShellChats: offline (could not reach service)');
534
+ console.log('ClawChats: offline (could not reach service)');
535
535
  }
536
536
  }
537
537
  async function handleReset() {
538
538
  try {
539
539
  fs.rmSync(CONFIG_DIR, { recursive: true, force: true });
540
- console.log('ShellChats data removed. Plugin disconnected.');
540
+ console.log('ClawChats data removed. Plugin disconnected.');
541
541
  }
542
542
  catch (e) {
543
543
  console.error(`Reset failed: ${e.message}`);
@@ -554,7 +554,7 @@ async function handleImport(sourcePath) {
554
554
  console.error(`Source must be a directory: ${resolvedSource}`);
555
555
  return;
556
556
  }
557
- // Destination: ~/.openclaw/shellchats/data/
557
+ // Destination: ~/.openclaw/clawchats/data/
558
558
  const destDataDir = path.join(CONFIG_DIR, 'data');
559
559
  fs.mkdirSync(destDataDir, { recursive: true });
560
560
  // Import .db files
@@ -586,7 +586,7 @@ async function handleImport(sourcePath) {
586
586
  }
587
587
  }
588
588
  // Also try to migrate config.json from the parent directory
589
- // e.g. if source is ~/.openclaw/shellchat/data/, config is at ~/.openclaw/shellchat/config.json
589
+ // e.g. if source is ~/.openclaw/clawchats/data/, config is at ~/.openclaw/clawchats/config.json
590
590
  const parentConfigPath = path.join(path.dirname(resolvedSource), 'config.json');
591
591
  if (fs.existsSync(parentConfigPath)) {
592
592
  try {
@@ -605,26 +605,26 @@ async function handleImport(sourcePath) {
605
605
  // ---------------------------------------------------------------------------
606
606
  const plugin = {
607
607
  id: PLUGIN_ID,
608
- name: 'ShellChats',
609
- description: 'Connects your gateway to ShellChats via WebRTC P2P',
608
+ name: 'ClawChats',
609
+ description: 'Connects your gateway to ClawChats via WebRTC P2P',
610
610
  register(api) {
611
611
  // Background service: signaling + gateway bridge + future WebRTC
612
612
  api.registerService({
613
613
  id: 'connector-service',
614
- start: (ctx) => startShellChat(ctx, api),
615
- stop: (ctx) => stopShellChat(ctx),
614
+ start: (ctx) => startClawChats(ctx, api),
615
+ stop: (ctx) => stopClawChats(ctx),
616
616
  });
617
617
  // CLI commands
618
618
  api.registerCli((ctx) => {
619
- const cmd = ctx.program.command('shellchats');
619
+ const cmd = ctx.program.command('clawchats');
620
620
  cmd.command('setup <token>')
621
- .description('Set up ShellChats with a setup token')
621
+ .description('Set up ClawChats with a setup token')
622
622
  .action((token) => handleSetup(String(token)));
623
623
  cmd.command('status')
624
- .description('Show ShellChats connection status')
624
+ .description('Show ClawChats connection status')
625
625
  .action(() => handleStatus());
626
626
  cmd.command('reset')
627
- .description('Disconnect and remove all ShellChats data')
627
+ .description('Disconnect and remove all ClawChats data')
628
628
  .action(() => handleReset());
629
629
  cmd.command('import <path>')
630
630
  .description('Import databases and config from a folder (e.g. migrate from old data directory)')
@@ -632,8 +632,8 @@ const plugin = {
632
632
  });
633
633
  // Slash command for status from any channel
634
634
  api.registerCommand({
635
- name: 'shellchats',
636
- description: 'Show ShellChats tunnel status',
635
+ name: 'clawchats',
636
+ description: 'Show ClawChats tunnel status',
637
637
  handler: () => ({ text: formatStatus() }),
638
638
  });
639
639
  },
package/dist/migrate.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Schema migration runner for the ShellChat plugin SQLite database.
2
+ * Schema migration runner for the ClawChats plugin SQLite database.
3
3
  *
4
4
  * - Tracks schema version in a `_schema_version` table
5
5
  * - Runs migrations sequentially from current version to target
package/dist/migrate.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Schema migration runner for the ShellChat plugin SQLite database.
2
+ * Schema migration runner for the ClawChats plugin SQLite database.
3
3
  *
4
4
  * - Tracks schema version in a `_schema_version` table
5
5
  * - Runs migrations sequentially from current version to target
package/dist/shim.js CHANGED
@@ -46,7 +46,7 @@ class FakeReq extends Readable {
46
46
  }
47
47
  else if (parsed && parsed['_multipart']) {
48
48
  // Multipart form data: { _multipart: true, fields: { key: string | { filename, contentType, data } } }
49
- const boundary = '----ShellChatBoundary' + Date.now();
49
+ const boundary = '----ClawChatsBoundary' + Date.now();
50
50
  this.headers['content-type'] = `multipart/form-data; boundary=${boundary}`;
51
51
  const fields = parsed['fields'] || {};
52
52
  const parts = [];
@@ -1,5 +1,5 @@
1
1
  /**
2
- * SignalingClient — persistent WSS connection to the ShellChat signaling server.
2
+ * SignalingClient — persistent WSS connection to the ClawChats signaling server.
3
3
  *
4
4
  * Responsibilities:
5
5
  * - Authenticate with the signaling server on connect (gateway-auth)
@@ -1,5 +1,5 @@
1
1
  /**
2
- * SignalingClient — persistent WSS connection to the ShellChat signaling server.
2
+ * SignalingClient — persistent WSS connection to the ClawChats signaling server.
3
3
  *
4
4
  * Responsibilities:
5
5
  * - Authenticate with the signaling server on connect (gateway-auth)
@@ -109,7 +109,7 @@ export declare class WebRTCPeerManager extends EventEmitter {
109
109
  handleIceCandidate(connectionId: string, candidate: unknown): void;
110
110
  /**
111
111
  * Close all active peer connections and DataChannels.
112
- * Called during plugin shutdown (stopShellChat).
112
+ * Called during plugin shutdown (stopClawChats).
113
113
  */
114
114
  closeAll(): void;
115
115
  /**
@@ -194,7 +194,7 @@ export class WebRTCPeerManager extends EventEmitter {
194
194
  }
195
195
  /**
196
196
  * Close all active peer connections and DataChannels.
197
- * Called during plugin shutdown (stopShellChat).
197
+ * Called during plugin shutdown (stopClawChats).
198
198
  */
199
199
  closeAll() {
200
200
  console.log(`[WebRTCPeerManager] Closing all connections (${this.peerConnections.size} peers, ${this.activeChannels.size} channels)`);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "connector",
3
- "name": "ShellChats",
4
- "description": "Connects your OpenClaw gateway to ShellChats via WebRTC P2P",
3
+ "name": "ClawChats",
4
+ "description": "Connects your OpenClaw gateway to ClawChats via WebRTC P2P",
5
5
  "kind": "integration",
6
6
  "configSchema": {
7
7
  "type": "object",
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@clawchatsai/connector",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "type": "module",
5
- "description": "ShellChat OpenClaw plugin — P2P tunnel + local API bridge",
5
+ "description": "ClawChats OpenClaw plugin — P2P tunnel + local API bridge",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "files": [
package/server.js CHANGED
@@ -1,4 +1,4 @@
1
- // ShellChat Backend Server
1
+ // ClawChats Backend Server
2
2
  // Single-file Node.js HTTP server with SQLite storage
3
3
  // See specs/backend-session-architecture.md for full spec
4
4
 
@@ -64,7 +64,7 @@ function _buildDeviceAuth(identity, { clientId, clientMode, role, scopes, token,
64
64
 
65
65
  // ─── Configuration ──────────────────────────────────────────────────────────
66
66
 
67
- const PORT = parseInt(process.env.SHELLCHAT_PORT || '3001', 10);
67
+ const PORT = parseInt(process.env.CLAWCHATS_PORT || process.env.SHELLCHAT_PORT || '3001', 10);
68
68
  const DATA_DIR = path.join(__dirname, 'data');
69
69
  const UPLOADS_DIR = path.join(__dirname, 'uploads');
70
70
  const WORKSPACES_FILE = path.join(DATA_DIR, 'workspaces.json');
@@ -174,9 +174,9 @@ function parseConfigField(field) {
174
174
  }
175
175
 
176
176
  // Load auth token from config.js or env var
177
- let AUTH_TOKEN = process.env.SHELLCHAT_AUTH_TOKEN || parseConfigField('authToken') || '';
177
+ let AUTH_TOKEN = process.env.CLAWCHATS_AUTH_TOKEN || process.env.SHELLCHAT_AUTH_TOKEN || parseConfigField('authToken') || '';
178
178
  if (!AUTH_TOKEN) {
179
- console.error('WARNING: No auth token configured. Set SHELLCHAT_AUTH_TOKEN or create config.js');
179
+ console.error('WARNING: No auth token configured. Set CLAWCHATS_AUTH_TOKEN or create config.js');
180
180
  }
181
181
 
182
182
  // Load gateway WebSocket URL
@@ -883,7 +883,7 @@ async function handleMarkMessagesRead(req, res, params) {
883
883
  // Broadcast unread-update to ALL browser clients (so other tabs/devices sync)
884
884
  const workspace = getWorkspaces().active;
885
885
  gatewayClient.broadcastToBrowsers(JSON.stringify({
886
- type: 'shellchat',
886
+ type: 'clawchats',
887
887
  event: 'unread-update',
888
888
  workspace,
889
889
  threadId,
@@ -2369,7 +2369,7 @@ class GatewayClient {
2369
2369
 
2370
2370
  saveAssistantMessage(sessionKey, message, seq) {
2371
2371
  const parsed = parseSessionKey(sessionKey);
2372
- if (!parsed) return; // Non-ShellChat session key, silently ignore
2372
+ if (!parsed) return; // Non-ClawChats session key, silently ignore
2373
2373
 
2374
2374
  // Guard: verify workspace still exists
2375
2375
  const ws = getWorkspaces();
@@ -2424,7 +2424,7 @@ class GatewayClient {
2424
2424
 
2425
2425
  // Broadcast message-saved for active thread reload
2426
2426
  this.broadcastToBrowsers(JSON.stringify({
2427
- type: 'shellchat',
2427
+ type: 'clawchats',
2428
2428
  event: 'message-saved',
2429
2429
  threadId: parsed.threadId,
2430
2430
  workspace: parsed.workspace,
@@ -2438,7 +2438,7 @@ class GatewayClient {
2438
2438
  // Always broadcast unread-update — browser sends read receipts to clear
2439
2439
  const workspaceUnreadTotal = db.prepare('SELECT COALESCE(SUM(unread_count), 0) as total FROM threads').get().total;
2440
2440
  this.broadcastToBrowsers(JSON.stringify({
2441
- type: 'shellchat',
2441
+ type: 'clawchats',
2442
2442
  event: 'unread-update',
2443
2443
  workspace: parsed.workspace,
2444
2444
  threadId: parsed.threadId,
@@ -2616,7 +2616,7 @@ class GatewayClient {
2616
2616
  if (!parsed) return;
2617
2617
 
2618
2618
  this.broadcastToBrowsers(JSON.stringify({
2619
- type: 'shellchat',
2619
+ type: 'clawchats',
2620
2620
  event: 'agent-activity',
2621
2621
  workspace: parsed.workspace,
2622
2622
  threadId: parsed.threadId,
@@ -2761,7 +2761,7 @@ class GatewayClient {
2761
2761
 
2762
2762
  // Notify browsers to re-render this message with activity data
2763
2763
  this.broadcastToBrowsers(JSON.stringify({
2764
- type: 'shellchat',
2764
+ type: 'clawchats',
2765
2765
  event: 'activity-saved',
2766
2766
  workspace: parsed.workspace,
2767
2767
  threadId: parsed.threadId,
@@ -2844,7 +2844,7 @@ class GatewayClient {
2844
2844
 
2845
2845
  broadcastGatewayStatus(connected) {
2846
2846
  const msg = JSON.stringify({
2847
- type: 'shellchat',
2847
+ type: 'clawchats',
2848
2848
  event: 'gateway-status',
2849
2849
  connected
2850
2850
  });
@@ -2873,7 +2873,7 @@ class GatewayClient {
2873
2873
  // Send current gateway status
2874
2874
  if (ws.readyState === WS.OPEN) {
2875
2875
  ws.send(JSON.stringify({
2876
- type: 'shellchat',
2876
+ type: 'clawchats',
2877
2877
  event: 'gateway-status',
2878
2878
  connected: this.connected
2879
2879
  }));
@@ -2887,7 +2887,7 @@ class GatewayClient {
2887
2887
  }
2888
2888
  if (streams.length > 0) {
2889
2889
  ws.send(JSON.stringify({
2890
- type: 'shellchat',
2890
+ type: 'clawchats',
2891
2891
  event: 'stream-sync',
2892
2892
  streams
2893
2893
  }));
@@ -2924,7 +2924,7 @@ class GatewayClient {
2924
2924
  // Broadcast unread-update clear to ALL browser clients
2925
2925
  const workspaceUnreadTotal = db.prepare('SELECT COALESCE(SUM(unread_count), 0) as total FROM threads').get().total;
2926
2926
  this.broadcastToBrowsers(JSON.stringify({
2927
- type: 'shellchat',
2927
+ type: 'clawchats',
2928
2928
  event: 'unread-update',
2929
2929
  workspace,
2930
2930
  threadId,
@@ -2952,7 +2952,7 @@ function syncThreadUnreadCount(db, threadId) {
2952
2952
  function parseSessionKey(sessionKey) {
2953
2953
  if (!sessionKey) return null;
2954
2954
  const match = sessionKey.match(/^agent:main:([^:]+):chat:([^:]+)$/);
2955
- if (!match) return null; // Non-ShellChat keys — silently ignore
2955
+ if (!match) return null; // Non-ClawChats keys — silently ignore
2956
2956
  return { workspace: match[1], threadId: match[2] };
2957
2957
  }
2958
2958
 
@@ -2973,7 +2973,7 @@ const gatewayClient = new GatewayClient();
2973
2973
 
2974
2974
  // ─── createApp Factory ───────────────────────────────────────────────────────
2975
2975
  // Returns an isolated instance of the app state + handlers.
2976
- // Used by the plugin (signaling/index.js) to embed ShellChat logic without
2976
+ // Used by the plugin (signaling/index.js) to embed ClawChats logic without
2977
2977
  // spinning up a standalone HTTP server.
2978
2978
 
2979
2979
  export function createApp(config = {}) {
@@ -2986,7 +2986,7 @@ export function createApp(config = {}) {
2986
2986
 
2987
2987
  let _AUTH_TOKEN = config.authToken !== undefined
2988
2988
  ? config.authToken
2989
- : (process.env.SHELLCHAT_AUTH_TOKEN || parseConfigField('authToken') || '');
2989
+ : (process.env.CLAWCHATS_AUTH_TOKEN || process.env.SHELLCHAT_AUTH_TOKEN || parseConfigField('authToken') || '');
2990
2990
 
2991
2991
  // Separate token for gateway WS auth (falls back to _AUTH_TOKEN for direct mode)
2992
2992
  const _GATEWAY_TOKEN = config.gatewayToken !== undefined
@@ -3232,7 +3232,7 @@ export function createApp(config = {}) {
3232
3232
  const remaining = syncThreadUnreadCount(db, threadId);
3233
3233
  const workspace = _getWorkspaces().active;
3234
3234
  _gatewayClient.broadcastToBrowsers(JSON.stringify({
3235
- type: 'shellchat', event: 'unread-update', workspace, threadId,
3235
+ type: 'clawchats', event: 'unread-update', workspace, threadId,
3236
3236
  action: 'read', messageIds, unreadCount: remaining, timestamp: Date.now()
3237
3237
  }));
3238
3238
  send(res, 200, { unread_count: remaining });
@@ -3679,9 +3679,9 @@ export function createApp(config = {}) {
3679
3679
  const threadInfo = db.prepare('SELECT title FROM threads WHERE id = ?').get(parsed.threadId);
3680
3680
  const unreadCount = db.prepare('SELECT COUNT(*) as c FROM unread_messages WHERE thread_id = ?').get(parsed.threadId).c;
3681
3681
  const preview = content.length > 120 ? content.substring(0, 120) + '...' : content;
3682
- this.broadcastToBrowsers(JSON.stringify({ type: 'shellchat', event: 'message-saved', threadId: parsed.threadId, workspace: parsed.workspace, messageId, timestamp: now, title: threadInfo?.title || 'Chat', preview, unreadCount }));
3682
+ this.broadcastToBrowsers(JSON.stringify({ type: 'clawchats', event: 'message-saved', threadId: parsed.threadId, workspace: parsed.workspace, messageId, timestamp: now, title: threadInfo?.title || 'Chat', preview, unreadCount }));
3683
3683
  const workspaceUnreadTotal = db.prepare('SELECT COALESCE(SUM(unread_count), 0) as total FROM threads').get().total;
3684
- 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 }));
3684
+ this.broadcastToBrowsers(JSON.stringify({ type: 'clawchats', event: 'unread-update', workspace: parsed.workspace, threadId: parsed.threadId, messageId, action: 'new', unreadCount, workspaceUnreadTotal, title: threadInfo?.title || 'Chat', preview, timestamp: now }));
3685
3685
  console.log(`Saved assistant message to ${parsed.workspace}/${parsed.threadId} (seq: ${seq})`);
3686
3686
  } catch (e) { console.error(`Failed to save assistant message:`, e.message); }
3687
3687
  }
@@ -3759,7 +3759,7 @@ export function createApp(config = {}) {
3759
3759
  broadcastActivityUpdate(runId, log) {
3760
3760
  const parsed = log.sessionKey ? parseSessionKey(log.sessionKey) : null;
3761
3761
  if (!parsed) return;
3762
- this.broadcastToBrowsers(JSON.stringify({ type: 'shellchat', event: 'agent-activity', workspace: parsed.workspace, threadId: parsed.threadId, runId, steps: log.steps, summary: this.generateActivitySummary(log.steps) }));
3762
+ this.broadcastToBrowsers(JSON.stringify({ type: 'clawchats', event: 'agent-activity', workspace: parsed.workspace, threadId: parsed.threadId, runId, steps: log.steps, summary: this.generateActivitySummary(log.steps) }));
3763
3763
  }
3764
3764
 
3765
3765
  finalizeActivityLog(runId, log) {
@@ -3824,7 +3824,7 @@ export function createApp(config = {}) {
3824
3824
  metadata.activitySummary = this.generateActivitySummary(log.steps);
3825
3825
  db.prepare('UPDATE messages SET metadata = ? WHERE id = ?').run(JSON.stringify(metadata), msg.id);
3826
3826
  console.log(`[ActivityLog] Saved ${toolSteps.length} tool steps for message ${msg.id}`);
3827
- this.broadcastToBrowsers(JSON.stringify({ type: 'shellchat', event: 'activity-saved', workspace: parsed.workspace, threadId: parsed.threadId, messageId: msg.id }));
3827
+ this.broadcastToBrowsers(JSON.stringify({ type: 'clawchats', event: 'activity-saved', workspace: parsed.workspace, threadId: parsed.threadId, messageId: msg.id }));
3828
3828
  }
3829
3829
  }
3830
3830
  } catch (e) { console.error('Failed to save activity log:', e.message); }
@@ -3864,7 +3864,7 @@ export function createApp(config = {}) {
3864
3864
  }
3865
3865
 
3866
3866
  broadcastGatewayStatus(connected) {
3867
- this.broadcastToBrowsers(JSON.stringify({ type: 'shellchat', event: 'gateway-status', connected }));
3867
+ this.broadcastToBrowsers(JSON.stringify({ type: 'clawchats', event: 'gateway-status', connected }));
3868
3868
  }
3869
3869
 
3870
3870
  sendToGateway(data) {
@@ -3883,12 +3883,12 @@ export function createApp(config = {}) {
3883
3883
  addBrowserClient(ws) {
3884
3884
  this.browserClients.set(ws, { activeWorkspace: null, activeThreadId: null });
3885
3885
  if (ws.readyState === WS.OPEN) {
3886
- ws.send(JSON.stringify({ type: 'shellchat', event: 'gateway-status', connected: this.connected }));
3886
+ ws.send(JSON.stringify({ type: 'clawchats', event: 'gateway-status', connected: this.connected }));
3887
3887
  const streams = [];
3888
3888
  for (const [sessionKey, state] of this.streamState.entries()) {
3889
3889
  if (state.state === 'streaming') streams.push({ sessionKey, threadId: state.threadId, buffer: state.buffer });
3890
3890
  }
3891
- if (streams.length > 0) ws.send(JSON.stringify({ type: 'shellchat', event: 'stream-sync', streams }));
3891
+ if (streams.length > 0) ws.send(JSON.stringify({ type: 'clawchats', event: 'stream-sync', streams }));
3892
3892
  }
3893
3893
  }
3894
3894
 
@@ -3908,7 +3908,7 @@ export function createApp(config = {}) {
3908
3908
  if (deleted.changes > 0) {
3909
3909
  syncThreadUnreadCount(db, threadId);
3910
3910
  const workspaceUnreadTotal = db.prepare('SELECT COALESCE(SUM(unread_count), 0) as total FROM threads').get().total;
3911
- this.broadcastToBrowsers(JSON.stringify({ type: 'shellchat', event: 'unread-update', workspace, threadId, action: 'clear', unreadCount: 0, workspaceUnreadTotal, timestamp: Date.now() }));
3911
+ this.broadcastToBrowsers(JSON.stringify({ type: 'clawchats', event: 'unread-update', workspace, threadId, action: 'clear', unreadCount: 0, workspaceUnreadTotal, timestamp: Date.now() }));
3912
3912
  }
3913
3913
  } catch (e) { console.error('Failed to auto-clear unreads on active-thread:', e.message); }
3914
3914
  }
@@ -4024,7 +4024,7 @@ export function createApp(config = {}) {
4024
4024
  const token = msg.params?.auth?.token;
4025
4025
  if (token === _AUTH_TOKEN || !_AUTH_TOKEN) {
4026
4026
  console.log('Browser client authenticated');
4027
- ws.send(JSON.stringify({ type: 'res', id: msg.id, ok: true, payload: { type: 'hello-ok', protocol: 3, server: { version: '0.1.0', host: 'shellchat-backend' } } }));
4027
+ ws.send(JSON.stringify({ type: 'res', id: msg.id, ok: true, payload: { type: 'hello-ok', protocol: 3, server: { version: '0.1.0', host: 'clawchats-backend' } } }));
4028
4028
  } else {
4029
4029
  console.log('Browser client auth failed');
4030
4030
  ws.send(JSON.stringify({ type: 'res', id: msg.id, ok: false, error: { code: 'AUTH_FAILED', message: 'Invalid auth token' } }));
@@ -4032,12 +4032,12 @@ export function createApp(config = {}) {
4032
4032
  }
4033
4033
  return;
4034
4034
  }
4035
- if (msg.type === 'shellchat') {
4035
+ if (msg.type === 'clawchats' || msg.type === 'shellchat') { // backward compat: accept legacy 'shellchat' type
4036
4036
  if (msg.action === 'active-thread') { _gatewayClient.setActiveThread(ws, msg.workspace, msg.threadId); console.log(`Browser client set active thread: ${msg.workspace}/${msg.threadId}`); return; }
4037
- if (msg.action === 'debug-start') { const result = _debugLogger.start(msg.ts, ws); if (result.error === 'already-active') ws.send(JSON.stringify({ type: 'shellchat', event: 'debug-error', error: 'Recording already active in another tab', sessionId: result.sessionId })); else ws.send(JSON.stringify({ type: 'shellchat', event: 'debug-started', sessionId: result.sessionId })); return; }
4038
- if (msg.action === 'debug-dump') { const { sessionId, files } = _debugLogger.saveDump(msg); ws.send(JSON.stringify({ type: 'shellchat', event: 'debug-saved', sessionId, files })); return; }
4037
+ if (msg.action === 'debug-start') { const result = _debugLogger.start(msg.ts, ws); if (result.error === 'already-active') ws.send(JSON.stringify({ type: 'clawchats', event: 'debug-error', error: 'Recording already active in another tab', sessionId: result.sessionId })); else ws.send(JSON.stringify({ type: 'clawchats', event: 'debug-started', sessionId: result.sessionId })); return; }
4038
+ if (msg.action === 'debug-dump') { const { sessionId, files } = _debugLogger.saveDump(msg); ws.send(JSON.stringify({ type: 'clawchats', event: 'debug-saved', sessionId, files })); return; }
4039
4039
  }
4040
- } catch { /* Not JSON or not a ShellChat message, forward to gateway */ }
4040
+ } catch { /* Not JSON or not a ClawChats message, forward to gateway */ }
4041
4041
  _gatewayClient.sendToGateway(msgStr);
4042
4042
  });
4043
4043
 
@@ -4086,7 +4086,7 @@ if (isDirectRun) {
4086
4086
  });
4087
4087
 
4088
4088
  server.listen(PORT, () => {
4089
- console.log(`ShellChat backend listening on port ${PORT}`);
4089
+ console.log(`ClawChats backend listening on port ${PORT}`);
4090
4090
  console.log(`Active workspace: ${app.getWorkspaces().active}`);
4091
4091
  console.log(`Data dir: ${app.dataDir}`);
4092
4092