@tjamescouch/agentchat 0.22.0 → 0.23.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 (135) hide show
  1. package/Dockerfile +1 -1
  2. package/dist/bin/agentchat.d.ts +7 -0
  3. package/dist/bin/agentchat.d.ts.map +1 -0
  4. package/dist/bin/agentchat.js +1511 -0
  5. package/dist/bin/agentchat.js.map +1 -0
  6. package/dist/lib/allowlist.d.ts +77 -0
  7. package/dist/lib/allowlist.d.ts.map +1 -0
  8. package/dist/lib/allowlist.js +151 -0
  9. package/dist/lib/allowlist.js.map +1 -0
  10. package/dist/lib/client.d.ts +147 -0
  11. package/dist/lib/client.d.ts.map +1 -0
  12. package/dist/lib/client.js +704 -0
  13. package/dist/lib/client.js.map +1 -0
  14. package/dist/lib/daemon.d.ts +122 -0
  15. package/dist/lib/daemon.d.ts.map +1 -0
  16. package/dist/lib/daemon.js +523 -0
  17. package/dist/lib/daemon.js.map +1 -0
  18. package/dist/lib/deploy/akash.d.ts +271 -0
  19. package/dist/lib/deploy/akash.d.ts.map +1 -0
  20. package/dist/lib/deploy/akash.js +671 -0
  21. package/dist/lib/deploy/akash.js.map +1 -0
  22. package/dist/lib/deploy/config.d.ts +62 -0
  23. package/dist/lib/deploy/config.d.ts.map +1 -0
  24. package/dist/lib/deploy/config.js +116 -0
  25. package/dist/lib/deploy/config.js.map +1 -0
  26. package/dist/lib/deploy/docker.d.ts +37 -0
  27. package/dist/lib/deploy/docker.d.ts.map +1 -0
  28. package/dist/lib/deploy/docker.js +122 -0
  29. package/dist/lib/deploy/docker.js.map +1 -0
  30. package/dist/lib/deploy/index.d.ts +11 -0
  31. package/dist/lib/deploy/index.d.ts.map +1 -0
  32. package/dist/lib/deploy/index.js +11 -0
  33. package/dist/lib/deploy/index.js.map +1 -0
  34. package/dist/lib/escrow-hooks.d.ts +199 -0
  35. package/dist/lib/escrow-hooks.d.ts.map +1 -0
  36. package/dist/lib/escrow-hooks.js +221 -0
  37. package/dist/lib/escrow-hooks.js.map +1 -0
  38. package/dist/lib/identity.d.ts +134 -0
  39. package/dist/lib/identity.d.ts.map +1 -0
  40. package/dist/lib/identity.js +334 -0
  41. package/dist/lib/identity.js.map +1 -0
  42. package/dist/lib/jitter.d.ts +42 -0
  43. package/dist/lib/jitter.d.ts.map +1 -0
  44. package/{lib → dist/lib}/jitter.js +16 -19
  45. package/dist/lib/jitter.js.map +1 -0
  46. package/dist/lib/proposals.d.ts +223 -0
  47. package/dist/lib/proposals.d.ts.map +1 -0
  48. package/dist/lib/proposals.js +379 -0
  49. package/dist/lib/proposals.js.map +1 -0
  50. package/dist/lib/protocol.d.ts +220 -0
  51. package/dist/lib/protocol.d.ts.map +1 -0
  52. package/dist/lib/protocol.js +507 -0
  53. package/dist/lib/protocol.js.map +1 -0
  54. package/dist/lib/receipts.d.ts +134 -0
  55. package/dist/lib/receipts.d.ts.map +1 -0
  56. package/dist/lib/receipts.js +270 -0
  57. package/dist/lib/receipts.js.map +1 -0
  58. package/dist/lib/reputation.d.ts +250 -0
  59. package/dist/lib/reputation.d.ts.map +1 -0
  60. package/dist/lib/reputation.js +586 -0
  61. package/dist/lib/reputation.js.map +1 -0
  62. package/dist/lib/security.d.ts +27 -0
  63. package/dist/lib/security.d.ts.map +1 -0
  64. package/dist/lib/security.js +150 -0
  65. package/dist/lib/security.js.map +1 -0
  66. package/dist/lib/server/handlers/admin.d.ts +26 -0
  67. package/dist/lib/server/handlers/admin.d.ts.map +1 -0
  68. package/dist/lib/server/handlers/admin.js +76 -0
  69. package/dist/lib/server/handlers/admin.js.map +1 -0
  70. package/dist/lib/server/handlers/identity.d.ts +36 -0
  71. package/dist/lib/server/handlers/identity.d.ts.map +1 -0
  72. package/dist/lib/server/handlers/identity.js +330 -0
  73. package/dist/lib/server/handlers/identity.js.map +1 -0
  74. package/dist/lib/server/handlers/index.d.ts +10 -0
  75. package/dist/lib/server/handlers/index.d.ts.map +1 -0
  76. package/dist/lib/server/handlers/index.js +15 -0
  77. package/dist/lib/server/handlers/index.js.map +1 -0
  78. package/dist/lib/server/handlers/message.d.ts +47 -0
  79. package/dist/lib/server/handlers/message.d.ts.map +1 -0
  80. package/dist/lib/server/handlers/message.js +265 -0
  81. package/dist/lib/server/handlers/message.js.map +1 -0
  82. package/dist/lib/server/handlers/presence.d.ts +18 -0
  83. package/dist/lib/server/handlers/presence.d.ts.map +1 -0
  84. package/dist/lib/server/handlers/presence.js +35 -0
  85. package/dist/lib/server/handlers/presence.js.map +1 -0
  86. package/dist/lib/server/handlers/proposal.d.ts +38 -0
  87. package/dist/lib/server/handlers/proposal.d.ts.map +1 -0
  88. package/dist/lib/server/handlers/proposal.js +273 -0
  89. package/dist/lib/server/handlers/proposal.js.map +1 -0
  90. package/dist/lib/server/handlers/skills.d.ts +22 -0
  91. package/dist/lib/server/handlers/skills.d.ts.map +1 -0
  92. package/dist/lib/server/handlers/skills.js +119 -0
  93. package/dist/lib/server/handlers/skills.js.map +1 -0
  94. package/dist/lib/server-directory.d.ts +85 -0
  95. package/dist/lib/server-directory.d.ts.map +1 -0
  96. package/dist/lib/server-directory.js +177 -0
  97. package/dist/lib/server-directory.js.map +1 -0
  98. package/dist/lib/server.d.ts +162 -0
  99. package/dist/lib/server.d.ts.map +1 -0
  100. package/dist/lib/server.js +602 -0
  101. package/dist/lib/server.js.map +1 -0
  102. package/dist/lib/types.d.ts +461 -0
  103. package/dist/lib/types.d.ts.map +1 -0
  104. package/dist/lib/types.js +98 -0
  105. package/dist/lib/types.js.map +1 -0
  106. package/package.json +22 -13
  107. package/bin/agentchat.js +0 -1617
  108. package/lib/chat.py +0 -241
  109. package/lib/client.js +0 -821
  110. package/lib/daemon.js +0 -562
  111. package/lib/deploy/akash.js +0 -811
  112. package/lib/deploy/config.js +0 -128
  113. package/lib/deploy/docker.js +0 -132
  114. package/lib/deploy/index.js +0 -24
  115. package/lib/elo_swarm.py +0 -569
  116. package/lib/escrow-hooks.js +0 -237
  117. package/lib/identity.js +0 -376
  118. package/lib/proposals.js +0 -426
  119. package/lib/protocol.js +0 -484
  120. package/lib/receipts.js +0 -294
  121. package/lib/reputation.js +0 -664
  122. package/lib/security.js +0 -183
  123. package/lib/server/handlers/identity.js +0 -242
  124. package/lib/server/handlers/index.js +0 -42
  125. package/lib/server/handlers/message.js +0 -306
  126. package/lib/server/handlers/presence.js +0 -44
  127. package/lib/server/handlers/proposal.js +0 -358
  128. package/lib/server/handlers/skills.js +0 -141
  129. package/lib/server-directory.js +0 -181
  130. package/lib/server.js +0 -528
  131. package/lib/supervisor/USAGE.md +0 -110
  132. package/lib/supervisor/agent-supervisor.sh +0 -135
  133. package/lib/supervisor/agentctl.sh +0 -250
  134. package/lib/supervisor/killswitch.sh +0 -36
  135. package/lib/supervisor/notify.sh +0 -19
package/lib/security.js DELETED
@@ -1,183 +0,0 @@
1
- /**
2
- * Security utilities for AgentChat
3
- * Prevents running agents in dangerous directories
4
- */
5
-
6
- import path from 'path';
7
- import os from 'os';
8
-
9
- // Directories that are absolutely forbidden (system roots)
10
- const FORBIDDEN_DIRECTORIES = new Set([
11
- '/',
12
- '/root',
13
- '/home',
14
- '/Users',
15
- '/var',
16
- '/etc',
17
- '/usr',
18
- '/bin',
19
- '/sbin',
20
- '/lib',
21
- '/opt',
22
- '/tmp',
23
- '/System',
24
- '/Applications',
25
- '/Library',
26
- '/private',
27
- '/private/var',
28
- '/private/tmp',
29
- 'C:\\',
30
- 'C:\\Windows',
31
- 'C:\\Program Files',
32
- 'C:\\Program Files (x86)',
33
- 'C:\\Users',
34
- ]);
35
-
36
- // Minimum depth from root required for a "project" directory
37
- // e.g., /Users/name/projects/myproject = depth 4 (minimum required)
38
- const MIN_SAFE_DEPTH = 3;
39
-
40
- /**
41
- * Get the depth of a path from root
42
- * @param {string} dirPath - Directory path to check
43
- * @returns {number} - Number of directory levels from root
44
- */
45
- function getPathDepth(dirPath) {
46
- const normalized = path.normalize(dirPath);
47
- const parts = normalized.split(path.sep).filter(p => p && p !== '.');
48
- return parts.length;
49
- }
50
-
51
- /**
52
- * Check if directory is a user's home directory
53
- * @param {string} dirPath - Directory path to check
54
- * @returns {boolean}
55
- */
56
- function isHomeDirectory(dirPath) {
57
- const normalized = path.normalize(dirPath);
58
- const homeDir = os.homedir();
59
-
60
- // Check exact match with home directory
61
- if (normalized === homeDir || normalized === homeDir + path.sep) {
62
- return true;
63
- }
64
-
65
- // Check common home directory patterns
66
- const homePatterns = [
67
- /^\/Users\/[^/]+$/, // macOS: /Users/username
68
- /^\/home\/[^/]+$/, // Linux: /home/username
69
- /^C:\\Users\\[^\\]+$/i, // Windows: C:\Users\username
70
- ];
71
-
72
- return homePatterns.some(pattern => pattern.test(normalized));
73
- }
74
-
75
- /**
76
- * Check if a directory is safe for running agentchat
77
- * @param {string} dirPath - Directory path to check (defaults to cwd)
78
- * @returns {{safe: boolean, error?: string, warning?: string, level: 'error'|'warning'|'ok'}}
79
- */
80
- export function checkDirectorySafety(dirPath = process.cwd()) {
81
- const normalized = path.normalize(path.resolve(dirPath));
82
-
83
- // Check forbidden directories
84
- if (FORBIDDEN_DIRECTORIES.has(normalized)) {
85
- return {
86
- safe: false,
87
- level: 'error',
88
- error: `Cannot run agentchat in system directory: ${normalized}\n` +
89
- `Please run from a project directory instead.`
90
- };
91
- }
92
-
93
- // Check if it's a home directory BEFORE depth check
94
- // Home directories are allowed but warn (they're at depth 2 which would fail depth check)
95
- if (isHomeDirectory(normalized)) {
96
- return {
97
- safe: true,
98
- level: 'warning',
99
- warning: `Running agentchat in home directory: ${normalized}\n` +
100
- `Consider running from a specific project directory instead.`
101
- };
102
- }
103
-
104
- // Check path depth (too shallow = too close to root)
105
- const depth = getPathDepth(normalized);
106
- if (depth < MIN_SAFE_DEPTH) {
107
- return {
108
- safe: false,
109
- level: 'error',
110
- error: `Cannot run agentchat in root-level directory: ${normalized}\n` +
111
- `This directory is too close to the filesystem root.\n` +
112
- `Please run from a project directory (at least ${MIN_SAFE_DEPTH} levels deep).`
113
- };
114
- }
115
-
116
- // All checks passed
117
- return {
118
- safe: true,
119
- level: 'ok'
120
- };
121
- }
122
-
123
- /**
124
- * Enforce directory safety check - throws if unsafe
125
- * @param {string} dirPath - Directory path to check (defaults to cwd)
126
- * @param {object} options - Options
127
- * @param {boolean} options.allowWarnings - If true, don't throw on warnings (default: true)
128
- * @param {boolean} options.silent - If true, don't print warnings (default: false)
129
- * @throws {Error} If directory is not safe
130
- */
131
- export function enforceDirectorySafety(dirPath = process.cwd(), options = {}) {
132
- const { allowWarnings = true, silent = false } = options;
133
-
134
- const result = checkDirectorySafety(dirPath);
135
-
136
- if (result.level === 'error') {
137
- throw new Error(result.error);
138
- }
139
-
140
- if (result.level === 'warning') {
141
- if (!silent) {
142
- console.error(`\n⚠️ WARNING: ${result.warning}\n`);
143
- }
144
- if (!allowWarnings) {
145
- throw new Error(result.warning);
146
- }
147
- }
148
-
149
- return result;
150
- }
151
-
152
- /**
153
- * Check if running in a project directory (has common project indicators)
154
- * @param {string} dirPath - Directory path to check
155
- * @returns {boolean}
156
- */
157
- export function looksLikeProjectDirectory(dirPath = process.cwd()) {
158
- const projectIndicators = [
159
- 'package.json',
160
- 'Cargo.toml',
161
- 'go.mod',
162
- 'pyproject.toml',
163
- 'setup.py',
164
- 'requirements.txt',
165
- 'Gemfile',
166
- 'pom.xml',
167
- 'build.gradle',
168
- 'Makefile',
169
- 'CMakeLists.txt',
170
- '.git',
171
- '.gitignore',
172
- 'README.md',
173
- 'README',
174
- ];
175
-
176
- // This is a heuristic check - doesn't actually verify files exist
177
- // Just checks if the path looks reasonable
178
- const normalized = path.normalize(path.resolve(dirPath));
179
- const depth = getPathDepth(normalized);
180
-
181
- // If it's deep enough and not a system directory, it probably looks like a project
182
- return depth >= MIN_SAFE_DEPTH && !FORBIDDEN_DIRECTORIES.has(normalized);
183
- }
@@ -1,242 +0,0 @@
1
- /**
2
- * Identity Handlers
3
- * Handles identify, verification request/response
4
- */
5
-
6
- import crypto from 'crypto';
7
- import {
8
- ServerMessageType,
9
- ErrorCode,
10
- createMessage,
11
- createError,
12
- generateAgentId,
13
- generateVerifyId,
14
- pubkeyToAgentId,
15
- } from '../../protocol.js';
16
-
17
- /**
18
- * Handle IDENTIFY command
19
- */
20
- export function handleIdentify(server, ws, msg) {
21
- // Check if already identified
22
- if (server.agents.has(ws)) {
23
- server._send(ws, createError(ErrorCode.INVALID_MSG, 'Already identified'));
24
- return;
25
- }
26
-
27
- let id;
28
-
29
- // Use pubkey-derived stable ID if pubkey provided
30
- if (msg.pubkey) {
31
- // Check if this pubkey has connected before
32
- const existingId = server.pubkeyToId.get(msg.pubkey);
33
- if (existingId) {
34
- // Returning agent - use their stable ID
35
- id = existingId;
36
- } else {
37
- // New agent with pubkey - generate stable ID from pubkey
38
- id = pubkeyToAgentId(msg.pubkey);
39
- server.pubkeyToId.set(msg.pubkey, id);
40
- }
41
-
42
- // Check if this ID is currently in use by another connection
43
- if (server.agentById.has(id)) {
44
- // Kick the old connection instead of rejecting the new one
45
- const oldWs = server.agentById.get(id);
46
- server._log('identity-takeover', { id, reason: 'New connection with same identity' });
47
- server._send(oldWs, createError(ErrorCode.INVALID_MSG, 'Disconnected: Another connection claimed this identity'));
48
- server._handleDisconnect(oldWs);
49
- oldWs.close(1000, 'Identity claimed by new connection');
50
- }
51
- } else {
52
- // Ephemeral agent - generate random ID
53
- id = generateAgentId();
54
- }
55
-
56
- const agent = {
57
- id,
58
- name: msg.name,
59
- pubkey: msg.pubkey || null,
60
- channels: new Set(),
61
- connectedAt: Date.now(),
62
- presence: 'online',
63
- statusText: null
64
- };
65
-
66
- server.agents.set(ws, agent);
67
- server.agentById.set(id, ws);
68
-
69
- // Determine if this is a new or returning identity
70
- const isReturning = msg.pubkey && server.pubkeyToId.has(msg.pubkey);
71
- const isEphemeral = !msg.pubkey;
72
-
73
- server._log('identify', {
74
- id,
75
- name: msg.name,
76
- hasPubkey: !!msg.pubkey,
77
- returning: isReturning,
78
- ephemeral: isEphemeral,
79
- ip: ws._realIp,
80
- user_agent: ws._userAgent
81
- });
82
-
83
- server._send(ws, createMessage(ServerMessageType.WELCOME, {
84
- agent_id: `@${id}`,
85
- server: server.serverName
86
- }));
87
- }
88
-
89
- /**
90
- * Handle VERIFY_REQUEST command
91
- */
92
- export function handleVerifyRequest(server, ws, msg) {
93
- const agent = server.agents.get(ws);
94
- if (!agent) {
95
- server._send(ws, createError(ErrorCode.AUTH_REQUIRED, 'Must IDENTIFY first'));
96
- return;
97
- }
98
-
99
- // Find target agent
100
- const targetId = msg.target.slice(1);
101
- const targetWs = server.agentById.get(targetId);
102
-
103
- if (!targetWs) {
104
- server._send(ws, createError(ErrorCode.AGENT_NOT_FOUND, `Agent ${msg.target} not found`));
105
- return;
106
- }
107
-
108
- const targetAgent = server.agents.get(targetWs);
109
-
110
- // Target must have a pubkey for verification
111
- if (!targetAgent.pubkey) {
112
- server._send(ws, createError(ErrorCode.NO_PUBKEY, `Agent ${msg.target} has no persistent identity`));
113
- return;
114
- }
115
-
116
- // Create verification request
117
- const requestId = generateVerifyId();
118
- const expires = Date.now() + server.verificationTimeoutMs;
119
-
120
- server.pendingVerifications.set(requestId, {
121
- from: `@${agent.id}`,
122
- fromWs: ws,
123
- target: msg.target,
124
- targetPubkey: targetAgent.pubkey,
125
- nonce: msg.nonce,
126
- expires
127
- });
128
-
129
- // Set timeout to clean up expired requests
130
- setTimeout(() => {
131
- const request = server.pendingVerifications.get(requestId);
132
- if (request) {
133
- server.pendingVerifications.delete(requestId);
134
- // Notify requester of timeout
135
- if (request.fromWs.readyState === 1) {
136
- server._send(request.fromWs, createMessage(ServerMessageType.VERIFY_FAILED, {
137
- request_id: requestId,
138
- target: request.target,
139
- reason: 'Verification timed out'
140
- }));
141
- }
142
- }
143
- }, server.verificationTimeoutMs);
144
-
145
- server._log('verify_request', { id: requestId, from: agent.id, target: targetId });
146
-
147
- // Forward to target agent
148
- server._send(targetWs, createMessage(ServerMessageType.VERIFY_REQUEST, {
149
- request_id: requestId,
150
- from: `@${agent.id}`,
151
- nonce: msg.nonce
152
- }));
153
-
154
- // Acknowledge to requester
155
- server._send(ws, createMessage(ServerMessageType.VERIFY_REQUEST, {
156
- request_id: requestId,
157
- target: msg.target,
158
- status: 'pending'
159
- }));
160
- }
161
-
162
- /**
163
- * Handle VERIFY_RESPONSE command
164
- */
165
- export function handleVerifyResponse(server, ws, msg) {
166
- const agent = server.agents.get(ws);
167
- if (!agent) {
168
- server._send(ws, createError(ErrorCode.AUTH_REQUIRED, 'Must IDENTIFY first'));
169
- return;
170
- }
171
-
172
- // Must have identity to respond to verification
173
- if (!agent.pubkey) {
174
- server._send(ws, createError(ErrorCode.SIGNATURE_REQUIRED, 'Responding to verification requires persistent identity'));
175
- return;
176
- }
177
-
178
- // Find the pending verification
179
- const request = server.pendingVerifications.get(msg.request_id);
180
- if (!request) {
181
- server._send(ws, createError(ErrorCode.VERIFICATION_EXPIRED, 'Verification request not found or expired'));
182
- return;
183
- }
184
-
185
- // Verify the responder is the target
186
- if (request.target !== `@${agent.id}`) {
187
- server._send(ws, createError(ErrorCode.INVALID_MSG, 'You are not the target of this verification'));
188
- return;
189
- }
190
-
191
- // Verify the nonce matches
192
- if (msg.nonce !== request.nonce) {
193
- server._send(ws, createError(ErrorCode.INVALID_MSG, 'Nonce mismatch'));
194
- return;
195
- }
196
-
197
- // Verify the signature
198
- let verified = false;
199
- try {
200
- const keyObj = crypto.createPublicKey(request.targetPubkey);
201
- verified = crypto.verify(
202
- null,
203
- Buffer.from(msg.nonce),
204
- keyObj,
205
- Buffer.from(msg.sig, 'base64')
206
- );
207
- } catch (err) {
208
- server._log('verify_error', { request_id: msg.request_id, error: err.message });
209
- }
210
-
211
- // Clean up the pending request
212
- server.pendingVerifications.delete(msg.request_id);
213
-
214
- server._log('verify_response', {
215
- request_id: msg.request_id,
216
- from: agent.id,
217
- verified
218
- });
219
-
220
- // Notify the original requester
221
- if (request.fromWs.readyState === 1) {
222
- if (verified) {
223
- server._send(request.fromWs, createMessage(ServerMessageType.VERIFY_SUCCESS, {
224
- request_id: msg.request_id,
225
- agent: request.target,
226
- pubkey: request.targetPubkey
227
- }));
228
- } else {
229
- server._send(request.fromWs, createMessage(ServerMessageType.VERIFY_FAILED, {
230
- request_id: msg.request_id,
231
- target: request.target,
232
- reason: 'Signature verification failed'
233
- }));
234
- }
235
- }
236
-
237
- // Notify the responder
238
- server._send(ws, createMessage(verified ? ServerMessageType.VERIFY_SUCCESS : ServerMessageType.VERIFY_FAILED, {
239
- request_id: msg.request_id,
240
- verified
241
- }));
242
- }
@@ -1,42 +0,0 @@
1
- /**
2
- * Server Handlers Index
3
- * Exports all handler functions
4
- */
5
-
6
- // Message handlers
7
- export {
8
- handleMsg,
9
- handleJoin,
10
- handleLeave,
11
- handleListChannels,
12
- handleListAgents,
13
- handleCreateChannel,
14
- handleInvite,
15
- } from './message.js';
16
-
17
- // Proposal handlers
18
- export {
19
- handleProposal,
20
- handleAccept,
21
- handleReject,
22
- handleComplete,
23
- handleDispute,
24
- } from './proposal.js';
25
-
26
- // Identity handlers
27
- export {
28
- handleIdentify,
29
- handleVerifyRequest,
30
- handleVerifyResponse,
31
- } from './identity.js';
32
-
33
- // Skills handlers
34
- export {
35
- handleRegisterSkills,
36
- handleSearchSkills,
37
- } from './skills.js';
38
-
39
- // Presence handlers
40
- export {
41
- handleSetPresence,
42
- } from './presence.js';