@nokai/cli 1.0.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 (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +193 -0
  3. package/dist/connection-manager.d.ts +45 -0
  4. package/dist/connection-manager.d.ts.map +1 -0
  5. package/dist/connection-manager.js +262 -0
  6. package/dist/connection-manager.js.map +1 -0
  7. package/dist/crypto.d.ts +8 -0
  8. package/dist/crypto.d.ts.map +1 -0
  9. package/dist/crypto.js +42 -0
  10. package/dist/crypto.js.map +1 -0
  11. package/dist/db.d.ts +47 -0
  12. package/dist/db.d.ts.map +1 -0
  13. package/dist/db.js +195 -0
  14. package/dist/db.js.map +1 -0
  15. package/dist/index.d.ts +3 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +9 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/message-protocol.d.ts +9 -0
  20. package/dist/message-protocol.d.ts.map +1 -0
  21. package/dist/message-protocol.js +85 -0
  22. package/dist/message-protocol.js.map +1 -0
  23. package/dist/peer-connection.d.ts +40 -0
  24. package/dist/peer-connection.d.ts.map +1 -0
  25. package/dist/peer-connection.js +159 -0
  26. package/dist/peer-connection.js.map +1 -0
  27. package/dist/profile.d.ts +11 -0
  28. package/dist/profile.d.ts.map +1 -0
  29. package/dist/profile.js +62 -0
  30. package/dist/profile.js.map +1 -0
  31. package/dist/server.d.ts +2 -0
  32. package/dist/server.d.ts.map +1 -0
  33. package/dist/server.js +185 -0
  34. package/dist/server.js.map +1 -0
  35. package/dist/shared/constants.d.ts +20 -0
  36. package/dist/shared/constants.d.ts.map +1 -0
  37. package/dist/shared/constants.js +23 -0
  38. package/dist/shared/constants.js.map +1 -0
  39. package/dist/shared/index.d.ts +3 -0
  40. package/dist/shared/index.d.ts.map +1 -0
  41. package/dist/shared/index.js +19 -0
  42. package/dist/shared/index.js.map +1 -0
  43. package/dist/shared/types.d.ts +128 -0
  44. package/dist/shared/types.d.ts.map +1 -0
  45. package/dist/shared/types.js +41 -0
  46. package/dist/shared/types.js.map +1 -0
  47. package/dist/signaling-client.d.ts +19 -0
  48. package/dist/signaling-client.d.ts.map +1 -0
  49. package/dist/signaling-client.js +83 -0
  50. package/dist/signaling-client.js.map +1 -0
  51. package/dist/tools/approve.d.ts +30 -0
  52. package/dist/tools/approve.d.ts.map +1 -0
  53. package/dist/tools/approve.js +46 -0
  54. package/dist/tools/approve.js.map +1 -0
  55. package/dist/tools/ask.d.ts +29 -0
  56. package/dist/tools/ask.d.ts.map +1 -0
  57. package/dist/tools/ask.js +43 -0
  58. package/dist/tools/ask.js.map +1 -0
  59. package/dist/tools/audit.d.ts +24 -0
  60. package/dist/tools/audit.d.ts.map +1 -0
  61. package/dist/tools/audit.js +39 -0
  62. package/dist/tools/audit.js.map +1 -0
  63. package/dist/tools/connect.d.ts +15 -0
  64. package/dist/tools/connect.d.ts.map +1 -0
  65. package/dist/tools/connect.js +62 -0
  66. package/dist/tools/connect.js.map +1 -0
  67. package/dist/tools/connections.d.ts +13 -0
  68. package/dist/tools/connections.d.ts.map +1 -0
  69. package/dist/tools/connections.js +34 -0
  70. package/dist/tools/connections.js.map +1 -0
  71. package/dist/tools/disconnect.d.ts +19 -0
  72. package/dist/tools/disconnect.d.ts.map +1 -0
  73. package/dist/tools/disconnect.js +23 -0
  74. package/dist/tools/disconnect.js.map +1 -0
  75. package/dist/tools/history.d.ts +24 -0
  76. package/dist/tools/history.d.ts.map +1 -0
  77. package/dist/tools/history.js +47 -0
  78. package/dist/tools/history.js.map +1 -0
  79. package/dist/tools/join.d.ts +22 -0
  80. package/dist/tools/join.d.ts.map +1 -0
  81. package/dist/tools/join.js +60 -0
  82. package/dist/tools/join.js.map +1 -0
  83. package/dist/tools/permissions.d.ts +24 -0
  84. package/dist/tools/permissions.d.ts.map +1 -0
  85. package/dist/tools/permissions.js +32 -0
  86. package/dist/tools/permissions.js.map +1 -0
  87. package/dist/tools/profile-tool.d.ts +29 -0
  88. package/dist/tools/profile-tool.d.ts.map +1 -0
  89. package/dist/tools/profile-tool.js +72 -0
  90. package/dist/tools/profile-tool.js.map +1 -0
  91. package/dist/tools/reconnect.d.ts +22 -0
  92. package/dist/tools/reconnect.d.ts.map +1 -0
  93. package/dist/tools/reconnect.js +88 -0
  94. package/dist/tools/reconnect.js.map +1 -0
  95. package/dist/tools/respond.d.ts +37 -0
  96. package/dist/tools/respond.d.ts.map +1 -0
  97. package/dist/tools/respond.js +31 -0
  98. package/dist/tools/respond.js.map +1 -0
  99. package/dist/tools/tell.d.ts +29 -0
  100. package/dist/tools/tell.d.ts.map +1 -0
  101. package/dist/tools/tell.js +45 -0
  102. package/dist/tools/tell.js.map +1 -0
  103. package/package.json +54 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 heiisenberrg
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,193 @@
1
+ # NokAI — Connecting AIs
2
+
3
+ > Every AI coding assistant is an island. NokAI makes them a team.
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
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.
8
+
9
+ **No code or conversation data ever touches the server.** The signaling server only brokers the initial handshake.
10
+
11
+ ## Quick Start
12
+
13
+ ```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
45
+ ```
46
+
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
69
+
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
+ ```
101
+
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
106
+
107
+ ## Security
108
+
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 |
117
+
118
+ ## Self-Hosting the Signaling Server
119
+
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
182
+
183
+ ## License
184
+
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.
@@ -0,0 +1,45 @@
1
+ import { EventEmitter } from "node:events";
2
+ import type { AgentProfile, PeerMessage, ConnectionRecord } from "./shared/index.js";
3
+ import { type NokaiDB } from "./db.js";
4
+ export declare class ConnectionManager extends EventEmitter {
5
+ private db;
6
+ private profile;
7
+ private activePeers;
8
+ private incomingHandler;
9
+ private heldQueries;
10
+ constructor(db: NokaiDB, profile: AgentProfile);
11
+ registerPeer(connectionId: string, peerName: string, peerPublicKey: string): void;
12
+ setPeerSend(connectionId: string, sendFn: (msg: string) => void): void;
13
+ private findPeerByName;
14
+ sendQuery(peerName: string, content: string, context?: string): PeerMessage;
15
+ sendResponse(peerName: string, replyTo: string, content: string, sourceFiles?: string[]): PeerMessage;
16
+ sendAction(peerName: string, content: string, context?: string): PeerMessage;
17
+ sendActionResult(peerName: string, replyTo: string, content: string, success: boolean, sourceFiles?: string[]): PeerMessage;
18
+ handleIncomingMessage(connectionId: string, rawData: string): void;
19
+ onIncomingMessage(handler: (msg: PeerMessage, peerName: string) => void): void;
20
+ getActiveConnections(): Array<{
21
+ connectionId: string;
22
+ peerName: string;
23
+ }>;
24
+ disconnectPeer(peerName: string): boolean;
25
+ setPeerClose(connectionId: string, closeFn: () => void): void;
26
+ reactivateConnection(connectionId: string, sendFn: (msg: string) => void): void;
27
+ queueMessage(connectionId: string, serializedMessage: string): void;
28
+ flushPendingMessages(connectionId: string): number;
29
+ getSavedConnections(): ConnectionRecord[];
30
+ findSavedConnection(peerName: string): ConnectionRecord | null;
31
+ holdQuery(peerName: string, query: {
32
+ id: string;
33
+ content: string;
34
+ timestamp: string;
35
+ }): void;
36
+ getHeldQueries(peerName: string): Array<{
37
+ id: string;
38
+ content: string;
39
+ peerName: string;
40
+ timestamp: string;
41
+ }>;
42
+ removeHeldQuery(peerName: string, messageId: string): boolean;
43
+ disconnectAll(): void;
44
+ }
45
+ //# sourceMappingURL=connection-manager.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,262 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConnectionManager = void 0;
4
+ const node_events_1 = require("node:events");
5
+ const message_protocol_js_1 = require("./message-protocol.js");
6
+ class ConnectionManager extends node_events_1.EventEmitter {
7
+ db;
8
+ profile;
9
+ activePeers = new Map(); // connectionId -> peer
10
+ incomingHandler = null;
11
+ heldQueries = new Map();
12
+ constructor(db, profile) {
13
+ super();
14
+ this.db = db;
15
+ this.profile = profile;
16
+ }
17
+ registerPeer(connectionId, peerName, peerPublicKey) {
18
+ this.activePeers.set(connectionId, {
19
+ connectionId,
20
+ peerName,
21
+ peerPublicKey,
22
+ send: null,
23
+ close: null,
24
+ });
25
+ this.db.saveConnection({
26
+ id: connectionId,
27
+ peerName,
28
+ peerPublicKey,
29
+ permission: "read-only",
30
+ createdAt: new Date().toISOString(),
31
+ lastConnected: new Date().toISOString(),
32
+ status: "active",
33
+ });
34
+ this.db.logEvent("connection_established", peerName, connectionId, null);
35
+ }
36
+ setPeerSend(connectionId, sendFn) {
37
+ const peer = this.activePeers.get(connectionId);
38
+ if (peer) {
39
+ peer.send = sendFn;
40
+ }
41
+ }
42
+ findPeerByName(peerName) {
43
+ for (const peer of this.activePeers.values()) {
44
+ if (peer.peerName === peerName)
45
+ return peer;
46
+ }
47
+ return undefined;
48
+ }
49
+ sendQuery(peerName, content, context) {
50
+ const peer = this.findPeerByName(peerName);
51
+ if (!peer) {
52
+ throw new Error(`No active connection with peer: ${peerName}`);
53
+ }
54
+ if (!peer.send) {
55
+ throw new Error(`Data channel not ready for peer: ${peerName}`);
56
+ }
57
+ const msg = (0, message_protocol_js_1.createQueryMessage)(this.profile.name, content, context);
58
+ const serialized = (0, message_protocol_js_1.serializeMessage)(msg);
59
+ peer.send(serialized);
60
+ this.db.logEvent("query_sent", peerName, peer.connectionId, content.slice(0, 100));
61
+ this.db.saveMessage({
62
+ id: msg.id,
63
+ connectionId: peer.connectionId,
64
+ direction: "sent",
65
+ type: msg.type,
66
+ content: msg.content,
67
+ sourceFiles: null,
68
+ replyTo: null,
69
+ timestamp: msg.timestamp,
70
+ });
71
+ return msg;
72
+ }
73
+ sendResponse(peerName, replyTo, content, sourceFiles) {
74
+ const peer = this.findPeerByName(peerName);
75
+ if (!peer) {
76
+ throw new Error(`No active connection with peer: ${peerName}`);
77
+ }
78
+ if (!peer.send) {
79
+ throw new Error(`Data channel not ready for peer: ${peerName}`);
80
+ }
81
+ const msg = (0, message_protocol_js_1.createResponseMessage)(this.profile.name, replyTo, content, sourceFiles);
82
+ const serialized = (0, message_protocol_js_1.serializeMessage)(msg);
83
+ peer.send(serialized);
84
+ this.db.saveMessage({
85
+ id: msg.id,
86
+ connectionId: peer.connectionId,
87
+ direction: "sent",
88
+ type: msg.type,
89
+ content: msg.content,
90
+ sourceFiles: sourceFiles ? JSON.stringify(sourceFiles) : null,
91
+ replyTo,
92
+ timestamp: msg.timestamp,
93
+ });
94
+ return msg;
95
+ }
96
+ sendAction(peerName, content, context) {
97
+ const peer = this.findPeerByName(peerName);
98
+ if (!peer) {
99
+ throw new Error(`No active connection with peer: ${peerName}`);
100
+ }
101
+ if (!peer.send) {
102
+ throw new Error(`Data channel not ready for peer: ${peerName}`);
103
+ }
104
+ // Check permission — actions require read-write
105
+ const conn = this.db.getConnectionByPeerName(peerName);
106
+ if (conn && conn.permission !== "read-write") {
107
+ throw new Error(`Permission denied: ${peerName} has "${conn.permission}" access. Actions require "read-write".`);
108
+ }
109
+ const msg = (0, message_protocol_js_1.createActionMessage)(this.profile.name, content, context);
110
+ const serialized = (0, message_protocol_js_1.serializeMessage)(msg);
111
+ peer.send(serialized);
112
+ this.db.logEvent("action_sent", peerName, peer.connectionId, content.slice(0, 100));
113
+ this.db.saveMessage({
114
+ id: msg.id,
115
+ connectionId: peer.connectionId,
116
+ direction: "sent",
117
+ type: msg.type,
118
+ content: msg.content,
119
+ sourceFiles: null,
120
+ replyTo: null,
121
+ timestamp: msg.timestamp,
122
+ });
123
+ return msg;
124
+ }
125
+ sendActionResult(peerName, replyTo, content, success, sourceFiles) {
126
+ const peer = this.findPeerByName(peerName);
127
+ if (!peer || !peer.send) {
128
+ throw new Error(`No active connection with peer: ${peerName}`);
129
+ }
130
+ const msg = (0, message_protocol_js_1.createActionResultMessage)(this.profile.name, replyTo, content, success, sourceFiles);
131
+ const serialized = (0, message_protocol_js_1.serializeMessage)(msg);
132
+ peer.send(serialized);
133
+ this.db.saveMessage({
134
+ id: msg.id,
135
+ connectionId: peer.connectionId,
136
+ direction: "sent",
137
+ type: msg.type,
138
+ content: msg.content,
139
+ sourceFiles: sourceFiles ? JSON.stringify(sourceFiles) : null,
140
+ replyTo,
141
+ timestamp: msg.timestamp,
142
+ });
143
+ return msg;
144
+ }
145
+ handleIncomingMessage(connectionId, rawData) {
146
+ const msg = (0, message_protocol_js_1.parseMessage)(rawData);
147
+ if (!msg)
148
+ return;
149
+ const peer = this.activePeers.get(connectionId);
150
+ if (!peer)
151
+ return;
152
+ this.db.saveMessage({
153
+ id: msg.id,
154
+ connectionId,
155
+ direction: "received",
156
+ type: msg.type,
157
+ content: msg.content,
158
+ sourceFiles: "sourceFiles" in msg && msg.sourceFiles ? JSON.stringify(msg.sourceFiles) : null,
159
+ replyTo: "replyTo" in msg ? msg.replyTo : null,
160
+ timestamp: msg.timestamp,
161
+ });
162
+ this.db.logEvent(`${msg.type}_received`, peer.peerName, connectionId, msg.content.slice(0, 100));
163
+ if (this.incomingHandler) {
164
+ this.incomingHandler(msg, peer.peerName);
165
+ }
166
+ }
167
+ onIncomingMessage(handler) {
168
+ this.incomingHandler = handler;
169
+ }
170
+ getActiveConnections() {
171
+ return Array.from(this.activePeers.values()).map((p) => ({
172
+ connectionId: p.connectionId,
173
+ peerName: p.peerName,
174
+ }));
175
+ }
176
+ disconnectPeer(peerName) {
177
+ for (const [id, peer] of this.activePeers.entries()) {
178
+ if (peer.peerName === peerName) {
179
+ if (peer.close)
180
+ peer.close();
181
+ this.activePeers.delete(id);
182
+ this.db.updateConnectionStatus(id, "dormant");
183
+ this.db.logEvent("connection_disconnected", peer.peerName, id, null);
184
+ return true;
185
+ }
186
+ }
187
+ return false;
188
+ }
189
+ setPeerClose(connectionId, closeFn) {
190
+ const peer = this.activePeers.get(connectionId);
191
+ if (peer) {
192
+ peer.close = closeFn;
193
+ }
194
+ }
195
+ reactivateConnection(connectionId, sendFn) {
196
+ const conn = this.db.getConnection(connectionId);
197
+ if (!conn) {
198
+ throw new Error(`Connection not found: ${connectionId}`);
199
+ }
200
+ this.activePeers.set(connectionId, {
201
+ connectionId,
202
+ peerName: conn.peerName,
203
+ peerPublicKey: conn.peerPublicKey,
204
+ send: sendFn,
205
+ close: null,
206
+ });
207
+ this.db.updateConnectionStatus(connectionId, "active");
208
+ this.db.updateLastConnected(connectionId, new Date().toISOString());
209
+ this.db.logEvent("connection_reactivated", conn.peerName, connectionId, null);
210
+ // Flush any queued messages
211
+ const flushed = this.flushPendingMessages(connectionId);
212
+ if (flushed > 0) {
213
+ console.error(`[NokAI] Delivered ${flushed} queued message(s)`);
214
+ }
215
+ }
216
+ queueMessage(connectionId, serializedMessage) {
217
+ const id = `pending_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
218
+ this.db.savePendingMessage(id, connectionId, serializedMessage);
219
+ }
220
+ flushPendingMessages(connectionId) {
221
+ const pending = this.db.getPendingMessages(connectionId);
222
+ if (pending.length === 0)
223
+ return 0;
224
+ const peer = this.activePeers.get(connectionId);
225
+ if (!peer || !peer.send)
226
+ return 0;
227
+ for (const msg of pending) {
228
+ peer.send(msg.content);
229
+ }
230
+ this.db.clearPendingMessages(connectionId);
231
+ return pending.length;
232
+ }
233
+ getSavedConnections() {
234
+ return this.db.listDormantConnections();
235
+ }
236
+ findSavedConnection(peerName) {
237
+ const saved = this.db.listDormantConnections();
238
+ return saved.find((c) => c.peerName === peerName) ?? null;
239
+ }
240
+ holdQuery(peerName, query) {
241
+ const existing = this.heldQueries.get(peerName) || [];
242
+ existing.push({ ...query, peerName });
243
+ this.heldQueries.set(peerName, existing);
244
+ }
245
+ getHeldQueries(peerName) {
246
+ return this.heldQueries.get(peerName) || [];
247
+ }
248
+ removeHeldQuery(peerName, messageId) {
249
+ const existing = this.heldQueries.get(peerName) || [];
250
+ const idx = existing.findIndex((q) => q.id === messageId);
251
+ if (idx === -1)
252
+ return false;
253
+ existing.splice(idx, 1);
254
+ this.heldQueries.set(peerName, existing);
255
+ return true;
256
+ }
257
+ disconnectAll() {
258
+ this.activePeers.clear();
259
+ }
260
+ }
261
+ exports.ConnectionManager = ConnectionManager;
262
+ //# sourceMappingURL=connection-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-manager.js","sourceRoot":"","sources":["../src/connection-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export interface Keypair {
2
+ publicKey: string;
3
+ privateKey: string;
4
+ }
5
+ export declare function generateKeypair(): Keypair;
6
+ export declare function sign(message: string, privateKeyHex: string): string;
7
+ export declare function verify(message: string, signatureHex: string, publicKeyHex: string): boolean;
8
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,IAAI,OAAO,CAUzC;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CASnE;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAa3F"}
package/dist/crypto.js ADDED
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateKeypair = generateKeypair;
4
+ exports.sign = sign;
5
+ exports.verify = verify;
6
+ const node_crypto_1 = require("node:crypto");
7
+ function generateKeypair() {
8
+ const { publicKey, privateKey } = (0, node_crypto_1.generateKeyPairSync)("ed25519", {
9
+ publicKeyEncoding: { type: "spki", format: "der" },
10
+ privateKeyEncoding: { type: "pkcs8", format: "der" },
11
+ });
12
+ return {
13
+ publicKey: publicKey.toString("hex"),
14
+ privateKey: privateKey.toString("hex"),
15
+ };
16
+ }
17
+ function sign(message, privateKeyHex) {
18
+ const privateKey = Buffer.from(privateKeyHex, "hex");
19
+ const keyObject = (0, node_crypto_1.createPrivateKey)({
20
+ key: privateKey,
21
+ format: "der",
22
+ type: "pkcs8",
23
+ });
24
+ const signature = (0, node_crypto_1.sign)(null, Buffer.from(message), keyObject);
25
+ return signature.toString("hex");
26
+ }
27
+ function verify(message, signatureHex, publicKeyHex) {
28
+ try {
29
+ const publicKey = Buffer.from(publicKeyHex, "hex");
30
+ const keyObject = (0, node_crypto_1.createPublicKey)({
31
+ key: publicKey,
32
+ format: "der",
33
+ type: "spki",
34
+ });
35
+ const signature = Buffer.from(signatureHex, "hex");
36
+ return (0, node_crypto_1.verify)(null, Buffer.from(message), keyObject, signature);
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
42
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":";;AAOA,0CAUC;AAED,oBASC;AAED,wBAaC;AA3CD,6CAAiI;AAOjI,SAAgB,eAAe;IAC7B,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAA,iCAAmB,EAAC,SAAS,EAAE;QAC/D,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;QAClD,kBAAkB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;KACrD,CAAC,CAAC;IAEH,OAAO;QACL,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC;QACpC,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;KACvC,CAAC;AACJ,CAAC;AAED,SAAgB,IAAI,CAAC,OAAe,EAAE,aAAqB;IACzD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,IAAA,8BAAgB,EAAC;QACjC,GAAG,EAAE,UAAU;QACf,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,IAAA,kBAAU,EAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,CAAC;IACpE,OAAO,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,SAAgB,MAAM,CAAC,OAAe,EAAE,YAAoB,EAAE,YAAoB;IAChF,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QACnD,MAAM,SAAS,GAAG,IAAA,6BAAe,EAAC;YAChC,GAAG,EAAE,SAAS;YACd,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QACnD,OAAO,IAAA,oBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
package/dist/db.d.ts ADDED
@@ -0,0 +1,47 @@
1
+ import type { ConnectionRecord, Permission } from "./shared/index.js";
2
+ export interface MessageRecord {
3
+ id: string;
4
+ connectionId: string;
5
+ direction: "sent" | "received";
6
+ type: string;
7
+ content: string;
8
+ sourceFiles: string | null;
9
+ replyTo: string | null;
10
+ timestamp: string;
11
+ }
12
+ export interface NokaiDB {
13
+ saveConnection(conn: ConnectionRecord): void;
14
+ getConnection(id: string): ConnectionRecord | null;
15
+ getConnectionByPeerName(peerName: string): ConnectionRecord | null;
16
+ listConnections(): ConnectionRecord[];
17
+ updateLastConnected(id: string, timestamp: string): void;
18
+ deleteConnection(id: string): void;
19
+ updateConnectionStatus(id: string, status: "active" | "dormant"): void;
20
+ getConnectionByPeerPublicKey(publicKey: string): ConnectionRecord | null;
21
+ listDormantConnections(): ConnectionRecord[];
22
+ saveMessage(msg: MessageRecord): void;
23
+ getMessages(connectionId: string, limit?: number): MessageRecord[];
24
+ savePendingMessage(id: string, connectionId: string, content: string): void;
25
+ getPendingMessages(connectionId: string): Array<{
26
+ id: string;
27
+ connectionId: string;
28
+ content: string;
29
+ createdAt: string;
30
+ }>;
31
+ clearPendingMessages(connectionId: string): void;
32
+ getApprovalMode(connectionId: string): "auto" | "manual";
33
+ setApprovalMode(connectionId: string, mode: "auto" | "manual"): void;
34
+ updatePermission(id: string, permission: Permission): void;
35
+ logEvent(eventType: string, peerName: string | null, connectionId: string | null, details: string | null): void;
36
+ getAuditLog(limit?: number): Array<{
37
+ id: number;
38
+ eventType: string;
39
+ peerName: string | null;
40
+ connectionId: string | null;
41
+ details: string | null;
42
+ timestamp: string;
43
+ }>;
44
+ close(): void;
45
+ }
46
+ export declare function createDatabase(dbPath: string): NokaiDB;
47
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEtE,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,OAAO;IACtB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC7C,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;IACnD,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;IACnE,eAAe,IAAI,gBAAgB,EAAE,CAAC;IACtC,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzD,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,sBAAsB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,IAAI,CAAC;IACvE,4BAA4B,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;IACzE,sBAAsB,IAAI,gBAAgB,EAAE,CAAC;IAC7C,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAAC;IACtC,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,aAAa,EAAE,CAAC;IACnE,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5E,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1H,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACjD,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;IACzD,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IACrE,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC3D,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAChH,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvK,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAyNtD"}