agent-relay 0.1.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/CHANGELOG.md +11 -0
- package/LICENSE +22 -0
- package/PROTOCOL.md +319 -0
- package/README.md +791 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +1591 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/daemon/connection.d.ts +60 -0
- package/dist/daemon/connection.d.ts.map +1 -0
- package/dist/daemon/connection.js +245 -0
- package/dist/daemon/connection.js.map +1 -0
- package/dist/daemon/index.d.ts +4 -0
- package/dist/daemon/index.d.ts.map +1 -0
- package/dist/daemon/index.js +4 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/router.d.ts +72 -0
- package/dist/daemon/router.d.ts.map +1 -0
- package/dist/daemon/router.js +183 -0
- package/dist/daemon/router.js.map +1 -0
- package/dist/daemon/server.d.ts +52 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +186 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/dashboard/public/index.html +690 -0
- package/dist/dashboard/server.d.ts +2 -0
- package/dist/dashboard/server.d.ts.map +1 -0
- package/dist/dashboard/server.js +220 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/games/index.d.ts +2 -0
- package/dist/games/index.d.ts.map +1 -0
- package/dist/games/index.js +2 -0
- package/dist/games/index.js.map +1 -0
- package/dist/games/tictactoe.d.ts +24 -0
- package/dist/games/tictactoe.d.ts.map +1 -0
- package/dist/games/tictactoe.js +160 -0
- package/dist/games/tictactoe.js.map +1 -0
- package/dist/hooks/inbox-check/hook.d.ts +28 -0
- package/dist/hooks/inbox-check/hook.d.ts.map +1 -0
- package/dist/hooks/inbox-check/hook.js +97 -0
- package/dist/hooks/inbox-check/hook.js.map +1 -0
- package/dist/hooks/inbox-check/index.d.ts +8 -0
- package/dist/hooks/inbox-check/index.d.ts.map +1 -0
- package/dist/hooks/inbox-check/index.js +8 -0
- package/dist/hooks/inbox-check/index.js.map +1 -0
- package/dist/hooks/inbox-check/types.d.ts +31 -0
- package/dist/hooks/inbox-check/types.d.ts.map +1 -0
- package/dist/hooks/inbox-check/types.js +5 -0
- package/dist/hooks/inbox-check/types.js.map +1 -0
- package/dist/hooks/inbox-check/utils.d.ts +44 -0
- package/dist/hooks/inbox-check/utils.d.ts.map +1 -0
- package/dist/hooks/inbox-check/utils.js +107 -0
- package/dist/hooks/inbox-check/utils.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol/framing.d.ts +32 -0
- package/dist/protocol/framing.d.ts.map +1 -0
- package/dist/protocol/framing.js +71 -0
- package/dist/protocol/framing.js.map +1 -0
- package/dist/protocol/index.d.ts +3 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/index.js +3 -0
- package/dist/protocol/index.js.map +1 -0
- package/dist/protocol/types.d.ts +104 -0
- package/dist/protocol/types.d.ts.map +1 -0
- package/dist/protocol/types.js +6 -0
- package/dist/protocol/types.js.map +1 -0
- package/dist/state/agent-state.d.ts +40 -0
- package/dist/state/agent-state.d.ts.map +1 -0
- package/dist/state/agent-state.js +120 -0
- package/dist/state/agent-state.js.map +1 -0
- package/dist/storage/adapter.d.ts +29 -0
- package/dist/storage/adapter.d.ts.map +1 -0
- package/dist/storage/adapter.js +2 -0
- package/dist/storage/adapter.js.map +1 -0
- package/dist/storage/sqlite-adapter.d.ts +15 -0
- package/dist/storage/sqlite-adapter.d.ts.map +1 -0
- package/dist/storage/sqlite-adapter.js +116 -0
- package/dist/storage/sqlite-adapter.js.map +1 -0
- package/dist/supervisor/inbox.d.ts +38 -0
- package/dist/supervisor/inbox.d.ts.map +1 -0
- package/dist/supervisor/inbox.js +162 -0
- package/dist/supervisor/inbox.js.map +1 -0
- package/dist/supervisor/index.d.ts +10 -0
- package/dist/supervisor/index.d.ts.map +1 -0
- package/dist/supervisor/index.js +10 -0
- package/dist/supervisor/index.js.map +1 -0
- package/dist/supervisor/spawner.d.ts +54 -0
- package/dist/supervisor/spawner.d.ts.map +1 -0
- package/dist/supervisor/spawner.js +282 -0
- package/dist/supervisor/spawner.js.map +1 -0
- package/dist/supervisor/state.d.ts +132 -0
- package/dist/supervisor/state.d.ts.map +1 -0
- package/dist/supervisor/state.js +465 -0
- package/dist/supervisor/state.js.map +1 -0
- package/dist/supervisor/supervisor.d.ts +67 -0
- package/dist/supervisor/supervisor.d.ts.map +1 -0
- package/dist/supervisor/supervisor.js +263 -0
- package/dist/supervisor/supervisor.js.map +1 -0
- package/dist/supervisor/types.d.ts +139 -0
- package/dist/supervisor/types.d.ts.map +1 -0
- package/dist/supervisor/types.js +12 -0
- package/dist/supervisor/types.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/name-generator.d.ts +17 -0
- package/dist/utils/name-generator.d.ts.map +1 -0
- package/dist/utils/name-generator.js +52 -0
- package/dist/utils/name-generator.js.map +1 -0
- package/dist/webhook/spawner.d.ts +79 -0
- package/dist/webhook/spawner.d.ts.map +1 -0
- package/dist/webhook/spawner.js +288 -0
- package/dist/webhook/spawner.js.map +1 -0
- package/dist/wrapper/client.d.ts +72 -0
- package/dist/wrapper/client.d.ts.map +1 -0
- package/dist/wrapper/client.js +306 -0
- package/dist/wrapper/client.js.map +1 -0
- package/dist/wrapper/inbox.d.ts +37 -0
- package/dist/wrapper/inbox.d.ts.map +1 -0
- package/dist/wrapper/inbox.js +73 -0
- package/dist/wrapper/inbox.js.map +1 -0
- package/dist/wrapper/index.d.ts +4 -0
- package/dist/wrapper/index.d.ts.map +1 -0
- package/dist/wrapper/index.js +7 -0
- package/dist/wrapper/index.js.map +1 -0
- package/dist/wrapper/parser.d.ts +94 -0
- package/dist/wrapper/parser.d.ts.map +1 -0
- package/dist/wrapper/parser.js +360 -0
- package/dist/wrapper/parser.js.map +1 -0
- package/dist/wrapper/pty-wrapper.d.ts +125 -0
- package/dist/wrapper/pty-wrapper.d.ts.map +1 -0
- package/dist/wrapper/pty-wrapper.js +494 -0
- package/dist/wrapper/pty-wrapper.js.map +1 -0
- package/dist/wrapper/tmux-wrapper.d.ts +131 -0
- package/dist/wrapper/tmux-wrapper.d.ts.map +1 -0
- package/dist/wrapper/tmux-wrapper.js +427 -0
- package/dist/wrapper/tmux-wrapper.js.map +1 -0
- package/install.sh +69 -0
- package/package.json +82 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Relay Supervisor
|
|
3
|
+
*
|
|
4
|
+
* Main supervisor loop that:
|
|
5
|
+
* 1. Watches registered agents for inbox messages
|
|
6
|
+
* 2. Spawns fresh CLI runs when messages arrive
|
|
7
|
+
* 3. Captures output and routes relay commands
|
|
8
|
+
* 4. Updates agent state for context preservation
|
|
9
|
+
*/
|
|
10
|
+
import fs from 'node:fs';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import { RelayClient } from '../wrapper/client.js';
|
|
13
|
+
import { StateRegistry } from './state.js';
|
|
14
|
+
import { CLISpawner } from './spawner.js';
|
|
15
|
+
import { claimInbox, finalizeClaim } from './inbox.js';
|
|
16
|
+
export class Supervisor {
|
|
17
|
+
config;
|
|
18
|
+
registry;
|
|
19
|
+
spawner;
|
|
20
|
+
client;
|
|
21
|
+
running = false;
|
|
22
|
+
pollTimer;
|
|
23
|
+
constructor(config = {}) {
|
|
24
|
+
this.config = {
|
|
25
|
+
dataDir: '/tmp/agent-relay',
|
|
26
|
+
pollIntervalMs: 2000,
|
|
27
|
+
maxRecentMessages: 20,
|
|
28
|
+
maxSummaryLength: 2000,
|
|
29
|
+
socketPath: '/tmp/agent-relay.sock',
|
|
30
|
+
verbose: false,
|
|
31
|
+
...config,
|
|
32
|
+
};
|
|
33
|
+
this.registry = new StateRegistry(this.config);
|
|
34
|
+
this.spawner = new CLISpawner(this.config);
|
|
35
|
+
this.client = new RelayClient({
|
|
36
|
+
agentName: '__supervisor__',
|
|
37
|
+
socketPath: this.config.socketPath,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Start the supervisor
|
|
42
|
+
*/
|
|
43
|
+
async start() {
|
|
44
|
+
if (this.running)
|
|
45
|
+
return;
|
|
46
|
+
console.log('[supervisor] Starting...');
|
|
47
|
+
// Connect to daemon
|
|
48
|
+
try {
|
|
49
|
+
await this.client.connect();
|
|
50
|
+
console.log('[supervisor] Connected to daemon');
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
console.error('[supervisor] Failed to connect to daemon:', err);
|
|
54
|
+
console.error('[supervisor] Running in standalone mode (no message routing)');
|
|
55
|
+
}
|
|
56
|
+
this.running = true;
|
|
57
|
+
this.schedulePoll();
|
|
58
|
+
console.log('[supervisor] Started, polling every', this.config.pollIntervalMs, 'ms');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Stop the supervisor
|
|
62
|
+
*/
|
|
63
|
+
stop() {
|
|
64
|
+
if (!this.running)
|
|
65
|
+
return;
|
|
66
|
+
console.log('[supervisor] Stopping...');
|
|
67
|
+
if (this.pollTimer) {
|
|
68
|
+
clearTimeout(this.pollTimer);
|
|
69
|
+
this.pollTimer = undefined;
|
|
70
|
+
}
|
|
71
|
+
this.client.disconnect();
|
|
72
|
+
this.running = false;
|
|
73
|
+
console.log('[supervisor] Stopped');
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Register a new agent
|
|
77
|
+
*/
|
|
78
|
+
registerAgent(registration) {
|
|
79
|
+
const manager = this.registry.getManager(registration.name);
|
|
80
|
+
// Check if already exists
|
|
81
|
+
let state = manager.load();
|
|
82
|
+
if (state) {
|
|
83
|
+
console.log(`[supervisor] Agent ${registration.name} already registered, updating`);
|
|
84
|
+
state = {
|
|
85
|
+
...state,
|
|
86
|
+
cli: registration.cli,
|
|
87
|
+
cwd: registration.cwd,
|
|
88
|
+
customCommand: registration.customCommand,
|
|
89
|
+
lastActiveTs: new Date().toISOString(),
|
|
90
|
+
};
|
|
91
|
+
manager.save(state);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
state = manager.create(registration.cli, registration.cwd, registration.customCommand);
|
|
95
|
+
console.log(`[supervisor] Registered new agent: ${registration.name}`);
|
|
96
|
+
}
|
|
97
|
+
return state;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Unregister an agent
|
|
101
|
+
*/
|
|
102
|
+
unregisterAgent(name) {
|
|
103
|
+
const agentDir = path.join(this.config.dataDir, name);
|
|
104
|
+
if (fs.existsSync(agentDir)) {
|
|
105
|
+
fs.rmSync(agentDir, { recursive: true });
|
|
106
|
+
console.log(`[supervisor] Unregistered agent: ${name}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Schedule next poll
|
|
111
|
+
*/
|
|
112
|
+
schedulePoll() {
|
|
113
|
+
if (!this.running)
|
|
114
|
+
return;
|
|
115
|
+
this.pollTimer = setTimeout(async () => {
|
|
116
|
+
await this.poll();
|
|
117
|
+
this.schedulePoll();
|
|
118
|
+
}, this.config.pollIntervalMs);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Poll all agents for new messages
|
|
122
|
+
*/
|
|
123
|
+
async poll() {
|
|
124
|
+
const agents = this.registry.listAgents();
|
|
125
|
+
for (const agentName of agents) {
|
|
126
|
+
try {
|
|
127
|
+
await this.processAgent(agentName);
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
console.error(`[supervisor] Error processing agent ${agentName}:`, err);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Process a single agent's inbox
|
|
136
|
+
*/
|
|
137
|
+
async processAgent(agentName) {
|
|
138
|
+
const manager = this.registry.getManager(agentName);
|
|
139
|
+
// Check if locked
|
|
140
|
+
if (manager.isLocked()) {
|
|
141
|
+
if (this.config.verbose) {
|
|
142
|
+
console.log(`[supervisor] Agent ${agentName} is locked, skipping`);
|
|
143
|
+
}
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
// Check inbox (claim atomically to avoid dropping new messages)
|
|
147
|
+
const inboxPath = manager.getInboxPath();
|
|
148
|
+
const claim = claimInbox(inboxPath);
|
|
149
|
+
if (!claim)
|
|
150
|
+
return;
|
|
151
|
+
const inboxContent = claim.content;
|
|
152
|
+
if (!inboxContent.includes('## Message from')) {
|
|
153
|
+
finalizeClaim(claim, true);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
// Load state
|
|
157
|
+
const state = manager.load();
|
|
158
|
+
if (!state) {
|
|
159
|
+
console.error(`[supervisor] No state for agent ${agentName}`);
|
|
160
|
+
finalizeClaim(claim, false);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
// Try to acquire lock
|
|
164
|
+
if (!manager.tryLock()) {
|
|
165
|
+
console.log(`[supervisor] Failed to acquire lock for ${agentName}`);
|
|
166
|
+
finalizeClaim(claim, false);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
let success = false;
|
|
170
|
+
try {
|
|
171
|
+
console.log(`[supervisor] Processing inbox for ${agentName}`);
|
|
172
|
+
// Record received messages into state for continuity
|
|
173
|
+
let currentState = manager.recordInboxReceived(state, inboxContent);
|
|
174
|
+
// Mark running (best-effort)
|
|
175
|
+
currentState = manager.setStatus(currentState, 'running');
|
|
176
|
+
// Build prompt with context
|
|
177
|
+
const prompt = manager.buildSpawnPrompt(currentState, inboxContent);
|
|
178
|
+
// Spawn CLI
|
|
179
|
+
const result = await this.spawner.spawn(currentState.cli, prompt, currentState.cwd, currentState.customCommand);
|
|
180
|
+
console.log(`[supervisor] ${agentName} exited with code ${result.exitCode}, ${result.relayCommands.length} relay commands`);
|
|
181
|
+
// Apply state markers from output
|
|
182
|
+
// Add decisions
|
|
183
|
+
for (const decision of result.stateMarkers.decisions) {
|
|
184
|
+
currentState = manager.addDecision(currentState, decision.what, decision.why);
|
|
185
|
+
console.log(`[supervisor] ${agentName} recorded decision: ${decision.what}`);
|
|
186
|
+
}
|
|
187
|
+
// Add TODOs
|
|
188
|
+
for (const todo of result.stateMarkers.todos) {
|
|
189
|
+
currentState = manager.addTodo(currentState, todo.task, todo.priority, todo.owner);
|
|
190
|
+
console.log(`[supervisor] ${agentName} added TODO: ${todo.task}`);
|
|
191
|
+
}
|
|
192
|
+
// Complete TODOs
|
|
193
|
+
for (const done of result.stateMarkers.dones) {
|
|
194
|
+
currentState = manager.completeTodo(currentState, done.taskMatch);
|
|
195
|
+
console.log(`[supervisor] ${agentName} completed TODO matching: ${done.taskMatch}`);
|
|
196
|
+
}
|
|
197
|
+
// Update summary if provided
|
|
198
|
+
if (result.stateMarkers.summary) {
|
|
199
|
+
currentState = manager.updateSummary(currentState, result.stateMarkers.summary);
|
|
200
|
+
if (this.config.verbose) {
|
|
201
|
+
console.log(`[supervisor] ${agentName} updated summary (${result.stateMarkers.summary.length} chars)`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Process relay commands
|
|
205
|
+
for (const cmd of result.relayCommands) {
|
|
206
|
+
// Add to state as sent message
|
|
207
|
+
currentState = manager.addExchange(currentState, {
|
|
208
|
+
direction: 'sent',
|
|
209
|
+
peer: cmd.to,
|
|
210
|
+
body: cmd.body,
|
|
211
|
+
timestamp: new Date().toISOString(),
|
|
212
|
+
});
|
|
213
|
+
// Route through daemon
|
|
214
|
+
this.client.sendMessage(cmd.to, cmd.body, cmd.kind);
|
|
215
|
+
console.log(`[supervisor] Routed: ${agentName} -> ${cmd.to}`);
|
|
216
|
+
}
|
|
217
|
+
// Mark idle and record checkpoint
|
|
218
|
+
currentState = manager.setStatus(currentState, 'idle');
|
|
219
|
+
manager.markInboxProcessed(currentState);
|
|
220
|
+
// Done with claimed inbox
|
|
221
|
+
success = true;
|
|
222
|
+
}
|
|
223
|
+
finally {
|
|
224
|
+
manager.releaseLock();
|
|
225
|
+
finalizeClaim(claim, success);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Get list of registered agents
|
|
230
|
+
*/
|
|
231
|
+
getAgents() {
|
|
232
|
+
return this.registry.listAgents();
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Get agent state
|
|
236
|
+
*/
|
|
237
|
+
getAgentState(name) {
|
|
238
|
+
return this.registry.getManager(name).load();
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Get lightweight diagnostics for CLI display.
|
|
242
|
+
*/
|
|
243
|
+
getAgentDiagnostics(name) {
|
|
244
|
+
const manager = this.registry.getManager(name);
|
|
245
|
+
const state = manager.load();
|
|
246
|
+
const inboxPath = manager.getInboxPath();
|
|
247
|
+
const statePath = manager.getStatePath();
|
|
248
|
+
const lockPath = manager.getLockPath();
|
|
249
|
+
const locked = manager.isLocked();
|
|
250
|
+
let hasUnreadInbox = false;
|
|
251
|
+
try {
|
|
252
|
+
if (fs.existsSync(inboxPath)) {
|
|
253
|
+
const content = fs.readFileSync(inboxPath, 'utf-8');
|
|
254
|
+
hasUnreadInbox = content.includes('## Message from');
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
hasUnreadInbox = false;
|
|
259
|
+
}
|
|
260
|
+
return { state, locked, inboxPath, statePath, lockPath, hasUnreadInbox };
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=supervisor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor.js","sourceRoot":"","sources":["../../src/supervisor/supervisor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for Agent Relay Supervisor
|
|
3
|
+
*/
|
|
4
|
+
export type CLIType = 'claude' | 'codex' | 'cursor' | 'custom';
|
|
5
|
+
/** A key decision made by the agent (append-only) */
|
|
6
|
+
export interface Decision {
|
|
7
|
+
/** Short description of what was decided */
|
|
8
|
+
what: string;
|
|
9
|
+
/** Why this decision was made */
|
|
10
|
+
why: string;
|
|
11
|
+
/** When the decision was made */
|
|
12
|
+
timestamp: string;
|
|
13
|
+
}
|
|
14
|
+
/** An active TODO/task */
|
|
15
|
+
export interface Todo {
|
|
16
|
+
/** Task description */
|
|
17
|
+
task: string;
|
|
18
|
+
/** Owner agent name (if assigned) */
|
|
19
|
+
owner?: string;
|
|
20
|
+
/** Priority: high, normal, low */
|
|
21
|
+
priority: 'high' | 'normal' | 'low';
|
|
22
|
+
/** When added */
|
|
23
|
+
addedTs: string;
|
|
24
|
+
}
|
|
25
|
+
/** A file modification record */
|
|
26
|
+
export interface FileModification {
|
|
27
|
+
/** File path relative to cwd */
|
|
28
|
+
path: string;
|
|
29
|
+
/** Short intent/reason for modification */
|
|
30
|
+
intent: string;
|
|
31
|
+
/** When modified */
|
|
32
|
+
timestamp: string;
|
|
33
|
+
}
|
|
34
|
+
/** Reference to external command/output */
|
|
35
|
+
export interface ExternalRef {
|
|
36
|
+
/** Command that was run */
|
|
37
|
+
command: string;
|
|
38
|
+
/** Key result/output summary */
|
|
39
|
+
resultSummary: string;
|
|
40
|
+
/** When run */
|
|
41
|
+
timestamp: string;
|
|
42
|
+
/** Optional pointer to full log file */
|
|
43
|
+
logPath?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface AgentState {
|
|
46
|
+
/** Schema version for migrations */
|
|
47
|
+
version: number;
|
|
48
|
+
/** Agent name */
|
|
49
|
+
name: string;
|
|
50
|
+
/** CLI type */
|
|
51
|
+
cli: CLIType;
|
|
52
|
+
/** Supervisor-visible status (best-effort; lockfile is source of truth) */
|
|
53
|
+
status?: 'idle' | 'running' | 'blocked';
|
|
54
|
+
/** Rolling summary of conversation (1-2k chars) */
|
|
55
|
+
summary: string;
|
|
56
|
+
/** Last N relay message exchanges */
|
|
57
|
+
recentMessages: RelayExchange[];
|
|
58
|
+
/** Working directory */
|
|
59
|
+
cwd: string;
|
|
60
|
+
/** Custom CLI command (for 'custom' type) */
|
|
61
|
+
customCommand?: string;
|
|
62
|
+
/** Last active timestamp */
|
|
63
|
+
lastActiveTs: string;
|
|
64
|
+
/** Created timestamp */
|
|
65
|
+
createdTs: string;
|
|
66
|
+
/** Last processed inbox timestamp (for restart deduplication) */
|
|
67
|
+
lastProcessedInboxTs?: string;
|
|
68
|
+
/** Stable key decisions (append-only) */
|
|
69
|
+
decisions: Decision[];
|
|
70
|
+
/** Active TODOs/tasks */
|
|
71
|
+
openTodos: Todo[];
|
|
72
|
+
/** Files touched with intent */
|
|
73
|
+
filesModified: FileModification[];
|
|
74
|
+
/** External command/output references */
|
|
75
|
+
externalRefs: ExternalRef[];
|
|
76
|
+
}
|
|
77
|
+
export interface RelayExchange {
|
|
78
|
+
/** Direction: sent or received */
|
|
79
|
+
direction: 'sent' | 'received';
|
|
80
|
+
/** Other agent name */
|
|
81
|
+
peer: string;
|
|
82
|
+
/** Message body */
|
|
83
|
+
body: string;
|
|
84
|
+
/** Timestamp */
|
|
85
|
+
timestamp: string;
|
|
86
|
+
}
|
|
87
|
+
export interface SupervisorConfig {
|
|
88
|
+
/** Base directory for agent data */
|
|
89
|
+
dataDir: string;
|
|
90
|
+
/** Polling interval in milliseconds */
|
|
91
|
+
pollIntervalMs: number;
|
|
92
|
+
/** Maximum recent messages to keep in state */
|
|
93
|
+
maxRecentMessages: number;
|
|
94
|
+
/** Maximum summary length in characters */
|
|
95
|
+
maxSummaryLength: number;
|
|
96
|
+
/** Socket path for daemon connection */
|
|
97
|
+
socketPath: string;
|
|
98
|
+
/** Enable verbose logging */
|
|
99
|
+
verbose: boolean;
|
|
100
|
+
}
|
|
101
|
+
export interface SpawnResult {
|
|
102
|
+
/** Exit code */
|
|
103
|
+
exitCode: number;
|
|
104
|
+
/** Stdout content */
|
|
105
|
+
stdout: string;
|
|
106
|
+
/** Stderr content */
|
|
107
|
+
stderr: string;
|
|
108
|
+
/** Parsed relay commands from output */
|
|
109
|
+
relayCommands: ParsedRelayCommand[];
|
|
110
|
+
/** Parsed state markers from output */
|
|
111
|
+
stateMarkers: {
|
|
112
|
+
decisions: {
|
|
113
|
+
what: string;
|
|
114
|
+
why: string;
|
|
115
|
+
}[];
|
|
116
|
+
todos: {
|
|
117
|
+
task: string;
|
|
118
|
+
priority: 'high' | 'normal' | 'low';
|
|
119
|
+
owner?: string;
|
|
120
|
+
}[];
|
|
121
|
+
dones: {
|
|
122
|
+
taskMatch: string;
|
|
123
|
+
}[];
|
|
124
|
+
summary?: string;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export interface ParsedRelayCommand {
|
|
128
|
+
to: string;
|
|
129
|
+
body: string;
|
|
130
|
+
kind: 'message' | 'thinking' | 'state';
|
|
131
|
+
}
|
|
132
|
+
export interface AgentRegistration {
|
|
133
|
+
name: string;
|
|
134
|
+
cli: CLIType;
|
|
135
|
+
cwd: string;
|
|
136
|
+
customCommand?: string;
|
|
137
|
+
}
|
|
138
|
+
export declare const DEFAULT_SUPERVISOR_CONFIG: SupervisorConfig;
|
|
139
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/supervisor/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for Agent Relay Supervisor
|
|
3
|
+
*/
|
|
4
|
+
export const DEFAULT_SUPERVISOR_CONFIG = {
|
|
5
|
+
dataDir: '/tmp/agent-relay',
|
|
6
|
+
pollIntervalMs: 2000,
|
|
7
|
+
maxRecentMessages: 20,
|
|
8
|
+
maxSummaryLength: 2000,
|
|
9
|
+
socketPath: '/tmp/agent-relay.sock',
|
|
10
|
+
verbose: false,
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/supervisor/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AA0IH,MAAM,CAAC,MAAM,yBAAyB,GAAqB;IACzD,OAAO,EAAE,kBAAkB;IAC3B,cAAc,EAAE,IAAI;IACpB,iBAAiB,EAAE,EAAE;IACrB,gBAAgB,EAAE,IAAI;IACtB,UAAU,EAAE,uBAAuB;IACnC,OAAO,EAAE,KAAK;CACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-generate memorable agent names using adjective+noun combinations.
|
|
3
|
+
* Inspired by mcp_agent_mail's approach.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Generate a random agent name (AdjectiveNoun format).
|
|
7
|
+
*/
|
|
8
|
+
export declare function generateAgentName(): string;
|
|
9
|
+
/**
|
|
10
|
+
* Generate a unique agent name, checking against existing names.
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateUniqueAgentName(existingNames: Set<string>, maxAttempts?: number): string;
|
|
13
|
+
/**
|
|
14
|
+
* Validate an agent name (must be alphanumeric, 2-32 chars).
|
|
15
|
+
*/
|
|
16
|
+
export declare function isValidAgentName(name: string): boolean;
|
|
17
|
+
//# sourceMappingURL=name-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"name-generator.d.ts","sourceRoot":"","sources":["../../src/utils/name-generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAwBH;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAI1C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,WAAW,SAAM,GAAG,MAAM,CAS7F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-generate memorable agent names using adjective+noun combinations.
|
|
3
|
+
* Inspired by mcp_agent_mail's approach.
|
|
4
|
+
*/
|
|
5
|
+
const ADJECTIVES = [
|
|
6
|
+
'Blue', 'Green', 'Red', 'Purple', 'Golden', 'Silver', 'Crystal', 'Amber',
|
|
7
|
+
'Coral', 'Jade', 'Ruby', 'Sapphire', 'Emerald', 'Onyx', 'Pearl', 'Copper',
|
|
8
|
+
'Bronze', 'Iron', 'Steel', 'Velvet', 'Silk', 'Cotton', 'Linen', 'Marble',
|
|
9
|
+
'Granite', 'Cobalt', 'Crimson', 'Azure', 'Indigo', 'Scarlet', 'Violet',
|
|
10
|
+
'Olive', 'Teal', 'Cyan', 'Magenta', 'Ochre', 'Rustic', 'Misty', 'Stormy',
|
|
11
|
+
'Sunny', 'Frosty', 'Dusty', 'Mossy', 'Rocky', 'Sandy', 'Snowy', 'Windy',
|
|
12
|
+
'Swift', 'Calm', 'Bold', 'Brave', 'Clever', 'Eager', 'Gentle', 'Happy',
|
|
13
|
+
'Jolly', 'Kind', 'Lively', 'Merry', 'Noble', 'Proud', 'Quick', 'Quiet',
|
|
14
|
+
];
|
|
15
|
+
const NOUNS = [
|
|
16
|
+
'Mountain', 'River', 'Forest', 'Ocean', 'Valley', 'Canyon', 'Desert', 'Island',
|
|
17
|
+
'Lake', 'Meadow', 'Prairie', 'Glacier', 'Volcano', 'Waterfall', 'Creek', 'Pond',
|
|
18
|
+
'Hill', 'Peak', 'Ridge', 'Cliff', 'Cave', 'Reef', 'Marsh', 'Grove',
|
|
19
|
+
'Fox', 'Wolf', 'Bear', 'Eagle', 'Hawk', 'Owl', 'Deer', 'Elk',
|
|
20
|
+
'Falcon', 'Raven', 'Swan', 'Crane', 'Heron', 'Otter', 'Beaver', 'Badger',
|
|
21
|
+
'Castle', 'Tower', 'Bridge', 'Harbor', 'Haven', 'Shelter', 'Beacon', 'Anchor',
|
|
22
|
+
'Stone', 'Pebble', 'Boulder', 'Crystal', 'Gem', 'Prism', 'Spark', 'Ember',
|
|
23
|
+
'Star', 'Moon', 'Sun', 'Comet', 'Cloud', 'Storm', 'Thunder', 'Lightning',
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* Generate a random agent name (AdjectiveNoun format).
|
|
27
|
+
*/
|
|
28
|
+
export function generateAgentName() {
|
|
29
|
+
const adjective = ADJECTIVES[Math.floor(Math.random() * ADJECTIVES.length)];
|
|
30
|
+
const noun = NOUNS[Math.floor(Math.random() * NOUNS.length)];
|
|
31
|
+
return `${adjective}${noun}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generate a unique agent name, checking against existing names.
|
|
35
|
+
*/
|
|
36
|
+
export function generateUniqueAgentName(existingNames, maxAttempts = 100) {
|
|
37
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
38
|
+
const name = generateAgentName();
|
|
39
|
+
if (!existingNames.has(name)) {
|
|
40
|
+
return name;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Fallback: append random suffix
|
|
44
|
+
return `${generateAgentName()}${Math.floor(Math.random() * 1000)}`;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Validate an agent name (must be alphanumeric, 2-32 chars).
|
|
48
|
+
*/
|
|
49
|
+
export function isValidAgentName(name) {
|
|
50
|
+
return /^[a-zA-Z][a-zA-Z0-9_-]{1,31}$/.test(name);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=name-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"name-generator.js","sourceRoot":"","sources":["../../src/utils/name-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webhook Spawner - Spawns agent CLIs when messages arrive
|
|
3
|
+
*
|
|
4
|
+
* Supports: claude, codex, gemini, cursor
|
|
5
|
+
*/
|
|
6
|
+
import { ChildProcess } from 'child_process';
|
|
7
|
+
export interface AgentConfig {
|
|
8
|
+
name: string;
|
|
9
|
+
cli: 'claude' | 'codex' | 'gemini' | 'cursor' | string;
|
|
10
|
+
projectDir: string;
|
|
11
|
+
dataDir: string;
|
|
12
|
+
enabled?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface SpawnResult {
|
|
15
|
+
agent: string;
|
|
16
|
+
pid?: number;
|
|
17
|
+
success: boolean;
|
|
18
|
+
error?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Spawn an agent CLI to check their inbox
|
|
22
|
+
*/
|
|
23
|
+
export declare function spawnAgent(config: AgentConfig): SpawnResult;
|
|
24
|
+
/**
|
|
25
|
+
* Spawn agent in background and capture output
|
|
26
|
+
*/
|
|
27
|
+
export declare function spawnAgentBackground(config: AgentConfig, onOutput?: (data: string) => void, onExit?: (code: number | null) => void): ChildProcess | null;
|
|
28
|
+
/**
|
|
29
|
+
* Watch for inbox changes and spawn agents
|
|
30
|
+
*/
|
|
31
|
+
export declare class InboxWatcher {
|
|
32
|
+
private watcher;
|
|
33
|
+
private agents;
|
|
34
|
+
private activeAgents;
|
|
35
|
+
private debounceTimers;
|
|
36
|
+
private dataDir;
|
|
37
|
+
private debounceMs;
|
|
38
|
+
constructor(dataDir: string, debounceMs?: number);
|
|
39
|
+
/**
|
|
40
|
+
* Register an agent to watch
|
|
41
|
+
*/
|
|
42
|
+
registerAgent(config: AgentConfig): void;
|
|
43
|
+
/**
|
|
44
|
+
* Load agents from team.json
|
|
45
|
+
*/
|
|
46
|
+
loadFromTeamConfig(): void;
|
|
47
|
+
/**
|
|
48
|
+
* Start watching for inbox changes
|
|
49
|
+
*/
|
|
50
|
+
start(onSpawn?: (result: SpawnResult) => void): void;
|
|
51
|
+
/**
|
|
52
|
+
* Handle inbox change with debouncing
|
|
53
|
+
*/
|
|
54
|
+
private handleInboxChange;
|
|
55
|
+
/**
|
|
56
|
+
* Spawn agent and track it
|
|
57
|
+
*/
|
|
58
|
+
private spawnForAgent;
|
|
59
|
+
/**
|
|
60
|
+
* Stop watching
|
|
61
|
+
*/
|
|
62
|
+
stop(): void;
|
|
63
|
+
/**
|
|
64
|
+
* Get status of all agents
|
|
65
|
+
*/
|
|
66
|
+
getStatus(): {
|
|
67
|
+
name: string;
|
|
68
|
+
enabled: boolean;
|
|
69
|
+
active: boolean;
|
|
70
|
+
}[];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Trigger webhook for a specific agent (called after team-send)
|
|
74
|
+
*/
|
|
75
|
+
export declare function triggerWebhook(agentName: string, dataDir: string, options?: {
|
|
76
|
+
spawn?: boolean;
|
|
77
|
+
http?: string;
|
|
78
|
+
}): Promise<SpawnResult>;
|
|
79
|
+
//# sourceMappingURL=spawner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawner.d.ts","sourceRoot":"","sources":["../../src/webhook/spawner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAS,YAAY,EAAE,MAAM,eAAe,CAAC;AAKpD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAoBD;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CA4B3D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,WAAW,EACnB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EACjC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GACrC,YAAY,GAAG,IAAI,CA0BrB;AAED;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,cAAc,CAA0C;IAChE,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;gBAEf,OAAO,EAAE,MAAM,EAAE,UAAU,SAAO;IAK9C;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAIxC;;OAEG;IACH,kBAAkB,IAAI,IAAI;IAmB1B;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IA6BpD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoCzB;;OAEG;IACH,OAAO,CAAC,aAAa;IAoCrB;;OAEG;IACH,IAAI,IAAI,IAAI;IAkBZ;;OAEG;IACH,SAAS,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,EAAE;CAOnE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IACR,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GACA,OAAO,CAAC,WAAW,CAAC,CAsDtB"}
|