@agent-relay/wrapper 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/dist/__fixtures__/claude-outputs.d.ts +49 -0
- package/dist/__fixtures__/claude-outputs.d.ts.map +1 -0
- package/dist/__fixtures__/claude-outputs.js +443 -0
- package/dist/__fixtures__/claude-outputs.js.map +1 -0
- package/dist/__fixtures__/codex-outputs.d.ts +9 -0
- package/dist/__fixtures__/codex-outputs.d.ts.map +1 -0
- package/dist/__fixtures__/codex-outputs.js +94 -0
- package/dist/__fixtures__/codex-outputs.js.map +1 -0
- package/dist/__fixtures__/gemini-outputs.d.ts +19 -0
- package/dist/__fixtures__/gemini-outputs.d.ts.map +1 -0
- package/dist/__fixtures__/gemini-outputs.js +144 -0
- package/dist/__fixtures__/gemini-outputs.js.map +1 -0
- package/dist/__fixtures__/index.d.ts +68 -0
- package/dist/__fixtures__/index.d.ts.map +1 -0
- package/dist/__fixtures__/index.js +44 -0
- package/dist/__fixtures__/index.js.map +1 -0
- package/dist/auth-detection.d.ts +49 -0
- package/dist/auth-detection.d.ts.map +1 -0
- package/dist/auth-detection.js +199 -0
- package/dist/auth-detection.js.map +1 -0
- package/dist/base-wrapper.d.ts +225 -0
- package/dist/base-wrapper.d.ts.map +1 -0
- package/dist/base-wrapper.js +572 -0
- package/dist/base-wrapper.js.map +1 -0
- package/dist/client.d.ts +254 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +801 -0
- package/dist/client.js.map +1 -0
- package/dist/id-generator.d.ts +35 -0
- package/dist/id-generator.d.ts.map +1 -0
- package/dist/id-generator.js +60 -0
- package/dist/id-generator.js.map +1 -0
- package/dist/idle-detector.d.ts +110 -0
- package/dist/idle-detector.d.ts.map +1 -0
- package/dist/idle-detector.js +304 -0
- package/dist/idle-detector.js.map +1 -0
- package/dist/inbox.d.ts +37 -0
- package/dist/inbox.d.ts.map +1 -0
- package/dist/inbox.js +73 -0
- package/dist/inbox.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/parser.d.ts +236 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +1238 -0
- package/dist/parser.js.map +1 -0
- package/dist/prompt-composer.d.ts +67 -0
- package/dist/prompt-composer.d.ts.map +1 -0
- package/dist/prompt-composer.js +168 -0
- package/dist/prompt-composer.js.map +1 -0
- package/dist/relay-pty-orchestrator.d.ts +407 -0
- package/dist/relay-pty-orchestrator.d.ts.map +1 -0
- package/dist/relay-pty-orchestrator.js +1885 -0
- package/dist/relay-pty-orchestrator.js.map +1 -0
- package/dist/shared.d.ts +201 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +341 -0
- package/dist/shared.js.map +1 -0
- package/dist/stuck-detector.d.ts +161 -0
- package/dist/stuck-detector.d.ts.map +1 -0
- package/dist/stuck-detector.js +402 -0
- package/dist/stuck-detector.js.map +1 -0
- package/dist/tmux-resolver.d.ts +55 -0
- package/dist/tmux-resolver.d.ts.map +1 -0
- package/dist/tmux-resolver.js +175 -0
- package/dist/tmux-resolver.js.map +1 -0
- package/dist/tmux-wrapper.d.ts +345 -0
- package/dist/tmux-wrapper.d.ts.map +1 -0
- package/dist/tmux-wrapper.js +1747 -0
- package/dist/tmux-wrapper.js.map +1 -0
- package/dist/trajectory-integration.d.ts +292 -0
- package/dist/trajectory-integration.d.ts.map +1 -0
- package/dist/trajectory-integration.js +979 -0
- package/dist/trajectory-integration.js.map +1 -0
- package/dist/wrapper-types.d.ts +41 -0
- package/dist/wrapper-types.d.ts.map +1 -0
- package/dist/wrapper-types.js +7 -0
- package/dist/wrapper-types.js.map +1 -0
- package/package.json +63 -0
- package/src/__fixtures__/claude-outputs.ts +471 -0
- package/src/__fixtures__/codex-outputs.ts +99 -0
- package/src/__fixtures__/gemini-outputs.ts +151 -0
- package/src/__fixtures__/index.ts +47 -0
- package/src/auth-detection.ts +244 -0
- package/src/base-wrapper.test.ts +540 -0
- package/src/base-wrapper.ts +741 -0
- package/src/client.test.ts +262 -0
- package/src/client.ts +984 -0
- package/src/id-generator.test.ts +71 -0
- package/src/id-generator.ts +69 -0
- package/src/idle-detector.test.ts +390 -0
- package/src/idle-detector.ts +370 -0
- package/src/inbox.test.ts +233 -0
- package/src/inbox.ts +89 -0
- package/src/index.ts +170 -0
- package/src/parser.regression.test.ts +251 -0
- package/src/parser.test.ts +1359 -0
- package/src/parser.ts +1477 -0
- package/src/prompt-composer.test.ts +219 -0
- package/src/prompt-composer.ts +231 -0
- package/src/relay-pty-orchestrator.test.ts +1027 -0
- package/src/relay-pty-orchestrator.ts +2270 -0
- package/src/shared.test.ts +221 -0
- package/src/shared.ts +454 -0
- package/src/stuck-detector.test.ts +303 -0
- package/src/stuck-detector.ts +511 -0
- package/src/tmux-resolver.test.ts +104 -0
- package/src/tmux-resolver.ts +207 -0
- package/src/tmux-wrapper.test.ts +316 -0
- package/src/tmux-wrapper.ts +2010 -0
- package/src/trajectory-detection.test.ts +151 -0
- package/src/trajectory-integration.ts +1261 -0
- package/src/wrapper-types.ts +45 -0
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BaseWrapper - Abstract base class for agent wrappers
|
|
3
|
+
*
|
|
4
|
+
* Provides shared functionality between TmuxWrapper and PtyWrapper:
|
|
5
|
+
* - Message queue management and deduplication
|
|
6
|
+
* - Spawn/release command parsing and execution
|
|
7
|
+
* - Continuity integration (agent ID, summary saving)
|
|
8
|
+
* - Relay command handling
|
|
9
|
+
* - Line joining for multi-line commands
|
|
10
|
+
*
|
|
11
|
+
* Subclasses implement:
|
|
12
|
+
* - start() - Initialize and start the agent process
|
|
13
|
+
* - stop() - Stop the agent process
|
|
14
|
+
* - performInjection() - Inject content into the agent
|
|
15
|
+
* - getCleanOutput() - Get cleaned output for parsing
|
|
16
|
+
*/
|
|
17
|
+
import { EventEmitter } from 'node:events';
|
|
18
|
+
import { RelayClient } from './client.js';
|
|
19
|
+
import { isPlaceholderTarget } from './parser.js';
|
|
20
|
+
import { getDefaultRelayPrefix, detectCliType, createInjectionMetrics, } from './shared.js';
|
|
21
|
+
import { DEFAULT_IDLE_BEFORE_INJECT_MS, DEFAULT_IDLE_CONFIDENCE_THRESHOLD, } from '@agent-relay/config/relay-config';
|
|
22
|
+
import { getContinuityManager, parseContinuityCommand, hasContinuityCommand, } from '@agent-relay/continuity';
|
|
23
|
+
import { UniversalIdleDetector } from './idle-detector.js';
|
|
24
|
+
import { StuckDetector } from './stuck-detector.js';
|
|
25
|
+
/**
|
|
26
|
+
* Abstract base class for agent wrappers
|
|
27
|
+
*/
|
|
28
|
+
export class BaseWrapper extends EventEmitter {
|
|
29
|
+
config;
|
|
30
|
+
client;
|
|
31
|
+
relayPrefix;
|
|
32
|
+
cliType;
|
|
33
|
+
running = false;
|
|
34
|
+
// Message queue state
|
|
35
|
+
messageQueue = [];
|
|
36
|
+
sentMessageHashes = new Set();
|
|
37
|
+
isInjecting = false;
|
|
38
|
+
receivedMessageIds = new Set();
|
|
39
|
+
injectionMetrics = createInjectionMetrics();
|
|
40
|
+
// Spawn/release state
|
|
41
|
+
processedSpawnCommands = new Set();
|
|
42
|
+
processedReleaseCommands = new Set();
|
|
43
|
+
pendingFencedSpawn = null;
|
|
44
|
+
// Continuity state
|
|
45
|
+
continuity;
|
|
46
|
+
agentId;
|
|
47
|
+
processedContinuityCommands = new Set();
|
|
48
|
+
sessionEndProcessed = false;
|
|
49
|
+
sessionEndData;
|
|
50
|
+
lastSummaryRawContent = '';
|
|
51
|
+
// Universal idle detection (shared across all wrapper types)
|
|
52
|
+
idleDetector;
|
|
53
|
+
// Stuck detection (extended idle, error loops, output loops)
|
|
54
|
+
stuckDetector;
|
|
55
|
+
constructor(config) {
|
|
56
|
+
super();
|
|
57
|
+
this.config = config;
|
|
58
|
+
this.relayPrefix = config.relayPrefix ?? getDefaultRelayPrefix();
|
|
59
|
+
this.cliType = config.cliType ?? detectCliType(config.command);
|
|
60
|
+
// Initialize relay client with full config
|
|
61
|
+
this.client = new RelayClient({
|
|
62
|
+
agentName: config.name,
|
|
63
|
+
socketPath: config.socketPath,
|
|
64
|
+
cli: this.cliType,
|
|
65
|
+
task: config.task,
|
|
66
|
+
workingDirectory: config.cwd,
|
|
67
|
+
quiet: true,
|
|
68
|
+
_internal: true, // Suppress deprecation warning for internal wrapper usage
|
|
69
|
+
});
|
|
70
|
+
// Initialize continuity manager (skip for spawned agents that don't need session recovery)
|
|
71
|
+
if (!config.skipContinuity) {
|
|
72
|
+
this.continuity = getContinuityManager({ defaultCli: this.cliType });
|
|
73
|
+
}
|
|
74
|
+
// Initialize universal idle detector for robust injection timing
|
|
75
|
+
this.idleDetector = new UniversalIdleDetector({
|
|
76
|
+
minSilenceMs: config.idleBeforeInjectMs ?? DEFAULT_IDLE_BEFORE_INJECT_MS,
|
|
77
|
+
confidenceThreshold: config.idleConfidenceThreshold ?? DEFAULT_IDLE_CONFIDENCE_THRESHOLD,
|
|
78
|
+
});
|
|
79
|
+
// Initialize stuck detector for extended idle and loop detection
|
|
80
|
+
this.stuckDetector = new StuckDetector();
|
|
81
|
+
this.stuckDetector.on('stuck', (event) => {
|
|
82
|
+
// Events are emitted for programmatic use - no terminal logging to avoid noise
|
|
83
|
+
this.emit('stuck', event);
|
|
84
|
+
});
|
|
85
|
+
this.stuckDetector.on('unstuck', () => {
|
|
86
|
+
this.emit('unstuck');
|
|
87
|
+
});
|
|
88
|
+
// Set up message handler for direct messages
|
|
89
|
+
this.client.onMessage = (from, payload, messageId, meta, originalTo) => {
|
|
90
|
+
this.handleIncomingMessage(from, payload, messageId, meta, originalTo);
|
|
91
|
+
};
|
|
92
|
+
// Set up channel message handler
|
|
93
|
+
this.client.onChannelMessage = (from, channel, body, envelope) => {
|
|
94
|
+
this.handleIncomingChannelMessage(from, channel, body, envelope);
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// =========================================================================
|
|
98
|
+
// Common getters
|
|
99
|
+
// =========================================================================
|
|
100
|
+
get isRunning() {
|
|
101
|
+
return this.running;
|
|
102
|
+
}
|
|
103
|
+
get name() {
|
|
104
|
+
return this.config.name;
|
|
105
|
+
}
|
|
106
|
+
getAgentId() {
|
|
107
|
+
return this.agentId;
|
|
108
|
+
}
|
|
109
|
+
getInjectionMetrics() {
|
|
110
|
+
const total = this.injectionMetrics.total;
|
|
111
|
+
const successes = this.injectionMetrics.successFirstTry + this.injectionMetrics.successWithRetry;
|
|
112
|
+
const successRate = total > 0
|
|
113
|
+
? (successes / total) * 100
|
|
114
|
+
: 100;
|
|
115
|
+
return {
|
|
116
|
+
...this.injectionMetrics,
|
|
117
|
+
successRate,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
get pendingMessageCount() {
|
|
121
|
+
return this.messageQueue.length;
|
|
122
|
+
}
|
|
123
|
+
// =========================================================================
|
|
124
|
+
// Idle detection (shared across all wrapper types)
|
|
125
|
+
// =========================================================================
|
|
126
|
+
/**
|
|
127
|
+
* Set the PID for process state inspection (Linux only).
|
|
128
|
+
* Call this after the agent process is started.
|
|
129
|
+
*/
|
|
130
|
+
setIdleDetectorPid(pid) {
|
|
131
|
+
this.idleDetector.setPid(pid);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Start stuck detection. Call after the agent process starts.
|
|
135
|
+
*/
|
|
136
|
+
startStuckDetection() {
|
|
137
|
+
this.stuckDetector.start();
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Stop stuck detection. Call when the agent process stops.
|
|
141
|
+
*/
|
|
142
|
+
stopStuckDetection() {
|
|
143
|
+
this.stuckDetector.stop();
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Check if the agent is currently stuck.
|
|
147
|
+
*/
|
|
148
|
+
isStuck() {
|
|
149
|
+
return this.stuckDetector.getIsStuck();
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get the reason for being stuck (if stuck).
|
|
153
|
+
*/
|
|
154
|
+
getStuckReason() {
|
|
155
|
+
return this.stuckDetector.getStuckReason();
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Feed output to the idle and stuck detectors.
|
|
159
|
+
* Call this whenever new output is received from the agent.
|
|
160
|
+
*/
|
|
161
|
+
feedIdleDetectorOutput(output) {
|
|
162
|
+
this.idleDetector.onOutput(output);
|
|
163
|
+
this.stuckDetector.onOutput(output);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Check if the agent is idle and ready for injection.
|
|
167
|
+
* Returns idle state with confidence signals.
|
|
168
|
+
*/
|
|
169
|
+
checkIdleForInjection() {
|
|
170
|
+
return this.idleDetector.checkIdle({
|
|
171
|
+
minSilenceMs: this.config.idleBeforeInjectMs ?? 1500,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Wait for the agent to become idle.
|
|
176
|
+
* Returns when idle or after timeout.
|
|
177
|
+
*/
|
|
178
|
+
async waitForIdleState(timeoutMs = 30000, pollMs = 200) {
|
|
179
|
+
return this.idleDetector.waitForIdle(timeoutMs, pollMs);
|
|
180
|
+
}
|
|
181
|
+
// =========================================================================
|
|
182
|
+
// Message handling
|
|
183
|
+
// =========================================================================
|
|
184
|
+
/**
|
|
185
|
+
* Handle incoming message from relay
|
|
186
|
+
*/
|
|
187
|
+
handleIncomingMessage(from, payload, messageId, meta, originalTo) {
|
|
188
|
+
// Deduplicate by message ID
|
|
189
|
+
if (this.receivedMessageIds.has(messageId))
|
|
190
|
+
return;
|
|
191
|
+
this.receivedMessageIds.add(messageId);
|
|
192
|
+
// Limit dedup set size
|
|
193
|
+
if (this.receivedMessageIds.size > 1000) {
|
|
194
|
+
const oldest = this.receivedMessageIds.values().next().value;
|
|
195
|
+
if (oldest)
|
|
196
|
+
this.receivedMessageIds.delete(oldest);
|
|
197
|
+
}
|
|
198
|
+
// Queue the message
|
|
199
|
+
const queuedMsg = {
|
|
200
|
+
from,
|
|
201
|
+
body: payload.body,
|
|
202
|
+
messageId,
|
|
203
|
+
thread: payload.thread,
|
|
204
|
+
importance: meta?.importance,
|
|
205
|
+
data: payload.data,
|
|
206
|
+
sync: meta?.sync,
|
|
207
|
+
originalTo,
|
|
208
|
+
};
|
|
209
|
+
this.messageQueue.push(queuedMsg);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Send an ACK for a sync message after processing completes.
|
|
213
|
+
* @param messageId - The message ID being acknowledged
|
|
214
|
+
* @param sync - Sync metadata from the original message
|
|
215
|
+
* @param response - Response status: 'OK' for success, 'ERROR' for failure
|
|
216
|
+
* @param responseData - Optional structured response data
|
|
217
|
+
*/
|
|
218
|
+
sendSyncAck(messageId, sync, response, responseData) {
|
|
219
|
+
if (!sync?.correlationId)
|
|
220
|
+
return;
|
|
221
|
+
this.client.sendAck({
|
|
222
|
+
ack_id: messageId,
|
|
223
|
+
seq: 0,
|
|
224
|
+
correlationId: sync.correlationId,
|
|
225
|
+
response,
|
|
226
|
+
responseData,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Handle incoming channel message from relay.
|
|
231
|
+
* Channel messages include a channel indicator so the agent knows to reply to the channel.
|
|
232
|
+
*/
|
|
233
|
+
handleIncomingChannelMessage(from, channel, body, envelope) {
|
|
234
|
+
const messageId = envelope.id;
|
|
235
|
+
// Deduplicate by message ID
|
|
236
|
+
if (this.receivedMessageIds.has(messageId))
|
|
237
|
+
return;
|
|
238
|
+
this.receivedMessageIds.add(messageId);
|
|
239
|
+
// Limit dedup set size
|
|
240
|
+
if (this.receivedMessageIds.size > 1000) {
|
|
241
|
+
const oldest = this.receivedMessageIds.values().next().value;
|
|
242
|
+
if (oldest)
|
|
243
|
+
this.receivedMessageIds.delete(oldest);
|
|
244
|
+
}
|
|
245
|
+
// Queue the message with channel indicator in the body
|
|
246
|
+
// Format: "Relay message from Alice [abc123] [#general]: message body"
|
|
247
|
+
// This lets the agent know to reply to the channel, not the sender
|
|
248
|
+
const queuedMsg = {
|
|
249
|
+
from,
|
|
250
|
+
body,
|
|
251
|
+
messageId,
|
|
252
|
+
thread: envelope.payload.thread,
|
|
253
|
+
data: {
|
|
254
|
+
_isChannelMessage: true,
|
|
255
|
+
_channel: channel,
|
|
256
|
+
_mentions: envelope.payload.mentions,
|
|
257
|
+
},
|
|
258
|
+
originalTo: channel, // Set channel as the reply target
|
|
259
|
+
};
|
|
260
|
+
console.error(`[base-wrapper] Received channel message: from=${from} channel=${channel} id=${messageId.substring(0, 8)}`);
|
|
261
|
+
this.messageQueue.push(queuedMsg);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Send a relay command via the client
|
|
265
|
+
*/
|
|
266
|
+
sendRelayCommand(cmd) {
|
|
267
|
+
// Validate target
|
|
268
|
+
if (isPlaceholderTarget(cmd.to)) {
|
|
269
|
+
console.error(`[base-wrapper] Skipped message - placeholder target: ${cmd.to}`);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
// Create hash for deduplication (use first 100 chars of body)
|
|
273
|
+
const hash = `${cmd.to}:${cmd.body.substring(0, 100)}`;
|
|
274
|
+
if (this.sentMessageHashes.has(hash)) {
|
|
275
|
+
console.error(`[base-wrapper] Skipped duplicate message to ${cmd.to}`);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
this.sentMessageHashes.add(hash);
|
|
279
|
+
// Limit hash set size
|
|
280
|
+
if (this.sentMessageHashes.size > 500) {
|
|
281
|
+
const oldest = this.sentMessageHashes.values().next().value;
|
|
282
|
+
if (oldest)
|
|
283
|
+
this.sentMessageHashes.delete(oldest);
|
|
284
|
+
}
|
|
285
|
+
// Only send if client ready
|
|
286
|
+
if (this.client.state !== 'READY') {
|
|
287
|
+
console.error(`[base-wrapper] Client not ready (state=${this.client.state}), dropping message to ${cmd.to}`);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
console.error(`[base-wrapper] sendRelayCommand: to=${cmd.to}, body=${cmd.body.substring(0, 50)}...`);
|
|
291
|
+
let sendMeta;
|
|
292
|
+
if (cmd.meta) {
|
|
293
|
+
sendMeta = {
|
|
294
|
+
importance: cmd.meta.importance,
|
|
295
|
+
replyTo: cmd.meta.replyTo,
|
|
296
|
+
requires_ack: cmd.meta.ackRequired,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
// Check if target is a channel (starts with #)
|
|
300
|
+
if (cmd.to.startsWith('#')) {
|
|
301
|
+
// Use CHANNEL_MESSAGE protocol for channel targets
|
|
302
|
+
console.error(`[base-wrapper] Sending CHANNEL_MESSAGE to ${cmd.to}`);
|
|
303
|
+
this.client.sendChannelMessage(cmd.to, cmd.body, {
|
|
304
|
+
thread: cmd.thread,
|
|
305
|
+
data: cmd.data,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
// Use SEND protocol for direct messages and broadcasts
|
|
310
|
+
if (cmd.sync?.blocking) {
|
|
311
|
+
this.client.sendAndWait(cmd.to, cmd.body, {
|
|
312
|
+
timeoutMs: cmd.sync.timeoutMs,
|
|
313
|
+
kind: cmd.kind,
|
|
314
|
+
data: cmd.data,
|
|
315
|
+
thread: cmd.thread,
|
|
316
|
+
}).catch((err) => {
|
|
317
|
+
console.error(`[base-wrapper] sendAndWait failed for ${cmd.to}: ${err.message}`);
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
this.client.sendMessage(cmd.to, cmd.body, cmd.kind, cmd.data, cmd.thread, sendMeta);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// =========================================================================
|
|
326
|
+
// Spawn/release handling
|
|
327
|
+
// =========================================================================
|
|
328
|
+
/**
|
|
329
|
+
* Parse spawn and release commands from output
|
|
330
|
+
*/
|
|
331
|
+
parseSpawnReleaseCommands(content) {
|
|
332
|
+
// Single-line spawn: ->relay:spawn Name cli "task"
|
|
333
|
+
const spawnPattern = new RegExp(`${this.relayPrefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}spawn\\s+(\\w+)\\s+(\\w+)\\s+"([^"]+)"`);
|
|
334
|
+
const spawnMatch = content.match(spawnPattern);
|
|
335
|
+
if (spawnMatch) {
|
|
336
|
+
const [, name, cli, task] = spawnMatch;
|
|
337
|
+
const cmdHash = `spawn:${name}:${cli}:${task}`;
|
|
338
|
+
if (!this.processedSpawnCommands.has(cmdHash)) {
|
|
339
|
+
this.processedSpawnCommands.add(cmdHash);
|
|
340
|
+
this.executeSpawn(name, cli, task);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// Fenced spawn: ->relay:spawn Name cli <<<\ntask\n>>>
|
|
344
|
+
const fencedSpawnPattern = new RegExp(`${this.relayPrefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}spawn\\s+(\\w+)\\s+(\\w+)\\s*<<<[\\s]*([\\s\\S]*?)>>>`);
|
|
345
|
+
const fencedSpawnMatch = content.match(fencedSpawnPattern);
|
|
346
|
+
if (fencedSpawnMatch) {
|
|
347
|
+
const [, name, cli, task] = fencedSpawnMatch;
|
|
348
|
+
const cmdHash = `spawn:${name}:${cli}:${task.trim()}`;
|
|
349
|
+
if (!this.processedSpawnCommands.has(cmdHash)) {
|
|
350
|
+
this.processedSpawnCommands.add(cmdHash);
|
|
351
|
+
this.executeSpawn(name, cli, task.trim());
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// Release: ->relay:release Name
|
|
355
|
+
const releasePattern = new RegExp(`${this.relayPrefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}release\\s+(\\w+)`);
|
|
356
|
+
const releaseMatch = content.match(releasePattern);
|
|
357
|
+
if (releaseMatch) {
|
|
358
|
+
const name = releaseMatch[1];
|
|
359
|
+
const cmdHash = `release:${name}`;
|
|
360
|
+
if (!this.processedReleaseCommands.has(cmdHash)) {
|
|
361
|
+
this.processedReleaseCommands.add(cmdHash);
|
|
362
|
+
this.executeRelease(name);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Execute a spawn command
|
|
368
|
+
*/
|
|
369
|
+
async executeSpawn(name, cli, task) {
|
|
370
|
+
// TODO: Re-enable daemon socket spawn when client.spawn() is implemented
|
|
371
|
+
// See: docs/SDK-MIGRATION-PLAN.md for planned implementation
|
|
372
|
+
// For now, go directly to dashboard API or callback
|
|
373
|
+
// Try dashboard API
|
|
374
|
+
if (this.config.dashboardPort) {
|
|
375
|
+
try {
|
|
376
|
+
const response = await fetch(`http://localhost:${this.config.dashboardPort}/api/spawn`, {
|
|
377
|
+
method: 'POST',
|
|
378
|
+
headers: { 'Content-Type': 'application/json' },
|
|
379
|
+
body: JSON.stringify({ name, cli, task }),
|
|
380
|
+
});
|
|
381
|
+
if (response.ok)
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
catch {
|
|
385
|
+
// Fall through to callback
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// Use callback as final fallback
|
|
389
|
+
if (this.config.onSpawn) {
|
|
390
|
+
await this.config.onSpawn(name, cli, task);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Execute a release command
|
|
395
|
+
*/
|
|
396
|
+
async executeRelease(name) {
|
|
397
|
+
// TODO: Re-enable daemon socket release when client.release() is implemented
|
|
398
|
+
// See: docs/SDK-MIGRATION-PLAN.md for planned implementation
|
|
399
|
+
// For now, go directly to dashboard API or callback
|
|
400
|
+
// Try dashboard API as fallback (backwards compatibility)
|
|
401
|
+
if (this.config.dashboardPort) {
|
|
402
|
+
try {
|
|
403
|
+
const response = await fetch(`http://localhost:${this.config.dashboardPort}/api/agents/${name}`, { method: 'DELETE' });
|
|
404
|
+
if (response.ok)
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
catch {
|
|
408
|
+
// Fall through to callback
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
// Use callback as final fallback
|
|
412
|
+
if (this.config.onRelease) {
|
|
413
|
+
await this.config.onRelease(name);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
// =========================================================================
|
|
417
|
+
// Continuity handling
|
|
418
|
+
// =========================================================================
|
|
419
|
+
/**
|
|
420
|
+
* Initialize agent ID for continuity/resume
|
|
421
|
+
*/
|
|
422
|
+
async initializeAgentId() {
|
|
423
|
+
if (!this.continuity)
|
|
424
|
+
return;
|
|
425
|
+
try {
|
|
426
|
+
let ledger;
|
|
427
|
+
// If resuming, try to find previous ledger
|
|
428
|
+
if (this.config.resumeAgentId) {
|
|
429
|
+
ledger = await this.continuity.findLedgerByAgentId(this.config.resumeAgentId);
|
|
430
|
+
}
|
|
431
|
+
// Otherwise get or create
|
|
432
|
+
if (!ledger) {
|
|
433
|
+
ledger = await this.continuity.getOrCreateLedger(this.config.name, this.cliType);
|
|
434
|
+
}
|
|
435
|
+
this.agentId = ledger.agentId;
|
|
436
|
+
}
|
|
437
|
+
catch (err) {
|
|
438
|
+
console.error(`[${this.config.name}] Failed to initialize agent ID: ${err.message}`);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Parse continuity commands from output
|
|
443
|
+
*/
|
|
444
|
+
async parseContinuityCommands(content) {
|
|
445
|
+
if (!this.continuity)
|
|
446
|
+
return;
|
|
447
|
+
if (!hasContinuityCommand(content))
|
|
448
|
+
return;
|
|
449
|
+
const command = parseContinuityCommand(content);
|
|
450
|
+
if (!command)
|
|
451
|
+
return;
|
|
452
|
+
// Deduplication
|
|
453
|
+
const cmdHash = `${command.type}:${command.content || command.query || command.item || 'no-content'}`;
|
|
454
|
+
if (command.content && this.processedContinuityCommands.has(cmdHash))
|
|
455
|
+
return;
|
|
456
|
+
this.processedContinuityCommands.add(cmdHash);
|
|
457
|
+
// Limit dedup set size
|
|
458
|
+
if (this.processedContinuityCommands.size > 100) {
|
|
459
|
+
const oldest = this.processedContinuityCommands.values().next().value;
|
|
460
|
+
if (oldest)
|
|
461
|
+
this.processedContinuityCommands.delete(oldest);
|
|
462
|
+
}
|
|
463
|
+
try {
|
|
464
|
+
const response = await this.continuity.handleCommand(this.config.name, command);
|
|
465
|
+
if (response) {
|
|
466
|
+
// Queue response for injection
|
|
467
|
+
this.messageQueue.push({
|
|
468
|
+
from: 'system',
|
|
469
|
+
body: response,
|
|
470
|
+
messageId: `continuity-${Date.now()}`,
|
|
471
|
+
thread: 'continuity-response',
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
catch (err) {
|
|
476
|
+
console.error(`[${this.config.name}] Continuity command error: ${err.message}`);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Save a parsed summary to the continuity ledger
|
|
481
|
+
*/
|
|
482
|
+
async saveSummaryToLedger(summary) {
|
|
483
|
+
if (!this.continuity)
|
|
484
|
+
return;
|
|
485
|
+
const updates = {};
|
|
486
|
+
if (summary.currentTask) {
|
|
487
|
+
updates.currentTask = summary.currentTask;
|
|
488
|
+
}
|
|
489
|
+
if (summary.completedTasks && summary.completedTasks.length > 0) {
|
|
490
|
+
updates.completed = summary.completedTasks;
|
|
491
|
+
}
|
|
492
|
+
if (summary.context) {
|
|
493
|
+
updates.inProgress = [summary.context];
|
|
494
|
+
}
|
|
495
|
+
if (summary.files && summary.files.length > 0) {
|
|
496
|
+
updates.fileContext = summary.files.map((f) => ({ path: f }));
|
|
497
|
+
}
|
|
498
|
+
if (Object.keys(updates).length > 0) {
|
|
499
|
+
await this.continuity.saveLedger(this.config.name, updates);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Reset session-specific state for wrapper reuse
|
|
504
|
+
*/
|
|
505
|
+
resetSessionState() {
|
|
506
|
+
this.sessionEndProcessed = false;
|
|
507
|
+
this.lastSummaryRawContent = '';
|
|
508
|
+
this.sessionEndData = undefined;
|
|
509
|
+
}
|
|
510
|
+
// =========================================================================
|
|
511
|
+
// Utility methods
|
|
512
|
+
// =========================================================================
|
|
513
|
+
/**
|
|
514
|
+
* Join continuation lines for multi-line relay/continuity commands.
|
|
515
|
+
* TUIs like Claude Code insert real newlines in output, causing
|
|
516
|
+
* messages to span multiple lines. This joins indented
|
|
517
|
+
* continuation lines back to the command line.
|
|
518
|
+
*/
|
|
519
|
+
joinContinuationLines(content) {
|
|
520
|
+
const lines = content.split('\n');
|
|
521
|
+
const result = [];
|
|
522
|
+
// Pattern to detect relay OR continuity command line (with optional bullet prefix)
|
|
523
|
+
const escapedPrefix = this.relayPrefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
524
|
+
const commandPattern = new RegExp(`^(?:\\s*(?:[>$%#→➜›»●•◦‣⁃\\-*⏺◆◇○□■]\\s*)*)?(?:${escapedPrefix}|->continuity:)`);
|
|
525
|
+
// Pattern to detect a continuation line (starts with spaces, no bullet/command)
|
|
526
|
+
const continuationPattern = /^[ \t]+[^>$%#→➜›»●•◦‣⁃\-*⏺◆◇○□■\s]/;
|
|
527
|
+
// Pattern to detect a new block/bullet (stops continuation)
|
|
528
|
+
const newBlockPattern = /^(?:\s*)?[>$%#→➜›»●•◦‣⁃\-*⏺◆◇○□■]/;
|
|
529
|
+
let i = 0;
|
|
530
|
+
while (i < lines.length) {
|
|
531
|
+
const line = lines[i];
|
|
532
|
+
// Check if this is a command line
|
|
533
|
+
if (commandPattern.test(line)) {
|
|
534
|
+
let joined = line;
|
|
535
|
+
let j = i + 1;
|
|
536
|
+
// Look ahead for continuation lines
|
|
537
|
+
while (j < lines.length) {
|
|
538
|
+
const nextLine = lines[j];
|
|
539
|
+
// Empty line stops continuation
|
|
540
|
+
if (nextLine.trim() === '')
|
|
541
|
+
break;
|
|
542
|
+
// New bullet/block stops continuation
|
|
543
|
+
if (newBlockPattern.test(nextLine))
|
|
544
|
+
break;
|
|
545
|
+
// Check if it looks like a continuation (indented text)
|
|
546
|
+
if (continuationPattern.test(nextLine)) {
|
|
547
|
+
// Join with newline to preserve multi-line message content
|
|
548
|
+
joined += '\n' + nextLine.trim();
|
|
549
|
+
j++;
|
|
550
|
+
}
|
|
551
|
+
else {
|
|
552
|
+
break;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
result.push(joined);
|
|
556
|
+
i = j; // Skip the lines we joined
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
result.push(line);
|
|
560
|
+
i++;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
return result.join('\n');
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Clean up resources
|
|
567
|
+
*/
|
|
568
|
+
destroyClient() {
|
|
569
|
+
this.client.destroy();
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
//# sourceMappingURL=base-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-wrapper.js","sourceRoot":"","sources":["../src/base-wrapper.ts"],"names":[],"mappings":"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"}
|