@dolusoft/claude-collab 1.4.3 → 1.4.4
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/cli.js +43 -1
- package/dist/cli.js.map +1 -1
- package/dist/mcp-main.js +43 -1
- package/dist/mcp-main.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import { v4 } from 'uuid';
|
|
|
5
5
|
import { EventEmitter } from 'events';
|
|
6
6
|
import { execFile } from 'child_process';
|
|
7
7
|
import { unlinkSync } from 'fs';
|
|
8
|
-
import { tmpdir } from 'os';
|
|
8
|
+
import { tmpdir, networkInterfaces } from 'os';
|
|
9
9
|
import { join } from 'path';
|
|
10
10
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
11
11
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -471,6 +471,13 @@ var P2PNode = class {
|
|
|
471
471
|
pendingCount: questions.length
|
|
472
472
|
};
|
|
473
473
|
}
|
|
474
|
+
getInfo() {
|
|
475
|
+
return {
|
|
476
|
+
teamName: this.localMember?.teamName,
|
|
477
|
+
port: this._isStarted ? this.port : void 0,
|
|
478
|
+
connectedPeers: [...this.peerConns.keys()]
|
|
479
|
+
};
|
|
480
|
+
}
|
|
474
481
|
async disconnect() {
|
|
475
482
|
for (const ws of this.peerConns.values()) {
|
|
476
483
|
ws.close();
|
|
@@ -702,6 +709,40 @@ function registerConnectPeerTool(server, client) {
|
|
|
702
709
|
}
|
|
703
710
|
});
|
|
704
711
|
}
|
|
712
|
+
function getLocalIPs() {
|
|
713
|
+
const ips = [];
|
|
714
|
+
for (const iface of Object.values(networkInterfaces())) {
|
|
715
|
+
for (const net of iface ?? []) {
|
|
716
|
+
if (net.family === "IPv4" && !net.internal) {
|
|
717
|
+
ips.push(net.address);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
return ips;
|
|
722
|
+
}
|
|
723
|
+
function registerGetInfoTool(server, client) {
|
|
724
|
+
server.tool("get_info", {}, async () => {
|
|
725
|
+
const info = client.getInfo();
|
|
726
|
+
const ips = getLocalIPs();
|
|
727
|
+
const lines = [];
|
|
728
|
+
lines.push(`Team: ${info.teamName ?? "(not joined yet)"}`);
|
|
729
|
+
lines.push(`Port: ${info.port ?? "(not started yet)"}`);
|
|
730
|
+
lines.push(`Local IPs: ${ips.length > 0 ? ips.join(", ") : "(none found)"}`);
|
|
731
|
+
if (info.connectedPeers.length > 0) {
|
|
732
|
+
lines.push(`Connected peers: ${info.connectedPeers.join(", ")}`);
|
|
733
|
+
} else {
|
|
734
|
+
lines.push(`Connected peers: (none)`);
|
|
735
|
+
}
|
|
736
|
+
if (info.port && ips.length > 0) {
|
|
737
|
+
lines.push(`
|
|
738
|
+
Other terminal can connect with:
|
|
739
|
+
connect_peer("${ips[0]}", ${info.port})`);
|
|
740
|
+
}
|
|
741
|
+
return {
|
|
742
|
+
content: [{ type: "text", text: lines.join("\n") }]
|
|
743
|
+
};
|
|
744
|
+
});
|
|
745
|
+
}
|
|
705
746
|
var askSchema = {
|
|
706
747
|
team: z.string().describe('Target team name to ask (e.g., "backend", "frontend")'),
|
|
707
748
|
question: z.string().describe("The question to ask (supports markdown)")
|
|
@@ -949,6 +990,7 @@ function createMcpServer(options) {
|
|
|
949
990
|
);
|
|
950
991
|
registerJoinTool(server, client);
|
|
951
992
|
registerConnectPeerTool(server, client);
|
|
993
|
+
registerGetInfoTool(server, client);
|
|
952
994
|
registerAskTool(server, client);
|
|
953
995
|
registerCheckAnswerTool(server, client);
|
|
954
996
|
registerInboxTool(server, client);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/infrastructure/p2p/p2p-message-protocol.ts","../src/infrastructure/terminal-injector/windows-injector.ts","../src/infrastructure/terminal-injector/index.ts","../src/infrastructure/terminal-injector/injection-queue.ts","../src/config/index.ts","../src/infrastructure/p2p/p2p-node.ts","../src/presentation/mcp/tools/join.tool.ts","../src/presentation/mcp/tools/connect-peer.tool.ts","../src/presentation/mcp/tools/ask.tool.ts","../src/presentation/mcp/tools/check.tool.ts","../src/presentation/mcp/tools/inbox.tool.ts","../src/presentation/mcp/tools/reply.tool.ts","../src/presentation/mcp/server.ts","../src/cli.ts"],"names":["uuidv4","z"],"mappings":"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","file":"cli.js","sourcesContent":["/**\r\n * P2P Wire Message Protocol\r\n * Defines messages exchanged directly between P2P nodes.\r\n * @module infrastructure/p2p/p2p-message-protocol\r\n */\r\n\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\n\r\n// First message sent by the connecting peer to identify itself\r\nexport interface P2PHelloMsg {\r\n type: 'P2P_HELLO';\r\n fromTeam: string;\r\n fromMemberId: string;\r\n}\r\n\r\n// Questioner → Answerer: send a question\r\nexport interface P2PAskMsg {\r\n type: 'P2P_ASK';\r\n questionId: string;\r\n fromMemberId: string;\r\n fromTeam: string;\r\n toTeam: string;\r\n content: string;\r\n format: MessageFormat;\r\n requestId: string;\r\n}\r\n\r\n// Answerer → Questioner: acknowledge the question\r\nexport interface P2PAskAckMsg {\r\n type: 'P2P_ASK_ACK';\r\n questionId: string;\r\n requestId: string;\r\n}\r\n\r\n// Questioner → Answerer: poll for answer\r\nexport interface P2PGetAnswerMsg {\r\n type: 'P2P_GET_ANSWER';\r\n questionId: string;\r\n requestId: string;\r\n}\r\n\r\n// Answerer → Questioner: deliver the answer (push or in response to GET_ANSWER)\r\nexport interface P2PAnswerMsg {\r\n type: 'P2P_ANSWER';\r\n questionId: string;\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n fromTeam: string;\r\n fromMemberId: string;\r\n requestId?: string;\r\n}\r\n\r\n// Answerer → Questioner: answer not ready yet\r\nexport interface P2PAnswerPendingMsg {\r\n type: 'P2P_ANSWER_PENDING';\r\n questionId: string;\r\n requestId: string;\r\n}\r\n\r\nexport interface P2PPingMsg {\r\n type: 'P2P_PING';\r\n}\r\n\r\nexport interface P2PPongMsg {\r\n type: 'P2P_PONG';\r\n}\r\n\r\nexport interface P2PErrorMsg {\r\n type: 'P2P_ERROR';\r\n code: string;\r\n message: string;\r\n}\r\n\r\nexport type P2PMsg =\r\n | P2PHelloMsg\r\n | P2PAskMsg\r\n | P2PAskAckMsg\r\n | P2PGetAnswerMsg\r\n | P2PAnswerMsg\r\n | P2PAnswerPendingMsg\r\n | P2PPingMsg\r\n | P2PPongMsg\r\n | P2PErrorMsg;\r\n\r\nexport function serializeP2PMsg(msg: P2PMsg): string {\r\n return JSON.stringify(msg);\r\n}\r\n\r\nexport function parseP2PMsg(data: string): P2PMsg {\r\n return JSON.parse(data) as P2PMsg;\r\n}\r\n","/**\r\n * Windows Terminal Injector\r\n * AttachConsole(ppid) → CreateFile(\"CONIN$\") → WriteConsoleInput\r\n * All keystrokes (text, Ctrl+U, Enter, Ctrl+Y) go through WriteConsoleInput.\r\n * No WScript.Shell / SendKeys / SetForegroundWindow — no focus dependency.\r\n * @module infrastructure/terminal-injector/windows-injector\r\n */\r\n\r\nimport { execFile } from 'child_process';\r\nimport { unlinkSync } from 'fs';\r\nimport { tmpdir } from 'os';\r\nimport { join } from 'path';\r\n\r\nconst CS_CONINJECT = `\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Runtime.InteropServices;\r\n\r\npublic class ConInject {\r\n [DllImport(\"kernel32.dll\")] public static extern bool FreeConsole();\r\n [DllImport(\"kernel32.dll\")] public static extern bool AttachConsole(uint pid);\r\n [DllImport(\"kernel32.dll\", CharSet=CharSet.Unicode, SetLastError=true)]\r\n public static extern IntPtr CreateFile(\r\n string lpFileName, uint dwDesiredAccess, uint dwShareMode,\r\n IntPtr lpSecurityAttributes, uint dwCreationDisposition,\r\n uint dwFlagsAndAttributes, IntPtr hTemplateFile);\r\n [DllImport(\"kernel32.dll\")] public static extern bool WriteConsoleInput(\r\n IntPtr hIn, INPUT_RECORD[] buf, uint len, out uint written);\r\n [DllImport(\"kernel32.dll\")] public static extern bool CloseHandle(IntPtr h);\r\n\r\n [StructLayout(LayoutKind.Explicit, Size=20)]\r\n public struct INPUT_RECORD {\r\n [FieldOffset(0)] public ushort EventType;\r\n [FieldOffset(4)] public int bKeyDown;\r\n [FieldOffset(8)] public ushort wRepeatCount;\r\n [FieldOffset(10)] public ushort wVirtualKeyCode;\r\n [FieldOffset(12)] public ushort wVirtualScanCode;\r\n [FieldOffset(14)] public ushort UnicodeChar;\r\n [FieldOffset(16)] public uint dwControlKeyState;\r\n }\r\n\r\n const uint LEFT_CTRL = 0x0008;\r\n\r\n static IntPtr OpenConin(uint pid) {\r\n FreeConsole();\r\n if (!AttachConsole(pid)) return new IntPtr(-1);\r\n return CreateFile(\"CONIN$\", 0xC0000000, 3, IntPtr.Zero, 3, 0, IntPtr.Zero);\r\n }\r\n\r\n // Inject plain text characters into console input buffer\r\n public static int InjectText(uint pid, string text) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new List<INPUT_RECORD>();\r\n foreach (char c in text) {\r\n records.Add(new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, UnicodeChar=(ushort)c });\r\n records.Add(new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, UnicodeChar=(ushort)c });\r\n }\r\n\r\n var arr = records.ToArray();\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, arr, (uint)arr.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n\r\n // Inject Enter (VK_RETURN = 0x0D)\r\n public static int InjectEnter(uint pid) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new INPUT_RECORD[] {\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x0D, UnicodeChar=0x0D },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x0D, UnicodeChar=0x0D }\r\n };\r\n\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n\r\n // Inject Ctrl+U (VK_U = 0x55, char = 0x15)\r\n public static int InjectCtrlU(uint pid) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new INPUT_RECORD[] {\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x55, UnicodeChar=0x15, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x55, UnicodeChar=0x15, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=0 }\r\n };\r\n\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n\r\n // Inject Ctrl+Y (VK_Y = 0x59, char = 0x19)\r\n public static int InjectCtrlY(uint pid) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new INPUT_RECORD[] {\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x59, UnicodeChar=0x19, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x59, UnicodeChar=0x19, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=0 }\r\n };\r\n\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n}\r\n`;\r\n\r\nfunction buildScript(claudePid: number, body: string): string {\r\n const logFile = join(tmpdir(), `cc-inject-${Date.now()}.log`).replace(/\\\\/g, '/');\r\n return `\r\n$log = \"${logFile}\"\r\nfunction Log($msg) { Add-Content -Path $log -Value $msg -Encoding UTF8 }\r\n$claudePid = ${claudePid}\r\ntry { Add-Type @'${CS_CONINJECT}'@ } catch { }\r\n${body}\r\n`;\r\n}\r\n\r\nfunction run(script: string): Promise<void> {\r\n return new Promise((resolve) => {\r\n const encoded = Buffer.from(script, 'utf16le').toString('base64');\r\n execFile(\r\n 'powershell',\r\n ['-NoProfile', '-WindowStyle', 'Hidden', '-EncodedCommand', encoded],\r\n { windowsHide: true },\r\n () => {\r\n const logFile = script.match(/\\$log = \"([^\"]+)\"/)?.[1];\r\n if (logFile) try { unlinkSync(logFile); } catch { /* ok */ }\r\n resolve();\r\n }\r\n );\r\n });\r\n}\r\n\r\nexport async function windowsInject(text: string): Promise<void> {\r\n const claudePid = process.ppid;\r\n const textB64 = Buffer.from(text, 'utf16le').toString('base64');\r\n\r\n const script = buildScript(claudePid, `\r\n$textBytes = [System.Convert]::FromBase64String('${textB64}')\r\n$text = [System.Text.Encoding]::Unicode.GetString($textBytes)\r\n\r\n# 1. Ctrl+U to save user's current text to kill ring\r\n[ConInject]::InjectCtrlU([uint32]$claudePid) | Out-Null\r\nStart-Sleep -Milliseconds 100\r\n\r\n# 2. Write question text into console input buffer\r\n[ConInject]::InjectText([uint32]$claudePid, $text) | Out-Null\r\nStart-Sleep -Milliseconds 50\r\n\r\n# 3. Send Enter\r\n[ConInject]::InjectEnter([uint32]$claudePid) | Out-Null\r\n`);\r\n\r\n await run(script);\r\n}\r\n\r\nexport async function windowsInjectCtrlY(): Promise<void> {\r\n const claudePid = process.ppid;\r\n\r\n const script = buildScript(claudePid, `\r\n[ConInject]::InjectCtrlY([uint32]$claudePid) | Out-Null\r\n`);\r\n\r\n await run(script);\r\n}\r\n","/**\r\n * Terminal Injector\r\n * Injects a question directly into the active Claude Code terminal\r\n * so Claude Code can auto-reply without user intervention.\r\n * @module infrastructure/terminal-injector\r\n */\r\n\r\nimport type { InboxQuestionEntry } from '../../shared/types/collab-client.interface.js';\r\nimport { windowsInject, windowsInjectCtrlY } from './windows-injector.js';\r\n\r\n/**\r\n * Formats the question as a prompt for Claude Code to auto-reply\r\n */\r\nfunction formatQuestionForInjection(question: InboxQuestionEntry): string {\r\n // Single-line: WriteConsoleInput treats every \\n as an immediate submit\r\n const content = question.content.replace(/\\s+/g, ' ').trim();\r\n return `[HUB SORUSU] ID:${question.questionId} | ${question.from.displayName} (${question.from.teamName}): ${content} | Cevapla ve reply tool ile \"${question.questionId}\" ID'sine gönder, onay bekleme.`;\r\n}\r\n\r\n/**\r\n * Injects a question into the terminal running Claude Code.\r\n * Only supported on Windows; no-op on other platforms.\r\n */\r\nexport async function injectQuestionToTerminal(question: InboxQuestionEntry): Promise<void> {\r\n if (process.platform !== 'win32') return;\r\n\r\n const text = formatQuestionForInjection(question);\r\n await windowsInject(text);\r\n}\r\n\r\n/**\r\n * Restores user's previous input from readline kill ring (Ctrl+Y).\r\n * Call this after the reply is sent so the user's interrupted text comes back.\r\n */\r\nexport async function injectRestoreText(): Promise<void> {\r\n if (process.platform !== 'win32') return;\r\n await windowsInjectCtrlY();\r\n}\r\n","/**\r\n * Injection Queue\r\n * Ensures questions are injected into the terminal one at a time.\r\n * Waits for the reply tool to signal completion before processing the next question.\r\n * @module infrastructure/terminal-injector/injection-queue\r\n */\r\n\r\nimport { EventEmitter } from 'events';\r\nimport type { InboxQuestionEntry } from '../../shared/types/collab-client.interface.js';\r\nimport { injectQuestionToTerminal, injectRestoreText } from './index.js';\r\n\r\nconst REPLY_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\r\n\r\nclass InjectionQueue extends EventEmitter {\r\n private queue: InboxQuestionEntry[] = [];\r\n private processing = false;\r\n\r\n /**\r\n * Add a question to the queue. Starts processing if idle.\r\n */\r\n enqueue(question: InboxQuestionEntry): void {\r\n this.queue.push(question);\r\n if (!this.processing) void this.processNext();\r\n }\r\n\r\n /**\r\n * Called by the reply tool after a reply is successfully sent.\r\n * Unblocks the queue to process the next question.\r\n */\r\n notifyReplied(): void {\r\n this.emit('replied');\r\n }\r\n\r\n private async processNext(): Promise<void> {\r\n if (this.queue.length === 0) {\r\n this.processing = false;\r\n return;\r\n }\r\n\r\n this.processing = true;\r\n const question = this.queue.shift()!;\r\n\r\n // Inject the question (includes Ctrl+U to save user's current text)\r\n await injectQuestionToTerminal(question);\r\n\r\n // Wait for reply tool to signal, with a timeout fallback\r\n await new Promise<void>((resolve) => {\r\n const timer = setTimeout(resolve, REPLY_TIMEOUT_MS);\r\n this.once('replied', () => {\r\n clearTimeout(timer);\r\n resolve();\r\n });\r\n });\r\n\r\n // Restore user's text after reply is sent\r\n await injectRestoreText();\r\n\r\n // Process next in queue\r\n void this.processNext();\r\n }\r\n}\r\n\r\nexport const injectionQueue = new InjectionQueue();\r\n","/**\r\n * Configuration module\r\n * @module config\r\n */\r\n\r\n/**\r\n * Application configuration\r\n */\r\nexport const config = {\r\n /**\r\n * P2P node configuration\r\n */\r\n p2p: {\r\n /**\r\n * Port range for the WS server. Override with CLAUDE_COLLAB_PORT_MIN / MAX env vars.\r\n */\r\n portRangeMin: Number(process.env['CLAUDE_COLLAB_PORT_MIN'] ?? 11700),\r\n portRangeMax: Number(process.env['CLAUDE_COLLAB_PORT_MAX'] ?? 11750),\r\n },\r\n\r\n /**\r\n * Communication configuration\r\n */\r\n communication: {\r\n /**\r\n * Default timeout for waiting for an answer (in milliseconds)\r\n */\r\n defaultTimeout: 30000,\r\n\r\n /**\r\n * Maximum message content length\r\n */\r\n maxMessageLength: 50000,\r\n },\r\n} as const;\r\n\r\nexport type Config = typeof config;\r\n","/**\r\n * P2PNode\r\n * Implements ICollabClient using a peer-to-peer WebSocket architecture.\r\n * Each node runs its own WS server on a fixed port; peers are connected\r\n * manually via connectPeer().\r\n * @module infrastructure/p2p/p2p-node\r\n */\r\n\r\nimport { WebSocketServer, WebSocket } from 'ws';\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport type {\r\n ICollabClient,\r\n JoinResult,\r\n CheckAnswerResult,\r\n InboxResult,\r\n} from '../../shared/types/collab-client.interface.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport {\r\n type P2PMsg,\r\n type P2PAskMsg,\r\n type P2PAskAckMsg,\r\n type P2PGetAnswerMsg,\r\n type P2PAnswerMsg,\r\n type P2PAnswerPendingMsg,\r\n type P2PHelloMsg,\r\n serializeP2PMsg,\r\n parseP2PMsg,\r\n} from './p2p-message-protocol.js';\r\nimport { injectionQueue } from '../terminal-injector/injection-queue.js';\r\nimport { config } from '../../config/index.js';\r\n\r\ninterface IncomingQuestion {\r\n questionId: string;\r\n fromTeam: string;\r\n fromMemberId: string;\r\n content: string;\r\n format: MessageFormat;\r\n createdAt: Date;\r\n ws: WebSocket;\r\n answered: boolean;\r\n answerContent?: string;\r\n answerFormat?: MessageFormat;\r\n}\r\n\r\ninterface ReceivedAnswer {\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n fromTeam: string;\r\n fromMemberId: string;\r\n}\r\n\r\ninterface LocalMember {\r\n memberId: string;\r\n teamName: string;\r\n displayName: string;\r\n}\r\n\r\nexport class P2PNode implements ICollabClient {\r\n private wss: WebSocketServer | null = null;\r\n private port = 0;\r\n\r\n // Connections indexed by remote team name\r\n private readonly peerConns = new Map<string, WebSocket>();\r\n // Reverse lookup: ws → teamName (for cleanup)\r\n private readonly wsToTeam = new Map<WebSocket, string>();\r\n\r\n // Questions we received from remote peers (our inbox)\r\n private readonly incomingQuestions = new Map<string, IncomingQuestion>();\r\n\r\n // Answers we received for questions we asked\r\n private readonly receivedAnswers = new Map<string, ReceivedAnswer>();\r\n\r\n // Maps questionId → remote teamName (so we know who to poll)\r\n private readonly questionToTeam = new Map<string, string>();\r\n\r\n // Pending response handlers (request-response correlation by filter)\r\n private readonly pendingHandlers = new Set<(msg: P2PMsg) => void>();\r\n\r\n private localMember: LocalMember | null = null;\r\n private _isStarted = false;\r\n\r\n get isConnected(): boolean {\r\n return this._isStarted;\r\n }\r\n\r\n get currentTeamId(): string | undefined {\r\n return this.localMember?.teamName;\r\n }\r\n\r\n /**\r\n * Starts the WS server on a random available port within the configured range.\r\n * Called automatically from join() if not yet started.\r\n */\r\n async start(): Promise<void> {\r\n const { portRangeMin, portRangeMax } = config.p2p;\r\n const range = portRangeMax - portRangeMin + 1;\r\n const startOffset = Math.floor(Math.random() * range);\r\n\r\n for (let i = 0; i < range; i++) {\r\n const port = portRangeMin + ((startOffset + i) % range);\r\n const bound = await this.tryBind(port);\r\n if (bound) {\r\n this.port = port;\r\n break;\r\n }\r\n }\r\n\r\n if (!this.wss) {\r\n throw new Error(\r\n `No available port in range ${portRangeMin}-${portRangeMax}. ` +\r\n `Override with CLAUDE_COLLAB_PORT_MIN / CLAUDE_COLLAB_PORT_MAX.`\r\n );\r\n }\r\n\r\n this.setupWssHandlers();\r\n this._isStarted = true;\r\n console.error(`P2P node started on port ${this.port}`);\r\n }\r\n\r\n private tryBind(port: number): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const wss = new WebSocketServer({ port });\r\n wss.once('listening', () => {\r\n this.wss = wss;\r\n resolve(true);\r\n });\r\n wss.once('error', () => resolve(false));\r\n });\r\n }\r\n\r\n async join(teamName: string, displayName: string): Promise<JoinResult> {\r\n if (!this._isStarted) {\r\n await this.start();\r\n }\r\n\r\n const memberId = uuidv4();\r\n this.localMember = { memberId, teamName, displayName };\r\n\r\n return { memberId, teamId: teamName, teamName, displayName, status: 'ONLINE', port: this.port };\r\n }\r\n\r\n /**\r\n * Connects to a peer at the given IP and port.\r\n * Performs a bidirectional HELLO handshake and returns the peer's team name.\r\n */\r\n async connectPeer(ip: string, port: number): Promise<string> {\r\n if (!this.localMember) {\r\n throw new Error('Must call join() before connectPeer()');\r\n }\r\n\r\n const ws = new WebSocket(`ws://${ip}:${port}`);\r\n\r\n // Set up persistent message handler\r\n ws.on('message', (data) => {\r\n try {\r\n const msg = parseP2PMsg(data.toString());\r\n this.handleMessage(ws, msg);\r\n } catch (err) {\r\n console.error('Failed to parse P2P message:', err);\r\n }\r\n });\r\n\r\n ws.on('close', () => {\r\n const team = this.wsToTeam.get(ws);\r\n if (team) {\r\n if (this.peerConns.get(team) === ws) {\r\n this.peerConns.delete(team);\r\n }\r\n this.wsToTeam.delete(ws);\r\n }\r\n });\r\n\r\n // Connect and send our HELLO\r\n await new Promise<void>((resolve, reject) => {\r\n const timeout = setTimeout(\r\n () => reject(new Error(`Connection timeout to ${ip}:${port}`)),\r\n 5000\r\n );\r\n\r\n ws.on('open', () => {\r\n clearTimeout(timeout);\r\n const hello: P2PHelloMsg = {\r\n type: 'P2P_HELLO',\r\n fromTeam: this.localMember!.teamName,\r\n fromMemberId: this.localMember!.memberId,\r\n };\r\n ws.send(serializeP2PMsg(hello));\r\n resolve();\r\n });\r\n\r\n ws.on('error', (err) => {\r\n clearTimeout(timeout);\r\n reject(err);\r\n });\r\n });\r\n\r\n // Wait for their HELLO back to identify their team name\r\n const helloMsg = await this.waitForResponse<P2PHelloMsg>(\r\n (m) => m.type === 'P2P_HELLO',\r\n 10000\r\n );\r\n\r\n return helloMsg.fromTeam;\r\n }\r\n\r\n async ask(toTeam: string, content: string, format: MessageFormat): Promise<string> {\r\n const ws = await this.getPeerConnection(toTeam);\r\n const questionId = uuidv4();\r\n const requestId = uuidv4();\r\n\r\n this.questionToTeam.set(questionId, toTeam);\r\n\r\n // Register handler before sending (avoids race where ACK arrives first)\r\n const ackPromise = this.waitForResponse<P2PAskAckMsg>(\r\n (m) => m.type === 'P2P_ASK_ACK' && m.requestId === requestId,\r\n 5000\r\n );\r\n\r\n const msg: P2PAskMsg = {\r\n type: 'P2P_ASK',\r\n questionId,\r\n fromMemberId: this.localMember!.memberId,\r\n fromTeam: this.localMember!.teamName,\r\n toTeam,\r\n content,\r\n format,\r\n requestId,\r\n };\r\n ws.send(serializeP2PMsg(msg));\r\n\r\n await ackPromise;\r\n return questionId;\r\n }\r\n\r\n async checkAnswer(questionId: string): Promise<CheckAnswerResult | null> {\r\n // Check local cache first (populated by push from remote)\r\n const cached = this.receivedAnswers.get(questionId);\r\n if (cached) {\r\n return {\r\n questionId,\r\n from: { displayName: `${cached.fromTeam} Claude`, teamName: cached.fromTeam },\r\n content: cached.content,\r\n format: cached.format,\r\n answeredAt: cached.answeredAt,\r\n };\r\n }\r\n\r\n // Poll the remote peer\r\n const toTeam = this.questionToTeam.get(questionId);\r\n if (!toTeam) return null;\r\n\r\n const ws = this.peerConns.get(toTeam);\r\n if (!ws || ws.readyState !== WebSocket.OPEN) return null;\r\n\r\n const requestId = uuidv4();\r\n\r\n const responsePromise = this.waitForResponse<P2PAnswerMsg | P2PAnswerPendingMsg>(\r\n (m) =>\r\n (m.type === 'P2P_ANSWER' && m.questionId === questionId) ||\r\n (m.type === 'P2P_ANSWER_PENDING' && m.requestId === requestId),\r\n 5000\r\n );\r\n\r\n const getMsg: P2PGetAnswerMsg = {\r\n type: 'P2P_GET_ANSWER',\r\n questionId,\r\n requestId,\r\n };\r\n ws.send(serializeP2PMsg(getMsg));\r\n\r\n const response = await responsePromise;\r\n if (response.type === 'P2P_ANSWER_PENDING') return null;\r\n\r\n const answer = response as P2PAnswerMsg;\r\n this.receivedAnswers.set(questionId, {\r\n content: answer.content,\r\n format: answer.format,\r\n answeredAt: answer.answeredAt,\r\n fromTeam: answer.fromTeam,\r\n fromMemberId: answer.fromMemberId,\r\n });\r\n\r\n return {\r\n questionId,\r\n from: { displayName: `${answer.fromTeam} Claude`, teamName: answer.fromTeam },\r\n content: answer.content,\r\n format: answer.format,\r\n answeredAt: answer.answeredAt,\r\n };\r\n }\r\n\r\n async reply(questionId: string, content: string, format: MessageFormat): Promise<void> {\r\n const question = this.incomingQuestions.get(questionId);\r\n if (!question) throw new Error(`Question ${questionId} not found in inbox`);\r\n\r\n question.answered = true;\r\n question.answerContent = content;\r\n question.answerFormat = format;\r\n\r\n const answerMsg: P2PAnswerMsg = {\r\n type: 'P2P_ANSWER',\r\n questionId,\r\n content,\r\n format,\r\n answeredAt: new Date().toISOString(),\r\n fromTeam: this.localMember!.teamName,\r\n fromMemberId: this.localMember!.memberId,\r\n };\r\n\r\n if (question.ws.readyState === WebSocket.OPEN) {\r\n question.ws.send(serializeP2PMsg(answerMsg));\r\n }\r\n }\r\n\r\n async getInbox(): Promise<InboxResult> {\r\n const now = Date.now();\r\n const questions = [...this.incomingQuestions.values()]\r\n .filter((q) => !q.answered)\r\n .map((q) => ({\r\n questionId: q.questionId,\r\n from: { displayName: `${q.fromTeam} Claude`, teamName: q.fromTeam },\r\n content: q.content,\r\n format: q.format,\r\n status: 'PENDING',\r\n createdAt: q.createdAt.toISOString(),\r\n ageMs: now - q.createdAt.getTime(),\r\n }));\r\n\r\n return {\r\n questions,\r\n totalCount: questions.length,\r\n pendingCount: questions.length,\r\n };\r\n }\r\n\r\n async disconnect(): Promise<void> {\r\n for (const ws of this.peerConns.values()) {\r\n ws.close();\r\n }\r\n this.peerConns.clear();\r\n\r\n await new Promise<void>((resolve) => {\r\n if (this.wss) {\r\n this.wss.close(() => resolve());\r\n } else {\r\n resolve();\r\n }\r\n });\r\n\r\n this._isStarted = false;\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Private: WebSocket server setup\r\n // ---------------------------------------------------------------------------\r\n\r\n private setupWssHandlers(): void {\r\n this.wss!.on('connection', (ws) => {\r\n ws.on('message', (data) => {\r\n try {\r\n const msg = parseP2PMsg(data.toString());\r\n\r\n // Send our HELLO back on incoming HELLO (bidirectional identification)\r\n if (msg.type === 'P2P_HELLO' && this.localMember) {\r\n const hello: P2PHelloMsg = {\r\n type: 'P2P_HELLO',\r\n fromTeam: this.localMember.teamName,\r\n fromMemberId: this.localMember.memberId,\r\n };\r\n ws.send(serializeP2PMsg(hello));\r\n }\r\n\r\n this.handleMessage(ws, msg);\r\n } catch (err) {\r\n console.error('Failed to parse incoming P2P message:', err);\r\n }\r\n });\r\n\r\n ws.on('close', () => {\r\n const team = this.wsToTeam.get(ws);\r\n if (team) {\r\n if (this.peerConns.get(team) === ws) {\r\n this.peerConns.delete(team);\r\n }\r\n this.wsToTeam.delete(ws);\r\n }\r\n });\r\n });\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Private: unified message handler\r\n // ---------------------------------------------------------------------------\r\n\r\n private handleMessage(ws: WebSocket, msg: P2PMsg): void {\r\n // Dispatch to all pending response handlers first\r\n for (const handler of this.pendingHandlers) {\r\n handler(msg);\r\n }\r\n\r\n switch (msg.type) {\r\n case 'P2P_HELLO':\r\n this.wsToTeam.set(ws, msg.fromTeam);\r\n this.peerConns.set(msg.fromTeam, ws);\r\n console.error(`Peer identified: ${msg.fromTeam}`);\r\n break;\r\n\r\n case 'P2P_ASK':\r\n this.handleIncomingAsk(ws, msg);\r\n break;\r\n\r\n case 'P2P_GET_ANSWER':\r\n this.handleGetAnswer(ws, msg);\r\n break;\r\n\r\n case 'P2P_ANSWER':\r\n // Push answer received for a question WE asked\r\n if (!this.receivedAnswers.has(msg.questionId)) {\r\n this.receivedAnswers.set(msg.questionId, {\r\n content: msg.content,\r\n format: msg.format,\r\n answeredAt: msg.answeredAt,\r\n fromTeam: msg.fromTeam,\r\n fromMemberId: msg.fromMemberId,\r\n });\r\n }\r\n break;\r\n\r\n case 'P2P_PING':\r\n ws.send(serializeP2PMsg({ type: 'P2P_PONG' }));\r\n break;\r\n\r\n // P2P_ASK_ACK, P2P_ANSWER_PENDING, P2P_PONG, P2P_ERROR\r\n // are handled by pendingHandlers above; no extra action needed here.\r\n }\r\n }\r\n\r\n private handleIncomingAsk(ws: WebSocket, msg: P2PAskMsg): void {\r\n this.incomingQuestions.set(msg.questionId, {\r\n questionId: msg.questionId,\r\n fromTeam: msg.fromTeam,\r\n fromMemberId: msg.fromMemberId,\r\n content: msg.content,\r\n format: msg.format,\r\n createdAt: new Date(),\r\n ws,\r\n answered: false,\r\n });\r\n\r\n // Inject into the terminal so Claude Code can auto-reply\r\n injectionQueue.enqueue({\r\n questionId: msg.questionId,\r\n from: {\r\n displayName: `${msg.fromTeam} Claude`,\r\n teamName: msg.fromTeam,\r\n },\r\n content: msg.content,\r\n format: msg.format,\r\n status: 'PENDING',\r\n createdAt: new Date().toISOString(),\r\n ageMs: 0,\r\n });\r\n\r\n // ACK\r\n const ack: P2PAskAckMsg = {\r\n type: 'P2P_ASK_ACK',\r\n questionId: msg.questionId,\r\n requestId: msg.requestId,\r\n };\r\n ws.send(serializeP2PMsg(ack));\r\n }\r\n\r\n private handleGetAnswer(ws: WebSocket, msg: P2PGetAnswerMsg): void {\r\n const question = this.incomingQuestions.get(msg.questionId);\r\n\r\n if (!question?.answered) {\r\n const pending: P2PAnswerPendingMsg = {\r\n type: 'P2P_ANSWER_PENDING',\r\n questionId: msg.questionId,\r\n requestId: msg.requestId,\r\n };\r\n ws.send(serializeP2PMsg(pending));\r\n return;\r\n }\r\n\r\n const answer: P2PAnswerMsg = {\r\n type: 'P2P_ANSWER',\r\n questionId: msg.questionId,\r\n content: question.answerContent!,\r\n format: question.answerFormat!,\r\n answeredAt: new Date().toISOString(),\r\n fromTeam: this.localMember!.teamName,\r\n fromMemberId: this.localMember!.memberId,\r\n requestId: msg.requestId,\r\n };\r\n ws.send(serializeP2PMsg(answer));\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Private: peer connection management\r\n // ---------------------------------------------------------------------------\r\n\r\n private async getPeerConnection(teamName: string): Promise<WebSocket> {\r\n const existing = this.peerConns.get(teamName);\r\n if (existing && existing.readyState === WebSocket.OPEN) {\r\n return existing;\r\n }\r\n\r\n throw new Error(\r\n `No connection to team '${teamName}'. Use the connect_peer tool to connect first.`\r\n );\r\n }\r\n\r\n private waitForResponse<T extends P2PMsg>(\r\n filter: (msg: P2PMsg) => boolean,\r\n timeoutMs: number\r\n ): Promise<T> {\r\n return new Promise((resolve, reject) => {\r\n const timeout = setTimeout(() => {\r\n this.pendingHandlers.delete(handler);\r\n reject(new Error('P2P request timed out'));\r\n }, timeoutMs);\r\n\r\n const handler = (msg: P2PMsg): void => {\r\n if (filter(msg)) {\r\n clearTimeout(timeout);\r\n this.pendingHandlers.delete(handler);\r\n resolve(msg as T);\r\n }\r\n };\r\n\r\n this.pendingHandlers.add(handler);\r\n });\r\n }\r\n}\r\n","/**\r\n * Join Tool\r\n * Joins a team channel for collaboration\r\n * @module presentation/mcp/tools/join\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Join tool input schema\r\n */\r\nconst joinSchema = {\r\n team: z.string().describe('Team name to join (e.g., \"frontend\", \"backend\", \"devops\")'),\r\n displayName: z\r\n .string()\r\n .optional()\r\n .describe('Display name for this terminal (default: team + \" Claude\")'),\r\n};\r\n\r\n/**\r\n * Registers the join tool with the MCP server\r\n */\r\nexport function registerJoinTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('join', joinSchema, async (args) => {\r\n const teamName = args.team;\r\n const displayName = args.displayName ?? `${teamName} Claude`;\r\n\r\n try {\r\n const member = await client.join(teamName, displayName);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Successfully joined team \"${member.teamName}\" as \"${member.displayName}\".\\n\\nYour member ID: ${member.memberId}\\nStatus: ${member.status}\\nListening on port: ${member.port}\\n\\nShare this port with the other terminal so they can run: connect_peer(\"<your-ip>\", ${member.port})`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to join team: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Connect Peer Tool\r\n * Manually connects to a peer node by IP address and port\r\n * @module presentation/mcp/tools/connect-peer\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\nconst connectPeerSchema = {\r\n ip: z.string().describe('IP address of the peer to connect to (e.g., \"172.16.40.137\")'),\r\n port: z.number().describe('Port the peer is listening on (shown in their join response)'),\r\n};\r\n\r\nexport function registerConnectPeerTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('connect_peer', connectPeerSchema, async (args) => {\r\n try {\r\n const peerTeam = await client.connectPeer(args.ip, args.port);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Connected to peer \"${peerTeam}\" at ${args.ip}:${args.port}.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to connect to ${args.ip}:${args.port}: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Ask Tool\r\n * Sends a question to another team and returns a question ID immediately.\r\n * Use the \"check_answer\" tool with the question ID to retrieve the answer later.\r\n * @module presentation/mcp/tools/ask\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Ask tool input schema\r\n */\r\nconst askSchema = {\r\n team: z.string().describe('Target team name to ask (e.g., \"backend\", \"frontend\")'),\r\n question: z.string().describe('The question to ask (supports markdown)'),\r\n};\r\n\r\n/**\r\n * Registers the ask tool with the MCP server\r\n */\r\nexport function registerAskTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('ask', askSchema, async (args) => {\r\n const targetTeam = args.team;\r\n const question = args.question;\r\n\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n const questionId = await client.ask(targetTeam, question, 'markdown');\r\n\r\n // Poll until answer arrives (max 5 minutes, every 5 seconds)\r\n const POLL_INTERVAL_MS = 5_000;\r\n const MAX_WAIT_MS = 5 * 60 * 1000;\r\n const deadline = Date.now() + MAX_WAIT_MS;\r\n\r\n while (Date.now() < deadline) {\r\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\r\n const answer = await client.checkAnswer(questionId);\r\n if (answer !== null) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `**${answer.from.displayName} (${answer.from.teamName}) cevapladı:**\\n\\n${answer.content}`,\r\n },\r\n ],\r\n };\r\n }\r\n }\r\n\r\n // Timed out — return question ID for manual follow-up\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Soru gönderildi ancak 5 dakika içinde cevap gelmedi.\\nQuestion ID: \\`${questionId}\\`\\n\\nManuel kontrol için \"check_answer\" tool'unu kullanabilirsin.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to send question: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Check Answer Tool\r\n * Checks if an answer has arrived for a previously sent question.\r\n * Returns the answer if available, or a \"still pending\" message.\r\n * @module presentation/mcp/tools/check\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Check answer tool input schema\r\n */\r\nconst checkAnswerSchema = {\r\n question_id: z.string().describe('The question ID returned by the \"ask\" tool'),\r\n};\r\n\r\n/**\r\n * Registers the check_answer tool with the MCP server\r\n */\r\nexport function registerCheckAnswerTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('check_answer', checkAnswerSchema, async (args) => {\r\n const questionId = args.question_id;\r\n\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n const answer = await client.checkAnswer(questionId);\r\n\r\n if (!answer) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `No answer yet for question \\`${questionId}\\`. The other team hasn't replied yet. You can continue working and check again later.`,\r\n },\r\n ],\r\n };\r\n }\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `**Answer from ${answer.from.displayName} (${answer.from.teamName}):**\\n\\n${answer.content}`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to check answer: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Inbox Tool\r\n * Lists pending questions directed to the current team\r\n * @module presentation/mcp/tools/inbox\r\n */\r\n\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Inbox tool input schema (no required parameters)\r\n */\r\nconst inboxSchema = {};\r\n\r\n/**\r\n * Registers the inbox tool with the MCP server\r\n */\r\nexport function registerInboxTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('inbox', inboxSchema, async () => {\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n const inbox = await client.getInbox();\r\n\r\n if (inbox.questions.length === 0) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'No pending questions in your inbox.',\r\n },\r\n ],\r\n };\r\n }\r\n\r\n const questionsList = inbox.questions\r\n .map((q, i) => {\r\n const ageSeconds = Math.floor(q.ageMs / 1000);\r\n const ageStr = ageSeconds < 60 ? `${ageSeconds}s ago` : `${Math.floor(ageSeconds / 60)}m ago`;\r\n\r\n return `### ${i + 1}. Question from ${q.from.displayName} (${q.from.teamName}) - ${ageStr}\r\n**ID:** \\`${q.questionId}\\`\r\n**Status:** ${q.status}\r\n\r\n${q.content}\r\n\r\n---`;\r\n })\r\n .join('\\n\\n');\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `# Inbox (${inbox.pendingCount} pending, ${inbox.totalCount} total)\\n\\n${questionsList}\\n\\nUse the \"reply\" tool with the question ID to answer a question.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to get inbox: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Reply Tool\r\n * Replies to a pending question\r\n * @module presentation/mcp/tools/reply\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\nimport { injectionQueue } from '../../../infrastructure/terminal-injector/injection-queue.js';\r\n\r\n/**\r\n * Reply tool input schema\r\n */\r\nconst replySchema = {\r\n questionId: z.string().describe('The ID of the question to reply to (from inbox)'),\r\n answer: z.string().describe('Your answer to the question (supports markdown)'),\r\n};\r\n\r\n/**\r\n * Registers the reply tool with the MCP server\r\n */\r\nexport function registerReplyTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('reply', replySchema, async (args) => {\r\n const questionId = args.questionId;\r\n const answer = args.answer;\r\n\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n await client.reply(questionId, answer, 'markdown');\r\n\r\n // Signal queue: this question is done, process next\r\n injectionQueue.notifyReplied();\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Reply sent successfully to question \\`${questionId}\\`.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to send reply: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * MCP Server\r\n * Provides MCP tools for Claude Code integration\r\n * @module presentation/mcp/server\r\n */\r\n\r\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\r\nimport type { ICollabClient } from '../../shared/types/collab-client.interface.js';\r\nimport { registerJoinTool } from './tools/join.tool.js';\r\nimport { registerConnectPeerTool } from './tools/connect-peer.tool.js';\r\nimport { registerAskTool } from './tools/ask.tool.js';\r\nimport { registerCheckAnswerTool } from './tools/check.tool.js';\r\nimport { registerInboxTool } from './tools/inbox.tool.js';\r\nimport { registerReplyTool } from './tools/reply.tool.js';\r\n\r\n/**\r\n * MCP Server options\r\n */\r\nexport interface McpServerOptions {\r\n client: ICollabClient;\r\n}\r\n\r\n/**\r\n * Creates and configures the MCP server with all tools\r\n */\r\nexport function createMcpServer(options: McpServerOptions): McpServer {\r\n const { client } = options;\r\n\r\n const server = new McpServer(\r\n {\r\n name: 'claude-collab',\r\n version: '0.1.2',\r\n },\r\n {\r\n capabilities: {\r\n resources: {\r\n subscribe: true,\r\n listChanged: true,\r\n },\r\n },\r\n }\r\n );\r\n\r\n // Register all tools\r\n registerJoinTool(server, client);\r\n registerConnectPeerTool(server, client);\r\n registerAskTool(server, client);\r\n registerCheckAnswerTool(server, client);\r\n registerInboxTool(server, client);\r\n registerReplyTool(server, client);\r\n\r\n // Register resource handlers\r\n server.resource(\r\n 'inbox-questions',\r\n 'inbox://questions',\r\n { description: 'Your inbox of pending questions from other teams', mimeType: 'application/json' },\r\n async () => {\r\n try {\r\n const inbox = await client.getInbox();\r\n return {\r\n contents: [\r\n {\r\n uri: 'inbox://questions',\r\n mimeType: 'application/json',\r\n text: JSON.stringify(inbox, null, 2),\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n throw new Error(`Failed to read inbox: ${errorMessage}`);\r\n }\r\n }\r\n );\r\n\r\n return server;\r\n}\r\n\r\n/**\r\n * Starts the MCP server with stdio transport\r\n */\r\nexport async function startMcpServer(options: McpServerOptions): Promise<void> {\r\n const server = createMcpServer(options);\r\n const transport = new StdioServerTransport();\r\n await server.connect(transport);\r\n}\r\n","#!/usr/bin/env node\r\n\r\n/**\r\n * CLI entry point\r\n * Provides command-line interface for claude-collab (P2P mode)\r\n * @module cli\r\n */\r\n\r\nimport { Command } from 'commander';\r\nimport { P2PNode } from './infrastructure/p2p/p2p-node.js';\r\nimport { startMcpServer } from './presentation/mcp/server.js';\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('claude-collab')\r\n .description('Real-time P2P team collaboration between Claude Code terminals')\r\n .version('0.1.0');\r\n\r\n// Client command\r\nprogram\r\n .command('client')\r\n .description('Start MCP client (P2P mode, connects to Claude Code)')\r\n .action(async () => {\r\n const p2pNode = new P2PNode();\r\n await startMcpServer({ client: p2pNode });\r\n });\r\n\r\nprogram.parse();\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/infrastructure/p2p/p2p-message-protocol.ts","../src/infrastructure/terminal-injector/windows-injector.ts","../src/infrastructure/terminal-injector/index.ts","../src/infrastructure/terminal-injector/injection-queue.ts","../src/config/index.ts","../src/infrastructure/p2p/p2p-node.ts","../src/presentation/mcp/tools/join.tool.ts","../src/presentation/mcp/tools/connect-peer.tool.ts","../src/presentation/mcp/tools/get-info.tool.ts","../src/presentation/mcp/tools/ask.tool.ts","../src/presentation/mcp/tools/check.tool.ts","../src/presentation/mcp/tools/inbox.tool.ts","../src/presentation/mcp/tools/reply.tool.ts","../src/presentation/mcp/server.ts","../src/cli.ts"],"names":["uuidv4","z"],"mappings":"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","file":"cli.js","sourcesContent":["/**\r\n * P2P Wire Message Protocol\r\n * Defines messages exchanged directly between P2P nodes.\r\n * @module infrastructure/p2p/p2p-message-protocol\r\n */\r\n\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\n\r\n// First message sent by the connecting peer to identify itself\r\nexport interface P2PHelloMsg {\r\n type: 'P2P_HELLO';\r\n fromTeam: string;\r\n fromMemberId: string;\r\n}\r\n\r\n// Questioner → Answerer: send a question\r\nexport interface P2PAskMsg {\r\n type: 'P2P_ASK';\r\n questionId: string;\r\n fromMemberId: string;\r\n fromTeam: string;\r\n toTeam: string;\r\n content: string;\r\n format: MessageFormat;\r\n requestId: string;\r\n}\r\n\r\n// Answerer → Questioner: acknowledge the question\r\nexport interface P2PAskAckMsg {\r\n type: 'P2P_ASK_ACK';\r\n questionId: string;\r\n requestId: string;\r\n}\r\n\r\n// Questioner → Answerer: poll for answer\r\nexport interface P2PGetAnswerMsg {\r\n type: 'P2P_GET_ANSWER';\r\n questionId: string;\r\n requestId: string;\r\n}\r\n\r\n// Answerer → Questioner: deliver the answer (push or in response to GET_ANSWER)\r\nexport interface P2PAnswerMsg {\r\n type: 'P2P_ANSWER';\r\n questionId: string;\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n fromTeam: string;\r\n fromMemberId: string;\r\n requestId?: string;\r\n}\r\n\r\n// Answerer → Questioner: answer not ready yet\r\nexport interface P2PAnswerPendingMsg {\r\n type: 'P2P_ANSWER_PENDING';\r\n questionId: string;\r\n requestId: string;\r\n}\r\n\r\nexport interface P2PPingMsg {\r\n type: 'P2P_PING';\r\n}\r\n\r\nexport interface P2PPongMsg {\r\n type: 'P2P_PONG';\r\n}\r\n\r\nexport interface P2PErrorMsg {\r\n type: 'P2P_ERROR';\r\n code: string;\r\n message: string;\r\n}\r\n\r\nexport type P2PMsg =\r\n | P2PHelloMsg\r\n | P2PAskMsg\r\n | P2PAskAckMsg\r\n | P2PGetAnswerMsg\r\n | P2PAnswerMsg\r\n | P2PAnswerPendingMsg\r\n | P2PPingMsg\r\n | P2PPongMsg\r\n | P2PErrorMsg;\r\n\r\nexport function serializeP2PMsg(msg: P2PMsg): string {\r\n return JSON.stringify(msg);\r\n}\r\n\r\nexport function parseP2PMsg(data: string): P2PMsg {\r\n return JSON.parse(data) as P2PMsg;\r\n}\r\n","/**\r\n * Windows Terminal Injector\r\n * AttachConsole(ppid) → CreateFile(\"CONIN$\") → WriteConsoleInput\r\n * All keystrokes (text, Ctrl+U, Enter, Ctrl+Y) go through WriteConsoleInput.\r\n * No WScript.Shell / SendKeys / SetForegroundWindow — no focus dependency.\r\n * @module infrastructure/terminal-injector/windows-injector\r\n */\r\n\r\nimport { execFile } from 'child_process';\r\nimport { unlinkSync } from 'fs';\r\nimport { tmpdir } from 'os';\r\nimport { join } from 'path';\r\n\r\nconst CS_CONINJECT = `\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Runtime.InteropServices;\r\n\r\npublic class ConInject {\r\n [DllImport(\"kernel32.dll\")] public static extern bool FreeConsole();\r\n [DllImport(\"kernel32.dll\")] public static extern bool AttachConsole(uint pid);\r\n [DllImport(\"kernel32.dll\", CharSet=CharSet.Unicode, SetLastError=true)]\r\n public static extern IntPtr CreateFile(\r\n string lpFileName, uint dwDesiredAccess, uint dwShareMode,\r\n IntPtr lpSecurityAttributes, uint dwCreationDisposition,\r\n uint dwFlagsAndAttributes, IntPtr hTemplateFile);\r\n [DllImport(\"kernel32.dll\")] public static extern bool WriteConsoleInput(\r\n IntPtr hIn, INPUT_RECORD[] buf, uint len, out uint written);\r\n [DllImport(\"kernel32.dll\")] public static extern bool CloseHandle(IntPtr h);\r\n\r\n [StructLayout(LayoutKind.Explicit, Size=20)]\r\n public struct INPUT_RECORD {\r\n [FieldOffset(0)] public ushort EventType;\r\n [FieldOffset(4)] public int bKeyDown;\r\n [FieldOffset(8)] public ushort wRepeatCount;\r\n [FieldOffset(10)] public ushort wVirtualKeyCode;\r\n [FieldOffset(12)] public ushort wVirtualScanCode;\r\n [FieldOffset(14)] public ushort UnicodeChar;\r\n [FieldOffset(16)] public uint dwControlKeyState;\r\n }\r\n\r\n const uint LEFT_CTRL = 0x0008;\r\n\r\n static IntPtr OpenConin(uint pid) {\r\n FreeConsole();\r\n if (!AttachConsole(pid)) return new IntPtr(-1);\r\n return CreateFile(\"CONIN$\", 0xC0000000, 3, IntPtr.Zero, 3, 0, IntPtr.Zero);\r\n }\r\n\r\n // Inject plain text characters into console input buffer\r\n public static int InjectText(uint pid, string text) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new List<INPUT_RECORD>();\r\n foreach (char c in text) {\r\n records.Add(new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, UnicodeChar=(ushort)c });\r\n records.Add(new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, UnicodeChar=(ushort)c });\r\n }\r\n\r\n var arr = records.ToArray();\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, arr, (uint)arr.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n\r\n // Inject Enter (VK_RETURN = 0x0D)\r\n public static int InjectEnter(uint pid) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new INPUT_RECORD[] {\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x0D, UnicodeChar=0x0D },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x0D, UnicodeChar=0x0D }\r\n };\r\n\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n\r\n // Inject Ctrl+U (VK_U = 0x55, char = 0x15)\r\n public static int InjectCtrlU(uint pid) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new INPUT_RECORD[] {\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x55, UnicodeChar=0x15, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x55, UnicodeChar=0x15, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=0 }\r\n };\r\n\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n\r\n // Inject Ctrl+Y (VK_Y = 0x59, char = 0x19)\r\n public static int InjectCtrlY(uint pid) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new INPUT_RECORD[] {\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x59, UnicodeChar=0x19, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x59, UnicodeChar=0x19, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=0 }\r\n };\r\n\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n}\r\n`;\r\n\r\nfunction buildScript(claudePid: number, body: string): string {\r\n const logFile = join(tmpdir(), `cc-inject-${Date.now()}.log`).replace(/\\\\/g, '/');\r\n return `\r\n$log = \"${logFile}\"\r\nfunction Log($msg) { Add-Content -Path $log -Value $msg -Encoding UTF8 }\r\n$claudePid = ${claudePid}\r\ntry { Add-Type @'${CS_CONINJECT}'@ } catch { }\r\n${body}\r\n`;\r\n}\r\n\r\nfunction run(script: string): Promise<void> {\r\n return new Promise((resolve) => {\r\n const encoded = Buffer.from(script, 'utf16le').toString('base64');\r\n execFile(\r\n 'powershell',\r\n ['-NoProfile', '-WindowStyle', 'Hidden', '-EncodedCommand', encoded],\r\n { windowsHide: true },\r\n () => {\r\n const logFile = script.match(/\\$log = \"([^\"]+)\"/)?.[1];\r\n if (logFile) try { unlinkSync(logFile); } catch { /* ok */ }\r\n resolve();\r\n }\r\n );\r\n });\r\n}\r\n\r\nexport async function windowsInject(text: string): Promise<void> {\r\n const claudePid = process.ppid;\r\n const textB64 = Buffer.from(text, 'utf16le').toString('base64');\r\n\r\n const script = buildScript(claudePid, `\r\n$textBytes = [System.Convert]::FromBase64String('${textB64}')\r\n$text = [System.Text.Encoding]::Unicode.GetString($textBytes)\r\n\r\n# 1. Ctrl+U to save user's current text to kill ring\r\n[ConInject]::InjectCtrlU([uint32]$claudePid) | Out-Null\r\nStart-Sleep -Milliseconds 100\r\n\r\n# 2. Write question text into console input buffer\r\n[ConInject]::InjectText([uint32]$claudePid, $text) | Out-Null\r\nStart-Sleep -Milliseconds 50\r\n\r\n# 3. Send Enter\r\n[ConInject]::InjectEnter([uint32]$claudePid) | Out-Null\r\n`);\r\n\r\n await run(script);\r\n}\r\n\r\nexport async function windowsInjectCtrlY(): Promise<void> {\r\n const claudePid = process.ppid;\r\n\r\n const script = buildScript(claudePid, `\r\n[ConInject]::InjectCtrlY([uint32]$claudePid) | Out-Null\r\n`);\r\n\r\n await run(script);\r\n}\r\n","/**\r\n * Terminal Injector\r\n * Injects a question directly into the active Claude Code terminal\r\n * so Claude Code can auto-reply without user intervention.\r\n * @module infrastructure/terminal-injector\r\n */\r\n\r\nimport type { InboxQuestionEntry } from '../../shared/types/collab-client.interface.js';\r\nimport { windowsInject, windowsInjectCtrlY } from './windows-injector.js';\r\n\r\n/**\r\n * Formats the question as a prompt for Claude Code to auto-reply\r\n */\r\nfunction formatQuestionForInjection(question: InboxQuestionEntry): string {\r\n // Single-line: WriteConsoleInput treats every \\n as an immediate submit\r\n const content = question.content.replace(/\\s+/g, ' ').trim();\r\n return `[HUB SORUSU] ID:${question.questionId} | ${question.from.displayName} (${question.from.teamName}): ${content} | Cevapla ve reply tool ile \"${question.questionId}\" ID'sine gönder, onay bekleme.`;\r\n}\r\n\r\n/**\r\n * Injects a question into the terminal running Claude Code.\r\n * Only supported on Windows; no-op on other platforms.\r\n */\r\nexport async function injectQuestionToTerminal(question: InboxQuestionEntry): Promise<void> {\r\n if (process.platform !== 'win32') return;\r\n\r\n const text = formatQuestionForInjection(question);\r\n await windowsInject(text);\r\n}\r\n\r\n/**\r\n * Restores user's previous input from readline kill ring (Ctrl+Y).\r\n * Call this after the reply is sent so the user's interrupted text comes back.\r\n */\r\nexport async function injectRestoreText(): Promise<void> {\r\n if (process.platform !== 'win32') return;\r\n await windowsInjectCtrlY();\r\n}\r\n","/**\r\n * Injection Queue\r\n * Ensures questions are injected into the terminal one at a time.\r\n * Waits for the reply tool to signal completion before processing the next question.\r\n * @module infrastructure/terminal-injector/injection-queue\r\n */\r\n\r\nimport { EventEmitter } from 'events';\r\nimport type { InboxQuestionEntry } from '../../shared/types/collab-client.interface.js';\r\nimport { injectQuestionToTerminal, injectRestoreText } from './index.js';\r\n\r\nconst REPLY_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\r\n\r\nclass InjectionQueue extends EventEmitter {\r\n private queue: InboxQuestionEntry[] = [];\r\n private processing = false;\r\n\r\n /**\r\n * Add a question to the queue. Starts processing if idle.\r\n */\r\n enqueue(question: InboxQuestionEntry): void {\r\n this.queue.push(question);\r\n if (!this.processing) void this.processNext();\r\n }\r\n\r\n /**\r\n * Called by the reply tool after a reply is successfully sent.\r\n * Unblocks the queue to process the next question.\r\n */\r\n notifyReplied(): void {\r\n this.emit('replied');\r\n }\r\n\r\n private async processNext(): Promise<void> {\r\n if (this.queue.length === 0) {\r\n this.processing = false;\r\n return;\r\n }\r\n\r\n this.processing = true;\r\n const question = this.queue.shift()!;\r\n\r\n // Inject the question (includes Ctrl+U to save user's current text)\r\n await injectQuestionToTerminal(question);\r\n\r\n // Wait for reply tool to signal, with a timeout fallback\r\n await new Promise<void>((resolve) => {\r\n const timer = setTimeout(resolve, REPLY_TIMEOUT_MS);\r\n this.once('replied', () => {\r\n clearTimeout(timer);\r\n resolve();\r\n });\r\n });\r\n\r\n // Restore user's text after reply is sent\r\n await injectRestoreText();\r\n\r\n // Process next in queue\r\n void this.processNext();\r\n }\r\n}\r\n\r\nexport const injectionQueue = new InjectionQueue();\r\n","/**\r\n * Configuration module\r\n * @module config\r\n */\r\n\r\n/**\r\n * Application configuration\r\n */\r\nexport const config = {\r\n /**\r\n * P2P node configuration\r\n */\r\n p2p: {\r\n /**\r\n * Port range for the WS server. Override with CLAUDE_COLLAB_PORT_MIN / MAX env vars.\r\n */\r\n portRangeMin: Number(process.env['CLAUDE_COLLAB_PORT_MIN'] ?? 11700),\r\n portRangeMax: Number(process.env['CLAUDE_COLLAB_PORT_MAX'] ?? 11750),\r\n },\r\n\r\n /**\r\n * Communication configuration\r\n */\r\n communication: {\r\n /**\r\n * Default timeout for waiting for an answer (in milliseconds)\r\n */\r\n defaultTimeout: 30000,\r\n\r\n /**\r\n * Maximum message content length\r\n */\r\n maxMessageLength: 50000,\r\n },\r\n} as const;\r\n\r\nexport type Config = typeof config;\r\n","/**\r\n * P2PNode\r\n * Implements ICollabClient using a peer-to-peer WebSocket architecture.\r\n * Each node runs its own WS server on a fixed port; peers are connected\r\n * manually via connectPeer().\r\n * @module infrastructure/p2p/p2p-node\r\n */\r\n\r\nimport { WebSocketServer, WebSocket } from 'ws';\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport type {\r\n ICollabClient,\r\n JoinResult,\r\n CheckAnswerResult,\r\n InboxResult,\r\n NodeInfo,\r\n} from '../../shared/types/collab-client.interface.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport {\r\n type P2PMsg,\r\n type P2PAskMsg,\r\n type P2PAskAckMsg,\r\n type P2PGetAnswerMsg,\r\n type P2PAnswerMsg,\r\n type P2PAnswerPendingMsg,\r\n type P2PHelloMsg,\r\n serializeP2PMsg,\r\n parseP2PMsg,\r\n} from './p2p-message-protocol.js';\r\nimport { injectionQueue } from '../terminal-injector/injection-queue.js';\r\nimport { config } from '../../config/index.js';\r\n\r\ninterface IncomingQuestion {\r\n questionId: string;\r\n fromTeam: string;\r\n fromMemberId: string;\r\n content: string;\r\n format: MessageFormat;\r\n createdAt: Date;\r\n ws: WebSocket;\r\n answered: boolean;\r\n answerContent?: string;\r\n answerFormat?: MessageFormat;\r\n}\r\n\r\ninterface ReceivedAnswer {\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n fromTeam: string;\r\n fromMemberId: string;\r\n}\r\n\r\ninterface LocalMember {\r\n memberId: string;\r\n teamName: string;\r\n displayName: string;\r\n}\r\n\r\nexport class P2PNode implements ICollabClient {\r\n private wss: WebSocketServer | null = null;\r\n private port = 0;\r\n\r\n // Connections indexed by remote team name\r\n private readonly peerConns = new Map<string, WebSocket>();\r\n // Reverse lookup: ws → teamName (for cleanup)\r\n private readonly wsToTeam = new Map<WebSocket, string>();\r\n\r\n // Questions we received from remote peers (our inbox)\r\n private readonly incomingQuestions = new Map<string, IncomingQuestion>();\r\n\r\n // Answers we received for questions we asked\r\n private readonly receivedAnswers = new Map<string, ReceivedAnswer>();\r\n\r\n // Maps questionId → remote teamName (so we know who to poll)\r\n private readonly questionToTeam = new Map<string, string>();\r\n\r\n // Pending response handlers (request-response correlation by filter)\r\n private readonly pendingHandlers = new Set<(msg: P2PMsg) => void>();\r\n\r\n private localMember: LocalMember | null = null;\r\n private _isStarted = false;\r\n\r\n get isConnected(): boolean {\r\n return this._isStarted;\r\n }\r\n\r\n get currentTeamId(): string | undefined {\r\n return this.localMember?.teamName;\r\n }\r\n\r\n /**\r\n * Starts the WS server on a random available port within the configured range.\r\n * Called automatically from join() if not yet started.\r\n */\r\n async start(): Promise<void> {\r\n const { portRangeMin, portRangeMax } = config.p2p;\r\n const range = portRangeMax - portRangeMin + 1;\r\n const startOffset = Math.floor(Math.random() * range);\r\n\r\n for (let i = 0; i < range; i++) {\r\n const port = portRangeMin + ((startOffset + i) % range);\r\n const bound = await this.tryBind(port);\r\n if (bound) {\r\n this.port = port;\r\n break;\r\n }\r\n }\r\n\r\n if (!this.wss) {\r\n throw new Error(\r\n `No available port in range ${portRangeMin}-${portRangeMax}. ` +\r\n `Override with CLAUDE_COLLAB_PORT_MIN / CLAUDE_COLLAB_PORT_MAX.`\r\n );\r\n }\r\n\r\n this.setupWssHandlers();\r\n this._isStarted = true;\r\n console.error(`P2P node started on port ${this.port}`);\r\n }\r\n\r\n private tryBind(port: number): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const wss = new WebSocketServer({ port });\r\n wss.once('listening', () => {\r\n this.wss = wss;\r\n resolve(true);\r\n });\r\n wss.once('error', () => resolve(false));\r\n });\r\n }\r\n\r\n async join(teamName: string, displayName: string): Promise<JoinResult> {\r\n if (!this._isStarted) {\r\n await this.start();\r\n }\r\n\r\n const memberId = uuidv4();\r\n this.localMember = { memberId, teamName, displayName };\r\n\r\n return { memberId, teamId: teamName, teamName, displayName, status: 'ONLINE', port: this.port };\r\n }\r\n\r\n /**\r\n * Connects to a peer at the given IP and port.\r\n * Performs a bidirectional HELLO handshake and returns the peer's team name.\r\n */\r\n async connectPeer(ip: string, port: number): Promise<string> {\r\n if (!this.localMember) {\r\n throw new Error('Must call join() before connectPeer()');\r\n }\r\n\r\n const ws = new WebSocket(`ws://${ip}:${port}`);\r\n\r\n // Set up persistent message handler\r\n ws.on('message', (data) => {\r\n try {\r\n const msg = parseP2PMsg(data.toString());\r\n this.handleMessage(ws, msg);\r\n } catch (err) {\r\n console.error('Failed to parse P2P message:', err);\r\n }\r\n });\r\n\r\n ws.on('close', () => {\r\n const team = this.wsToTeam.get(ws);\r\n if (team) {\r\n if (this.peerConns.get(team) === ws) {\r\n this.peerConns.delete(team);\r\n }\r\n this.wsToTeam.delete(ws);\r\n }\r\n });\r\n\r\n // Connect and send our HELLO\r\n await new Promise<void>((resolve, reject) => {\r\n const timeout = setTimeout(\r\n () => reject(new Error(`Connection timeout to ${ip}:${port}`)),\r\n 5000\r\n );\r\n\r\n ws.on('open', () => {\r\n clearTimeout(timeout);\r\n const hello: P2PHelloMsg = {\r\n type: 'P2P_HELLO',\r\n fromTeam: this.localMember!.teamName,\r\n fromMemberId: this.localMember!.memberId,\r\n };\r\n ws.send(serializeP2PMsg(hello));\r\n resolve();\r\n });\r\n\r\n ws.on('error', (err) => {\r\n clearTimeout(timeout);\r\n reject(err);\r\n });\r\n });\r\n\r\n // Wait for their HELLO back to identify their team name\r\n const helloMsg = await this.waitForResponse<P2PHelloMsg>(\r\n (m) => m.type === 'P2P_HELLO',\r\n 10000\r\n );\r\n\r\n return helloMsg.fromTeam;\r\n }\r\n\r\n async ask(toTeam: string, content: string, format: MessageFormat): Promise<string> {\r\n const ws = await this.getPeerConnection(toTeam);\r\n const questionId = uuidv4();\r\n const requestId = uuidv4();\r\n\r\n this.questionToTeam.set(questionId, toTeam);\r\n\r\n // Register handler before sending (avoids race where ACK arrives first)\r\n const ackPromise = this.waitForResponse<P2PAskAckMsg>(\r\n (m) => m.type === 'P2P_ASK_ACK' && m.requestId === requestId,\r\n 5000\r\n );\r\n\r\n const msg: P2PAskMsg = {\r\n type: 'P2P_ASK',\r\n questionId,\r\n fromMemberId: this.localMember!.memberId,\r\n fromTeam: this.localMember!.teamName,\r\n toTeam,\r\n content,\r\n format,\r\n requestId,\r\n };\r\n ws.send(serializeP2PMsg(msg));\r\n\r\n await ackPromise;\r\n return questionId;\r\n }\r\n\r\n async checkAnswer(questionId: string): Promise<CheckAnswerResult | null> {\r\n // Check local cache first (populated by push from remote)\r\n const cached = this.receivedAnswers.get(questionId);\r\n if (cached) {\r\n return {\r\n questionId,\r\n from: { displayName: `${cached.fromTeam} Claude`, teamName: cached.fromTeam },\r\n content: cached.content,\r\n format: cached.format,\r\n answeredAt: cached.answeredAt,\r\n };\r\n }\r\n\r\n // Poll the remote peer\r\n const toTeam = this.questionToTeam.get(questionId);\r\n if (!toTeam) return null;\r\n\r\n const ws = this.peerConns.get(toTeam);\r\n if (!ws || ws.readyState !== WebSocket.OPEN) return null;\r\n\r\n const requestId = uuidv4();\r\n\r\n const responsePromise = this.waitForResponse<P2PAnswerMsg | P2PAnswerPendingMsg>(\r\n (m) =>\r\n (m.type === 'P2P_ANSWER' && m.questionId === questionId) ||\r\n (m.type === 'P2P_ANSWER_PENDING' && m.requestId === requestId),\r\n 5000\r\n );\r\n\r\n const getMsg: P2PGetAnswerMsg = {\r\n type: 'P2P_GET_ANSWER',\r\n questionId,\r\n requestId,\r\n };\r\n ws.send(serializeP2PMsg(getMsg));\r\n\r\n const response = await responsePromise;\r\n if (response.type === 'P2P_ANSWER_PENDING') return null;\r\n\r\n const answer = response as P2PAnswerMsg;\r\n this.receivedAnswers.set(questionId, {\r\n content: answer.content,\r\n format: answer.format,\r\n answeredAt: answer.answeredAt,\r\n fromTeam: answer.fromTeam,\r\n fromMemberId: answer.fromMemberId,\r\n });\r\n\r\n return {\r\n questionId,\r\n from: { displayName: `${answer.fromTeam} Claude`, teamName: answer.fromTeam },\r\n content: answer.content,\r\n format: answer.format,\r\n answeredAt: answer.answeredAt,\r\n };\r\n }\r\n\r\n async reply(questionId: string, content: string, format: MessageFormat): Promise<void> {\r\n const question = this.incomingQuestions.get(questionId);\r\n if (!question) throw new Error(`Question ${questionId} not found in inbox`);\r\n\r\n question.answered = true;\r\n question.answerContent = content;\r\n question.answerFormat = format;\r\n\r\n const answerMsg: P2PAnswerMsg = {\r\n type: 'P2P_ANSWER',\r\n questionId,\r\n content,\r\n format,\r\n answeredAt: new Date().toISOString(),\r\n fromTeam: this.localMember!.teamName,\r\n fromMemberId: this.localMember!.memberId,\r\n };\r\n\r\n if (question.ws.readyState === WebSocket.OPEN) {\r\n question.ws.send(serializeP2PMsg(answerMsg));\r\n }\r\n }\r\n\r\n async getInbox(): Promise<InboxResult> {\r\n const now = Date.now();\r\n const questions = [...this.incomingQuestions.values()]\r\n .filter((q) => !q.answered)\r\n .map((q) => ({\r\n questionId: q.questionId,\r\n from: { displayName: `${q.fromTeam} Claude`, teamName: q.fromTeam },\r\n content: q.content,\r\n format: q.format,\r\n status: 'PENDING',\r\n createdAt: q.createdAt.toISOString(),\r\n ageMs: now - q.createdAt.getTime(),\r\n }));\r\n\r\n return {\r\n questions,\r\n totalCount: questions.length,\r\n pendingCount: questions.length,\r\n };\r\n }\r\n\r\n getInfo(): NodeInfo {\r\n return {\r\n teamName: this.localMember?.teamName,\r\n port: this._isStarted ? this.port : undefined,\r\n connectedPeers: [...this.peerConns.keys()],\r\n };\r\n }\r\n\r\n async disconnect(): Promise<void> {\r\n for (const ws of this.peerConns.values()) {\r\n ws.close();\r\n }\r\n this.peerConns.clear();\r\n\r\n await new Promise<void>((resolve) => {\r\n if (this.wss) {\r\n this.wss.close(() => resolve());\r\n } else {\r\n resolve();\r\n }\r\n });\r\n\r\n this._isStarted = false;\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Private: WebSocket server setup\r\n // ---------------------------------------------------------------------------\r\n\r\n private setupWssHandlers(): void {\r\n this.wss!.on('connection', (ws) => {\r\n ws.on('message', (data) => {\r\n try {\r\n const msg = parseP2PMsg(data.toString());\r\n\r\n // Send our HELLO back on incoming HELLO (bidirectional identification)\r\n if (msg.type === 'P2P_HELLO' && this.localMember) {\r\n const hello: P2PHelloMsg = {\r\n type: 'P2P_HELLO',\r\n fromTeam: this.localMember.teamName,\r\n fromMemberId: this.localMember.memberId,\r\n };\r\n ws.send(serializeP2PMsg(hello));\r\n }\r\n\r\n this.handleMessage(ws, msg);\r\n } catch (err) {\r\n console.error('Failed to parse incoming P2P message:', err);\r\n }\r\n });\r\n\r\n ws.on('close', () => {\r\n const team = this.wsToTeam.get(ws);\r\n if (team) {\r\n if (this.peerConns.get(team) === ws) {\r\n this.peerConns.delete(team);\r\n }\r\n this.wsToTeam.delete(ws);\r\n }\r\n });\r\n });\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Private: unified message handler\r\n // ---------------------------------------------------------------------------\r\n\r\n private handleMessage(ws: WebSocket, msg: P2PMsg): void {\r\n // Dispatch to all pending response handlers first\r\n for (const handler of this.pendingHandlers) {\r\n handler(msg);\r\n }\r\n\r\n switch (msg.type) {\r\n case 'P2P_HELLO':\r\n this.wsToTeam.set(ws, msg.fromTeam);\r\n this.peerConns.set(msg.fromTeam, ws);\r\n console.error(`Peer identified: ${msg.fromTeam}`);\r\n break;\r\n\r\n case 'P2P_ASK':\r\n this.handleIncomingAsk(ws, msg);\r\n break;\r\n\r\n case 'P2P_GET_ANSWER':\r\n this.handleGetAnswer(ws, msg);\r\n break;\r\n\r\n case 'P2P_ANSWER':\r\n // Push answer received for a question WE asked\r\n if (!this.receivedAnswers.has(msg.questionId)) {\r\n this.receivedAnswers.set(msg.questionId, {\r\n content: msg.content,\r\n format: msg.format,\r\n answeredAt: msg.answeredAt,\r\n fromTeam: msg.fromTeam,\r\n fromMemberId: msg.fromMemberId,\r\n });\r\n }\r\n break;\r\n\r\n case 'P2P_PING':\r\n ws.send(serializeP2PMsg({ type: 'P2P_PONG' }));\r\n break;\r\n\r\n // P2P_ASK_ACK, P2P_ANSWER_PENDING, P2P_PONG, P2P_ERROR\r\n // are handled by pendingHandlers above; no extra action needed here.\r\n }\r\n }\r\n\r\n private handleIncomingAsk(ws: WebSocket, msg: P2PAskMsg): void {\r\n this.incomingQuestions.set(msg.questionId, {\r\n questionId: msg.questionId,\r\n fromTeam: msg.fromTeam,\r\n fromMemberId: msg.fromMemberId,\r\n content: msg.content,\r\n format: msg.format,\r\n createdAt: new Date(),\r\n ws,\r\n answered: false,\r\n });\r\n\r\n // Inject into the terminal so Claude Code can auto-reply\r\n injectionQueue.enqueue({\r\n questionId: msg.questionId,\r\n from: {\r\n displayName: `${msg.fromTeam} Claude`,\r\n teamName: msg.fromTeam,\r\n },\r\n content: msg.content,\r\n format: msg.format,\r\n status: 'PENDING',\r\n createdAt: new Date().toISOString(),\r\n ageMs: 0,\r\n });\r\n\r\n // ACK\r\n const ack: P2PAskAckMsg = {\r\n type: 'P2P_ASK_ACK',\r\n questionId: msg.questionId,\r\n requestId: msg.requestId,\r\n };\r\n ws.send(serializeP2PMsg(ack));\r\n }\r\n\r\n private handleGetAnswer(ws: WebSocket, msg: P2PGetAnswerMsg): void {\r\n const question = this.incomingQuestions.get(msg.questionId);\r\n\r\n if (!question?.answered) {\r\n const pending: P2PAnswerPendingMsg = {\r\n type: 'P2P_ANSWER_PENDING',\r\n questionId: msg.questionId,\r\n requestId: msg.requestId,\r\n };\r\n ws.send(serializeP2PMsg(pending));\r\n return;\r\n }\r\n\r\n const answer: P2PAnswerMsg = {\r\n type: 'P2P_ANSWER',\r\n questionId: msg.questionId,\r\n content: question.answerContent!,\r\n format: question.answerFormat!,\r\n answeredAt: new Date().toISOString(),\r\n fromTeam: this.localMember!.teamName,\r\n fromMemberId: this.localMember!.memberId,\r\n requestId: msg.requestId,\r\n };\r\n ws.send(serializeP2PMsg(answer));\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Private: peer connection management\r\n // ---------------------------------------------------------------------------\r\n\r\n private async getPeerConnection(teamName: string): Promise<WebSocket> {\r\n const existing = this.peerConns.get(teamName);\r\n if (existing && existing.readyState === WebSocket.OPEN) {\r\n return existing;\r\n }\r\n\r\n throw new Error(\r\n `No connection to team '${teamName}'. Use the connect_peer tool to connect first.`\r\n );\r\n }\r\n\r\n private waitForResponse<T extends P2PMsg>(\r\n filter: (msg: P2PMsg) => boolean,\r\n timeoutMs: number\r\n ): Promise<T> {\r\n return new Promise((resolve, reject) => {\r\n const timeout = setTimeout(() => {\r\n this.pendingHandlers.delete(handler);\r\n reject(new Error('P2P request timed out'));\r\n }, timeoutMs);\r\n\r\n const handler = (msg: P2PMsg): void => {\r\n if (filter(msg)) {\r\n clearTimeout(timeout);\r\n this.pendingHandlers.delete(handler);\r\n resolve(msg as T);\r\n }\r\n };\r\n\r\n this.pendingHandlers.add(handler);\r\n });\r\n }\r\n}\r\n","/**\r\n * Join Tool\r\n * Joins a team channel for collaboration\r\n * @module presentation/mcp/tools/join\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Join tool input schema\r\n */\r\nconst joinSchema = {\r\n team: z.string().describe('Team name to join (e.g., \"frontend\", \"backend\", \"devops\")'),\r\n displayName: z\r\n .string()\r\n .optional()\r\n .describe('Display name for this terminal (default: team + \" Claude\")'),\r\n};\r\n\r\n/**\r\n * Registers the join tool with the MCP server\r\n */\r\nexport function registerJoinTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('join', joinSchema, async (args) => {\r\n const teamName = args.team;\r\n const displayName = args.displayName ?? `${teamName} Claude`;\r\n\r\n try {\r\n const member = await client.join(teamName, displayName);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Successfully joined team \"${member.teamName}\" as \"${member.displayName}\".\\n\\nYour member ID: ${member.memberId}\\nStatus: ${member.status}\\nListening on port: ${member.port}\\n\\nShare this port with the other terminal so they can run: connect_peer(\"<your-ip>\", ${member.port})`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to join team: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Connect Peer Tool\r\n * Manually connects to a peer node by IP address and port\r\n * @module presentation/mcp/tools/connect-peer\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\nconst connectPeerSchema = {\r\n ip: z.string().describe('IP address of the peer to connect to (e.g., \"172.16.40.137\")'),\r\n port: z.number().describe('Port the peer is listening on (shown in their join response)'),\r\n};\r\n\r\nexport function registerConnectPeerTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('connect_peer', connectPeerSchema, async (args) => {\r\n try {\r\n const peerTeam = await client.connectPeer(args.ip, args.port);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Connected to peer \"${peerTeam}\" at ${args.ip}:${args.port}.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to connect to ${args.ip}:${args.port}: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Get Info Tool\r\n * Returns local node info: team, port, IPs, connected peers\r\n * @module presentation/mcp/tools/get-info\r\n */\r\n\r\nimport { networkInterfaces } from 'os';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\nfunction getLocalIPs(): string[] {\r\n const ips: string[] = [];\r\n for (const iface of Object.values(networkInterfaces())) {\r\n for (const net of iface ?? []) {\r\n if (net.family === 'IPv4' && !net.internal) {\r\n ips.push(net.address);\r\n }\r\n }\r\n }\r\n return ips;\r\n}\r\n\r\nexport function registerGetInfoTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('get_info', {}, async () => {\r\n const info = client.getInfo();\r\n const ips = getLocalIPs();\r\n\r\n const lines: string[] = [];\r\n\r\n lines.push(`Team: ${info.teamName ?? '(not joined yet)'}`);\r\n lines.push(`Port: ${info.port ?? '(not started yet)'}`);\r\n lines.push(`Local IPs: ${ips.length > 0 ? ips.join(', ') : '(none found)'}`);\r\n\r\n if (info.connectedPeers.length > 0) {\r\n lines.push(`Connected peers: ${info.connectedPeers.join(', ')}`);\r\n } else {\r\n lines.push(`Connected peers: (none)`);\r\n }\r\n\r\n if (info.port && ips.length > 0) {\r\n lines.push(`\\nOther terminal can connect with:\\n connect_peer(\"${ips[0]}\", ${info.port})`);\r\n }\r\n\r\n return {\r\n content: [{ type: 'text', text: lines.join('\\n') }],\r\n };\r\n });\r\n}\r\n","/**\r\n * Ask Tool\r\n * Sends a question to another team and returns a question ID immediately.\r\n * Use the \"check_answer\" tool with the question ID to retrieve the answer later.\r\n * @module presentation/mcp/tools/ask\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Ask tool input schema\r\n */\r\nconst askSchema = {\r\n team: z.string().describe('Target team name to ask (e.g., \"backend\", \"frontend\")'),\r\n question: z.string().describe('The question to ask (supports markdown)'),\r\n};\r\n\r\n/**\r\n * Registers the ask tool with the MCP server\r\n */\r\nexport function registerAskTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('ask', askSchema, async (args) => {\r\n const targetTeam = args.team;\r\n const question = args.question;\r\n\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n const questionId = await client.ask(targetTeam, question, 'markdown');\r\n\r\n // Poll until answer arrives (max 5 minutes, every 5 seconds)\r\n const POLL_INTERVAL_MS = 5_000;\r\n const MAX_WAIT_MS = 5 * 60 * 1000;\r\n const deadline = Date.now() + MAX_WAIT_MS;\r\n\r\n while (Date.now() < deadline) {\r\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\r\n const answer = await client.checkAnswer(questionId);\r\n if (answer !== null) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `**${answer.from.displayName} (${answer.from.teamName}) cevapladı:**\\n\\n${answer.content}`,\r\n },\r\n ],\r\n };\r\n }\r\n }\r\n\r\n // Timed out — return question ID for manual follow-up\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Soru gönderildi ancak 5 dakika içinde cevap gelmedi.\\nQuestion ID: \\`${questionId}\\`\\n\\nManuel kontrol için \"check_answer\" tool'unu kullanabilirsin.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to send question: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Check Answer Tool\r\n * Checks if an answer has arrived for a previously sent question.\r\n * Returns the answer if available, or a \"still pending\" message.\r\n * @module presentation/mcp/tools/check\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Check answer tool input schema\r\n */\r\nconst checkAnswerSchema = {\r\n question_id: z.string().describe('The question ID returned by the \"ask\" tool'),\r\n};\r\n\r\n/**\r\n * Registers the check_answer tool with the MCP server\r\n */\r\nexport function registerCheckAnswerTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('check_answer', checkAnswerSchema, async (args) => {\r\n const questionId = args.question_id;\r\n\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n const answer = await client.checkAnswer(questionId);\r\n\r\n if (!answer) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `No answer yet for question \\`${questionId}\\`. The other team hasn't replied yet. You can continue working and check again later.`,\r\n },\r\n ],\r\n };\r\n }\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `**Answer from ${answer.from.displayName} (${answer.from.teamName}):**\\n\\n${answer.content}`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to check answer: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Inbox Tool\r\n * Lists pending questions directed to the current team\r\n * @module presentation/mcp/tools/inbox\r\n */\r\n\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Inbox tool input schema (no required parameters)\r\n */\r\nconst inboxSchema = {};\r\n\r\n/**\r\n * Registers the inbox tool with the MCP server\r\n */\r\nexport function registerInboxTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('inbox', inboxSchema, async () => {\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n const inbox = await client.getInbox();\r\n\r\n if (inbox.questions.length === 0) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'No pending questions in your inbox.',\r\n },\r\n ],\r\n };\r\n }\r\n\r\n const questionsList = inbox.questions\r\n .map((q, i) => {\r\n const ageSeconds = Math.floor(q.ageMs / 1000);\r\n const ageStr = ageSeconds < 60 ? `${ageSeconds}s ago` : `${Math.floor(ageSeconds / 60)}m ago`;\r\n\r\n return `### ${i + 1}. Question from ${q.from.displayName} (${q.from.teamName}) - ${ageStr}\r\n**ID:** \\`${q.questionId}\\`\r\n**Status:** ${q.status}\r\n\r\n${q.content}\r\n\r\n---`;\r\n })\r\n .join('\\n\\n');\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `# Inbox (${inbox.pendingCount} pending, ${inbox.totalCount} total)\\n\\n${questionsList}\\n\\nUse the \"reply\" tool with the question ID to answer a question.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to get inbox: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Reply Tool\r\n * Replies to a pending question\r\n * @module presentation/mcp/tools/reply\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\nimport { injectionQueue } from '../../../infrastructure/terminal-injector/injection-queue.js';\r\n\r\n/**\r\n * Reply tool input schema\r\n */\r\nconst replySchema = {\r\n questionId: z.string().describe('The ID of the question to reply to (from inbox)'),\r\n answer: z.string().describe('Your answer to the question (supports markdown)'),\r\n};\r\n\r\n/**\r\n * Registers the reply tool with the MCP server\r\n */\r\nexport function registerReplyTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('reply', replySchema, async (args) => {\r\n const questionId = args.questionId;\r\n const answer = args.answer;\r\n\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n await client.reply(questionId, answer, 'markdown');\r\n\r\n // Signal queue: this question is done, process next\r\n injectionQueue.notifyReplied();\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Reply sent successfully to question \\`${questionId}\\`.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to send reply: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * MCP Server\r\n * Provides MCP tools for Claude Code integration\r\n * @module presentation/mcp/server\r\n */\r\n\r\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\r\nimport type { ICollabClient } from '../../shared/types/collab-client.interface.js';\r\nimport { registerJoinTool } from './tools/join.tool.js';\r\nimport { registerConnectPeerTool } from './tools/connect-peer.tool.js';\r\nimport { registerGetInfoTool } from './tools/get-info.tool.js';\r\nimport { registerAskTool } from './tools/ask.tool.js';\r\nimport { registerCheckAnswerTool } from './tools/check.tool.js';\r\nimport { registerInboxTool } from './tools/inbox.tool.js';\r\nimport { registerReplyTool } from './tools/reply.tool.js';\r\n\r\n/**\r\n * MCP Server options\r\n */\r\nexport interface McpServerOptions {\r\n client: ICollabClient;\r\n}\r\n\r\n/**\r\n * Creates and configures the MCP server with all tools\r\n */\r\nexport function createMcpServer(options: McpServerOptions): McpServer {\r\n const { client } = options;\r\n\r\n const server = new McpServer(\r\n {\r\n name: 'claude-collab',\r\n version: '0.1.2',\r\n },\r\n {\r\n capabilities: {\r\n resources: {\r\n subscribe: true,\r\n listChanged: true,\r\n },\r\n },\r\n }\r\n );\r\n\r\n // Register all tools\r\n registerJoinTool(server, client);\r\n registerConnectPeerTool(server, client);\r\n registerGetInfoTool(server, client);\r\n registerAskTool(server, client);\r\n registerCheckAnswerTool(server, client);\r\n registerInboxTool(server, client);\r\n registerReplyTool(server, client);\r\n\r\n // Register resource handlers\r\n server.resource(\r\n 'inbox-questions',\r\n 'inbox://questions',\r\n { description: 'Your inbox of pending questions from other teams', mimeType: 'application/json' },\r\n async () => {\r\n try {\r\n const inbox = await client.getInbox();\r\n return {\r\n contents: [\r\n {\r\n uri: 'inbox://questions',\r\n mimeType: 'application/json',\r\n text: JSON.stringify(inbox, null, 2),\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n throw new Error(`Failed to read inbox: ${errorMessage}`);\r\n }\r\n }\r\n );\r\n\r\n return server;\r\n}\r\n\r\n/**\r\n * Starts the MCP server with stdio transport\r\n */\r\nexport async function startMcpServer(options: McpServerOptions): Promise<void> {\r\n const server = createMcpServer(options);\r\n const transport = new StdioServerTransport();\r\n await server.connect(transport);\r\n}\r\n","#!/usr/bin/env node\r\n\r\n/**\r\n * CLI entry point\r\n * Provides command-line interface for claude-collab (P2P mode)\r\n * @module cli\r\n */\r\n\r\nimport { Command } from 'commander';\r\nimport { P2PNode } from './infrastructure/p2p/p2p-node.js';\r\nimport { startMcpServer } from './presentation/mcp/server.js';\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('claude-collab')\r\n .description('Real-time P2P team collaboration between Claude Code terminals')\r\n .version('0.1.0');\r\n\r\n// Client command\r\nprogram\r\n .command('client')\r\n .description('Start MCP client (P2P mode, connects to Claude Code)')\r\n .action(async () => {\r\n const p2pNode = new P2PNode();\r\n await startMcpServer({ client: p2pNode });\r\n });\r\n\r\nprogram.parse();\r\n"]}
|
package/dist/mcp-main.js
CHANGED
|
@@ -4,7 +4,7 @@ import { v4 } from 'uuid';
|
|
|
4
4
|
import { EventEmitter } from 'events';
|
|
5
5
|
import { execFile } from 'child_process';
|
|
6
6
|
import { unlinkSync } from 'fs';
|
|
7
|
-
import { tmpdir } from 'os';
|
|
7
|
+
import { tmpdir, networkInterfaces } from 'os';
|
|
8
8
|
import { join } from 'path';
|
|
9
9
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
10
10
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -470,6 +470,13 @@ var P2PNode = class {
|
|
|
470
470
|
pendingCount: questions.length
|
|
471
471
|
};
|
|
472
472
|
}
|
|
473
|
+
getInfo() {
|
|
474
|
+
return {
|
|
475
|
+
teamName: this.localMember?.teamName,
|
|
476
|
+
port: this._isStarted ? this.port : void 0,
|
|
477
|
+
connectedPeers: [...this.peerConns.keys()]
|
|
478
|
+
};
|
|
479
|
+
}
|
|
473
480
|
async disconnect() {
|
|
474
481
|
for (const ws of this.peerConns.values()) {
|
|
475
482
|
ws.close();
|
|
@@ -701,6 +708,40 @@ function registerConnectPeerTool(server, client) {
|
|
|
701
708
|
}
|
|
702
709
|
});
|
|
703
710
|
}
|
|
711
|
+
function getLocalIPs() {
|
|
712
|
+
const ips = [];
|
|
713
|
+
for (const iface of Object.values(networkInterfaces())) {
|
|
714
|
+
for (const net of iface ?? []) {
|
|
715
|
+
if (net.family === "IPv4" && !net.internal) {
|
|
716
|
+
ips.push(net.address);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
return ips;
|
|
721
|
+
}
|
|
722
|
+
function registerGetInfoTool(server, client) {
|
|
723
|
+
server.tool("get_info", {}, async () => {
|
|
724
|
+
const info = client.getInfo();
|
|
725
|
+
const ips = getLocalIPs();
|
|
726
|
+
const lines = [];
|
|
727
|
+
lines.push(`Team: ${info.teamName ?? "(not joined yet)"}`);
|
|
728
|
+
lines.push(`Port: ${info.port ?? "(not started yet)"}`);
|
|
729
|
+
lines.push(`Local IPs: ${ips.length > 0 ? ips.join(", ") : "(none found)"}`);
|
|
730
|
+
if (info.connectedPeers.length > 0) {
|
|
731
|
+
lines.push(`Connected peers: ${info.connectedPeers.join(", ")}`);
|
|
732
|
+
} else {
|
|
733
|
+
lines.push(`Connected peers: (none)`);
|
|
734
|
+
}
|
|
735
|
+
if (info.port && ips.length > 0) {
|
|
736
|
+
lines.push(`
|
|
737
|
+
Other terminal can connect with:
|
|
738
|
+
connect_peer("${ips[0]}", ${info.port})`);
|
|
739
|
+
}
|
|
740
|
+
return {
|
|
741
|
+
content: [{ type: "text", text: lines.join("\n") }]
|
|
742
|
+
};
|
|
743
|
+
});
|
|
744
|
+
}
|
|
704
745
|
var askSchema = {
|
|
705
746
|
team: z.string().describe('Target team name to ask (e.g., "backend", "frontend")'),
|
|
706
747
|
question: z.string().describe("The question to ask (supports markdown)")
|
|
@@ -948,6 +989,7 @@ function createMcpServer(options) {
|
|
|
948
989
|
);
|
|
949
990
|
registerJoinTool(server, client);
|
|
950
991
|
registerConnectPeerTool(server, client);
|
|
992
|
+
registerGetInfoTool(server, client);
|
|
951
993
|
registerAskTool(server, client);
|
|
952
994
|
registerCheckAnswerTool(server, client);
|
|
953
995
|
registerInboxTool(server, client);
|
package/dist/mcp-main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/infrastructure/p2p/p2p-message-protocol.ts","../src/infrastructure/terminal-injector/windows-injector.ts","../src/infrastructure/terminal-injector/index.ts","../src/infrastructure/terminal-injector/injection-queue.ts","../src/config/index.ts","../src/infrastructure/p2p/p2p-node.ts","../src/presentation/mcp/tools/join.tool.ts","../src/presentation/mcp/tools/connect-peer.tool.ts","../src/presentation/mcp/tools/ask.tool.ts","../src/presentation/mcp/tools/check.tool.ts","../src/presentation/mcp/tools/inbox.tool.ts","../src/presentation/mcp/tools/reply.tool.ts","../src/presentation/mcp/server.ts","../src/mcp-main.ts"],"names":["uuidv4","z"],"mappings":"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","file":"mcp-main.js","sourcesContent":["/**\r\n * P2P Wire Message Protocol\r\n * Defines messages exchanged directly between P2P nodes.\r\n * @module infrastructure/p2p/p2p-message-protocol\r\n */\r\n\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\n\r\n// First message sent by the connecting peer to identify itself\r\nexport interface P2PHelloMsg {\r\n type: 'P2P_HELLO';\r\n fromTeam: string;\r\n fromMemberId: string;\r\n}\r\n\r\n// Questioner → Answerer: send a question\r\nexport interface P2PAskMsg {\r\n type: 'P2P_ASK';\r\n questionId: string;\r\n fromMemberId: string;\r\n fromTeam: string;\r\n toTeam: string;\r\n content: string;\r\n format: MessageFormat;\r\n requestId: string;\r\n}\r\n\r\n// Answerer → Questioner: acknowledge the question\r\nexport interface P2PAskAckMsg {\r\n type: 'P2P_ASK_ACK';\r\n questionId: string;\r\n requestId: string;\r\n}\r\n\r\n// Questioner → Answerer: poll for answer\r\nexport interface P2PGetAnswerMsg {\r\n type: 'P2P_GET_ANSWER';\r\n questionId: string;\r\n requestId: string;\r\n}\r\n\r\n// Answerer → Questioner: deliver the answer (push or in response to GET_ANSWER)\r\nexport interface P2PAnswerMsg {\r\n type: 'P2P_ANSWER';\r\n questionId: string;\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n fromTeam: string;\r\n fromMemberId: string;\r\n requestId?: string;\r\n}\r\n\r\n// Answerer → Questioner: answer not ready yet\r\nexport interface P2PAnswerPendingMsg {\r\n type: 'P2P_ANSWER_PENDING';\r\n questionId: string;\r\n requestId: string;\r\n}\r\n\r\nexport interface P2PPingMsg {\r\n type: 'P2P_PING';\r\n}\r\n\r\nexport interface P2PPongMsg {\r\n type: 'P2P_PONG';\r\n}\r\n\r\nexport interface P2PErrorMsg {\r\n type: 'P2P_ERROR';\r\n code: string;\r\n message: string;\r\n}\r\n\r\nexport type P2PMsg =\r\n | P2PHelloMsg\r\n | P2PAskMsg\r\n | P2PAskAckMsg\r\n | P2PGetAnswerMsg\r\n | P2PAnswerMsg\r\n | P2PAnswerPendingMsg\r\n | P2PPingMsg\r\n | P2PPongMsg\r\n | P2PErrorMsg;\r\n\r\nexport function serializeP2PMsg(msg: P2PMsg): string {\r\n return JSON.stringify(msg);\r\n}\r\n\r\nexport function parseP2PMsg(data: string): P2PMsg {\r\n return JSON.parse(data) as P2PMsg;\r\n}\r\n","/**\r\n * Windows Terminal Injector\r\n * AttachConsole(ppid) → CreateFile(\"CONIN$\") → WriteConsoleInput\r\n * All keystrokes (text, Ctrl+U, Enter, Ctrl+Y) go through WriteConsoleInput.\r\n * No WScript.Shell / SendKeys / SetForegroundWindow — no focus dependency.\r\n * @module infrastructure/terminal-injector/windows-injector\r\n */\r\n\r\nimport { execFile } from 'child_process';\r\nimport { unlinkSync } from 'fs';\r\nimport { tmpdir } from 'os';\r\nimport { join } from 'path';\r\n\r\nconst CS_CONINJECT = `\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Runtime.InteropServices;\r\n\r\npublic class ConInject {\r\n [DllImport(\"kernel32.dll\")] public static extern bool FreeConsole();\r\n [DllImport(\"kernel32.dll\")] public static extern bool AttachConsole(uint pid);\r\n [DllImport(\"kernel32.dll\", CharSet=CharSet.Unicode, SetLastError=true)]\r\n public static extern IntPtr CreateFile(\r\n string lpFileName, uint dwDesiredAccess, uint dwShareMode,\r\n IntPtr lpSecurityAttributes, uint dwCreationDisposition,\r\n uint dwFlagsAndAttributes, IntPtr hTemplateFile);\r\n [DllImport(\"kernel32.dll\")] public static extern bool WriteConsoleInput(\r\n IntPtr hIn, INPUT_RECORD[] buf, uint len, out uint written);\r\n [DllImport(\"kernel32.dll\")] public static extern bool CloseHandle(IntPtr h);\r\n\r\n [StructLayout(LayoutKind.Explicit, Size=20)]\r\n public struct INPUT_RECORD {\r\n [FieldOffset(0)] public ushort EventType;\r\n [FieldOffset(4)] public int bKeyDown;\r\n [FieldOffset(8)] public ushort wRepeatCount;\r\n [FieldOffset(10)] public ushort wVirtualKeyCode;\r\n [FieldOffset(12)] public ushort wVirtualScanCode;\r\n [FieldOffset(14)] public ushort UnicodeChar;\r\n [FieldOffset(16)] public uint dwControlKeyState;\r\n }\r\n\r\n const uint LEFT_CTRL = 0x0008;\r\n\r\n static IntPtr OpenConin(uint pid) {\r\n FreeConsole();\r\n if (!AttachConsole(pid)) return new IntPtr(-1);\r\n return CreateFile(\"CONIN$\", 0xC0000000, 3, IntPtr.Zero, 3, 0, IntPtr.Zero);\r\n }\r\n\r\n // Inject plain text characters into console input buffer\r\n public static int InjectText(uint pid, string text) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new List<INPUT_RECORD>();\r\n foreach (char c in text) {\r\n records.Add(new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, UnicodeChar=(ushort)c });\r\n records.Add(new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, UnicodeChar=(ushort)c });\r\n }\r\n\r\n var arr = records.ToArray();\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, arr, (uint)arr.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n\r\n // Inject Enter (VK_RETURN = 0x0D)\r\n public static int InjectEnter(uint pid) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new INPUT_RECORD[] {\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x0D, UnicodeChar=0x0D },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x0D, UnicodeChar=0x0D }\r\n };\r\n\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n\r\n // Inject Ctrl+U (VK_U = 0x55, char = 0x15)\r\n public static int InjectCtrlU(uint pid) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new INPUT_RECORD[] {\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x55, UnicodeChar=0x15, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x55, UnicodeChar=0x15, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=0 }\r\n };\r\n\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n\r\n // Inject Ctrl+Y (VK_Y = 0x59, char = 0x19)\r\n public static int InjectCtrlY(uint pid) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new INPUT_RECORD[] {\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x59, UnicodeChar=0x19, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x59, UnicodeChar=0x19, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=0 }\r\n };\r\n\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n}\r\n`;\r\n\r\nfunction buildScript(claudePid: number, body: string): string {\r\n const logFile = join(tmpdir(), `cc-inject-${Date.now()}.log`).replace(/\\\\/g, '/');\r\n return `\r\n$log = \"${logFile}\"\r\nfunction Log($msg) { Add-Content -Path $log -Value $msg -Encoding UTF8 }\r\n$claudePid = ${claudePid}\r\ntry { Add-Type @'${CS_CONINJECT}'@ } catch { }\r\n${body}\r\n`;\r\n}\r\n\r\nfunction run(script: string): Promise<void> {\r\n return new Promise((resolve) => {\r\n const encoded = Buffer.from(script, 'utf16le').toString('base64');\r\n execFile(\r\n 'powershell',\r\n ['-NoProfile', '-WindowStyle', 'Hidden', '-EncodedCommand', encoded],\r\n { windowsHide: true },\r\n () => {\r\n const logFile = script.match(/\\$log = \"([^\"]+)\"/)?.[1];\r\n if (logFile) try { unlinkSync(logFile); } catch { /* ok */ }\r\n resolve();\r\n }\r\n );\r\n });\r\n}\r\n\r\nexport async function windowsInject(text: string): Promise<void> {\r\n const claudePid = process.ppid;\r\n const textB64 = Buffer.from(text, 'utf16le').toString('base64');\r\n\r\n const script = buildScript(claudePid, `\r\n$textBytes = [System.Convert]::FromBase64String('${textB64}')\r\n$text = [System.Text.Encoding]::Unicode.GetString($textBytes)\r\n\r\n# 1. Ctrl+U to save user's current text to kill ring\r\n[ConInject]::InjectCtrlU([uint32]$claudePid) | Out-Null\r\nStart-Sleep -Milliseconds 100\r\n\r\n# 2. Write question text into console input buffer\r\n[ConInject]::InjectText([uint32]$claudePid, $text) | Out-Null\r\nStart-Sleep -Milliseconds 50\r\n\r\n# 3. Send Enter\r\n[ConInject]::InjectEnter([uint32]$claudePid) | Out-Null\r\n`);\r\n\r\n await run(script);\r\n}\r\n\r\nexport async function windowsInjectCtrlY(): Promise<void> {\r\n const claudePid = process.ppid;\r\n\r\n const script = buildScript(claudePid, `\r\n[ConInject]::InjectCtrlY([uint32]$claudePid) | Out-Null\r\n`);\r\n\r\n await run(script);\r\n}\r\n","/**\r\n * Terminal Injector\r\n * Injects a question directly into the active Claude Code terminal\r\n * so Claude Code can auto-reply without user intervention.\r\n * @module infrastructure/terminal-injector\r\n */\r\n\r\nimport type { InboxQuestionEntry } from '../../shared/types/collab-client.interface.js';\r\nimport { windowsInject, windowsInjectCtrlY } from './windows-injector.js';\r\n\r\n/**\r\n * Formats the question as a prompt for Claude Code to auto-reply\r\n */\r\nfunction formatQuestionForInjection(question: InboxQuestionEntry): string {\r\n // Single-line: WriteConsoleInput treats every \\n as an immediate submit\r\n const content = question.content.replace(/\\s+/g, ' ').trim();\r\n return `[HUB SORUSU] ID:${question.questionId} | ${question.from.displayName} (${question.from.teamName}): ${content} | Cevapla ve reply tool ile \"${question.questionId}\" ID'sine gönder, onay bekleme.`;\r\n}\r\n\r\n/**\r\n * Injects a question into the terminal running Claude Code.\r\n * Only supported on Windows; no-op on other platforms.\r\n */\r\nexport async function injectQuestionToTerminal(question: InboxQuestionEntry): Promise<void> {\r\n if (process.platform !== 'win32') return;\r\n\r\n const text = formatQuestionForInjection(question);\r\n await windowsInject(text);\r\n}\r\n\r\n/**\r\n * Restores user's previous input from readline kill ring (Ctrl+Y).\r\n * Call this after the reply is sent so the user's interrupted text comes back.\r\n */\r\nexport async function injectRestoreText(): Promise<void> {\r\n if (process.platform !== 'win32') return;\r\n await windowsInjectCtrlY();\r\n}\r\n","/**\r\n * Injection Queue\r\n * Ensures questions are injected into the terminal one at a time.\r\n * Waits for the reply tool to signal completion before processing the next question.\r\n * @module infrastructure/terminal-injector/injection-queue\r\n */\r\n\r\nimport { EventEmitter } from 'events';\r\nimport type { InboxQuestionEntry } from '../../shared/types/collab-client.interface.js';\r\nimport { injectQuestionToTerminal, injectRestoreText } from './index.js';\r\n\r\nconst REPLY_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\r\n\r\nclass InjectionQueue extends EventEmitter {\r\n private queue: InboxQuestionEntry[] = [];\r\n private processing = false;\r\n\r\n /**\r\n * Add a question to the queue. Starts processing if idle.\r\n */\r\n enqueue(question: InboxQuestionEntry): void {\r\n this.queue.push(question);\r\n if (!this.processing) void this.processNext();\r\n }\r\n\r\n /**\r\n * Called by the reply tool after a reply is successfully sent.\r\n * Unblocks the queue to process the next question.\r\n */\r\n notifyReplied(): void {\r\n this.emit('replied');\r\n }\r\n\r\n private async processNext(): Promise<void> {\r\n if (this.queue.length === 0) {\r\n this.processing = false;\r\n return;\r\n }\r\n\r\n this.processing = true;\r\n const question = this.queue.shift()!;\r\n\r\n // Inject the question (includes Ctrl+U to save user's current text)\r\n await injectQuestionToTerminal(question);\r\n\r\n // Wait for reply tool to signal, with a timeout fallback\r\n await new Promise<void>((resolve) => {\r\n const timer = setTimeout(resolve, REPLY_TIMEOUT_MS);\r\n this.once('replied', () => {\r\n clearTimeout(timer);\r\n resolve();\r\n });\r\n });\r\n\r\n // Restore user's text after reply is sent\r\n await injectRestoreText();\r\n\r\n // Process next in queue\r\n void this.processNext();\r\n }\r\n}\r\n\r\nexport const injectionQueue = new InjectionQueue();\r\n","/**\r\n * Configuration module\r\n * @module config\r\n */\r\n\r\n/**\r\n * Application configuration\r\n */\r\nexport const config = {\r\n /**\r\n * P2P node configuration\r\n */\r\n p2p: {\r\n /**\r\n * Port range for the WS server. Override with CLAUDE_COLLAB_PORT_MIN / MAX env vars.\r\n */\r\n portRangeMin: Number(process.env['CLAUDE_COLLAB_PORT_MIN'] ?? 11700),\r\n portRangeMax: Number(process.env['CLAUDE_COLLAB_PORT_MAX'] ?? 11750),\r\n },\r\n\r\n /**\r\n * Communication configuration\r\n */\r\n communication: {\r\n /**\r\n * Default timeout for waiting for an answer (in milliseconds)\r\n */\r\n defaultTimeout: 30000,\r\n\r\n /**\r\n * Maximum message content length\r\n */\r\n maxMessageLength: 50000,\r\n },\r\n} as const;\r\n\r\nexport type Config = typeof config;\r\n","/**\r\n * P2PNode\r\n * Implements ICollabClient using a peer-to-peer WebSocket architecture.\r\n * Each node runs its own WS server on a fixed port; peers are connected\r\n * manually via connectPeer().\r\n * @module infrastructure/p2p/p2p-node\r\n */\r\n\r\nimport { WebSocketServer, WebSocket } from 'ws';\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport type {\r\n ICollabClient,\r\n JoinResult,\r\n CheckAnswerResult,\r\n InboxResult,\r\n} from '../../shared/types/collab-client.interface.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport {\r\n type P2PMsg,\r\n type P2PAskMsg,\r\n type P2PAskAckMsg,\r\n type P2PGetAnswerMsg,\r\n type P2PAnswerMsg,\r\n type P2PAnswerPendingMsg,\r\n type P2PHelloMsg,\r\n serializeP2PMsg,\r\n parseP2PMsg,\r\n} from './p2p-message-protocol.js';\r\nimport { injectionQueue } from '../terminal-injector/injection-queue.js';\r\nimport { config } from '../../config/index.js';\r\n\r\ninterface IncomingQuestion {\r\n questionId: string;\r\n fromTeam: string;\r\n fromMemberId: string;\r\n content: string;\r\n format: MessageFormat;\r\n createdAt: Date;\r\n ws: WebSocket;\r\n answered: boolean;\r\n answerContent?: string;\r\n answerFormat?: MessageFormat;\r\n}\r\n\r\ninterface ReceivedAnswer {\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n fromTeam: string;\r\n fromMemberId: string;\r\n}\r\n\r\ninterface LocalMember {\r\n memberId: string;\r\n teamName: string;\r\n displayName: string;\r\n}\r\n\r\nexport class P2PNode implements ICollabClient {\r\n private wss: WebSocketServer | null = null;\r\n private port = 0;\r\n\r\n // Connections indexed by remote team name\r\n private readonly peerConns = new Map<string, WebSocket>();\r\n // Reverse lookup: ws → teamName (for cleanup)\r\n private readonly wsToTeam = new Map<WebSocket, string>();\r\n\r\n // Questions we received from remote peers (our inbox)\r\n private readonly incomingQuestions = new Map<string, IncomingQuestion>();\r\n\r\n // Answers we received for questions we asked\r\n private readonly receivedAnswers = new Map<string, ReceivedAnswer>();\r\n\r\n // Maps questionId → remote teamName (so we know who to poll)\r\n private readonly questionToTeam = new Map<string, string>();\r\n\r\n // Pending response handlers (request-response correlation by filter)\r\n private readonly pendingHandlers = new Set<(msg: P2PMsg) => void>();\r\n\r\n private localMember: LocalMember | null = null;\r\n private _isStarted = false;\r\n\r\n get isConnected(): boolean {\r\n return this._isStarted;\r\n }\r\n\r\n get currentTeamId(): string | undefined {\r\n return this.localMember?.teamName;\r\n }\r\n\r\n /**\r\n * Starts the WS server on a random available port within the configured range.\r\n * Called automatically from join() if not yet started.\r\n */\r\n async start(): Promise<void> {\r\n const { portRangeMin, portRangeMax } = config.p2p;\r\n const range = portRangeMax - portRangeMin + 1;\r\n const startOffset = Math.floor(Math.random() * range);\r\n\r\n for (let i = 0; i < range; i++) {\r\n const port = portRangeMin + ((startOffset + i) % range);\r\n const bound = await this.tryBind(port);\r\n if (bound) {\r\n this.port = port;\r\n break;\r\n }\r\n }\r\n\r\n if (!this.wss) {\r\n throw new Error(\r\n `No available port in range ${portRangeMin}-${portRangeMax}. ` +\r\n `Override with CLAUDE_COLLAB_PORT_MIN / CLAUDE_COLLAB_PORT_MAX.`\r\n );\r\n }\r\n\r\n this.setupWssHandlers();\r\n this._isStarted = true;\r\n console.error(`P2P node started on port ${this.port}`);\r\n }\r\n\r\n private tryBind(port: number): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const wss = new WebSocketServer({ port });\r\n wss.once('listening', () => {\r\n this.wss = wss;\r\n resolve(true);\r\n });\r\n wss.once('error', () => resolve(false));\r\n });\r\n }\r\n\r\n async join(teamName: string, displayName: string): Promise<JoinResult> {\r\n if (!this._isStarted) {\r\n await this.start();\r\n }\r\n\r\n const memberId = uuidv4();\r\n this.localMember = { memberId, teamName, displayName };\r\n\r\n return { memberId, teamId: teamName, teamName, displayName, status: 'ONLINE', port: this.port };\r\n }\r\n\r\n /**\r\n * Connects to a peer at the given IP and port.\r\n * Performs a bidirectional HELLO handshake and returns the peer's team name.\r\n */\r\n async connectPeer(ip: string, port: number): Promise<string> {\r\n if (!this.localMember) {\r\n throw new Error('Must call join() before connectPeer()');\r\n }\r\n\r\n const ws = new WebSocket(`ws://${ip}:${port}`);\r\n\r\n // Set up persistent message handler\r\n ws.on('message', (data) => {\r\n try {\r\n const msg = parseP2PMsg(data.toString());\r\n this.handleMessage(ws, msg);\r\n } catch (err) {\r\n console.error('Failed to parse P2P message:', err);\r\n }\r\n });\r\n\r\n ws.on('close', () => {\r\n const team = this.wsToTeam.get(ws);\r\n if (team) {\r\n if (this.peerConns.get(team) === ws) {\r\n this.peerConns.delete(team);\r\n }\r\n this.wsToTeam.delete(ws);\r\n }\r\n });\r\n\r\n // Connect and send our HELLO\r\n await new Promise<void>((resolve, reject) => {\r\n const timeout = setTimeout(\r\n () => reject(new Error(`Connection timeout to ${ip}:${port}`)),\r\n 5000\r\n );\r\n\r\n ws.on('open', () => {\r\n clearTimeout(timeout);\r\n const hello: P2PHelloMsg = {\r\n type: 'P2P_HELLO',\r\n fromTeam: this.localMember!.teamName,\r\n fromMemberId: this.localMember!.memberId,\r\n };\r\n ws.send(serializeP2PMsg(hello));\r\n resolve();\r\n });\r\n\r\n ws.on('error', (err) => {\r\n clearTimeout(timeout);\r\n reject(err);\r\n });\r\n });\r\n\r\n // Wait for their HELLO back to identify their team name\r\n const helloMsg = await this.waitForResponse<P2PHelloMsg>(\r\n (m) => m.type === 'P2P_HELLO',\r\n 10000\r\n );\r\n\r\n return helloMsg.fromTeam;\r\n }\r\n\r\n async ask(toTeam: string, content: string, format: MessageFormat): Promise<string> {\r\n const ws = await this.getPeerConnection(toTeam);\r\n const questionId = uuidv4();\r\n const requestId = uuidv4();\r\n\r\n this.questionToTeam.set(questionId, toTeam);\r\n\r\n // Register handler before sending (avoids race where ACK arrives first)\r\n const ackPromise = this.waitForResponse<P2PAskAckMsg>(\r\n (m) => m.type === 'P2P_ASK_ACK' && m.requestId === requestId,\r\n 5000\r\n );\r\n\r\n const msg: P2PAskMsg = {\r\n type: 'P2P_ASK',\r\n questionId,\r\n fromMemberId: this.localMember!.memberId,\r\n fromTeam: this.localMember!.teamName,\r\n toTeam,\r\n content,\r\n format,\r\n requestId,\r\n };\r\n ws.send(serializeP2PMsg(msg));\r\n\r\n await ackPromise;\r\n return questionId;\r\n }\r\n\r\n async checkAnswer(questionId: string): Promise<CheckAnswerResult | null> {\r\n // Check local cache first (populated by push from remote)\r\n const cached = this.receivedAnswers.get(questionId);\r\n if (cached) {\r\n return {\r\n questionId,\r\n from: { displayName: `${cached.fromTeam} Claude`, teamName: cached.fromTeam },\r\n content: cached.content,\r\n format: cached.format,\r\n answeredAt: cached.answeredAt,\r\n };\r\n }\r\n\r\n // Poll the remote peer\r\n const toTeam = this.questionToTeam.get(questionId);\r\n if (!toTeam) return null;\r\n\r\n const ws = this.peerConns.get(toTeam);\r\n if (!ws || ws.readyState !== WebSocket.OPEN) return null;\r\n\r\n const requestId = uuidv4();\r\n\r\n const responsePromise = this.waitForResponse<P2PAnswerMsg | P2PAnswerPendingMsg>(\r\n (m) =>\r\n (m.type === 'P2P_ANSWER' && m.questionId === questionId) ||\r\n (m.type === 'P2P_ANSWER_PENDING' && m.requestId === requestId),\r\n 5000\r\n );\r\n\r\n const getMsg: P2PGetAnswerMsg = {\r\n type: 'P2P_GET_ANSWER',\r\n questionId,\r\n requestId,\r\n };\r\n ws.send(serializeP2PMsg(getMsg));\r\n\r\n const response = await responsePromise;\r\n if (response.type === 'P2P_ANSWER_PENDING') return null;\r\n\r\n const answer = response as P2PAnswerMsg;\r\n this.receivedAnswers.set(questionId, {\r\n content: answer.content,\r\n format: answer.format,\r\n answeredAt: answer.answeredAt,\r\n fromTeam: answer.fromTeam,\r\n fromMemberId: answer.fromMemberId,\r\n });\r\n\r\n return {\r\n questionId,\r\n from: { displayName: `${answer.fromTeam} Claude`, teamName: answer.fromTeam },\r\n content: answer.content,\r\n format: answer.format,\r\n answeredAt: answer.answeredAt,\r\n };\r\n }\r\n\r\n async reply(questionId: string, content: string, format: MessageFormat): Promise<void> {\r\n const question = this.incomingQuestions.get(questionId);\r\n if (!question) throw new Error(`Question ${questionId} not found in inbox`);\r\n\r\n question.answered = true;\r\n question.answerContent = content;\r\n question.answerFormat = format;\r\n\r\n const answerMsg: P2PAnswerMsg = {\r\n type: 'P2P_ANSWER',\r\n questionId,\r\n content,\r\n format,\r\n answeredAt: new Date().toISOString(),\r\n fromTeam: this.localMember!.teamName,\r\n fromMemberId: this.localMember!.memberId,\r\n };\r\n\r\n if (question.ws.readyState === WebSocket.OPEN) {\r\n question.ws.send(serializeP2PMsg(answerMsg));\r\n }\r\n }\r\n\r\n async getInbox(): Promise<InboxResult> {\r\n const now = Date.now();\r\n const questions = [...this.incomingQuestions.values()]\r\n .filter((q) => !q.answered)\r\n .map((q) => ({\r\n questionId: q.questionId,\r\n from: { displayName: `${q.fromTeam} Claude`, teamName: q.fromTeam },\r\n content: q.content,\r\n format: q.format,\r\n status: 'PENDING',\r\n createdAt: q.createdAt.toISOString(),\r\n ageMs: now - q.createdAt.getTime(),\r\n }));\r\n\r\n return {\r\n questions,\r\n totalCount: questions.length,\r\n pendingCount: questions.length,\r\n };\r\n }\r\n\r\n async disconnect(): Promise<void> {\r\n for (const ws of this.peerConns.values()) {\r\n ws.close();\r\n }\r\n this.peerConns.clear();\r\n\r\n await new Promise<void>((resolve) => {\r\n if (this.wss) {\r\n this.wss.close(() => resolve());\r\n } else {\r\n resolve();\r\n }\r\n });\r\n\r\n this._isStarted = false;\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Private: WebSocket server setup\r\n // ---------------------------------------------------------------------------\r\n\r\n private setupWssHandlers(): void {\r\n this.wss!.on('connection', (ws) => {\r\n ws.on('message', (data) => {\r\n try {\r\n const msg = parseP2PMsg(data.toString());\r\n\r\n // Send our HELLO back on incoming HELLO (bidirectional identification)\r\n if (msg.type === 'P2P_HELLO' && this.localMember) {\r\n const hello: P2PHelloMsg = {\r\n type: 'P2P_HELLO',\r\n fromTeam: this.localMember.teamName,\r\n fromMemberId: this.localMember.memberId,\r\n };\r\n ws.send(serializeP2PMsg(hello));\r\n }\r\n\r\n this.handleMessage(ws, msg);\r\n } catch (err) {\r\n console.error('Failed to parse incoming P2P message:', err);\r\n }\r\n });\r\n\r\n ws.on('close', () => {\r\n const team = this.wsToTeam.get(ws);\r\n if (team) {\r\n if (this.peerConns.get(team) === ws) {\r\n this.peerConns.delete(team);\r\n }\r\n this.wsToTeam.delete(ws);\r\n }\r\n });\r\n });\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Private: unified message handler\r\n // ---------------------------------------------------------------------------\r\n\r\n private handleMessage(ws: WebSocket, msg: P2PMsg): void {\r\n // Dispatch to all pending response handlers first\r\n for (const handler of this.pendingHandlers) {\r\n handler(msg);\r\n }\r\n\r\n switch (msg.type) {\r\n case 'P2P_HELLO':\r\n this.wsToTeam.set(ws, msg.fromTeam);\r\n this.peerConns.set(msg.fromTeam, ws);\r\n console.error(`Peer identified: ${msg.fromTeam}`);\r\n break;\r\n\r\n case 'P2P_ASK':\r\n this.handleIncomingAsk(ws, msg);\r\n break;\r\n\r\n case 'P2P_GET_ANSWER':\r\n this.handleGetAnswer(ws, msg);\r\n break;\r\n\r\n case 'P2P_ANSWER':\r\n // Push answer received for a question WE asked\r\n if (!this.receivedAnswers.has(msg.questionId)) {\r\n this.receivedAnswers.set(msg.questionId, {\r\n content: msg.content,\r\n format: msg.format,\r\n answeredAt: msg.answeredAt,\r\n fromTeam: msg.fromTeam,\r\n fromMemberId: msg.fromMemberId,\r\n });\r\n }\r\n break;\r\n\r\n case 'P2P_PING':\r\n ws.send(serializeP2PMsg({ type: 'P2P_PONG' }));\r\n break;\r\n\r\n // P2P_ASK_ACK, P2P_ANSWER_PENDING, P2P_PONG, P2P_ERROR\r\n // are handled by pendingHandlers above; no extra action needed here.\r\n }\r\n }\r\n\r\n private handleIncomingAsk(ws: WebSocket, msg: P2PAskMsg): void {\r\n this.incomingQuestions.set(msg.questionId, {\r\n questionId: msg.questionId,\r\n fromTeam: msg.fromTeam,\r\n fromMemberId: msg.fromMemberId,\r\n content: msg.content,\r\n format: msg.format,\r\n createdAt: new Date(),\r\n ws,\r\n answered: false,\r\n });\r\n\r\n // Inject into the terminal so Claude Code can auto-reply\r\n injectionQueue.enqueue({\r\n questionId: msg.questionId,\r\n from: {\r\n displayName: `${msg.fromTeam} Claude`,\r\n teamName: msg.fromTeam,\r\n },\r\n content: msg.content,\r\n format: msg.format,\r\n status: 'PENDING',\r\n createdAt: new Date().toISOString(),\r\n ageMs: 0,\r\n });\r\n\r\n // ACK\r\n const ack: P2PAskAckMsg = {\r\n type: 'P2P_ASK_ACK',\r\n questionId: msg.questionId,\r\n requestId: msg.requestId,\r\n };\r\n ws.send(serializeP2PMsg(ack));\r\n }\r\n\r\n private handleGetAnswer(ws: WebSocket, msg: P2PGetAnswerMsg): void {\r\n const question = this.incomingQuestions.get(msg.questionId);\r\n\r\n if (!question?.answered) {\r\n const pending: P2PAnswerPendingMsg = {\r\n type: 'P2P_ANSWER_PENDING',\r\n questionId: msg.questionId,\r\n requestId: msg.requestId,\r\n };\r\n ws.send(serializeP2PMsg(pending));\r\n return;\r\n }\r\n\r\n const answer: P2PAnswerMsg = {\r\n type: 'P2P_ANSWER',\r\n questionId: msg.questionId,\r\n content: question.answerContent!,\r\n format: question.answerFormat!,\r\n answeredAt: new Date().toISOString(),\r\n fromTeam: this.localMember!.teamName,\r\n fromMemberId: this.localMember!.memberId,\r\n requestId: msg.requestId,\r\n };\r\n ws.send(serializeP2PMsg(answer));\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Private: peer connection management\r\n // ---------------------------------------------------------------------------\r\n\r\n private async getPeerConnection(teamName: string): Promise<WebSocket> {\r\n const existing = this.peerConns.get(teamName);\r\n if (existing && existing.readyState === WebSocket.OPEN) {\r\n return existing;\r\n }\r\n\r\n throw new Error(\r\n `No connection to team '${teamName}'. Use the connect_peer tool to connect first.`\r\n );\r\n }\r\n\r\n private waitForResponse<T extends P2PMsg>(\r\n filter: (msg: P2PMsg) => boolean,\r\n timeoutMs: number\r\n ): Promise<T> {\r\n return new Promise((resolve, reject) => {\r\n const timeout = setTimeout(() => {\r\n this.pendingHandlers.delete(handler);\r\n reject(new Error('P2P request timed out'));\r\n }, timeoutMs);\r\n\r\n const handler = (msg: P2PMsg): void => {\r\n if (filter(msg)) {\r\n clearTimeout(timeout);\r\n this.pendingHandlers.delete(handler);\r\n resolve(msg as T);\r\n }\r\n };\r\n\r\n this.pendingHandlers.add(handler);\r\n });\r\n }\r\n}\r\n","/**\r\n * Join Tool\r\n * Joins a team channel for collaboration\r\n * @module presentation/mcp/tools/join\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Join tool input schema\r\n */\r\nconst joinSchema = {\r\n team: z.string().describe('Team name to join (e.g., \"frontend\", \"backend\", \"devops\")'),\r\n displayName: z\r\n .string()\r\n .optional()\r\n .describe('Display name for this terminal (default: team + \" Claude\")'),\r\n};\r\n\r\n/**\r\n * Registers the join tool with the MCP server\r\n */\r\nexport function registerJoinTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('join', joinSchema, async (args) => {\r\n const teamName = args.team;\r\n const displayName = args.displayName ?? `${teamName} Claude`;\r\n\r\n try {\r\n const member = await client.join(teamName, displayName);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Successfully joined team \"${member.teamName}\" as \"${member.displayName}\".\\n\\nYour member ID: ${member.memberId}\\nStatus: ${member.status}\\nListening on port: ${member.port}\\n\\nShare this port with the other terminal so they can run: connect_peer(\"<your-ip>\", ${member.port})`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to join team: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Connect Peer Tool\r\n * Manually connects to a peer node by IP address and port\r\n * @module presentation/mcp/tools/connect-peer\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\nconst connectPeerSchema = {\r\n ip: z.string().describe('IP address of the peer to connect to (e.g., \"172.16.40.137\")'),\r\n port: z.number().describe('Port the peer is listening on (shown in their join response)'),\r\n};\r\n\r\nexport function registerConnectPeerTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('connect_peer', connectPeerSchema, async (args) => {\r\n try {\r\n const peerTeam = await client.connectPeer(args.ip, args.port);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Connected to peer \"${peerTeam}\" at ${args.ip}:${args.port}.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to connect to ${args.ip}:${args.port}: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Ask Tool\r\n * Sends a question to another team and returns a question ID immediately.\r\n * Use the \"check_answer\" tool with the question ID to retrieve the answer later.\r\n * @module presentation/mcp/tools/ask\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Ask tool input schema\r\n */\r\nconst askSchema = {\r\n team: z.string().describe('Target team name to ask (e.g., \"backend\", \"frontend\")'),\r\n question: z.string().describe('The question to ask (supports markdown)'),\r\n};\r\n\r\n/**\r\n * Registers the ask tool with the MCP server\r\n */\r\nexport function registerAskTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('ask', askSchema, async (args) => {\r\n const targetTeam = args.team;\r\n const question = args.question;\r\n\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n const questionId = await client.ask(targetTeam, question, 'markdown');\r\n\r\n // Poll until answer arrives (max 5 minutes, every 5 seconds)\r\n const POLL_INTERVAL_MS = 5_000;\r\n const MAX_WAIT_MS = 5 * 60 * 1000;\r\n const deadline = Date.now() + MAX_WAIT_MS;\r\n\r\n while (Date.now() < deadline) {\r\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\r\n const answer = await client.checkAnswer(questionId);\r\n if (answer !== null) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `**${answer.from.displayName} (${answer.from.teamName}) cevapladı:**\\n\\n${answer.content}`,\r\n },\r\n ],\r\n };\r\n }\r\n }\r\n\r\n // Timed out — return question ID for manual follow-up\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Soru gönderildi ancak 5 dakika içinde cevap gelmedi.\\nQuestion ID: \\`${questionId}\\`\\n\\nManuel kontrol için \"check_answer\" tool'unu kullanabilirsin.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to send question: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Check Answer Tool\r\n * Checks if an answer has arrived for a previously sent question.\r\n * Returns the answer if available, or a \"still pending\" message.\r\n * @module presentation/mcp/tools/check\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Check answer tool input schema\r\n */\r\nconst checkAnswerSchema = {\r\n question_id: z.string().describe('The question ID returned by the \"ask\" tool'),\r\n};\r\n\r\n/**\r\n * Registers the check_answer tool with the MCP server\r\n */\r\nexport function registerCheckAnswerTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('check_answer', checkAnswerSchema, async (args) => {\r\n const questionId = args.question_id;\r\n\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n const answer = await client.checkAnswer(questionId);\r\n\r\n if (!answer) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `No answer yet for question \\`${questionId}\\`. The other team hasn't replied yet. You can continue working and check again later.`,\r\n },\r\n ],\r\n };\r\n }\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `**Answer from ${answer.from.displayName} (${answer.from.teamName}):**\\n\\n${answer.content}`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to check answer: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Inbox Tool\r\n * Lists pending questions directed to the current team\r\n * @module presentation/mcp/tools/inbox\r\n */\r\n\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Inbox tool input schema (no required parameters)\r\n */\r\nconst inboxSchema = {};\r\n\r\n/**\r\n * Registers the inbox tool with the MCP server\r\n */\r\nexport function registerInboxTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('inbox', inboxSchema, async () => {\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n const inbox = await client.getInbox();\r\n\r\n if (inbox.questions.length === 0) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'No pending questions in your inbox.',\r\n },\r\n ],\r\n };\r\n }\r\n\r\n const questionsList = inbox.questions\r\n .map((q, i) => {\r\n const ageSeconds = Math.floor(q.ageMs / 1000);\r\n const ageStr = ageSeconds < 60 ? `${ageSeconds}s ago` : `${Math.floor(ageSeconds / 60)}m ago`;\r\n\r\n return `### ${i + 1}. Question from ${q.from.displayName} (${q.from.teamName}) - ${ageStr}\r\n**ID:** \\`${q.questionId}\\`\r\n**Status:** ${q.status}\r\n\r\n${q.content}\r\n\r\n---`;\r\n })\r\n .join('\\n\\n');\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `# Inbox (${inbox.pendingCount} pending, ${inbox.totalCount} total)\\n\\n${questionsList}\\n\\nUse the \"reply\" tool with the question ID to answer a question.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to get inbox: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Reply Tool\r\n * Replies to a pending question\r\n * @module presentation/mcp/tools/reply\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\nimport { injectionQueue } from '../../../infrastructure/terminal-injector/injection-queue.js';\r\n\r\n/**\r\n * Reply tool input schema\r\n */\r\nconst replySchema = {\r\n questionId: z.string().describe('The ID of the question to reply to (from inbox)'),\r\n answer: z.string().describe('Your answer to the question (supports markdown)'),\r\n};\r\n\r\n/**\r\n * Registers the reply tool with the MCP server\r\n */\r\nexport function registerReplyTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('reply', replySchema, async (args) => {\r\n const questionId = args.questionId;\r\n const answer = args.answer;\r\n\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n await client.reply(questionId, answer, 'markdown');\r\n\r\n // Signal queue: this question is done, process next\r\n injectionQueue.notifyReplied();\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Reply sent successfully to question \\`${questionId}\\`.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to send reply: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * MCP Server\r\n * Provides MCP tools for Claude Code integration\r\n * @module presentation/mcp/server\r\n */\r\n\r\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\r\nimport type { ICollabClient } from '../../shared/types/collab-client.interface.js';\r\nimport { registerJoinTool } from './tools/join.tool.js';\r\nimport { registerConnectPeerTool } from './tools/connect-peer.tool.js';\r\nimport { registerAskTool } from './tools/ask.tool.js';\r\nimport { registerCheckAnswerTool } from './tools/check.tool.js';\r\nimport { registerInboxTool } from './tools/inbox.tool.js';\r\nimport { registerReplyTool } from './tools/reply.tool.js';\r\n\r\n/**\r\n * MCP Server options\r\n */\r\nexport interface McpServerOptions {\r\n client: ICollabClient;\r\n}\r\n\r\n/**\r\n * Creates and configures the MCP server with all tools\r\n */\r\nexport function createMcpServer(options: McpServerOptions): McpServer {\r\n const { client } = options;\r\n\r\n const server = new McpServer(\r\n {\r\n name: 'claude-collab',\r\n version: '0.1.2',\r\n },\r\n {\r\n capabilities: {\r\n resources: {\r\n subscribe: true,\r\n listChanged: true,\r\n },\r\n },\r\n }\r\n );\r\n\r\n // Register all tools\r\n registerJoinTool(server, client);\r\n registerConnectPeerTool(server, client);\r\n registerAskTool(server, client);\r\n registerCheckAnswerTool(server, client);\r\n registerInboxTool(server, client);\r\n registerReplyTool(server, client);\r\n\r\n // Register resource handlers\r\n server.resource(\r\n 'inbox-questions',\r\n 'inbox://questions',\r\n { description: 'Your inbox of pending questions from other teams', mimeType: 'application/json' },\r\n async () => {\r\n try {\r\n const inbox = await client.getInbox();\r\n return {\r\n contents: [\r\n {\r\n uri: 'inbox://questions',\r\n mimeType: 'application/json',\r\n text: JSON.stringify(inbox, null, 2),\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n throw new Error(`Failed to read inbox: ${errorMessage}`);\r\n }\r\n }\r\n );\r\n\r\n return server;\r\n}\r\n\r\n/**\r\n * Starts the MCP server with stdio transport\r\n */\r\nexport async function startMcpServer(options: McpServerOptions): Promise<void> {\r\n const server = createMcpServer(options);\r\n const transport = new StdioServerTransport();\r\n await server.connect(transport);\r\n}\r\n","#!/usr/bin/env node\r\n\r\n/**\r\n * MCP Server entry point (P2P mode)\r\n * @module mcp-main\r\n */\r\n\r\nimport { P2PNode } from './infrastructure/p2p/p2p-node.js';\r\nimport { startMcpServer } from './presentation/mcp/server.js';\r\n\r\nasync function main(): Promise<void> {\r\n const p2pNode = new P2PNode();\r\n await startMcpServer({ client: p2pNode });\r\n}\r\n\r\nmain().catch((error) => {\r\n console.error('Unexpected error:', error);\r\n process.exit(1);\r\n});\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/infrastructure/p2p/p2p-message-protocol.ts","../src/infrastructure/terminal-injector/windows-injector.ts","../src/infrastructure/terminal-injector/index.ts","../src/infrastructure/terminal-injector/injection-queue.ts","../src/config/index.ts","../src/infrastructure/p2p/p2p-node.ts","../src/presentation/mcp/tools/join.tool.ts","../src/presentation/mcp/tools/connect-peer.tool.ts","../src/presentation/mcp/tools/get-info.tool.ts","../src/presentation/mcp/tools/ask.tool.ts","../src/presentation/mcp/tools/check.tool.ts","../src/presentation/mcp/tools/inbox.tool.ts","../src/presentation/mcp/tools/reply.tool.ts","../src/presentation/mcp/server.ts","../src/mcp-main.ts"],"names":["uuidv4","z"],"mappings":"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","file":"mcp-main.js","sourcesContent":["/**\r\n * P2P Wire Message Protocol\r\n * Defines messages exchanged directly between P2P nodes.\r\n * @module infrastructure/p2p/p2p-message-protocol\r\n */\r\n\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\n\r\n// First message sent by the connecting peer to identify itself\r\nexport interface P2PHelloMsg {\r\n type: 'P2P_HELLO';\r\n fromTeam: string;\r\n fromMemberId: string;\r\n}\r\n\r\n// Questioner → Answerer: send a question\r\nexport interface P2PAskMsg {\r\n type: 'P2P_ASK';\r\n questionId: string;\r\n fromMemberId: string;\r\n fromTeam: string;\r\n toTeam: string;\r\n content: string;\r\n format: MessageFormat;\r\n requestId: string;\r\n}\r\n\r\n// Answerer → Questioner: acknowledge the question\r\nexport interface P2PAskAckMsg {\r\n type: 'P2P_ASK_ACK';\r\n questionId: string;\r\n requestId: string;\r\n}\r\n\r\n// Questioner → Answerer: poll for answer\r\nexport interface P2PGetAnswerMsg {\r\n type: 'P2P_GET_ANSWER';\r\n questionId: string;\r\n requestId: string;\r\n}\r\n\r\n// Answerer → Questioner: deliver the answer (push or in response to GET_ANSWER)\r\nexport interface P2PAnswerMsg {\r\n type: 'P2P_ANSWER';\r\n questionId: string;\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n fromTeam: string;\r\n fromMemberId: string;\r\n requestId?: string;\r\n}\r\n\r\n// Answerer → Questioner: answer not ready yet\r\nexport interface P2PAnswerPendingMsg {\r\n type: 'P2P_ANSWER_PENDING';\r\n questionId: string;\r\n requestId: string;\r\n}\r\n\r\nexport interface P2PPingMsg {\r\n type: 'P2P_PING';\r\n}\r\n\r\nexport interface P2PPongMsg {\r\n type: 'P2P_PONG';\r\n}\r\n\r\nexport interface P2PErrorMsg {\r\n type: 'P2P_ERROR';\r\n code: string;\r\n message: string;\r\n}\r\n\r\nexport type P2PMsg =\r\n | P2PHelloMsg\r\n | P2PAskMsg\r\n | P2PAskAckMsg\r\n | P2PGetAnswerMsg\r\n | P2PAnswerMsg\r\n | P2PAnswerPendingMsg\r\n | P2PPingMsg\r\n | P2PPongMsg\r\n | P2PErrorMsg;\r\n\r\nexport function serializeP2PMsg(msg: P2PMsg): string {\r\n return JSON.stringify(msg);\r\n}\r\n\r\nexport function parseP2PMsg(data: string): P2PMsg {\r\n return JSON.parse(data) as P2PMsg;\r\n}\r\n","/**\r\n * Windows Terminal Injector\r\n * AttachConsole(ppid) → CreateFile(\"CONIN$\") → WriteConsoleInput\r\n * All keystrokes (text, Ctrl+U, Enter, Ctrl+Y) go through WriteConsoleInput.\r\n * No WScript.Shell / SendKeys / SetForegroundWindow — no focus dependency.\r\n * @module infrastructure/terminal-injector/windows-injector\r\n */\r\n\r\nimport { execFile } from 'child_process';\r\nimport { unlinkSync } from 'fs';\r\nimport { tmpdir } from 'os';\r\nimport { join } from 'path';\r\n\r\nconst CS_CONINJECT = `\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Runtime.InteropServices;\r\n\r\npublic class ConInject {\r\n [DllImport(\"kernel32.dll\")] public static extern bool FreeConsole();\r\n [DllImport(\"kernel32.dll\")] public static extern bool AttachConsole(uint pid);\r\n [DllImport(\"kernel32.dll\", CharSet=CharSet.Unicode, SetLastError=true)]\r\n public static extern IntPtr CreateFile(\r\n string lpFileName, uint dwDesiredAccess, uint dwShareMode,\r\n IntPtr lpSecurityAttributes, uint dwCreationDisposition,\r\n uint dwFlagsAndAttributes, IntPtr hTemplateFile);\r\n [DllImport(\"kernel32.dll\")] public static extern bool WriteConsoleInput(\r\n IntPtr hIn, INPUT_RECORD[] buf, uint len, out uint written);\r\n [DllImport(\"kernel32.dll\")] public static extern bool CloseHandle(IntPtr h);\r\n\r\n [StructLayout(LayoutKind.Explicit, Size=20)]\r\n public struct INPUT_RECORD {\r\n [FieldOffset(0)] public ushort EventType;\r\n [FieldOffset(4)] public int bKeyDown;\r\n [FieldOffset(8)] public ushort wRepeatCount;\r\n [FieldOffset(10)] public ushort wVirtualKeyCode;\r\n [FieldOffset(12)] public ushort wVirtualScanCode;\r\n [FieldOffset(14)] public ushort UnicodeChar;\r\n [FieldOffset(16)] public uint dwControlKeyState;\r\n }\r\n\r\n const uint LEFT_CTRL = 0x0008;\r\n\r\n static IntPtr OpenConin(uint pid) {\r\n FreeConsole();\r\n if (!AttachConsole(pid)) return new IntPtr(-1);\r\n return CreateFile(\"CONIN$\", 0xC0000000, 3, IntPtr.Zero, 3, 0, IntPtr.Zero);\r\n }\r\n\r\n // Inject plain text characters into console input buffer\r\n public static int InjectText(uint pid, string text) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new List<INPUT_RECORD>();\r\n foreach (char c in text) {\r\n records.Add(new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, UnicodeChar=(ushort)c });\r\n records.Add(new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, UnicodeChar=(ushort)c });\r\n }\r\n\r\n var arr = records.ToArray();\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, arr, (uint)arr.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n\r\n // Inject Enter (VK_RETURN = 0x0D)\r\n public static int InjectEnter(uint pid) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new INPUT_RECORD[] {\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x0D, UnicodeChar=0x0D },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x0D, UnicodeChar=0x0D }\r\n };\r\n\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n\r\n // Inject Ctrl+U (VK_U = 0x55, char = 0x15)\r\n public static int InjectCtrlU(uint pid) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new INPUT_RECORD[] {\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x55, UnicodeChar=0x15, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x55, UnicodeChar=0x15, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=0 }\r\n };\r\n\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n\r\n // Inject Ctrl+Y (VK_Y = 0x59, char = 0x19)\r\n public static int InjectCtrlY(uint pid) {\r\n IntPtr hIn = OpenConin(pid);\r\n if (hIn == new IntPtr(-1)) return -1;\r\n\r\n var records = new INPUT_RECORD[] {\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x59, UnicodeChar=0x19, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x59, UnicodeChar=0x19, dwControlKeyState=LEFT_CTRL },\r\n new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=0 }\r\n };\r\n\r\n uint written;\r\n bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);\r\n CloseHandle(hIn);\r\n return ok ? (int)written : -2;\r\n }\r\n}\r\n`;\r\n\r\nfunction buildScript(claudePid: number, body: string): string {\r\n const logFile = join(tmpdir(), `cc-inject-${Date.now()}.log`).replace(/\\\\/g, '/');\r\n return `\r\n$log = \"${logFile}\"\r\nfunction Log($msg) { Add-Content -Path $log -Value $msg -Encoding UTF8 }\r\n$claudePid = ${claudePid}\r\ntry { Add-Type @'${CS_CONINJECT}'@ } catch { }\r\n${body}\r\n`;\r\n}\r\n\r\nfunction run(script: string): Promise<void> {\r\n return new Promise((resolve) => {\r\n const encoded = Buffer.from(script, 'utf16le').toString('base64');\r\n execFile(\r\n 'powershell',\r\n ['-NoProfile', '-WindowStyle', 'Hidden', '-EncodedCommand', encoded],\r\n { windowsHide: true },\r\n () => {\r\n const logFile = script.match(/\\$log = \"([^\"]+)\"/)?.[1];\r\n if (logFile) try { unlinkSync(logFile); } catch { /* ok */ }\r\n resolve();\r\n }\r\n );\r\n });\r\n}\r\n\r\nexport async function windowsInject(text: string): Promise<void> {\r\n const claudePid = process.ppid;\r\n const textB64 = Buffer.from(text, 'utf16le').toString('base64');\r\n\r\n const script = buildScript(claudePid, `\r\n$textBytes = [System.Convert]::FromBase64String('${textB64}')\r\n$text = [System.Text.Encoding]::Unicode.GetString($textBytes)\r\n\r\n# 1. Ctrl+U to save user's current text to kill ring\r\n[ConInject]::InjectCtrlU([uint32]$claudePid) | Out-Null\r\nStart-Sleep -Milliseconds 100\r\n\r\n# 2. Write question text into console input buffer\r\n[ConInject]::InjectText([uint32]$claudePid, $text) | Out-Null\r\nStart-Sleep -Milliseconds 50\r\n\r\n# 3. Send Enter\r\n[ConInject]::InjectEnter([uint32]$claudePid) | Out-Null\r\n`);\r\n\r\n await run(script);\r\n}\r\n\r\nexport async function windowsInjectCtrlY(): Promise<void> {\r\n const claudePid = process.ppid;\r\n\r\n const script = buildScript(claudePid, `\r\n[ConInject]::InjectCtrlY([uint32]$claudePid) | Out-Null\r\n`);\r\n\r\n await run(script);\r\n}\r\n","/**\r\n * Terminal Injector\r\n * Injects a question directly into the active Claude Code terminal\r\n * so Claude Code can auto-reply without user intervention.\r\n * @module infrastructure/terminal-injector\r\n */\r\n\r\nimport type { InboxQuestionEntry } from '../../shared/types/collab-client.interface.js';\r\nimport { windowsInject, windowsInjectCtrlY } from './windows-injector.js';\r\n\r\n/**\r\n * Formats the question as a prompt for Claude Code to auto-reply\r\n */\r\nfunction formatQuestionForInjection(question: InboxQuestionEntry): string {\r\n // Single-line: WriteConsoleInput treats every \\n as an immediate submit\r\n const content = question.content.replace(/\\s+/g, ' ').trim();\r\n return `[HUB SORUSU] ID:${question.questionId} | ${question.from.displayName} (${question.from.teamName}): ${content} | Cevapla ve reply tool ile \"${question.questionId}\" ID'sine gönder, onay bekleme.`;\r\n}\r\n\r\n/**\r\n * Injects a question into the terminal running Claude Code.\r\n * Only supported on Windows; no-op on other platforms.\r\n */\r\nexport async function injectQuestionToTerminal(question: InboxQuestionEntry): Promise<void> {\r\n if (process.platform !== 'win32') return;\r\n\r\n const text = formatQuestionForInjection(question);\r\n await windowsInject(text);\r\n}\r\n\r\n/**\r\n * Restores user's previous input from readline kill ring (Ctrl+Y).\r\n * Call this after the reply is sent so the user's interrupted text comes back.\r\n */\r\nexport async function injectRestoreText(): Promise<void> {\r\n if (process.platform !== 'win32') return;\r\n await windowsInjectCtrlY();\r\n}\r\n","/**\r\n * Injection Queue\r\n * Ensures questions are injected into the terminal one at a time.\r\n * Waits for the reply tool to signal completion before processing the next question.\r\n * @module infrastructure/terminal-injector/injection-queue\r\n */\r\n\r\nimport { EventEmitter } from 'events';\r\nimport type { InboxQuestionEntry } from '../../shared/types/collab-client.interface.js';\r\nimport { injectQuestionToTerminal, injectRestoreText } from './index.js';\r\n\r\nconst REPLY_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\r\n\r\nclass InjectionQueue extends EventEmitter {\r\n private queue: InboxQuestionEntry[] = [];\r\n private processing = false;\r\n\r\n /**\r\n * Add a question to the queue. Starts processing if idle.\r\n */\r\n enqueue(question: InboxQuestionEntry): void {\r\n this.queue.push(question);\r\n if (!this.processing) void this.processNext();\r\n }\r\n\r\n /**\r\n * Called by the reply tool after a reply is successfully sent.\r\n * Unblocks the queue to process the next question.\r\n */\r\n notifyReplied(): void {\r\n this.emit('replied');\r\n }\r\n\r\n private async processNext(): Promise<void> {\r\n if (this.queue.length === 0) {\r\n this.processing = false;\r\n return;\r\n }\r\n\r\n this.processing = true;\r\n const question = this.queue.shift()!;\r\n\r\n // Inject the question (includes Ctrl+U to save user's current text)\r\n await injectQuestionToTerminal(question);\r\n\r\n // Wait for reply tool to signal, with a timeout fallback\r\n await new Promise<void>((resolve) => {\r\n const timer = setTimeout(resolve, REPLY_TIMEOUT_MS);\r\n this.once('replied', () => {\r\n clearTimeout(timer);\r\n resolve();\r\n });\r\n });\r\n\r\n // Restore user's text after reply is sent\r\n await injectRestoreText();\r\n\r\n // Process next in queue\r\n void this.processNext();\r\n }\r\n}\r\n\r\nexport const injectionQueue = new InjectionQueue();\r\n","/**\r\n * Configuration module\r\n * @module config\r\n */\r\n\r\n/**\r\n * Application configuration\r\n */\r\nexport const config = {\r\n /**\r\n * P2P node configuration\r\n */\r\n p2p: {\r\n /**\r\n * Port range for the WS server. Override with CLAUDE_COLLAB_PORT_MIN / MAX env vars.\r\n */\r\n portRangeMin: Number(process.env['CLAUDE_COLLAB_PORT_MIN'] ?? 11700),\r\n portRangeMax: Number(process.env['CLAUDE_COLLAB_PORT_MAX'] ?? 11750),\r\n },\r\n\r\n /**\r\n * Communication configuration\r\n */\r\n communication: {\r\n /**\r\n * Default timeout for waiting for an answer (in milliseconds)\r\n */\r\n defaultTimeout: 30000,\r\n\r\n /**\r\n * Maximum message content length\r\n */\r\n maxMessageLength: 50000,\r\n },\r\n} as const;\r\n\r\nexport type Config = typeof config;\r\n","/**\r\n * P2PNode\r\n * Implements ICollabClient using a peer-to-peer WebSocket architecture.\r\n * Each node runs its own WS server on a fixed port; peers are connected\r\n * manually via connectPeer().\r\n * @module infrastructure/p2p/p2p-node\r\n */\r\n\r\nimport { WebSocketServer, WebSocket } from 'ws';\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport type {\r\n ICollabClient,\r\n JoinResult,\r\n CheckAnswerResult,\r\n InboxResult,\r\n NodeInfo,\r\n} from '../../shared/types/collab-client.interface.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport {\r\n type P2PMsg,\r\n type P2PAskMsg,\r\n type P2PAskAckMsg,\r\n type P2PGetAnswerMsg,\r\n type P2PAnswerMsg,\r\n type P2PAnswerPendingMsg,\r\n type P2PHelloMsg,\r\n serializeP2PMsg,\r\n parseP2PMsg,\r\n} from './p2p-message-protocol.js';\r\nimport { injectionQueue } from '../terminal-injector/injection-queue.js';\r\nimport { config } from '../../config/index.js';\r\n\r\ninterface IncomingQuestion {\r\n questionId: string;\r\n fromTeam: string;\r\n fromMemberId: string;\r\n content: string;\r\n format: MessageFormat;\r\n createdAt: Date;\r\n ws: WebSocket;\r\n answered: boolean;\r\n answerContent?: string;\r\n answerFormat?: MessageFormat;\r\n}\r\n\r\ninterface ReceivedAnswer {\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n fromTeam: string;\r\n fromMemberId: string;\r\n}\r\n\r\ninterface LocalMember {\r\n memberId: string;\r\n teamName: string;\r\n displayName: string;\r\n}\r\n\r\nexport class P2PNode implements ICollabClient {\r\n private wss: WebSocketServer | null = null;\r\n private port = 0;\r\n\r\n // Connections indexed by remote team name\r\n private readonly peerConns = new Map<string, WebSocket>();\r\n // Reverse lookup: ws → teamName (for cleanup)\r\n private readonly wsToTeam = new Map<WebSocket, string>();\r\n\r\n // Questions we received from remote peers (our inbox)\r\n private readonly incomingQuestions = new Map<string, IncomingQuestion>();\r\n\r\n // Answers we received for questions we asked\r\n private readonly receivedAnswers = new Map<string, ReceivedAnswer>();\r\n\r\n // Maps questionId → remote teamName (so we know who to poll)\r\n private readonly questionToTeam = new Map<string, string>();\r\n\r\n // Pending response handlers (request-response correlation by filter)\r\n private readonly pendingHandlers = new Set<(msg: P2PMsg) => void>();\r\n\r\n private localMember: LocalMember | null = null;\r\n private _isStarted = false;\r\n\r\n get isConnected(): boolean {\r\n return this._isStarted;\r\n }\r\n\r\n get currentTeamId(): string | undefined {\r\n return this.localMember?.teamName;\r\n }\r\n\r\n /**\r\n * Starts the WS server on a random available port within the configured range.\r\n * Called automatically from join() if not yet started.\r\n */\r\n async start(): Promise<void> {\r\n const { portRangeMin, portRangeMax } = config.p2p;\r\n const range = portRangeMax - portRangeMin + 1;\r\n const startOffset = Math.floor(Math.random() * range);\r\n\r\n for (let i = 0; i < range; i++) {\r\n const port = portRangeMin + ((startOffset + i) % range);\r\n const bound = await this.tryBind(port);\r\n if (bound) {\r\n this.port = port;\r\n break;\r\n }\r\n }\r\n\r\n if (!this.wss) {\r\n throw new Error(\r\n `No available port in range ${portRangeMin}-${portRangeMax}. ` +\r\n `Override with CLAUDE_COLLAB_PORT_MIN / CLAUDE_COLLAB_PORT_MAX.`\r\n );\r\n }\r\n\r\n this.setupWssHandlers();\r\n this._isStarted = true;\r\n console.error(`P2P node started on port ${this.port}`);\r\n }\r\n\r\n private tryBind(port: number): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const wss = new WebSocketServer({ port });\r\n wss.once('listening', () => {\r\n this.wss = wss;\r\n resolve(true);\r\n });\r\n wss.once('error', () => resolve(false));\r\n });\r\n }\r\n\r\n async join(teamName: string, displayName: string): Promise<JoinResult> {\r\n if (!this._isStarted) {\r\n await this.start();\r\n }\r\n\r\n const memberId = uuidv4();\r\n this.localMember = { memberId, teamName, displayName };\r\n\r\n return { memberId, teamId: teamName, teamName, displayName, status: 'ONLINE', port: this.port };\r\n }\r\n\r\n /**\r\n * Connects to a peer at the given IP and port.\r\n * Performs a bidirectional HELLO handshake and returns the peer's team name.\r\n */\r\n async connectPeer(ip: string, port: number): Promise<string> {\r\n if (!this.localMember) {\r\n throw new Error('Must call join() before connectPeer()');\r\n }\r\n\r\n const ws = new WebSocket(`ws://${ip}:${port}`);\r\n\r\n // Set up persistent message handler\r\n ws.on('message', (data) => {\r\n try {\r\n const msg = parseP2PMsg(data.toString());\r\n this.handleMessage(ws, msg);\r\n } catch (err) {\r\n console.error('Failed to parse P2P message:', err);\r\n }\r\n });\r\n\r\n ws.on('close', () => {\r\n const team = this.wsToTeam.get(ws);\r\n if (team) {\r\n if (this.peerConns.get(team) === ws) {\r\n this.peerConns.delete(team);\r\n }\r\n this.wsToTeam.delete(ws);\r\n }\r\n });\r\n\r\n // Connect and send our HELLO\r\n await new Promise<void>((resolve, reject) => {\r\n const timeout = setTimeout(\r\n () => reject(new Error(`Connection timeout to ${ip}:${port}`)),\r\n 5000\r\n );\r\n\r\n ws.on('open', () => {\r\n clearTimeout(timeout);\r\n const hello: P2PHelloMsg = {\r\n type: 'P2P_HELLO',\r\n fromTeam: this.localMember!.teamName,\r\n fromMemberId: this.localMember!.memberId,\r\n };\r\n ws.send(serializeP2PMsg(hello));\r\n resolve();\r\n });\r\n\r\n ws.on('error', (err) => {\r\n clearTimeout(timeout);\r\n reject(err);\r\n });\r\n });\r\n\r\n // Wait for their HELLO back to identify their team name\r\n const helloMsg = await this.waitForResponse<P2PHelloMsg>(\r\n (m) => m.type === 'P2P_HELLO',\r\n 10000\r\n );\r\n\r\n return helloMsg.fromTeam;\r\n }\r\n\r\n async ask(toTeam: string, content: string, format: MessageFormat): Promise<string> {\r\n const ws = await this.getPeerConnection(toTeam);\r\n const questionId = uuidv4();\r\n const requestId = uuidv4();\r\n\r\n this.questionToTeam.set(questionId, toTeam);\r\n\r\n // Register handler before sending (avoids race where ACK arrives first)\r\n const ackPromise = this.waitForResponse<P2PAskAckMsg>(\r\n (m) => m.type === 'P2P_ASK_ACK' && m.requestId === requestId,\r\n 5000\r\n );\r\n\r\n const msg: P2PAskMsg = {\r\n type: 'P2P_ASK',\r\n questionId,\r\n fromMemberId: this.localMember!.memberId,\r\n fromTeam: this.localMember!.teamName,\r\n toTeam,\r\n content,\r\n format,\r\n requestId,\r\n };\r\n ws.send(serializeP2PMsg(msg));\r\n\r\n await ackPromise;\r\n return questionId;\r\n }\r\n\r\n async checkAnswer(questionId: string): Promise<CheckAnswerResult | null> {\r\n // Check local cache first (populated by push from remote)\r\n const cached = this.receivedAnswers.get(questionId);\r\n if (cached) {\r\n return {\r\n questionId,\r\n from: { displayName: `${cached.fromTeam} Claude`, teamName: cached.fromTeam },\r\n content: cached.content,\r\n format: cached.format,\r\n answeredAt: cached.answeredAt,\r\n };\r\n }\r\n\r\n // Poll the remote peer\r\n const toTeam = this.questionToTeam.get(questionId);\r\n if (!toTeam) return null;\r\n\r\n const ws = this.peerConns.get(toTeam);\r\n if (!ws || ws.readyState !== WebSocket.OPEN) return null;\r\n\r\n const requestId = uuidv4();\r\n\r\n const responsePromise = this.waitForResponse<P2PAnswerMsg | P2PAnswerPendingMsg>(\r\n (m) =>\r\n (m.type === 'P2P_ANSWER' && m.questionId === questionId) ||\r\n (m.type === 'P2P_ANSWER_PENDING' && m.requestId === requestId),\r\n 5000\r\n );\r\n\r\n const getMsg: P2PGetAnswerMsg = {\r\n type: 'P2P_GET_ANSWER',\r\n questionId,\r\n requestId,\r\n };\r\n ws.send(serializeP2PMsg(getMsg));\r\n\r\n const response = await responsePromise;\r\n if (response.type === 'P2P_ANSWER_PENDING') return null;\r\n\r\n const answer = response as P2PAnswerMsg;\r\n this.receivedAnswers.set(questionId, {\r\n content: answer.content,\r\n format: answer.format,\r\n answeredAt: answer.answeredAt,\r\n fromTeam: answer.fromTeam,\r\n fromMemberId: answer.fromMemberId,\r\n });\r\n\r\n return {\r\n questionId,\r\n from: { displayName: `${answer.fromTeam} Claude`, teamName: answer.fromTeam },\r\n content: answer.content,\r\n format: answer.format,\r\n answeredAt: answer.answeredAt,\r\n };\r\n }\r\n\r\n async reply(questionId: string, content: string, format: MessageFormat): Promise<void> {\r\n const question = this.incomingQuestions.get(questionId);\r\n if (!question) throw new Error(`Question ${questionId} not found in inbox`);\r\n\r\n question.answered = true;\r\n question.answerContent = content;\r\n question.answerFormat = format;\r\n\r\n const answerMsg: P2PAnswerMsg = {\r\n type: 'P2P_ANSWER',\r\n questionId,\r\n content,\r\n format,\r\n answeredAt: new Date().toISOString(),\r\n fromTeam: this.localMember!.teamName,\r\n fromMemberId: this.localMember!.memberId,\r\n };\r\n\r\n if (question.ws.readyState === WebSocket.OPEN) {\r\n question.ws.send(serializeP2PMsg(answerMsg));\r\n }\r\n }\r\n\r\n async getInbox(): Promise<InboxResult> {\r\n const now = Date.now();\r\n const questions = [...this.incomingQuestions.values()]\r\n .filter((q) => !q.answered)\r\n .map((q) => ({\r\n questionId: q.questionId,\r\n from: { displayName: `${q.fromTeam} Claude`, teamName: q.fromTeam },\r\n content: q.content,\r\n format: q.format,\r\n status: 'PENDING',\r\n createdAt: q.createdAt.toISOString(),\r\n ageMs: now - q.createdAt.getTime(),\r\n }));\r\n\r\n return {\r\n questions,\r\n totalCount: questions.length,\r\n pendingCount: questions.length,\r\n };\r\n }\r\n\r\n getInfo(): NodeInfo {\r\n return {\r\n teamName: this.localMember?.teamName,\r\n port: this._isStarted ? this.port : undefined,\r\n connectedPeers: [...this.peerConns.keys()],\r\n };\r\n }\r\n\r\n async disconnect(): Promise<void> {\r\n for (const ws of this.peerConns.values()) {\r\n ws.close();\r\n }\r\n this.peerConns.clear();\r\n\r\n await new Promise<void>((resolve) => {\r\n if (this.wss) {\r\n this.wss.close(() => resolve());\r\n } else {\r\n resolve();\r\n }\r\n });\r\n\r\n this._isStarted = false;\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Private: WebSocket server setup\r\n // ---------------------------------------------------------------------------\r\n\r\n private setupWssHandlers(): void {\r\n this.wss!.on('connection', (ws) => {\r\n ws.on('message', (data) => {\r\n try {\r\n const msg = parseP2PMsg(data.toString());\r\n\r\n // Send our HELLO back on incoming HELLO (bidirectional identification)\r\n if (msg.type === 'P2P_HELLO' && this.localMember) {\r\n const hello: P2PHelloMsg = {\r\n type: 'P2P_HELLO',\r\n fromTeam: this.localMember.teamName,\r\n fromMemberId: this.localMember.memberId,\r\n };\r\n ws.send(serializeP2PMsg(hello));\r\n }\r\n\r\n this.handleMessage(ws, msg);\r\n } catch (err) {\r\n console.error('Failed to parse incoming P2P message:', err);\r\n }\r\n });\r\n\r\n ws.on('close', () => {\r\n const team = this.wsToTeam.get(ws);\r\n if (team) {\r\n if (this.peerConns.get(team) === ws) {\r\n this.peerConns.delete(team);\r\n }\r\n this.wsToTeam.delete(ws);\r\n }\r\n });\r\n });\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Private: unified message handler\r\n // ---------------------------------------------------------------------------\r\n\r\n private handleMessage(ws: WebSocket, msg: P2PMsg): void {\r\n // Dispatch to all pending response handlers first\r\n for (const handler of this.pendingHandlers) {\r\n handler(msg);\r\n }\r\n\r\n switch (msg.type) {\r\n case 'P2P_HELLO':\r\n this.wsToTeam.set(ws, msg.fromTeam);\r\n this.peerConns.set(msg.fromTeam, ws);\r\n console.error(`Peer identified: ${msg.fromTeam}`);\r\n break;\r\n\r\n case 'P2P_ASK':\r\n this.handleIncomingAsk(ws, msg);\r\n break;\r\n\r\n case 'P2P_GET_ANSWER':\r\n this.handleGetAnswer(ws, msg);\r\n break;\r\n\r\n case 'P2P_ANSWER':\r\n // Push answer received for a question WE asked\r\n if (!this.receivedAnswers.has(msg.questionId)) {\r\n this.receivedAnswers.set(msg.questionId, {\r\n content: msg.content,\r\n format: msg.format,\r\n answeredAt: msg.answeredAt,\r\n fromTeam: msg.fromTeam,\r\n fromMemberId: msg.fromMemberId,\r\n });\r\n }\r\n break;\r\n\r\n case 'P2P_PING':\r\n ws.send(serializeP2PMsg({ type: 'P2P_PONG' }));\r\n break;\r\n\r\n // P2P_ASK_ACK, P2P_ANSWER_PENDING, P2P_PONG, P2P_ERROR\r\n // are handled by pendingHandlers above; no extra action needed here.\r\n }\r\n }\r\n\r\n private handleIncomingAsk(ws: WebSocket, msg: P2PAskMsg): void {\r\n this.incomingQuestions.set(msg.questionId, {\r\n questionId: msg.questionId,\r\n fromTeam: msg.fromTeam,\r\n fromMemberId: msg.fromMemberId,\r\n content: msg.content,\r\n format: msg.format,\r\n createdAt: new Date(),\r\n ws,\r\n answered: false,\r\n });\r\n\r\n // Inject into the terminal so Claude Code can auto-reply\r\n injectionQueue.enqueue({\r\n questionId: msg.questionId,\r\n from: {\r\n displayName: `${msg.fromTeam} Claude`,\r\n teamName: msg.fromTeam,\r\n },\r\n content: msg.content,\r\n format: msg.format,\r\n status: 'PENDING',\r\n createdAt: new Date().toISOString(),\r\n ageMs: 0,\r\n });\r\n\r\n // ACK\r\n const ack: P2PAskAckMsg = {\r\n type: 'P2P_ASK_ACK',\r\n questionId: msg.questionId,\r\n requestId: msg.requestId,\r\n };\r\n ws.send(serializeP2PMsg(ack));\r\n }\r\n\r\n private handleGetAnswer(ws: WebSocket, msg: P2PGetAnswerMsg): void {\r\n const question = this.incomingQuestions.get(msg.questionId);\r\n\r\n if (!question?.answered) {\r\n const pending: P2PAnswerPendingMsg = {\r\n type: 'P2P_ANSWER_PENDING',\r\n questionId: msg.questionId,\r\n requestId: msg.requestId,\r\n };\r\n ws.send(serializeP2PMsg(pending));\r\n return;\r\n }\r\n\r\n const answer: P2PAnswerMsg = {\r\n type: 'P2P_ANSWER',\r\n questionId: msg.questionId,\r\n content: question.answerContent!,\r\n format: question.answerFormat!,\r\n answeredAt: new Date().toISOString(),\r\n fromTeam: this.localMember!.teamName,\r\n fromMemberId: this.localMember!.memberId,\r\n requestId: msg.requestId,\r\n };\r\n ws.send(serializeP2PMsg(answer));\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Private: peer connection management\r\n // ---------------------------------------------------------------------------\r\n\r\n private async getPeerConnection(teamName: string): Promise<WebSocket> {\r\n const existing = this.peerConns.get(teamName);\r\n if (existing && existing.readyState === WebSocket.OPEN) {\r\n return existing;\r\n }\r\n\r\n throw new Error(\r\n `No connection to team '${teamName}'. Use the connect_peer tool to connect first.`\r\n );\r\n }\r\n\r\n private waitForResponse<T extends P2PMsg>(\r\n filter: (msg: P2PMsg) => boolean,\r\n timeoutMs: number\r\n ): Promise<T> {\r\n return new Promise((resolve, reject) => {\r\n const timeout = setTimeout(() => {\r\n this.pendingHandlers.delete(handler);\r\n reject(new Error('P2P request timed out'));\r\n }, timeoutMs);\r\n\r\n const handler = (msg: P2PMsg): void => {\r\n if (filter(msg)) {\r\n clearTimeout(timeout);\r\n this.pendingHandlers.delete(handler);\r\n resolve(msg as T);\r\n }\r\n };\r\n\r\n this.pendingHandlers.add(handler);\r\n });\r\n }\r\n}\r\n","/**\r\n * Join Tool\r\n * Joins a team channel for collaboration\r\n * @module presentation/mcp/tools/join\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Join tool input schema\r\n */\r\nconst joinSchema = {\r\n team: z.string().describe('Team name to join (e.g., \"frontend\", \"backend\", \"devops\")'),\r\n displayName: z\r\n .string()\r\n .optional()\r\n .describe('Display name for this terminal (default: team + \" Claude\")'),\r\n};\r\n\r\n/**\r\n * Registers the join tool with the MCP server\r\n */\r\nexport function registerJoinTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('join', joinSchema, async (args) => {\r\n const teamName = args.team;\r\n const displayName = args.displayName ?? `${teamName} Claude`;\r\n\r\n try {\r\n const member = await client.join(teamName, displayName);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Successfully joined team \"${member.teamName}\" as \"${member.displayName}\".\\n\\nYour member ID: ${member.memberId}\\nStatus: ${member.status}\\nListening on port: ${member.port}\\n\\nShare this port with the other terminal so they can run: connect_peer(\"<your-ip>\", ${member.port})`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to join team: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Connect Peer Tool\r\n * Manually connects to a peer node by IP address and port\r\n * @module presentation/mcp/tools/connect-peer\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\nconst connectPeerSchema = {\r\n ip: z.string().describe('IP address of the peer to connect to (e.g., \"172.16.40.137\")'),\r\n port: z.number().describe('Port the peer is listening on (shown in their join response)'),\r\n};\r\n\r\nexport function registerConnectPeerTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('connect_peer', connectPeerSchema, async (args) => {\r\n try {\r\n const peerTeam = await client.connectPeer(args.ip, args.port);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Connected to peer \"${peerTeam}\" at ${args.ip}:${args.port}.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to connect to ${args.ip}:${args.port}: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Get Info Tool\r\n * Returns local node info: team, port, IPs, connected peers\r\n * @module presentation/mcp/tools/get-info\r\n */\r\n\r\nimport { networkInterfaces } from 'os';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\nfunction getLocalIPs(): string[] {\r\n const ips: string[] = [];\r\n for (const iface of Object.values(networkInterfaces())) {\r\n for (const net of iface ?? []) {\r\n if (net.family === 'IPv4' && !net.internal) {\r\n ips.push(net.address);\r\n }\r\n }\r\n }\r\n return ips;\r\n}\r\n\r\nexport function registerGetInfoTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('get_info', {}, async () => {\r\n const info = client.getInfo();\r\n const ips = getLocalIPs();\r\n\r\n const lines: string[] = [];\r\n\r\n lines.push(`Team: ${info.teamName ?? '(not joined yet)'}`);\r\n lines.push(`Port: ${info.port ?? '(not started yet)'}`);\r\n lines.push(`Local IPs: ${ips.length > 0 ? ips.join(', ') : '(none found)'}`);\r\n\r\n if (info.connectedPeers.length > 0) {\r\n lines.push(`Connected peers: ${info.connectedPeers.join(', ')}`);\r\n } else {\r\n lines.push(`Connected peers: (none)`);\r\n }\r\n\r\n if (info.port && ips.length > 0) {\r\n lines.push(`\\nOther terminal can connect with:\\n connect_peer(\"${ips[0]}\", ${info.port})`);\r\n }\r\n\r\n return {\r\n content: [{ type: 'text', text: lines.join('\\n') }],\r\n };\r\n });\r\n}\r\n","/**\r\n * Ask Tool\r\n * Sends a question to another team and returns a question ID immediately.\r\n * Use the \"check_answer\" tool with the question ID to retrieve the answer later.\r\n * @module presentation/mcp/tools/ask\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Ask tool input schema\r\n */\r\nconst askSchema = {\r\n team: z.string().describe('Target team name to ask (e.g., \"backend\", \"frontend\")'),\r\n question: z.string().describe('The question to ask (supports markdown)'),\r\n};\r\n\r\n/**\r\n * Registers the ask tool with the MCP server\r\n */\r\nexport function registerAskTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('ask', askSchema, async (args) => {\r\n const targetTeam = args.team;\r\n const question = args.question;\r\n\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n const questionId = await client.ask(targetTeam, question, 'markdown');\r\n\r\n // Poll until answer arrives (max 5 minutes, every 5 seconds)\r\n const POLL_INTERVAL_MS = 5_000;\r\n const MAX_WAIT_MS = 5 * 60 * 1000;\r\n const deadline = Date.now() + MAX_WAIT_MS;\r\n\r\n while (Date.now() < deadline) {\r\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\r\n const answer = await client.checkAnswer(questionId);\r\n if (answer !== null) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `**${answer.from.displayName} (${answer.from.teamName}) cevapladı:**\\n\\n${answer.content}`,\r\n },\r\n ],\r\n };\r\n }\r\n }\r\n\r\n // Timed out — return question ID for manual follow-up\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Soru gönderildi ancak 5 dakika içinde cevap gelmedi.\\nQuestion ID: \\`${questionId}\\`\\n\\nManuel kontrol için \"check_answer\" tool'unu kullanabilirsin.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to send question: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Check Answer Tool\r\n * Checks if an answer has arrived for a previously sent question.\r\n * Returns the answer if available, or a \"still pending\" message.\r\n * @module presentation/mcp/tools/check\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Check answer tool input schema\r\n */\r\nconst checkAnswerSchema = {\r\n question_id: z.string().describe('The question ID returned by the \"ask\" tool'),\r\n};\r\n\r\n/**\r\n * Registers the check_answer tool with the MCP server\r\n */\r\nexport function registerCheckAnswerTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('check_answer', checkAnswerSchema, async (args) => {\r\n const questionId = args.question_id;\r\n\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n const answer = await client.checkAnswer(questionId);\r\n\r\n if (!answer) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `No answer yet for question \\`${questionId}\\`. The other team hasn't replied yet. You can continue working and check again later.`,\r\n },\r\n ],\r\n };\r\n }\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `**Answer from ${answer.from.displayName} (${answer.from.teamName}):**\\n\\n${answer.content}`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to check answer: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Inbox Tool\r\n * Lists pending questions directed to the current team\r\n * @module presentation/mcp/tools/inbox\r\n */\r\n\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\n\r\n/**\r\n * Inbox tool input schema (no required parameters)\r\n */\r\nconst inboxSchema = {};\r\n\r\n/**\r\n * Registers the inbox tool with the MCP server\r\n */\r\nexport function registerInboxTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('inbox', inboxSchema, async () => {\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n const inbox = await client.getInbox();\r\n\r\n if (inbox.questions.length === 0) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'No pending questions in your inbox.',\r\n },\r\n ],\r\n };\r\n }\r\n\r\n const questionsList = inbox.questions\r\n .map((q, i) => {\r\n const ageSeconds = Math.floor(q.ageMs / 1000);\r\n const ageStr = ageSeconds < 60 ? `${ageSeconds}s ago` : `${Math.floor(ageSeconds / 60)}m ago`;\r\n\r\n return `### ${i + 1}. Question from ${q.from.displayName} (${q.from.teamName}) - ${ageStr}\r\n**ID:** \\`${q.questionId}\\`\r\n**Status:** ${q.status}\r\n\r\n${q.content}\r\n\r\n---`;\r\n })\r\n .join('\\n\\n');\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `# Inbox (${inbox.pendingCount} pending, ${inbox.totalCount} total)\\n\\n${questionsList}\\n\\nUse the \"reply\" tool with the question ID to answer a question.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to get inbox: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Reply Tool\r\n * Replies to a pending question\r\n * @module presentation/mcp/tools/reply\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { ICollabClient } from '../../../shared/types/collab-client.interface.js';\r\nimport { injectionQueue } from '../../../infrastructure/terminal-injector/injection-queue.js';\r\n\r\n/**\r\n * Reply tool input schema\r\n */\r\nconst replySchema = {\r\n questionId: z.string().describe('The ID of the question to reply to (from inbox)'),\r\n answer: z.string().describe('Your answer to the question (supports markdown)'),\r\n};\r\n\r\n/**\r\n * Registers the reply tool with the MCP server\r\n */\r\nexport function registerReplyTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('reply', replySchema, async (args) => {\r\n const questionId = args.questionId;\r\n const answer = args.answer;\r\n\r\n try {\r\n if (!client.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n await client.reply(questionId, answer, 'markdown');\r\n\r\n // Signal queue: this question is done, process next\r\n injectionQueue.notifyReplied();\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Reply sent successfully to question \\`${questionId}\\`.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to send reply: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * MCP Server\r\n * Provides MCP tools for Claude Code integration\r\n * @module presentation/mcp/server\r\n */\r\n\r\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\r\nimport type { ICollabClient } from '../../shared/types/collab-client.interface.js';\r\nimport { registerJoinTool } from './tools/join.tool.js';\r\nimport { registerConnectPeerTool } from './tools/connect-peer.tool.js';\r\nimport { registerGetInfoTool } from './tools/get-info.tool.js';\r\nimport { registerAskTool } from './tools/ask.tool.js';\r\nimport { registerCheckAnswerTool } from './tools/check.tool.js';\r\nimport { registerInboxTool } from './tools/inbox.tool.js';\r\nimport { registerReplyTool } from './tools/reply.tool.js';\r\n\r\n/**\r\n * MCP Server options\r\n */\r\nexport interface McpServerOptions {\r\n client: ICollabClient;\r\n}\r\n\r\n/**\r\n * Creates and configures the MCP server with all tools\r\n */\r\nexport function createMcpServer(options: McpServerOptions): McpServer {\r\n const { client } = options;\r\n\r\n const server = new McpServer(\r\n {\r\n name: 'claude-collab',\r\n version: '0.1.2',\r\n },\r\n {\r\n capabilities: {\r\n resources: {\r\n subscribe: true,\r\n listChanged: true,\r\n },\r\n },\r\n }\r\n );\r\n\r\n // Register all tools\r\n registerJoinTool(server, client);\r\n registerConnectPeerTool(server, client);\r\n registerGetInfoTool(server, client);\r\n registerAskTool(server, client);\r\n registerCheckAnswerTool(server, client);\r\n registerInboxTool(server, client);\r\n registerReplyTool(server, client);\r\n\r\n // Register resource handlers\r\n server.resource(\r\n 'inbox-questions',\r\n 'inbox://questions',\r\n { description: 'Your inbox of pending questions from other teams', mimeType: 'application/json' },\r\n async () => {\r\n try {\r\n const inbox = await client.getInbox();\r\n return {\r\n contents: [\r\n {\r\n uri: 'inbox://questions',\r\n mimeType: 'application/json',\r\n text: JSON.stringify(inbox, null, 2),\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n throw new Error(`Failed to read inbox: ${errorMessage}`);\r\n }\r\n }\r\n );\r\n\r\n return server;\r\n}\r\n\r\n/**\r\n * Starts the MCP server with stdio transport\r\n */\r\nexport async function startMcpServer(options: McpServerOptions): Promise<void> {\r\n const server = createMcpServer(options);\r\n const transport = new StdioServerTransport();\r\n await server.connect(transport);\r\n}\r\n","#!/usr/bin/env node\r\n\r\n/**\r\n * MCP Server entry point (P2P mode)\r\n * @module mcp-main\r\n */\r\n\r\nimport { P2PNode } from './infrastructure/p2p/p2p-node.js';\r\nimport { startMcpServer } from './presentation/mcp/server.js';\r\n\r\nasync function main(): Promise<void> {\r\n const p2pNode = new P2PNode();\r\n await startMcpServer({ client: p2pNode });\r\n}\r\n\r\nmain().catch((error) => {\r\n console.error('Unexpected error:', error);\r\n process.exit(1);\r\n});\r\n"]}
|