@lifeaitools/clauth 1.5.45 → 1.5.47

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 (2) hide show
  1. package/cli/commands/serve.js +114 -133
  2. package/package.json +1 -1
@@ -5149,154 +5149,108 @@ function stopTerminalSession(session_id) {
5149
5149
  return { stopped: true, session_id };
5150
5150
  }
5151
5151
 
5152
- // ── Chitchat helpers file-relay transport ───────────────────────────────
5153
- // claude.ai sends messages by writing to inbox files. A running /rdc:collab
5154
- // CLI session watches inbox, acts, writes responses to outbox. clauth reads
5155
- // outbox and returns them to claude.ai via chitchat_recv. Dave can watch the
5156
- // terminal, interject, and see exactly what Claude Code is doing.
5152
+ // ── ClaudeAItoCLIrealtime collab between claude.ai and a running Claude Code terminal ──
5157
5153
  //
5158
- // Session dirs: <root>/.rdc/relay/sessions/<session_id>/inbox/ + outbox/
5154
+ // Flow:
5155
+ // claude.ai calls chitchat_start(name)
5156
+ // → clauth creates session, spawns a visible Windows Terminal running:
5157
+ // claude /rdc:collab --session <id>
5158
+ // → clauth queues a greeting to outbox so claude.ai gets an immediate reply
5159
+ // claude.ai calls chitchat_send(id, msg) → pushes to in-memory inbox queue
5160
+ // Claude Code calls chitchat_poll(id) → shifts from inbox queue
5161
+ // Claude Code calls chitchat_reply(id, msg) → pushes to in-memory outbox queue
5162
+ // claude.ai calls chitchat_recv(id) → shifts from outbox queue
5159
5163
  //
5160
- // cwd is resolved from the vault's first fileserver mount at call time.
5161
- // Falls back to C:/Dev/regen-root if vault is locked or no mount configured.
5164
+ // Pure in-memory. No files. No CLI spawning on send/recv.
5162
5165
 
5163
- const CHITCHAT_FALLBACK_CWD = 'C:/Dev/regen-root';
5166
+ const CHITCHAT_CWD = 'C:/Dev/regen-root';
5164
5167
 
5165
- async function resolveChitchatRoot(vault) {
5166
- try {
5167
- const { mounts } = await getFileserverMounts(vault);
5168
- if (mounts && mounts.length > 0) return mounts[0].path;
5169
- } catch {}
5170
- return CHITCHAT_FALLBACK_CWD;
5171
- }
5172
-
5173
- function chitchatSessionDir(rootPath, session_id) {
5174
- return path.join(rootPath, '.rdc', 'relay', 'sessions', session_id);
5175
- }
5176
-
5177
- async function startChitchatSession(name, vault) {
5178
- const rootPath = await resolveChitchatRoot(vault);
5168
+ async function startChitchatSession(name) {
5179
5169
  const session_id = generateSessionId();
5180
- const sessionDir = chitchatSessionDir(rootPath, session_id);
5181
-
5182
- // Create inbox + outbox dirs
5183
- fs.mkdirSync(path.join(sessionDir, 'inbox'), { recursive: true });
5184
- fs.mkdirSync(path.join(sessionDir, 'outbox'), { recursive: true });
5185
-
5186
- // Write session metadata
5187
- fs.writeFileSync(path.join(sessionDir, 'status.json'), JSON.stringify({
5188
- session_id,
5189
- name,
5190
- status: 'waiting',
5191
- started_at: new Date().toISOString(),
5192
- cwd: rootPath,
5193
- }, null, 2));
5194
-
5195
5170
  const session = {
5196
5171
  session_id,
5197
5172
  name,
5198
- status: 'waiting', // waiting = CLI not yet connected
5173
+ status: 'ready',
5199
5174
  started_at: new Date().toISOString(),
5200
5175
  is_chitchat: true,
5201
- cwd: rootPath,
5202
- sessionDir,
5203
5176
  turn: 0,
5204
- lastResponse: undefined,
5205
- lastResponseAt: undefined,
5177
+ inbox: [], // claude.ai → Claude Code
5178
+ outbox: [], // Claude Code → claude.ai
5206
5179
  };
5207
5180
  terminalSessions.set(session_id, session);
5208
- console.log(`[chitchat] started session ${session_id} name=${name} dir=${sessionDir}`);
5209
5181
 
5210
- return {
5211
- session_id,
5212
- status: 'waiting',
5213
- name,
5214
- cwd: rootPath,
5215
- next_step: `Open a terminal and run: /rdc:collab --session ${session_id}`,
5216
- inbox: path.join(sessionDir, 'inbox'),
5217
- outbox: path.join(sessionDir, 'outbox'),
5218
- };
5182
+ // Spawn a visible Windows Terminal running /rdc:collab --session <id>
5183
+ const binary = findClaudeBinary();
5184
+ if (binary) {
5185
+ try {
5186
+ const cmd = `start cmd /k "cd /d ${CHITCHAT_CWD} && ${binary} /rdc:collab --session ${session_id}"`;
5187
+ require('child_process').exec(cmd, { shell: true });
5188
+ console.log(`[ClaudeAItoCLI] spawned terminal for session ${session_id}`);
5189
+ } catch (err) {
5190
+ console.warn(`[ClaudeAItoCLI] could not spawn terminal: ${err.message}`);
5191
+ }
5192
+ } else {
5193
+ console.warn(`[ClaudeAItoCLI] claude CLI not found — terminal not spawned. Run /rdc:collab --session ${session_id} manually.`);
5194
+ }
5195
+
5196
+ // Queue greeting so claude.ai gets an immediate response on first chitchat_recv
5197
+ session.outbox.push({
5198
+ turn: 0,
5199
+ message: `Hey! Claude Code is live — session ${session_id} ready. What's up?`,
5200
+ sent_at: new Date().toISOString(),
5201
+ });
5202
+
5203
+ console.log(`[ClaudeAItoCLI] started session ${session_id} name=${name}`);
5204
+ return { session_id, status: 'ready', name };
5219
5205
  }
5220
5206
 
5207
+ // claude.ai → inbox (Claude Code reads via chitchat_poll)
5221
5208
  function sendChitchatMessage(session_id, message) {
5222
5209
  const session = terminalSessions.get(session_id);
5223
- if (!session) return { error: 'not_found', message: `Chitchat session ${session_id} not found` };
5224
- if (!session.is_chitchat) return { error: 'wrong_type', message: 'Use terminal_send for non-chitchat sessions' };
5210
+ if (!session) return { error: 'not_found', message: `Session ${session_id} not found` };
5211
+ if (!session.is_chitchat) return { error: 'wrong_type', message: 'Not a ClaudeAItoCLI session' };
5225
5212
  if (session.status === 'stopped') return { error: 'stopped', message: 'Session is stopped' };
5226
5213
 
5227
- const ts = new Date().toISOString().replace(/[:.]/g, '-');
5228
5214
  session.turn = (session.turn || 0) + 1;
5229
- const filename = `${ts}-turn${session.turn}.md`;
5230
- const inboxPath = path.join(session.sessionDir, 'inbox', filename);
5231
-
5232
- const content = [
5233
- '---',
5234
- `from: claude-ai`,
5235
- `to: claude-code`,
5236
- `session_id: ${session_id}`,
5237
- `turn: ${session.turn}`,
5238
- `sent_at: ${new Date().toISOString()}`,
5239
- `status: pending`,
5240
- '---',
5241
- '',
5242
- message,
5243
- ].join('\n');
5244
-
5245
- try {
5246
- fs.writeFileSync(inboxPath, content, 'utf-8');
5247
- } catch (err) {
5248
- return { error: 'write_failed', message: `Could not write to inbox: ${err.message}` };
5249
- }
5250
-
5251
- session.status = 'busy';
5252
- console.log(`[chitchat] session ${session_id} turn=${session.turn} message written to inbox`);
5253
- return { queued: true, session_id, turn: session.turn, inbox_file: filename };
5215
+ const turn = session.turn;
5216
+ session.inbox.push({ turn, message, sent_at: new Date().toISOString() });
5217
+ console.log(`[ClaudeAItoCLI] session ${session_id} turn=${turn} message queued`);
5218
+ return { queued: true, session_id, turn };
5254
5219
  }
5255
5220
 
5221
+ // claude.ai ← outbox (drains all pending replies in one call)
5256
5222
  function recvChitchatResponse(session_id) {
5257
5223
  const session = terminalSessions.get(session_id);
5258
- if (!session) return { error: 'not_found', message: `Chitchat session ${session_id} not found` };
5224
+ if (!session) return { error: 'not_found', message: `Session ${session_id} not found` };
5259
5225
 
5260
- const outboxDir = path.join(session.sessionDir, 'outbox');
5261
- let files;
5262
- try {
5263
- files = fs.readdirSync(outboxDir).filter(f => f.endsWith('.md')).sort();
5264
- } catch {
5265
- return { session_id, status: session.status, turn: session.turn || 0, response: null,
5266
- message: 'Outbox not readable — is /rdc:collab running?' };
5267
- }
5226
+ const messages = session.outbox.splice(0);
5227
+ if (!messages.length) return { session_id, status: 'busy', count: 0, messages: [] };
5268
5228
 
5269
- if (files.length === 0) {
5270
- return { session_id, status: 'busy', turn: session.turn || 0, response: null,
5271
- message: session.status === 'waiting'
5272
- ? 'Waiting for /rdc:collab to connect — open your terminal and run it'
5273
- : 'Claude Code is working — poll again in a few seconds' };
5274
- }
5229
+ console.log(`[ClaudeAItoCLI] session ${session_id} dequeued ${messages.length} response(s)`);
5230
+ return { session_id, status: 'ready', count: messages.length, messages };
5231
+ }
5275
5232
 
5276
- // Read the latest response file
5277
- const latest = files[files.length - 1];
5278
- const responsePath = path.join(outboxDir, latest);
5279
- let raw;
5280
- try {
5281
- raw = fs.readFileSync(responsePath, 'utf-8');
5282
- } catch (err) {
5283
- return { error: 'read_failed', message: `Could not read outbox: ${err.message}` };
5284
- }
5233
+ // Claude Code reads all pending messages from claude.ai in one call
5234
+ function pollChitchatMessage(session_id) {
5235
+ const session = terminalSessions.get(session_id);
5236
+ if (!session) return { error: 'not_found', message: `Session ${session_id} not found` };
5285
5237
 
5286
- // Strip frontmatter, return body
5287
- const body = raw.replace(/^---[\s\S]*?---\n?/, '').trim();
5288
- const respondedAt = new Date().toISOString();
5238
+ const messages = session.inbox.splice(0);
5239
+ if (!messages.length) return { session_id, status: 'idle', count: 0, messages: [] };
5289
5240
 
5290
- // Archive the file so next recv doesn't return it again
5291
- const archivePath = responsePath + '.processed';
5292
- try { fs.renameSync(responsePath, archivePath); } catch {}
5241
+ console.log(`[ClaudeAItoCLI] session ${session_id} dequeued ${messages.length} message(s)`);
5242
+ return { session_id, status: 'ready', count: messages.length, messages };
5243
+ }
5293
5244
 
5294
- session.status = 'ready';
5295
- session.lastResponse = body;
5296
- session.lastResponseAt = respondedAt;
5297
- console.log(`[chitchat] session ${session_id} response received from outbox file=${latest}`);
5245
+ // Claude Code sends response back to claude.ai
5246
+ function replyChitchatMessage(session_id, message) {
5247
+ const session = terminalSessions.get(session_id);
5248
+ if (!session) return { error: 'not_found', message: `Session ${session_id} not found` };
5249
+ if (!session.is_chitchat) return { error: 'wrong_type', message: 'Not a ClaudeAItoCLI session' };
5298
5250
 
5299
- return { session_id, status: 'ready', turn: session.turn || 0, response: body, responded_at: respondedAt };
5251
+ session.outbox.push({ turn: session.turn, message, sent_at: new Date().toISOString() });
5252
+ console.log(`[ClaudeAItoCLI] session ${session_id} reply queued turn=${session.turn}`);
5253
+ return { queued: true, session_id, turn: session.turn };
5300
5254
  }
5301
5255
 
5302
5256
  function listChitchatSessions() {
@@ -5320,25 +5274,11 @@ function stopChitchatSession(session_id) {
5320
5274
  const session = terminalSessions.get(session_id);
5321
5275
  if (!session) return { error: 'not_found', message: `Session ${session_id} not found` };
5322
5276
 
5323
- // Write a stop signal to inbox so the running /rdc:collab loop knows to exit
5324
- try {
5325
- const ts = new Date().toISOString().replace(/[:.]/g, '-');
5326
- const stopFile = path.join(session.sessionDir, 'inbox', `${ts}-stop.md`);
5327
- fs.writeFileSync(stopFile, [
5328
- '---',
5329
- 'from: claude-ai',
5330
- 'to: claude-code',
5331
- `session_id: ${session_id}`,
5332
- 'type: stop',
5333
- `sent_at: ${new Date().toISOString()}`,
5334
- '---',
5335
- '',
5336
- 'Session ended by claude.ai. Write final summary and exit.',
5337
- ].join('\n'));
5338
- } catch {}
5277
+ // Push a stop signal into the inbox so the running /rdc:collab loop knows to exit on its next poll
5278
+ session.inbox.push({ turn: session.turn, type: 'stop', message: 'Session ended by claude.ai.', sent_at: new Date().toISOString() });
5339
5279
 
5340
5280
  terminalSessions.delete(session_id);
5341
- console.log(`[chitchat] stopped session ${session_id}`);
5281
+ console.log(`[ClaudeAItoCLI] stopped session ${session_id}`);
5342
5282
  return { stopped: true, session_id };
5343
5283
  }
5344
5284
 
@@ -5635,6 +5575,31 @@ const MCP_TOOLS = [
5635
5575
  additionalProperties: false,
5636
5576
  },
5637
5577
  },
5578
+ {
5579
+ name: "chitchat_poll",
5580
+ description: "Claude Code calls this to read the next pending message from claude.ai. Returns { status: 'idle' } if nothing queued, { status: 'ready', message: '...' } when a message is waiting.",
5581
+ inputSchema: {
5582
+ type: "object",
5583
+ properties: {
5584
+ session_id: { type: "string", description: "Session ID from chitchat_start" },
5585
+ },
5586
+ required: ["session_id"],
5587
+ additionalProperties: false,
5588
+ },
5589
+ },
5590
+ {
5591
+ name: "chitchat_reply",
5592
+ description: "Claude Code calls this to send its response back to claude.ai. claude.ai retrieves it via chitchat_recv.",
5593
+ inputSchema: {
5594
+ type: "object",
5595
+ properties: {
5596
+ session_id: { type: "string", description: "Session ID from chitchat_start" },
5597
+ message: { type: "string", description: "Response text from Claude Code" },
5598
+ },
5599
+ required: ["session_id", "message"],
5600
+ additionalProperties: false,
5601
+ },
5602
+ },
5638
5603
 
5639
5604
  // ── Google Workspace (gws CLI) ──────────────────────────────────────────
5640
5605
  {
@@ -6426,6 +6391,22 @@ async function handleMcpTool(vault, name, args) {
6426
6391
  return mcpResult(JSON.stringify(result));
6427
6392
  }
6428
6393
 
6394
+ case "chitchat_poll": {
6395
+ const { session_id } = args;
6396
+ if (!session_id) return mcpError("session_id required");
6397
+ const result = pollChitchatMessage(session_id);
6398
+ if (result.error) return mcpError(`${result.error}: ${result.message}`);
6399
+ return mcpResult(JSON.stringify(result));
6400
+ }
6401
+
6402
+ case "chitchat_reply": {
6403
+ const { session_id, message } = args;
6404
+ if (!session_id || !message) return mcpError("session_id and message required");
6405
+ const result = replyChitchatMessage(session_id, message);
6406
+ if (result.error) return mcpError(`${result.error}: ${result.message}`);
6407
+ return mcpResult(JSON.stringify(result));
6408
+ }
6409
+
6429
6410
  default:
6430
6411
  return mcpError(`Unknown tool: ${name}`);
6431
6412
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifeaitools/clauth",
3
- "version": "1.5.45",
3
+ "version": "1.5.47",
4
4
  "description": "Hardware-bound credential vault for the LIFEAI infrastructure stack",
5
5
  "type": "module",
6
6
  "bin": {