@nokai/cli 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +16 -173
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +239 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/connection-manager.d.ts +9 -1
  7. package/dist/connection-manager.d.ts.map +1 -1
  8. package/dist/connection-manager.js +85 -1
  9. package/dist/connection-manager.js.map +1 -1
  10. package/dist/index.js +16 -4
  11. package/dist/index.js.map +1 -1
  12. package/dist/message-protocol.d.ts +3 -1
  13. package/dist/message-protocol.d.ts.map +1 -1
  14. package/dist/message-protocol.js +25 -1
  15. package/dist/message-protocol.js.map +1 -1
  16. package/dist/peer-connection.d.ts.map +1 -1
  17. package/dist/peer-connection.js +2 -5
  18. package/dist/peer-connection.js.map +1 -1
  19. package/dist/profile.d.ts +9 -0
  20. package/dist/profile.d.ts.map +1 -1
  21. package/dist/profile.js +31 -2
  22. package/dist/profile.js.map +1 -1
  23. package/dist/server.d.ts.map +1 -1
  24. package/dist/server.js +113 -6
  25. package/dist/server.js.map +1 -1
  26. package/dist/shared/constants.d.ts +12 -0
  27. package/dist/shared/constants.d.ts.map +1 -1
  28. package/dist/shared/constants.js +13 -1
  29. package/dist/shared/constants.js.map +1 -1
  30. package/dist/shared/types.d.ts +19 -1
  31. package/dist/shared/types.d.ts.map +1 -1
  32. package/dist/shared/types.js +7 -0
  33. package/dist/shared/types.js.map +1 -1
  34. package/dist/signaling-client.d.ts +18 -3
  35. package/dist/signaling-client.d.ts.map +1 -1
  36. package/dist/signaling-client.js +83 -7
  37. package/dist/signaling-client.js.map +1 -1
  38. package/dist/tools/ask.d.ts.map +1 -1
  39. package/dist/tools/ask.js +2 -1
  40. package/dist/tools/ask.js.map +1 -1
  41. package/dist/tools/connect.d.ts +19 -2
  42. package/dist/tools/connect.d.ts.map +1 -1
  43. package/dist/tools/connect.js +187 -43
  44. package/dist/tools/connect.js.map +1 -1
  45. package/dist/tools/discover.d.ts +12 -0
  46. package/dist/tools/discover.d.ts.map +1 -0
  47. package/dist/tools/discover.js +67 -0
  48. package/dist/tools/discover.js.map +1 -0
  49. package/dist/tools/id.d.ts +12 -0
  50. package/dist/tools/id.d.ts.map +1 -0
  51. package/dist/tools/id.js +24 -0
  52. package/dist/tools/id.js.map +1 -0
  53. package/dist/tools/invite.d.ts +32 -0
  54. package/dist/tools/invite.d.ts.map +1 -0
  55. package/dist/tools/invite.js +144 -0
  56. package/dist/tools/invite.js.map +1 -0
  57. package/dist/tools/reconnect.d.ts.map +1 -1
  58. package/dist/tools/reconnect.js +6 -2
  59. package/dist/tools/reconnect.js.map +1 -1
  60. package/dist/tools/share.d.ts +37 -0
  61. package/dist/tools/share.d.ts.map +1 -0
  62. package/dist/tools/share.js +153 -0
  63. package/dist/tools/share.js.map +1 -0
  64. package/dist/tools/tell.d.ts.map +1 -1
  65. package/dist/tools/tell.js +2 -1
  66. package/dist/tools/tell.js.map +1 -1
  67. package/package.json +4 -3
package/README.md CHANGED
@@ -4,190 +4,33 @@
4
4
 
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
6
 
7
- NokAI is an MCP server that enables **peer-to-peer communication between AI coding assistants**. Connect your Claude Code with your teammate's Cursor, exchange questions about each other's codebases, and even send action requests — all through encrypted WebRTC data channels.
7
+ NokAI lets AI coding assistants talk to each other. Connect your Claude Code with your teammate's Cursor, ask questions about their codebase, share files, and send action requests — without leaving your editor.
8
8
 
9
- **No code or conversation data ever touches the server.** The signaling server only brokers the initial handshake.
10
-
11
- ## Quick Start
9
+ ## Get Started
12
10
 
13
11
  ```bash
14
- # Install globally
15
- npm install -g nokai
16
-
17
- # Add to Claude Code MCP settings
18
- # See docs/setup/ for your specific tool
19
- ```
20
-
21
- ### Connect with a Teammate
22
-
23
- ```
24
- You: "Connect me with my teammate"
25
- NokAI: 🔗 Connection code: 847293 (expires in 5 minutes)
26
-
27
- --- Your teammate ---
28
-
29
- Teammate: "Join NokAI with code 847293"
30
- NokAI: ✓ Connected with Michael!
31
- ```
32
-
33
- ### Ask Questions Across Codebases
34
-
35
- ```
36
- You: "Ask Sara what the message type for /cmd_vel is
37
- and build me the Flutter model for it"
38
-
39
- NokAI: → Asking Sara...
40
- ← Sara: geometry_msgs/msg/Twist at 10Hz
41
- Fields: linear.x (float64), angular.z (float64)
42
-
43
- Building your Flutter model class...
44
- ✓ Created lib/models/twist_model.dart
12
+ npm install -g @nokai/cli
13
+ nokai
45
14
  ```
46
15
 
47
- ## Supported Platforms
48
-
49
- | Platform | Status | Setup Guide |
50
- |---|---|---|
51
- | Claude Code (CLI & VS Code) | ✅ Full support | [docs/setup/claude-code.md](docs/setup/claude-code.md) |
52
- | Cursor | ✅ Full support | [docs/setup/cursor.md](docs/setup/cursor.md) |
53
- | Windsurf (Codeium) | ✅ Full support | [docs/setup/windsurf.md](docs/setup/windsurf.md) |
54
- | Any MCP tool | ✅ Full support | [docs/setup/generic-mcp.md](docs/setup/generic-mcp.md) |
55
-
56
- ## Tools (13)
57
-
58
- ### Connection
59
-
60
- | Tool | Description |
61
- |---|---|
62
- | `nokai_connect` | Generate a 6-digit OTP connection code |
63
- | `nokai_join` | Join using an OTP code |
64
- | `nokai_reconnect` | Reconnect to a saved peer (no new OTP) |
65
- | `nokai_disconnect` | Disconnect from a peer |
66
- | `nokai_connections` | List all active and saved connections |
67
-
68
- ### Communication
16
+ The setup wizard will ask your name, which AI tool you use, and configure everything automatically. No JSON editing required.
69
17
 
70
- | Tool | Description |
71
- |---|---|
72
- | `nokai_ask` | Ask a question to a peer's AI agent |
73
- | `nokai_respond` | Reply to an incoming question |
74
- | `nokai_tell` | Send an action request (requires read-write permission) |
75
-
76
- ### Management
77
-
78
- | Tool | Description |
79
- |---|---|
80
- | `nokai_permissions` | View/change permission levels (read-only, read-write, ask-only) |
81
- | `nokai_approve` | Toggle manual approval mode for incoming queries |
82
- | `nokai_history` | Browse past message exchanges |
83
- | `nokai_audit` | View audit log of all events |
84
- | `nokai_profile` | Manage agent profile and capability cards |
85
-
86
- ## Architecture
87
-
88
- ```
89
- Your Machine Teammate's Machine
90
- ┌────────────────┐ ┌────────────────┐
91
- │ AI Assistant │ │ AI Assistant │
92
- │ (Claude/Cursor) │ │ (Claude/Cursor) │
93
- │ ↕ MCP │ │ ↕ MCP │
94
- │ NokAI Server │◄══════════════════►│ NokAI Server │
95
- │ (local) │ Encrypted P2P │ (local) │
96
- └────────────────┘ (WebRTC) └────────────────┘
97
- │ │
98
- └──────── Signaling Server ───────────┘
99
- (handshake only)
100
- ```
18
+ ## What You Can Do
101
19
 
102
- - **P2P by default** — messages flow directly between machines
103
- - **TURN fallback** — relay for firewalled networks (env vars)
104
- - **Offline queue** — messages queued locally, delivered on reconnect
105
- - **End-to-end encrypted** — WebRTC DTLS + Ed25519 signatures
20
+ - **Ask across codebases** — query a teammate's agent about their code
21
+ - **Send action requests** — ask a peer's agent to make changes
22
+ - **Share files** — send files and project context directly to another agent
23
+ - **Connect your own projects** — link your mobile and web sessions
24
+ - **Discover peers** — see who's online and reconnect instantly
106
25
 
107
- ## Security
26
+ ## Works With
108
27
 
109
- | Feature | Implementation |
110
- |---|---|
111
- | Agent identity | Ed25519 keypair per agent |
112
- | Connection auth | 6-digit OTP, 5-min expiry, single-use |
113
- | Transport | WebRTC DTLS encryption |
114
- | Server access | Signaling server never sees message content |
115
- | Local storage | Private keys at `~/.nokai/profile.json` (chmod 600) |
116
- | Reconnection | Peer confirmation required, public key verification |
28
+ Claude Code, Cursor, Windsurf, and any MCP-compatible tool.
117
29
 
118
- ## Self-Hosting the Signaling Server
30
+ ## Full Docs
119
31
 
120
- The signaling server runs on Cloudflare Workers (free tier):
121
-
122
- ```bash
123
- cd packages/signaling-server
124
- npx wrangler d1 create nokai-signaling # Create D1 database
125
- # Update wrangler.toml with the database ID
126
- npx wrangler deploy # Deploy to Cloudflare
127
- ```
128
-
129
- Set your deployed URL as `NOKAI_SIGNALING_URL` in your MCP config.
130
-
131
- ## Environment Variables
132
-
133
- | Variable | Required | Default | Description |
134
- |---|---|---|---|
135
- | `NOKAI_AGENT_NAME` | No | "Agent" | Your agent's display name |
136
- | `NOKAI_SIGNALING_URL` | No | — | Signaling server WebSocket URL |
137
- | `NOKAI_TURN_SERVER` | No | — | TURN relay server URL |
138
- | `NOKAI_TURN_USERNAME` | No | — | TURN server username |
139
- | `NOKAI_TURN_PASSWORD` | No | — | TURN server password |
140
-
141
- ## Development
142
-
143
- ```bash
144
- # Clone and install
145
- git clone https://github.com/heiisenberrg/nokAI.git
146
- cd nokAI
147
- npm install
148
-
149
- # Build all packages
150
- npm run build
151
-
152
- # Run tests (125 tests)
153
- npm test
154
-
155
- # Dev mode (MCP server)
156
- cd packages/mcp-server && npm run dev
157
- ```
158
-
159
- ## Project Structure
160
-
161
- ```
162
- nokai/
163
- ├── packages/
164
- │ ├── shared/ # Shared types, constants, type guards
165
- │ ├── mcp-server/ # MCP server + P2P engine (13 tools)
166
- │ │ ├── src/tools/ # Tool handlers
167
- │ │ └── tests/ # 100+ tests
168
- │ └── signaling-server/ # Cloudflare Workers signaling server
169
- └── docs/setup/ # Platform-specific setup guides
170
- ```
171
-
172
- ## Roadmap
173
-
174
- - [x] v0.1.0 — Core: connect, ask, respond via P2P
175
- - [x] v0.2.0 — Reconnection, history, TURN, offline queue, approval mode
176
- - [x] v0.3.0 — Actions (tell), permission levels
177
- - [x] v0.4.0 — Audit logs, agent profiles
178
- - [x] v1.0.0 — Multi-platform, npm packaging
179
- - [ ] v1.1.0 — Web dashboard for connection management
180
- - [ ] v1.2.0 — Agent capability discovery within organizations
181
- - [ ] v2.0.0 — Cross-organization connections
32
+ https://nokai.pages.dev
182
33
 
183
34
  ## License
184
35
 
185
- MIT — see [LICENSE](LICENSE)
186
-
187
- ## Contributing
188
-
189
- Contributions welcome! Please open an issue first to discuss.
190
-
191
- ---
192
-
193
- Built with frustration at copy-pasting between Slack and Claude.
36
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function runCli(): Promise<void>;
2
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAuPA,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAS5C"}
package/dist/cli.js ADDED
@@ -0,0 +1,239 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runCli = runCli;
4
+ const node_readline_1 = require("node:readline");
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = require("node:path");
7
+ const profile_js_1 = require("./profile.js");
8
+ const rl = (0, node_readline_1.createInterface)({ input: process.stdin, output: process.stdout });
9
+ function ask(question) {
10
+ return new Promise((resolve) => {
11
+ rl.question(question, (answer) => resolve(answer.trim()));
12
+ });
13
+ }
14
+ function choose(question, options) {
15
+ return new Promise((resolve) => {
16
+ console.log(`\n ${question}\n`);
17
+ options.forEach((opt, i) => {
18
+ console.log(` ${i + 1}) ${opt}`);
19
+ });
20
+ console.log();
21
+ rl.question(" Enter number: ", (answer) => {
22
+ const idx = parseInt(answer.trim(), 10) - 1;
23
+ if (idx >= 0 && idx < options.length) {
24
+ resolve(options[idx]);
25
+ }
26
+ else {
27
+ resolve(options[0]);
28
+ }
29
+ });
30
+ });
31
+ }
32
+ function getPlatforms() {
33
+ const home = process.env.HOME || process.env.USERPROFILE || "~";
34
+ return [
35
+ {
36
+ name: "Claude Code",
37
+ configPath: (0, node_path_1.join)(home, ".claude.json"),
38
+ configDir: (0, node_path_1.join)(home),
39
+ },
40
+ {
41
+ name: "Cursor",
42
+ configPath: (0, node_path_1.join)(process.cwd(), ".cursor", "mcp.json"),
43
+ configDir: (0, node_path_1.join)(process.cwd(), ".cursor"),
44
+ },
45
+ {
46
+ name: "Windsurf",
47
+ configPath: (0, node_path_1.join)(home, ".codeium", "windsurf", "mcp_config.json"),
48
+ configDir: (0, node_path_1.join)(home, ".codeium", "windsurf"),
49
+ },
50
+ {
51
+ name: "VS Code (Extension)",
52
+ configPath: "",
53
+ configDir: "",
54
+ },
55
+ {
56
+ name: "Other",
57
+ configPath: "",
58
+ configDir: "",
59
+ },
60
+ ];
61
+ }
62
+ function writeMcpConfig(platform, agentName, signalingUrl) {
63
+ if (!platform.configPath)
64
+ return false;
65
+ try {
66
+ // Ensure directory exists
67
+ if (platform.configDir && !(0, node_fs_1.existsSync)(platform.configDir)) {
68
+ (0, node_fs_1.mkdirSync)(platform.configDir, { recursive: true });
69
+ }
70
+ // Read existing config or create new
71
+ let config = {};
72
+ if ((0, node_fs_1.existsSync)(platform.configPath)) {
73
+ try {
74
+ config = JSON.parse((0, node_fs_1.readFileSync)(platform.configPath, "utf-8"));
75
+ }
76
+ catch {
77
+ config = {};
78
+ }
79
+ }
80
+ // Add/update mcpServers.nokai
81
+ if (!config.mcpServers || typeof config.mcpServers !== "object") {
82
+ config.mcpServers = {};
83
+ }
84
+ config.mcpServers.nokai = {
85
+ command: "nokai",
86
+ args: ["serve"],
87
+ env: {
88
+ NOKAI_AGENT_NAME: agentName,
89
+ NOKAI_SIGNALING_URL: signalingUrl,
90
+ },
91
+ };
92
+ (0, node_fs_1.writeFileSync)(platform.configPath, JSON.stringify(config, null, 2), "utf-8");
93
+ return true;
94
+ }
95
+ catch {
96
+ return false;
97
+ }
98
+ }
99
+ const SIGNALING_URL = "wss://nokai-signaling.ajaykkumar-rajen.workers.dev";
100
+ async function firstTimeSetup() {
101
+ console.log("\n ✨ Welcome to NokAI! Let's set you up.\n");
102
+ // Ask for agent name
103
+ const name = await ask(" What would you like to name your agent? ");
104
+ if (!name) {
105
+ console.log(" Agent name is required.");
106
+ rl.close();
107
+ return;
108
+ }
109
+ // Choose platform
110
+ const platforms = getPlatforms();
111
+ const platformNames = platforms.map((p) => p.name);
112
+ const chosen = await choose("Which AI tool are you using?", platformNames);
113
+ const platform = platforms.find((p) => p.name === chosen) || platforms[platforms.length - 1];
114
+ // Create profile
115
+ const profileDir = (0, profile_js_1.getProfileDir)();
116
+ const profile = (0, profile_js_1.createProfile)(name, profileDir);
117
+ console.log(`\n ✓ Agent created: ${name}`);
118
+ console.log(` ✓ Your NokAI ID: ${profile.nokaiId}`);
119
+ // Configure MCP
120
+ if (platform.configPath) {
121
+ const confirm = await ask(`\n Add NokAI to ${platform.name} config? (${platform.configPath}) [Y/n] `);
122
+ if (confirm.toLowerCase() !== "n") {
123
+ const success = writeMcpConfig(platform, name, SIGNALING_URL);
124
+ if (success) {
125
+ console.log(` ✓ MCP configuration added to ${platform.name}`);
126
+ }
127
+ else {
128
+ console.log(` ✗ Failed to write config. You can add it manually.`);
129
+ showManualConfig(name);
130
+ }
131
+ }
132
+ else {
133
+ showManualConfig(name);
134
+ }
135
+ }
136
+ else if (platform.name === "VS Code (Extension)") {
137
+ console.log(`\n Install the NokAI VS Code extension and set your Signaling URL in settings.`);
138
+ console.log(` Signaling URL: ${SIGNALING_URL}`);
139
+ }
140
+ else {
141
+ showManualConfig(name);
142
+ }
143
+ console.log(`\n You're ready! Restart your AI tool to activate NokAI.`);
144
+ console.log(` Share your NokAI ID with teammates: ${profile.nokaiId}\n`);
145
+ rl.close();
146
+ }
147
+ function showManualConfig(agentName) {
148
+ console.log(`\n Add this to your MCP configuration:\n`);
149
+ console.log(JSON.stringify({
150
+ mcpServers: {
151
+ nokai: {
152
+ command: "nokai",
153
+ args: ["serve"],
154
+ env: {
155
+ NOKAI_AGENT_NAME: agentName,
156
+ NOKAI_SIGNALING_URL: SIGNALING_URL,
157
+ },
158
+ },
159
+ },
160
+ }, null, 2).split("\n").map((l) => ` ${l}`).join("\n"));
161
+ }
162
+ async function returningUser() {
163
+ const profileDir = (0, profile_js_1.getProfileDir)();
164
+ const profile = (0, profile_js_1.loadProfile)(profileDir);
165
+ if (!profile) {
166
+ return firstTimeSetup();
167
+ }
168
+ console.log(`\n Welcome back, ${profile.name}! (${profile.nokaiId})\n`);
169
+ const action = await choose("What would you like to do?", [
170
+ "Connect to a teammate",
171
+ "Connect my own projects",
172
+ "Show my NokAI ID",
173
+ "View connections",
174
+ "Reconfigure MCP settings",
175
+ "Exit",
176
+ ]);
177
+ switch (action) {
178
+ case "Connect to a teammate": {
179
+ const peerId = await ask("\n Enter teammate's NokAI ID (e.g., NKI-XXXX-XXXX): ");
180
+ if (peerId) {
181
+ console.log(`\n To connect, use this in your AI tool:`);
182
+ console.log(` nokai_connect mode=teammate id=${peerId}\n`);
183
+ }
184
+ break;
185
+ }
186
+ case "Connect my own projects": {
187
+ console.log(`\n To connect your sessions, use this in your AI tool:`);
188
+ console.log(` nokai_connect mode=self\n`);
189
+ console.log(` This will list your active sessions and let you connect them.\n`);
190
+ break;
191
+ }
192
+ case "Show my NokAI ID": {
193
+ console.log(`\n NokAI ID: ${profile.nokaiId}`);
194
+ console.log(` Agent Name: ${profile.name}`);
195
+ console.log(` Device ID: ${profile.deviceId}\n`);
196
+ console.log(` Share your NokAI ID with teammates so they can connect to you.\n`);
197
+ break;
198
+ }
199
+ case "View connections": {
200
+ console.log(`\n To view connections, use nokai_connections in your AI tool.\n`);
201
+ break;
202
+ }
203
+ case "Reconfigure MCP settings": {
204
+ const platforms = getPlatforms();
205
+ const platformNames = platforms.map((p) => p.name);
206
+ const chosen = await choose("Which AI tool?", platformNames);
207
+ const platform = platforms.find((p) => p.name === chosen) || platforms[platforms.length - 1];
208
+ if (platform.configPath) {
209
+ const success = writeMcpConfig(platform, profile.name, SIGNALING_URL);
210
+ if (success) {
211
+ console.log(`\n ✓ MCP configuration updated for ${platform.name}`);
212
+ console.log(` Restart your AI tool to apply changes.\n`);
213
+ }
214
+ else {
215
+ console.log(`\n ✗ Failed to write config.`);
216
+ showManualConfig(profile.name);
217
+ }
218
+ }
219
+ else {
220
+ showManualConfig(profile.name);
221
+ }
222
+ break;
223
+ }
224
+ case "Exit":
225
+ break;
226
+ }
227
+ rl.close();
228
+ }
229
+ async function runCli() {
230
+ const profileDir = (0, profile_js_1.getProfileDir)();
231
+ const profile = (0, profile_js_1.loadProfile)(profileDir);
232
+ if (!profile) {
233
+ await firstTimeSetup();
234
+ }
235
+ else {
236
+ await returningUser();
237
+ }
238
+ }
239
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,19 @@
1
1
  import { EventEmitter } from "node:events";
2
2
  import type { AgentProfile, PeerMessage, ConnectionRecord } from "./shared/index.js";
3
3
  import { type NokaiDB } from "./db.js";
4
+ import type { SharedFile, ProjectContext } from "./shared/index.js";
4
5
  export declare class ConnectionManager extends EventEmitter {
5
6
  private db;
6
7
  private profile;
7
8
  private activePeers;
8
9
  private incomingHandler;
9
10
  private heldQueries;
10
- constructor(db: NokaiDB, profile: AgentProfile);
11
+ private signalingUrl;
12
+ private pendingBytes;
13
+ private transferReportTimer;
14
+ constructor(db: NokaiDB, profile: AgentProfile, signalingUrl?: string);
15
+ private trackBytes;
16
+ private flushTransferStats;
11
17
  registerPeer(connectionId: string, peerName: string, peerPublicKey: string): void;
12
18
  setPeerSend(connectionId: string, sendFn: (msg: string) => void): void;
13
19
  private findPeerByName;
@@ -15,6 +21,8 @@ export declare class ConnectionManager extends EventEmitter {
15
21
  sendResponse(peerName: string, replyTo: string, content: string, sourceFiles?: string[]): PeerMessage;
16
22
  sendAction(peerName: string, content: string, context?: string): PeerMessage;
17
23
  sendActionResult(peerName: string, replyTo: string, content: string, success: boolean, sourceFiles?: string[]): PeerMessage;
24
+ sendShareFiles(peerName: string, files: SharedFile[]): PeerMessage;
25
+ sendShareContext(peerName: string, context: ProjectContext): PeerMessage;
18
26
  handleIncomingMessage(connectionId: string, rawData: string): void;
19
27
  onIncomingMessage(handler: (msg: PeerMessage, peerName: string) => void): void;
20
28
  getActiveConnections(): Array<{
@@ -1 +1 @@
1
- {"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../src/connection-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,SAAS,CAAC;AAkBvC,qBAAa,iBAAkB,SAAQ,YAAY;IACjD,OAAO,CAAC,EAAE,CAAU;IACpB,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,eAAe,CAA+D;IACtF,OAAO,CAAC,WAAW,CAAuG;gBAE9G,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY;IAM9C,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAqBjF,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAOtE,OAAO,CAAC,cAAc;IAOtB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,WAAW;IA4B3E,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,WAAW;IA2BrG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,WAAW;IAkC5E,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,WAAW;IAwB3H,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAwBlE,iBAAiB,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAI9E,oBAAoB,IAAI,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAOzE,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAazC,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI;IAO7D,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAyB/E,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI;IAKnE,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAelD,mBAAmB,IAAI,gBAAgB,EAAE;IAIzC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAK9D,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAM5F,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAI7G,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAS7D,aAAa,IAAI,IAAI;CAGtB"}
1
+ {"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../src/connection-manager.ts"],"names":[],"mappings":"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"}
@@ -3,16 +3,47 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ConnectionManager = void 0;
4
4
  const node_events_1 = require("node:events");
5
5
  const message_protocol_js_1 = require("./message-protocol.js");
6
+ async function reportStats(signalingUrl, endpoint, body) {
7
+ try {
8
+ const httpUrl = signalingUrl.replace("wss://", "https://").replace("ws://", "http://");
9
+ await fetch(`${httpUrl}/stats/${endpoint}`, {
10
+ method: "POST",
11
+ headers: { "Content-Type": "application/json" },
12
+ body: JSON.stringify(body),
13
+ });
14
+ }
15
+ catch {
16
+ // Stats reporting is best-effort, don't break on failure
17
+ }
18
+ }
6
19
  class ConnectionManager extends node_events_1.EventEmitter {
7
20
  db;
8
21
  profile;
9
22
  activePeers = new Map(); // connectionId -> peer
10
23
  incomingHandler = null;
11
24
  heldQueries = new Map();
12
- constructor(db, profile) {
25
+ signalingUrl;
26
+ pendingBytes = 0;
27
+ transferReportTimer = null;
28
+ constructor(db, profile, signalingUrl) {
13
29
  super();
14
30
  this.db = db;
15
31
  this.profile = profile;
32
+ this.signalingUrl = signalingUrl || "";
33
+ // Periodically flush transfer stats (every 60 seconds)
34
+ if (this.signalingUrl) {
35
+ this.transferReportTimer = setInterval(() => this.flushTransferStats(), 60000);
36
+ }
37
+ }
38
+ trackBytes(size) {
39
+ this.pendingBytes += size;
40
+ }
41
+ async flushTransferStats() {
42
+ if (this.pendingBytes > 0 && this.signalingUrl) {
43
+ const bytes = this.pendingBytes;
44
+ this.pendingBytes = 0;
45
+ await reportStats(this.signalingUrl, "transfer", { bytes });
46
+ }
16
47
  }
17
48
  registerPeer(connectionId, peerName, peerPublicKey) {
18
49
  this.activePeers.set(connectionId, {
@@ -32,6 +63,10 @@ class ConnectionManager extends node_events_1.EventEmitter {
32
63
  status: "active",
33
64
  });
34
65
  this.db.logEvent("connection_established", peerName, connectionId, null);
66
+ // Report session to stats
67
+ if (this.signalingUrl) {
68
+ reportStats(this.signalingUrl, "session", {});
69
+ }
35
70
  }
36
71
  setPeerSend(connectionId, sendFn) {
37
72
  const peer = this.activePeers.get(connectionId);
@@ -57,6 +92,7 @@ class ConnectionManager extends node_events_1.EventEmitter {
57
92
  const msg = (0, message_protocol_js_1.createQueryMessage)(this.profile.name, content, context);
58
93
  const serialized = (0, message_protocol_js_1.serializeMessage)(msg);
59
94
  peer.send(serialized);
95
+ this.trackBytes(serialized.length);
60
96
  this.db.logEvent("query_sent", peerName, peer.connectionId, content.slice(0, 100));
61
97
  this.db.saveMessage({
62
98
  id: msg.id,
@@ -81,6 +117,7 @@ class ConnectionManager extends node_events_1.EventEmitter {
81
117
  const msg = (0, message_protocol_js_1.createResponseMessage)(this.profile.name, replyTo, content, sourceFiles);
82
118
  const serialized = (0, message_protocol_js_1.serializeMessage)(msg);
83
119
  peer.send(serialized);
120
+ this.trackBytes(serialized.length);
84
121
  this.db.saveMessage({
85
122
  id: msg.id,
86
123
  connectionId: peer.connectionId,
@@ -109,6 +146,7 @@ class ConnectionManager extends node_events_1.EventEmitter {
109
146
  const msg = (0, message_protocol_js_1.createActionMessage)(this.profile.name, content, context);
110
147
  const serialized = (0, message_protocol_js_1.serializeMessage)(msg);
111
148
  peer.send(serialized);
149
+ this.trackBytes(serialized.length);
112
150
  this.db.logEvent("action_sent", peerName, peer.connectionId, content.slice(0, 100));
113
151
  this.db.saveMessage({
114
152
  id: msg.id,
@@ -130,6 +168,7 @@ class ConnectionManager extends node_events_1.EventEmitter {
130
168
  const msg = (0, message_protocol_js_1.createActionResultMessage)(this.profile.name, replyTo, content, success, sourceFiles);
131
169
  const serialized = (0, message_protocol_js_1.serializeMessage)(msg);
132
170
  peer.send(serialized);
171
+ this.trackBytes(serialized.length);
133
172
  this.db.saveMessage({
134
173
  id: msg.id,
135
174
  connectionId: peer.connectionId,
@@ -142,7 +181,52 @@ class ConnectionManager extends node_events_1.EventEmitter {
142
181
  });
143
182
  return msg;
144
183
  }
184
+ sendShareFiles(peerName, files) {
185
+ const peer = this.findPeerByName(peerName);
186
+ if (!peer || !peer.send) {
187
+ throw new Error(`No active connection with peer: ${peerName}`);
188
+ }
189
+ const msg = (0, message_protocol_js_1.createShareFileMessage)(this.profile.name, files);
190
+ const serialized = (0, message_protocol_js_1.serializeMessage)(msg);
191
+ peer.send(serialized);
192
+ this.trackBytes(serialized.length);
193
+ this.db.logEvent("share_files_sent", peerName, peer.connectionId, `${files.length} file(s)`);
194
+ this.db.saveMessage({
195
+ id: msg.id,
196
+ connectionId: peer.connectionId,
197
+ direction: "sent",
198
+ type: msg.type,
199
+ content: msg.content,
200
+ sourceFiles: JSON.stringify(files.map((f) => f.path)),
201
+ replyTo: null,
202
+ timestamp: msg.timestamp,
203
+ });
204
+ return msg;
205
+ }
206
+ sendShareContext(peerName, context) {
207
+ const peer = this.findPeerByName(peerName);
208
+ if (!peer || !peer.send) {
209
+ throw new Error(`No active connection with peer: ${peerName}`);
210
+ }
211
+ const msg = (0, message_protocol_js_1.createShareContextMessage)(this.profile.name, context);
212
+ const serialized = (0, message_protocol_js_1.serializeMessage)(msg);
213
+ peer.send(serialized);
214
+ this.trackBytes(serialized.length);
215
+ this.db.logEvent("share_context_sent", peerName, peer.connectionId, "project context");
216
+ this.db.saveMessage({
217
+ id: msg.id,
218
+ connectionId: peer.connectionId,
219
+ direction: "sent",
220
+ type: msg.type,
221
+ content: msg.content,
222
+ sourceFiles: null,
223
+ replyTo: null,
224
+ timestamp: msg.timestamp,
225
+ });
226
+ return msg;
227
+ }
145
228
  handleIncomingMessage(connectionId, rawData) {
229
+ this.trackBytes(rawData.length);
146
230
  const msg = (0, message_protocol_js_1.parseMessage)(rawData);
147
231
  if (!msg)
148
232
  return;