@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.
- package/Dockerfile +1 -1
- package/dist/bin/agentchat.d.ts +7 -0
- package/dist/bin/agentchat.d.ts.map +1 -0
- package/dist/bin/agentchat.js +1511 -0
- package/dist/bin/agentchat.js.map +1 -0
- package/dist/lib/allowlist.d.ts +77 -0
- package/dist/lib/allowlist.d.ts.map +1 -0
- package/dist/lib/allowlist.js +151 -0
- package/dist/lib/allowlist.js.map +1 -0
- package/dist/lib/client.d.ts +147 -0
- package/dist/lib/client.d.ts.map +1 -0
- package/dist/lib/client.js +704 -0
- package/dist/lib/client.js.map +1 -0
- package/dist/lib/daemon.d.ts +122 -0
- package/dist/lib/daemon.d.ts.map +1 -0
- package/dist/lib/daemon.js +523 -0
- package/dist/lib/daemon.js.map +1 -0
- package/dist/lib/deploy/akash.d.ts +271 -0
- package/dist/lib/deploy/akash.d.ts.map +1 -0
- package/dist/lib/deploy/akash.js +671 -0
- package/dist/lib/deploy/akash.js.map +1 -0
- package/dist/lib/deploy/config.d.ts +62 -0
- package/dist/lib/deploy/config.d.ts.map +1 -0
- package/dist/lib/deploy/config.js +116 -0
- package/dist/lib/deploy/config.js.map +1 -0
- package/dist/lib/deploy/docker.d.ts +37 -0
- package/dist/lib/deploy/docker.d.ts.map +1 -0
- package/dist/lib/deploy/docker.js +122 -0
- package/dist/lib/deploy/docker.js.map +1 -0
- package/dist/lib/deploy/index.d.ts +11 -0
- package/dist/lib/deploy/index.d.ts.map +1 -0
- package/dist/lib/deploy/index.js +11 -0
- package/dist/lib/deploy/index.js.map +1 -0
- package/dist/lib/escrow-hooks.d.ts +199 -0
- package/dist/lib/escrow-hooks.d.ts.map +1 -0
- package/dist/lib/escrow-hooks.js +221 -0
- package/dist/lib/escrow-hooks.js.map +1 -0
- package/dist/lib/identity.d.ts +134 -0
- package/dist/lib/identity.d.ts.map +1 -0
- package/dist/lib/identity.js +334 -0
- package/dist/lib/identity.js.map +1 -0
- package/dist/lib/jitter.d.ts +42 -0
- package/dist/lib/jitter.d.ts.map +1 -0
- package/{lib → dist/lib}/jitter.js +16 -19
- package/dist/lib/jitter.js.map +1 -0
- package/dist/lib/proposals.d.ts +223 -0
- package/dist/lib/proposals.d.ts.map +1 -0
- package/dist/lib/proposals.js +379 -0
- package/dist/lib/proposals.js.map +1 -0
- package/dist/lib/protocol.d.ts +220 -0
- package/dist/lib/protocol.d.ts.map +1 -0
- package/dist/lib/protocol.js +507 -0
- package/dist/lib/protocol.js.map +1 -0
- package/dist/lib/receipts.d.ts +134 -0
- package/dist/lib/receipts.d.ts.map +1 -0
- package/dist/lib/receipts.js +270 -0
- package/dist/lib/receipts.js.map +1 -0
- package/dist/lib/reputation.d.ts +250 -0
- package/dist/lib/reputation.d.ts.map +1 -0
- package/dist/lib/reputation.js +586 -0
- package/dist/lib/reputation.js.map +1 -0
- package/dist/lib/security.d.ts +27 -0
- package/dist/lib/security.d.ts.map +1 -0
- package/dist/lib/security.js +150 -0
- package/dist/lib/security.js.map +1 -0
- package/dist/lib/server/handlers/admin.d.ts +26 -0
- package/dist/lib/server/handlers/admin.d.ts.map +1 -0
- package/dist/lib/server/handlers/admin.js +76 -0
- package/dist/lib/server/handlers/admin.js.map +1 -0
- package/dist/lib/server/handlers/identity.d.ts +36 -0
- package/dist/lib/server/handlers/identity.d.ts.map +1 -0
- package/dist/lib/server/handlers/identity.js +330 -0
- package/dist/lib/server/handlers/identity.js.map +1 -0
- package/dist/lib/server/handlers/index.d.ts +10 -0
- package/dist/lib/server/handlers/index.d.ts.map +1 -0
- package/dist/lib/server/handlers/index.js +15 -0
- package/dist/lib/server/handlers/index.js.map +1 -0
- package/dist/lib/server/handlers/message.d.ts +47 -0
- package/dist/lib/server/handlers/message.d.ts.map +1 -0
- package/dist/lib/server/handlers/message.js +265 -0
- package/dist/lib/server/handlers/message.js.map +1 -0
- package/dist/lib/server/handlers/presence.d.ts +18 -0
- package/dist/lib/server/handlers/presence.d.ts.map +1 -0
- package/dist/lib/server/handlers/presence.js +35 -0
- package/dist/lib/server/handlers/presence.js.map +1 -0
- package/dist/lib/server/handlers/proposal.d.ts +38 -0
- package/dist/lib/server/handlers/proposal.d.ts.map +1 -0
- package/dist/lib/server/handlers/proposal.js +273 -0
- package/dist/lib/server/handlers/proposal.js.map +1 -0
- package/dist/lib/server/handlers/skills.d.ts +22 -0
- package/dist/lib/server/handlers/skills.d.ts.map +1 -0
- package/dist/lib/server/handlers/skills.js +119 -0
- package/dist/lib/server/handlers/skills.js.map +1 -0
- package/dist/lib/server-directory.d.ts +85 -0
- package/dist/lib/server-directory.d.ts.map +1 -0
- package/dist/lib/server-directory.js +177 -0
- package/dist/lib/server-directory.js.map +1 -0
- package/dist/lib/server.d.ts +162 -0
- package/dist/lib/server.d.ts.map +1 -0
- package/dist/lib/server.js +602 -0
- package/dist/lib/server.js.map +1 -0
- package/dist/lib/types.d.ts +461 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +98 -0
- package/dist/lib/types.js.map +1 -0
- package/package.json +22 -13
- package/bin/agentchat.js +0 -1617
- package/lib/chat.py +0 -241
- package/lib/client.js +0 -821
- package/lib/daemon.js +0 -562
- package/lib/deploy/akash.js +0 -811
- package/lib/deploy/config.js +0 -128
- package/lib/deploy/docker.js +0 -132
- package/lib/deploy/index.js +0 -24
- package/lib/elo_swarm.py +0 -569
- package/lib/escrow-hooks.js +0 -237
- package/lib/identity.js +0 -376
- package/lib/proposals.js +0 -426
- package/lib/protocol.js +0 -484
- package/lib/receipts.js +0 -294
- package/lib/reputation.js +0 -664
- package/lib/security.js +0 -183
- package/lib/server/handlers/identity.js +0 -242
- package/lib/server/handlers/index.js +0 -42
- package/lib/server/handlers/message.js +0 -306
- package/lib/server/handlers/presence.js +0 -44
- package/lib/server/handlers/proposal.js +0 -358
- package/lib/server/handlers/skills.js +0 -141
- package/lib/server-directory.js +0 -181
- package/lib/server.js +0 -528
- package/lib/supervisor/USAGE.md +0 -110
- package/lib/supervisor/agent-supervisor.sh +0 -135
- package/lib/supervisor/agentctl.sh +0 -250
- package/lib/supervisor/killswitch.sh +0 -36
- 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';
|