@dolusoft/claude-collab 1.4.1 → 1.4.2

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 CHANGED
@@ -26,8 +26,6 @@ using System.Runtime.InteropServices;
26
26
  public class ConInject {
27
27
  [DllImport("kernel32.dll")] public static extern bool FreeConsole();
28
28
  [DllImport("kernel32.dll")] public static extern bool AttachConsole(uint pid);
29
- [DllImport("kernel32.dll")] public static extern IntPtr GetConsoleWindow();
30
- [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hwnd);
31
29
  [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
32
30
  public static extern IntPtr CreateFile(
33
31
  string lpFileName, uint dwDesiredAccess, uint dwShareMode,
@@ -56,7 +54,7 @@ public class ConInject {
56
54
  return CreateFile("CONIN$", 0xC0000000, 3, IntPtr.Zero, 3, 0, IntPtr.Zero);
57
55
  }
58
56
 
59
- // Inject only text characters into console input buffer (no Ctrl keys, no Enter)
57
+ // Inject plain text characters into console input buffer
60
58
  public static int InjectText(uint pid, string text) {
61
59
  IntPtr hIn = OpenConin(pid);
62
60
  if (hIn == new IntPtr(-1)) return -1;
@@ -74,13 +72,56 @@ public class ConInject {
74
72
  return ok ? (int)written : -2;
75
73
  }
76
74
 
77
- // Focus the console window for WScript.Shell.SendKeys
78
- public static IntPtr FocusConsole(uint pid) {
79
- FreeConsole();
80
- if (!AttachConsole(pid)) return IntPtr.Zero;
81
- IntPtr hwnd = GetConsoleWindow();
82
- if (hwnd != IntPtr.Zero) SetForegroundWindow(hwnd);
83
- return hwnd;
75
+ // Inject Enter (VK_RETURN = 0x0D)
76
+ public static int InjectEnter(uint pid) {
77
+ IntPtr hIn = OpenConin(pid);
78
+ if (hIn == new IntPtr(-1)) return -1;
79
+
80
+ var records = new INPUT_RECORD[] {
81
+ new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x0D, UnicodeChar=0x0D },
82
+ new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x0D, UnicodeChar=0x0D }
83
+ };
84
+
85
+ uint written;
86
+ bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);
87
+ CloseHandle(hIn);
88
+ return ok ? (int)written : -2;
89
+ }
90
+
91
+ // Inject Ctrl+U (VK_U = 0x55, char = 0x15)
92
+ public static int InjectCtrlU(uint pid) {
93
+ IntPtr hIn = OpenConin(pid);
94
+ if (hIn == new IntPtr(-1)) return -1;
95
+
96
+ var records = new INPUT_RECORD[] {
97
+ new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=LEFT_CTRL },
98
+ new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x55, UnicodeChar=0x15, dwControlKeyState=LEFT_CTRL },
99
+ new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x55, UnicodeChar=0x15, dwControlKeyState=LEFT_CTRL },
100
+ new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=0 }
101
+ };
102
+
103
+ uint written;
104
+ bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);
105
+ CloseHandle(hIn);
106
+ return ok ? (int)written : -2;
107
+ }
108
+
109
+ // Inject Ctrl+Y (VK_Y = 0x59, char = 0x19)
110
+ public static int InjectCtrlY(uint pid) {
111
+ IntPtr hIn = OpenConin(pid);
112
+ if (hIn == new IntPtr(-1)) return -1;
113
+
114
+ var records = new INPUT_RECORD[] {
115
+ new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=LEFT_CTRL },
116
+ new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x59, UnicodeChar=0x19, dwControlKeyState=LEFT_CTRL },
117
+ new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x59, UnicodeChar=0x19, dwControlKeyState=LEFT_CTRL },
118
+ new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=0 }
119
+ };
120
+
121
+ uint written;
122
+ bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);
123
+ CloseHandle(hIn);
124
+ return ok ? (int)written : -2;
84
125
  }
85
126
  }
86
127
  `;
@@ -118,33 +159,24 @@ async function windowsInject(text) {
118
159
  const script = buildScript(claudePid, `
119
160
  $textBytes = [System.Convert]::FromBase64String('${textB64}')
120
161
  $text = [System.Text.Encoding]::Unicode.GetString($textBytes)
121
- $wsh = New-Object -ComObject WScript.Shell
122
162
 
123
- # 1. Focus console and send Ctrl+U to save user's current text to kill ring
124
- $hwnd = [ConInject]::FocusConsole([uint32]$claudePid)
125
- Start-Sleep -Milliseconds 150
126
- $wsh.SendKeys('^u')
127
- Start-Sleep -Milliseconds 150
163
+ # 1. Ctrl+U to save user's current text to kill ring
164
+ [ConInject]::InjectCtrlU([uint32]$claudePid) | Out-Null
165
+ Start-Sleep -Milliseconds 100
128
166
 
129
167
  # 2. Write question text into console input buffer
130
168
  [ConInject]::InjectText([uint32]$claudePid, $text) | Out-Null
169
+ Start-Sleep -Milliseconds 50
131
170
 
132
- # 3. Re-focus (InjectText calls FreeConsole internally, focus may be lost)
133
- [ConInject]::FocusConsole([uint32]$claudePid) | Out-Null
134
- Start-Sleep -Milliseconds 150
135
-
136
- # 4. Send Enter
137
- $wsh.SendKeys('~')
171
+ # 3. Send Enter
172
+ [ConInject]::InjectEnter([uint32]$claudePid) | Out-Null
138
173
  `);
139
174
  await run(script);
140
175
  }
141
176
  async function windowsInjectCtrlY() {
142
177
  const claudePid = process.ppid;
143
178
  const script = buildScript(claudePid, `
144
- $wsh = New-Object -ComObject WScript.Shell
145
- $hwnd = [ConInject]::FocusConsole([uint32]$claudePid)
146
- Start-Sleep -Milliseconds 150
147
- $wsh.SendKeys('^y')
179
+ [ConInject]::InjectCtrlY([uint32]$claudePid) | Out-Null
148
180
  `);
149
181
  await run(script);
150
182
  }
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 * CONIN$ gives the real console input handle (not the MCP pipe stdin).\r\n * ppid = Claude Code process — the one actively reading from the console.\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\")] public static extern IntPtr GetConsoleWindow();\r\n [DllImport(\"user32.dll\")] public static extern bool SetForegroundWindow(IntPtr hwnd);\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 only text characters into console input buffer (no Ctrl keys, no Enter)\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 // Focus the console window for WScript.Shell.SendKeys\r\n public static IntPtr FocusConsole(uint pid) {\r\n FreeConsole();\r\n if (!AttachConsole(pid)) return IntPtr.Zero;\r\n IntPtr hwnd = GetConsoleWindow();\r\n if (hwnd != IntPtr.Zero) SetForegroundWindow(hwnd);\r\n return hwnd;\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$wsh = New-Object -ComObject WScript.Shell\r\n\r\n# 1. Focus console and send Ctrl+U to save user's current text to kill ring\r\n$hwnd = [ConInject]::FocusConsole([uint32]$claudePid)\r\nStart-Sleep -Milliseconds 150\r\n$wsh.SendKeys('^u')\r\nStart-Sleep -Milliseconds 150\r\n\r\n# 2. Write question text into console input buffer\r\n[ConInject]::InjectText([uint32]$claudePid, $text) | Out-Null\r\n\r\n# 3. Re-focus (InjectText calls FreeConsole internally, focus may be lost)\r\n[ConInject]::FocusConsole([uint32]$claudePid) | Out-Null\r\nStart-Sleep -Milliseconds 150\r\n\r\n# 4. Send Enter\r\n$wsh.SendKeys('~')\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$wsh = New-Object -ComObject WScript.Shell\r\n$hwnd = [ConInject]::FocusConsole([uint32]$claudePid)\r\nStart-Sleep -Milliseconds 150\r\n$wsh.SendKeys('^y')\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 * Fixed port for the WS server. Override with CLAUDE_COLLAB_PORT env var.\r\n */\r\n port: Number(process.env['CLAUDE_COLLAB_PORT'] ?? 11777),\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 the configured fixed port.\r\n * Called automatically from join() if not yet started.\r\n */\r\n async start(): Promise<void> {\r\n this.port = config.p2p.port;\r\n this.wss = new WebSocketServer({ port: this.port });\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 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' };\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 targetPort = port ?? config.p2p.port;\r\n const ws = new WebSocket(`ws://${ip}:${targetPort}`);\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}:${targetPort}`)),\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}\\nTeam ID: ${member.teamId}\\nStatus: ${member.status}`,\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\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\nimport { config } from '../../../config/index.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\r\n .number()\r\n .optional()\r\n .describe(`Port the peer is listening on (default: ${config.p2p.port})`),\r\n};\r\n\r\nexport function registerConnectPeerTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('connect_peer', connectPeerSchema, async (args) => {\r\n const targetPort = args.port ?? config.p2p.port;\r\n\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}:${targetPort}.`,\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}:${targetPort}: ${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\r\n try {\r\n await p2pNode.start();\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n console.error(`Failed to start P2P node: ${errorMessage}`);\r\n process.exit(1);\r\n }\r\n\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/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 * Fixed port for the WS server. Override with CLAUDE_COLLAB_PORT env var.\r\n */\r\n port: Number(process.env['CLAUDE_COLLAB_PORT'] ?? 11777),\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 the configured fixed port.\r\n * Called automatically from join() if not yet started.\r\n */\r\n async start(): Promise<void> {\r\n this.port = config.p2p.port;\r\n this.wss = new WebSocketServer({ port: this.port });\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 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' };\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 targetPort = port ?? config.p2p.port;\r\n const ws = new WebSocket(`ws://${ip}:${targetPort}`);\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}:${targetPort}`)),\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}\\nTeam ID: ${member.teamId}\\nStatus: ${member.status}`,\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\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\nimport { config } from '../../../config/index.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\r\n .number()\r\n .optional()\r\n .describe(`Port the peer is listening on (default: ${config.p2p.port})`),\r\n};\r\n\r\nexport function registerConnectPeerTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('connect_peer', connectPeerSchema, async (args) => {\r\n const targetPort = args.port ?? config.p2p.port;\r\n\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}:${targetPort}.`,\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}:${targetPort}: ${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\r\n try {\r\n await p2pNode.start();\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n console.error(`Failed to start P2P node: ${errorMessage}`);\r\n process.exit(1);\r\n }\r\n\r\n await startMcpServer({ client: p2pNode });\r\n });\r\n\r\nprogram.parse();\r\n"]}
package/dist/mcp-main.js CHANGED
@@ -25,8 +25,6 @@ using System.Runtime.InteropServices;
25
25
  public class ConInject {
26
26
  [DllImport("kernel32.dll")] public static extern bool FreeConsole();
27
27
  [DllImport("kernel32.dll")] public static extern bool AttachConsole(uint pid);
28
- [DllImport("kernel32.dll")] public static extern IntPtr GetConsoleWindow();
29
- [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hwnd);
30
28
  [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
31
29
  public static extern IntPtr CreateFile(
32
30
  string lpFileName, uint dwDesiredAccess, uint dwShareMode,
@@ -55,7 +53,7 @@ public class ConInject {
55
53
  return CreateFile("CONIN$", 0xC0000000, 3, IntPtr.Zero, 3, 0, IntPtr.Zero);
56
54
  }
57
55
 
58
- // Inject only text characters into console input buffer (no Ctrl keys, no Enter)
56
+ // Inject plain text characters into console input buffer
59
57
  public static int InjectText(uint pid, string text) {
60
58
  IntPtr hIn = OpenConin(pid);
61
59
  if (hIn == new IntPtr(-1)) return -1;
@@ -73,13 +71,56 @@ public class ConInject {
73
71
  return ok ? (int)written : -2;
74
72
  }
75
73
 
76
- // Focus the console window for WScript.Shell.SendKeys
77
- public static IntPtr FocusConsole(uint pid) {
78
- FreeConsole();
79
- if (!AttachConsole(pid)) return IntPtr.Zero;
80
- IntPtr hwnd = GetConsoleWindow();
81
- if (hwnd != IntPtr.Zero) SetForegroundWindow(hwnd);
82
- return hwnd;
74
+ // Inject Enter (VK_RETURN = 0x0D)
75
+ public static int InjectEnter(uint pid) {
76
+ IntPtr hIn = OpenConin(pid);
77
+ if (hIn == new IntPtr(-1)) return -1;
78
+
79
+ var records = new INPUT_RECORD[] {
80
+ new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x0D, UnicodeChar=0x0D },
81
+ new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x0D, UnicodeChar=0x0D }
82
+ };
83
+
84
+ uint written;
85
+ bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);
86
+ CloseHandle(hIn);
87
+ return ok ? (int)written : -2;
88
+ }
89
+
90
+ // Inject Ctrl+U (VK_U = 0x55, char = 0x15)
91
+ public static int InjectCtrlU(uint pid) {
92
+ IntPtr hIn = OpenConin(pid);
93
+ if (hIn == new IntPtr(-1)) return -1;
94
+
95
+ var records = new INPUT_RECORD[] {
96
+ new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=LEFT_CTRL },
97
+ new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x55, UnicodeChar=0x15, dwControlKeyState=LEFT_CTRL },
98
+ new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x55, UnicodeChar=0x15, dwControlKeyState=LEFT_CTRL },
99
+ new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=0 }
100
+ };
101
+
102
+ uint written;
103
+ bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);
104
+ CloseHandle(hIn);
105
+ return ok ? (int)written : -2;
106
+ }
107
+
108
+ // Inject Ctrl+Y (VK_Y = 0x59, char = 0x19)
109
+ public static int InjectCtrlY(uint pid) {
110
+ IntPtr hIn = OpenConin(pid);
111
+ if (hIn == new IntPtr(-1)) return -1;
112
+
113
+ var records = new INPUT_RECORD[] {
114
+ new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=LEFT_CTRL },
115
+ new INPUT_RECORD { EventType=1, bKeyDown=1, wRepeatCount=1, wVirtualKeyCode=0x59, UnicodeChar=0x19, dwControlKeyState=LEFT_CTRL },
116
+ new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0x59, UnicodeChar=0x19, dwControlKeyState=LEFT_CTRL },
117
+ new INPUT_RECORD { EventType=1, bKeyDown=0, wRepeatCount=1, wVirtualKeyCode=0xA2, dwControlKeyState=0 }
118
+ };
119
+
120
+ uint written;
121
+ bool ok = WriteConsoleInput(hIn, records, (uint)records.Length, out written);
122
+ CloseHandle(hIn);
123
+ return ok ? (int)written : -2;
83
124
  }
84
125
  }
85
126
  `;
@@ -117,33 +158,24 @@ async function windowsInject(text) {
117
158
  const script = buildScript(claudePid, `
118
159
  $textBytes = [System.Convert]::FromBase64String('${textB64}')
119
160
  $text = [System.Text.Encoding]::Unicode.GetString($textBytes)
120
- $wsh = New-Object -ComObject WScript.Shell
121
161
 
122
- # 1. Focus console and send Ctrl+U to save user's current text to kill ring
123
- $hwnd = [ConInject]::FocusConsole([uint32]$claudePid)
124
- Start-Sleep -Milliseconds 150
125
- $wsh.SendKeys('^u')
126
- Start-Sleep -Milliseconds 150
162
+ # 1. Ctrl+U to save user's current text to kill ring
163
+ [ConInject]::InjectCtrlU([uint32]$claudePid) | Out-Null
164
+ Start-Sleep -Milliseconds 100
127
165
 
128
166
  # 2. Write question text into console input buffer
129
167
  [ConInject]::InjectText([uint32]$claudePid, $text) | Out-Null
168
+ Start-Sleep -Milliseconds 50
130
169
 
131
- # 3. Re-focus (InjectText calls FreeConsole internally, focus may be lost)
132
- [ConInject]::FocusConsole([uint32]$claudePid) | Out-Null
133
- Start-Sleep -Milliseconds 150
134
-
135
- # 4. Send Enter
136
- $wsh.SendKeys('~')
170
+ # 3. Send Enter
171
+ [ConInject]::InjectEnter([uint32]$claudePid) | Out-Null
137
172
  `);
138
173
  await run(script);
139
174
  }
140
175
  async function windowsInjectCtrlY() {
141
176
  const claudePid = process.ppid;
142
177
  const script = buildScript(claudePid, `
143
- $wsh = New-Object -ComObject WScript.Shell
144
- $hwnd = [ConInject]::FocusConsole([uint32]$claudePid)
145
- Start-Sleep -Milliseconds 150
146
- $wsh.SendKeys('^y')
178
+ [ConInject]::InjectCtrlY([uint32]$claudePid) | Out-Null
147
179
  `);
148
180
  await run(script);
149
181
  }
@@ -582,9 +614,9 @@ var joinSchema = {
582
614
  displayName: z.string().optional().describe('Display name for this terminal (default: team + " Claude")')
583
615
  };
584
616
  function registerJoinTool(server, client) {
585
- server.tool("join", joinSchema, async (args2) => {
586
- const teamName = args2.team;
587
- const displayName = args2.displayName ?? `${teamName} Claude`;
617
+ server.tool("join", joinSchema, async (args) => {
618
+ const teamName = args.team;
619
+ const displayName = args.displayName ?? `${teamName} Claude`;
588
620
  try {
589
621
  const member = await client.join(teamName, displayName);
590
622
  return {
@@ -618,15 +650,15 @@ var connectPeerSchema = {
618
650
  port: z.number().optional().describe(`Port the peer is listening on (default: ${config.p2p.port})`)
619
651
  };
620
652
  function registerConnectPeerTool(server, client) {
621
- server.tool("connect_peer", connectPeerSchema, async (args2) => {
622
- const targetPort = args2.port ?? config.p2p.port;
653
+ server.tool("connect_peer", connectPeerSchema, async (args) => {
654
+ const targetPort = args.port ?? config.p2p.port;
623
655
  try {
624
- const peerTeam = await client.connectPeer(args2.ip, args2.port);
656
+ const peerTeam = await client.connectPeer(args.ip, args.port);
625
657
  return {
626
658
  content: [
627
659
  {
628
660
  type: "text",
629
- text: `Connected to peer "${peerTeam}" at ${args2.ip}:${targetPort}.`
661
+ text: `Connected to peer "${peerTeam}" at ${args.ip}:${targetPort}.`
630
662
  }
631
663
  ]
632
664
  };
@@ -636,7 +668,7 @@ function registerConnectPeerTool(server, client) {
636
668
  content: [
637
669
  {
638
670
  type: "text",
639
- text: `Failed to connect to ${args2.ip}:${targetPort}: ${errorMessage}`
671
+ text: `Failed to connect to ${args.ip}:${targetPort}: ${errorMessage}`
640
672
  }
641
673
  ],
642
674
  isError: true
@@ -649,9 +681,9 @@ var askSchema = {
649
681
  question: z.string().describe("The question to ask (supports markdown)")
650
682
  };
651
683
  function registerAskTool(server, client) {
652
- server.tool("ask", askSchema, async (args2) => {
653
- const targetTeam = args2.team;
654
- const question = args2.question;
684
+ server.tool("ask", askSchema, async (args) => {
685
+ const targetTeam = args.team;
686
+ const question = args.question;
655
687
  try {
656
688
  if (!client.currentTeamId) {
657
689
  return {
@@ -713,8 +745,8 @@ var checkAnswerSchema = {
713
745
  question_id: z.string().describe('The question ID returned by the "ask" tool')
714
746
  };
715
747
  function registerCheckAnswerTool(server, client) {
716
- server.tool("check_answer", checkAnswerSchema, async (args2) => {
717
- const questionId = args2.question_id;
748
+ server.tool("check_answer", checkAnswerSchema, async (args) => {
749
+ const questionId = args.question_id;
718
750
  try {
719
751
  if (!client.currentTeamId) {
720
752
  return {
@@ -832,9 +864,9 @@ var replySchema = {
832
864
  answer: z.string().describe("Your answer to the question (supports markdown)")
833
865
  };
834
866
  function registerReplyTool(server, client) {
835
- server.tool("reply", replySchema, async (args2) => {
836
- const questionId = args2.questionId;
837
- const answer = args2.answer;
867
+ server.tool("reply", replySchema, async (args) => {
868
+ const questionId = args.questionId;
869
+ const answer = args.answer;
838
870
  try {
839
871
  if (!client.currentTeamId) {
840
872
  return {
@@ -926,40 +958,10 @@ async function startMcpServer(options) {
926
958
  }
927
959
 
928
960
  // src/mcp-main.ts
929
- var args = process.argv.slice(2);
930
- function parseArgs() {
931
- const options = {};
932
- for (let i = 0; i < args.length; i++) {
933
- const arg = args[i];
934
- const nextArg = args[i + 1];
935
- if (arg === "--team" && nextArg) {
936
- options.team = nextArg;
937
- i++;
938
- } else if (arg === "-h" || arg === "--help") {
939
- console.error(`
940
- Claude Collab MCP Client (P2P mode)
941
-
942
- Usage:
943
- mcp-main [options]
944
-
945
- Options:
946
- --team <team> Team to auto-join (optional)
947
- -h, --help Show this help message
948
- `);
949
- process.exit(0);
950
- }
951
- }
952
- return options;
953
- }
954
961
  async function main() {
955
- const options = parseArgs();
956
962
  const p2pNode = new P2PNode();
957
963
  try {
958
964
  await p2pNode.start();
959
- if (options.team) {
960
- await p2pNode.join(options.team, `${options.team} Claude`);
961
- console.error(`Auto-joined team: ${options.team}`);
962
- }
963
965
  } catch (error) {
964
966
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
965
967
  console.error(`Failed to start P2P node: ${errorMessage}`);
@@ -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","args","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 * CONIN$ gives the real console input handle (not the MCP pipe stdin).\r\n * ppid = Claude Code process — the one actively reading from the console.\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\")] public static extern IntPtr GetConsoleWindow();\r\n [DllImport(\"user32.dll\")] public static extern bool SetForegroundWindow(IntPtr hwnd);\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 only text characters into console input buffer (no Ctrl keys, no Enter)\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 // Focus the console window for WScript.Shell.SendKeys\r\n public static IntPtr FocusConsole(uint pid) {\r\n FreeConsole();\r\n if (!AttachConsole(pid)) return IntPtr.Zero;\r\n IntPtr hwnd = GetConsoleWindow();\r\n if (hwnd != IntPtr.Zero) SetForegroundWindow(hwnd);\r\n return hwnd;\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$wsh = New-Object -ComObject WScript.Shell\r\n\r\n# 1. Focus console and send Ctrl+U to save user's current text to kill ring\r\n$hwnd = [ConInject]::FocusConsole([uint32]$claudePid)\r\nStart-Sleep -Milliseconds 150\r\n$wsh.SendKeys('^u')\r\nStart-Sleep -Milliseconds 150\r\n\r\n# 2. Write question text into console input buffer\r\n[ConInject]::InjectText([uint32]$claudePid, $text) | Out-Null\r\n\r\n# 3. Re-focus (InjectText calls FreeConsole internally, focus may be lost)\r\n[ConInject]::FocusConsole([uint32]$claudePid) | Out-Null\r\nStart-Sleep -Milliseconds 150\r\n\r\n# 4. Send Enter\r\n$wsh.SendKeys('~')\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$wsh = New-Object -ComObject WScript.Shell\r\n$hwnd = [ConInject]::FocusConsole([uint32]$claudePid)\r\nStart-Sleep -Milliseconds 150\r\n$wsh.SendKeys('^y')\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 * Fixed port for the WS server. Override with CLAUDE_COLLAB_PORT env var.\r\n */\r\n port: Number(process.env['CLAUDE_COLLAB_PORT'] ?? 11777),\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 the configured fixed port.\r\n * Called automatically from join() if not yet started.\r\n */\r\n async start(): Promise<void> {\r\n this.port = config.p2p.port;\r\n this.wss = new WebSocketServer({ port: this.port });\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 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' };\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 targetPort = port ?? config.p2p.port;\r\n const ws = new WebSocket(`ws://${ip}:${targetPort}`);\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}:${targetPort}`)),\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}\\nTeam ID: ${member.teamId}\\nStatus: ${member.status}`,\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\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\nimport { config } from '../../../config/index.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\r\n .number()\r\n .optional()\r\n .describe(`Port the peer is listening on (default: ${config.p2p.port})`),\r\n};\r\n\r\nexport function registerConnectPeerTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('connect_peer', connectPeerSchema, async (args) => {\r\n const targetPort = args.port ?? config.p2p.port;\r\n\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}:${targetPort}.`,\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}:${targetPort}: ${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\nconst args = process.argv.slice(2);\r\n\r\ninterface ClientOptions {\r\n team?: string;\r\n}\r\n\r\nfunction parseArgs(): ClientOptions {\r\n const options: ClientOptions = {};\r\n\r\n for (let i = 0; i < args.length; i++) {\r\n const arg = args[i];\r\n const nextArg = args[i + 1];\r\n\r\n if (arg === '--team' && nextArg) {\r\n options.team = nextArg;\r\n i++;\r\n } else if (arg === '-h' || arg === '--help') {\r\n console.error(`\r\nClaude Collab MCP Client (P2P mode)\r\n\r\nUsage:\r\n mcp-main [options]\r\n\r\nOptions:\r\n --team <team> Team to auto-join (optional)\r\n -h, --help Show this help message\r\n`);\r\n process.exit(0);\r\n }\r\n }\r\n\r\n return options;\r\n}\r\n\r\nasync function main(): Promise<void> {\r\n const options = parseArgs();\r\n\r\n const p2pNode = new P2PNode();\r\n\r\n try {\r\n await p2pNode.start();\r\n\r\n if (options.team) {\r\n await p2pNode.join(options.team, `${options.team} Claude`);\r\n console.error(`Auto-joined team: ${options.team}`);\r\n }\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n console.error(`Failed to start P2P node: ${errorMessage}`);\r\n process.exit(1);\r\n }\r\n\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/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 * Fixed port for the WS server. Override with CLAUDE_COLLAB_PORT env var.\r\n */\r\n port: Number(process.env['CLAUDE_COLLAB_PORT'] ?? 11777),\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 the configured fixed port.\r\n * Called automatically from join() if not yet started.\r\n */\r\n async start(): Promise<void> {\r\n this.port = config.p2p.port;\r\n this.wss = new WebSocketServer({ port: this.port });\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 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' };\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 targetPort = port ?? config.p2p.port;\r\n const ws = new WebSocket(`ws://${ip}:${targetPort}`);\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}:${targetPort}`)),\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}\\nTeam ID: ${member.teamId}\\nStatus: ${member.status}`,\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\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\nimport { config } from '../../../config/index.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\r\n .number()\r\n .optional()\r\n .describe(`Port the peer is listening on (default: ${config.p2p.port})`),\r\n};\r\n\r\nexport function registerConnectPeerTool(server: McpServer, client: ICollabClient): void {\r\n server.tool('connect_peer', connectPeerSchema, async (args) => {\r\n const targetPort = args.port ?? config.p2p.port;\r\n\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}:${targetPort}.`,\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}:${targetPort}: ${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\r\n try {\r\n await p2pNode.start();\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n console.error(`Failed to start P2P node: ${errorMessage}`);\r\n process.exit(1);\r\n }\r\n\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dolusoft/claude-collab",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
4
4
  "description": "Real-time team collaboration between Claude Code terminals via MCP",
5
5
  "type": "module",
6
6
  "main": "./dist/mcp-main.js",