@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 +58 -26
- package/dist/cli.js.map +1 -1
- package/dist/mcp-main.js +74 -72
- package/dist/mcp-main.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
-
//
|
|
78
|
-
public static
|
|
79
|
-
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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.
|
|
124
|
-
|
|
125
|
-
Start-Sleep -Milliseconds
|
|
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.
|
|
133
|
-
[ConInject]::
|
|
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
|
-
$
|
|
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
|
|
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
|
-
//
|
|
77
|
-
public static
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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.
|
|
123
|
-
|
|
124
|
-
Start-Sleep -Milliseconds
|
|
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.
|
|
132
|
-
[ConInject]::
|
|
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
|
-
$
|
|
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 (
|
|
586
|
-
const teamName =
|
|
587
|
-
const displayName =
|
|
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 (
|
|
622
|
-
const targetPort =
|
|
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(
|
|
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 ${
|
|
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 ${
|
|
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 (
|
|
653
|
-
const targetTeam =
|
|
654
|
-
const 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 (
|
|
717
|
-
const questionId =
|
|
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 (
|
|
836
|
-
const questionId =
|
|
837
|
-
const 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}`);
|
package/dist/mcp-main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/infrastructure/p2p/p2p-message-protocol.ts","../src/infrastructure/terminal-injector/windows-injector.ts","../src/infrastructure/terminal-injector/index.ts","../src/infrastructure/terminal-injector/injection-queue.ts","../src/config/index.ts","../src/infrastructure/p2p/p2p-node.ts","../src/presentation/mcp/tools/join.tool.ts","../src/presentation/mcp/tools/connect-peer.tool.ts","../src/presentation/mcp/tools/ask.tool.ts","../src/presentation/mcp/tools/check.tool.ts","../src/presentation/mcp/tools/inbox.tool.ts","../src/presentation/mcp/tools/reply.tool.ts","../src/presentation/mcp/server.ts","../src/mcp-main.ts"],"names":["uuidv4","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"]}
|