@coralai/claude-code-agent 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/README.md +111 -0
- package/dist/agent.d.ts +240 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +592 -0
- package/dist/agent.js.map +1 -0
- package/dist/errors.d.ts +27 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +33 -0
- package/dist/errors.js.map +1 -0
- package/dist/hooks/fs.d.ts +26 -0
- package/dist/hooks/fs.d.ts.map +1 -0
- package/dist/hooks/fs.js +61 -0
- package/dist/hooks/fs.js.map +1 -0
- package/dist/hooks/index.d.ts +18 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/permissions.d.ts +42 -0
- package/dist/hooks/permissions.d.ts.map +1 -0
- package/dist/hooks/permissions.js +79 -0
- package/dist/hooks/permissions.js.map +1 -0
- package/dist/hooks/terminal.d.ts +56 -0
- package/dist/hooks/terminal.d.ts.map +1 -0
- package/dist/hooks/terminal.js +127 -0
- package/dist/hooks/terminal.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/acp-client-interface.d.ts +107 -0
- package/dist/internal/acp-client-interface.d.ts.map +1 -0
- package/dist/internal/acp-client-interface.js +17 -0
- package/dist/internal/acp-client-interface.js.map +1 -0
- package/dist/internal/acp-types.d.ts +64 -0
- package/dist/internal/acp-types.d.ts.map +1 -0
- package/dist/internal/acp-types.js +17 -0
- package/dist/internal/acp-types.js.map +1 -0
- package/dist/internal/agent-runtime-interface.d.ts +40 -0
- package/dist/internal/agent-runtime-interface.d.ts.map +1 -0
- package/dist/internal/agent-runtime-interface.js +17 -0
- package/dist/internal/agent-runtime-interface.js.map +1 -0
- package/dist/internal/local-acp-client.d.ts +27 -0
- package/dist/internal/local-acp-client.d.ts.map +1 -0
- package/dist/internal/local-acp-client.js +26 -0
- package/dist/internal/local-acp-client.js.map +1 -0
- package/dist/internal/sdk-adapter.d.ts +24 -0
- package/dist/internal/sdk-adapter.d.ts.map +1 -0
- package/dist/internal/sdk-adapter.js +453 -0
- package/dist/internal/sdk-adapter.js.map +1 -0
- package/dist/internal/session-accumulator.d.ts +55 -0
- package/dist/internal/session-accumulator.d.ts.map +1 -0
- package/dist/internal/session-accumulator.js +133 -0
- package/dist/internal/session-accumulator.js.map +1 -0
- package/dist/prompt-handle.d.ts +70 -0
- package/dist/prompt-handle.d.ts.map +1 -0
- package/dist/prompt-handle.js +137 -0
- package/dist/prompt-handle.js.map +1 -0
- package/dist/recording/index.d.ts +10 -0
- package/dist/recording/index.d.ts.map +1 -0
- package/dist/recording/index.js +10 -0
- package/dist/recording/index.js.map +1 -0
- package/dist/recording/replayer.d.ts +17 -0
- package/dist/recording/replayer.d.ts.map +1 -0
- package/dist/recording/replayer.js +68 -0
- package/dist/recording/replayer.js.map +1 -0
- package/dist/recording/writer.d.ts +32 -0
- package/dist/recording/writer.d.ts.map +1 -0
- package/dist/recording/writer.js +122 -0
- package/dist/recording/writer.js.map +1 -0
- package/dist/telemetry/index.d.ts +8 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +8 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/otel-adapter.d.ts +105 -0
- package/dist/telemetry/otel-adapter.d.ts.map +1 -0
- package/dist/telemetry/otel-adapter.js +153 -0
- package/dist/telemetry/otel-adapter.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module AcpSdkAdapter
|
|
3
|
+
* @description ACP SDK 适配器,通过 JSON-RPC over stdio 实现 Agent 客户端协议通信
|
|
4
|
+
*
|
|
5
|
+
* @author eddy
|
|
6
|
+
* @organization wykj
|
|
7
|
+
* @ownership wykj/eddy
|
|
8
|
+
*
|
|
9
|
+
* @created 2026-03-31
|
|
10
|
+
* @updated 2026-04-03
|
|
11
|
+
*
|
|
12
|
+
* @role adapter
|
|
13
|
+
* @layer provider
|
|
14
|
+
* @boundedContext acp
|
|
15
|
+
*/
|
|
16
|
+
import { execFileSync, spawn } from 'node:child_process';
|
|
17
|
+
import { readFileSync } from 'node:fs';
|
|
18
|
+
import { resolve } from 'node:path';
|
|
19
|
+
import { Readable, Writable } from 'node:stream';
|
|
20
|
+
import { ClientSideConnection, ndJsonStream } from '@agentclientprotocol/sdk';
|
|
21
|
+
import { FileSystemHandlers } from '../hooks/fs.js';
|
|
22
|
+
import { resolvePermission } from '../hooks/permissions.js';
|
|
23
|
+
import { SessionUpdateAccumulator } from './session-accumulator.js';
|
|
24
|
+
import { TerminalManager } from '../hooks/terminal.js';
|
|
25
|
+
/** Check if a command exists in PATH */
|
|
26
|
+
function commandExists(cmd) {
|
|
27
|
+
try {
|
|
28
|
+
execFileSync('which', [cmd], { stdio: 'ignore' });
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Resolve agent command: prefer global binary, fallback to npx */
|
|
36
|
+
function resolveAgent(globalBin, npxPkg) {
|
|
37
|
+
if (commandExists(globalBin))
|
|
38
|
+
return { command: globalBin, args: [] };
|
|
39
|
+
return { command: 'npx', args: ['-y', npxPkg] };
|
|
40
|
+
}
|
|
41
|
+
const BUILTIN_AGENTS = {
|
|
42
|
+
claude: resolveAgent('claude-agent-acp', '@agentclientprotocol/claude-agent-acp'),
|
|
43
|
+
};
|
|
44
|
+
/** Load custom agents from ~/.coral/agents.json, merge with builtins. */
|
|
45
|
+
export function loadAgentRegistry() {
|
|
46
|
+
const registry = { ...BUILTIN_AGENTS };
|
|
47
|
+
try {
|
|
48
|
+
const home = process.env.HOME || '/home/coral';
|
|
49
|
+
const custom = JSON.parse(readFileSync(resolve(home, '.coral', 'agents.json'), 'utf-8'));
|
|
50
|
+
if (custom && typeof custom === 'object') {
|
|
51
|
+
for (const [name, entry] of Object.entries(custom)) {
|
|
52
|
+
const e = entry;
|
|
53
|
+
if (e.command) {
|
|
54
|
+
registry[name] = { command: e.command, args: e.args ?? [] };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch { /* no custom agents file */ }
|
|
60
|
+
return registry;
|
|
61
|
+
}
|
|
62
|
+
function isChildAlive(child) {
|
|
63
|
+
return child.exitCode == null && child.signalCode == null && !child.killed;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Cross-process PID liveness check via signal 0.
|
|
67
|
+
* Inlined here (was imported from ../outputParser) to keep this adapter
|
|
68
|
+
* self-contained for Phase 1 extraction into @coralai/claude-code-agent.
|
|
69
|
+
*/
|
|
70
|
+
function isPidAlive(pid) {
|
|
71
|
+
if (!pid || pid <= 0)
|
|
72
|
+
return false;
|
|
73
|
+
try {
|
|
74
|
+
process.kill(pid, 0);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export class AcpSdkAdapter {
|
|
82
|
+
sessions = new Map();
|
|
83
|
+
defaultPermissionMode;
|
|
84
|
+
constructor(permissionMode) {
|
|
85
|
+
this.defaultPermissionMode =
|
|
86
|
+
permissionMode ?? process.env.ACP_PERMISSION_MODE ?? 'approve-all';
|
|
87
|
+
}
|
|
88
|
+
async ensureSession(input) {
|
|
89
|
+
const existing = this.sessions.get(input.sessionName);
|
|
90
|
+
if (existing && !input.resetExisting && isChildAlive(existing.child)) {
|
|
91
|
+
return {
|
|
92
|
+
sessionId: existing.sessionId,
|
|
93
|
+
sessionState: existing.activePromise ? 'busy' : 'ready',
|
|
94
|
+
paneText: existing.accumulator.getRecentText(),
|
|
95
|
+
lastSeenAt: new Date().toISOString(),
|
|
96
|
+
pid: existing.child.pid ?? null,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (existing) {
|
|
100
|
+
await this.destroySession(existing);
|
|
101
|
+
this.sessions.delete(input.sessionName);
|
|
102
|
+
}
|
|
103
|
+
// Resolve adapter command
|
|
104
|
+
const allAgents = loadAgentRegistry();
|
|
105
|
+
const registry = allAgents[input.tool];
|
|
106
|
+
if (!registry)
|
|
107
|
+
throw new Error(`Unknown ACP tool: ${input.tool}`);
|
|
108
|
+
process.stderr.write(`[acp-adapter] Spawning ${input.tool}: ${registry.command} ${registry.args.join(' ')} (cwd=${input.cwd})\n`);
|
|
109
|
+
// Spawn ACP adapter child process.
|
|
110
|
+
// extraEnv flows through the shim to claude and then to hook scripts —
|
|
111
|
+
// used by SPS to inject SPS_CARD_ID / SPS_STAGE / SPS_PROJECT / SPS_WORKER_SLOT.
|
|
112
|
+
const child = spawn(registry.command, registry.args, {
|
|
113
|
+
cwd: input.cwd,
|
|
114
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
115
|
+
env: { ...process.env, ...(input.extraEnv ?? {}) },
|
|
116
|
+
});
|
|
117
|
+
// IMPORTANT: Register spawn/error listeners and await spawn BEFORE any async
|
|
118
|
+
// operations (like dynamic imports). Otherwise the spawn event can fire during
|
|
119
|
+
// an await gap and the once('spawn') listener misses it.
|
|
120
|
+
const spawnTimeout = setTimeout(() => {
|
|
121
|
+
try {
|
|
122
|
+
child.kill('SIGKILL');
|
|
123
|
+
}
|
|
124
|
+
catch { /* noop */ }
|
|
125
|
+
}, 60_000);
|
|
126
|
+
spawnTimeout.unref();
|
|
127
|
+
try {
|
|
128
|
+
await new Promise((resolve, reject) => {
|
|
129
|
+
child.once('spawn', () => resolve());
|
|
130
|
+
child.once('error', (err) => reject(new Error(`Failed to spawn ${input.tool} ACP adapter: ${err.message}`)));
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
clearTimeout(spawnTimeout);
|
|
135
|
+
throw err;
|
|
136
|
+
}
|
|
137
|
+
clearTimeout(spawnTimeout);
|
|
138
|
+
process.stderr.write(`[acp-adapter] Spawn succeeded (pid=${child.pid}), establishing JSON-RPC...\n`);
|
|
139
|
+
// Capture stderr to log file for crash diagnosis (safe to await here — spawn already resolved)
|
|
140
|
+
const stderrLogFile = input.logsDir
|
|
141
|
+
? resolve(input.logsDir, `acp-stderr-${input.tool}-${Date.now()}.log`)
|
|
142
|
+
: null;
|
|
143
|
+
let stderrFd = null;
|
|
144
|
+
if (stderrLogFile) {
|
|
145
|
+
try {
|
|
146
|
+
const { openSync, writeSync, closeSync } = await import('node:fs');
|
|
147
|
+
stderrFd = openSync(stderrLogFile, 'a');
|
|
148
|
+
child.stderr?.on('data', (chunk) => {
|
|
149
|
+
try {
|
|
150
|
+
writeSync(stderrFd, chunk);
|
|
151
|
+
}
|
|
152
|
+
catch { /* non-fatal */ }
|
|
153
|
+
});
|
|
154
|
+
child.once('exit', (code, signal) => {
|
|
155
|
+
const exitInfo = `\n[acp-stderr] Process exited: code=${code}, signal=${signal}, pid=${child.pid}\n`;
|
|
156
|
+
try {
|
|
157
|
+
writeSync(stderrFd, Buffer.from(exitInfo));
|
|
158
|
+
}
|
|
159
|
+
catch { /* non-fatal */ }
|
|
160
|
+
if (stderrFd != null)
|
|
161
|
+
try {
|
|
162
|
+
closeSync(stderrFd);
|
|
163
|
+
}
|
|
164
|
+
catch { /* noop */ }
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
child.stderr?.on('data', () => { });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
child.stderr?.on('data', () => { });
|
|
173
|
+
}
|
|
174
|
+
// Establish JSON-RPC connection over stdio
|
|
175
|
+
const stream = ndJsonStream(Writable.toWeb(child.stdin), Readable.toWeb(child.stdout));
|
|
176
|
+
const accumulator = new SessionUpdateAccumulator();
|
|
177
|
+
const permissionMode = this.defaultPermissionMode;
|
|
178
|
+
// Set up log file for sps logs compatibility
|
|
179
|
+
if (input.logsDir) {
|
|
180
|
+
const logFileName = `${input.sessionName}-acp-${Date.now()}.log`;
|
|
181
|
+
accumulator.setLogFile(`${input.logsDir}/${logFileName}`);
|
|
182
|
+
}
|
|
183
|
+
const fsHandlers = new FileSystemHandlers({ cwd: input.cwd, permissionMode });
|
|
184
|
+
const terminalMgr = new TerminalManager({ cwd: input.cwd, permissionMode });
|
|
185
|
+
const conn = new ClientSideConnection(() => ({
|
|
186
|
+
sessionUpdate: async (params) => {
|
|
187
|
+
accumulator.handleUpdate(params.update);
|
|
188
|
+
},
|
|
189
|
+
requestPermission: async (params) => {
|
|
190
|
+
accumulator.hasPendingPermission = true;
|
|
191
|
+
const result = resolvePermission(params, permissionMode);
|
|
192
|
+
accumulator.hasPendingPermission = false;
|
|
193
|
+
return result;
|
|
194
|
+
},
|
|
195
|
+
readTextFile: async (params) => {
|
|
196
|
+
return fsHandlers.readTextFile(params);
|
|
197
|
+
},
|
|
198
|
+
writeTextFile: async (params) => {
|
|
199
|
+
return fsHandlers.writeTextFile(params);
|
|
200
|
+
},
|
|
201
|
+
createTerminal: async (params) => {
|
|
202
|
+
return terminalMgr.createTerminal(params);
|
|
203
|
+
},
|
|
204
|
+
terminalOutput: async (params) => {
|
|
205
|
+
return terminalMgr.terminalOutput(params);
|
|
206
|
+
},
|
|
207
|
+
waitForTerminalExit: async (params) => {
|
|
208
|
+
return terminalMgr.waitForTerminalExit(params);
|
|
209
|
+
},
|
|
210
|
+
killTerminal: async (params) => {
|
|
211
|
+
return terminalMgr.killTerminal(params);
|
|
212
|
+
},
|
|
213
|
+
releaseTerminal: async (params) => {
|
|
214
|
+
return terminalMgr.releaseTerminal(params);
|
|
215
|
+
},
|
|
216
|
+
}), stream);
|
|
217
|
+
// Protocol initialization
|
|
218
|
+
process.stderr.write(`[acp-adapter] Initializing ${input.tool} ACP protocol...\n`);
|
|
219
|
+
const _initResult = await conn.initialize({
|
|
220
|
+
protocolVersion: 1,
|
|
221
|
+
clientCapabilities: {
|
|
222
|
+
fs: { readTextFile: true, writeTextFile: true },
|
|
223
|
+
terminal: true,
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
process.stderr.write(`[acp-adapter] Protocol initialized. Creating session...\n`);
|
|
227
|
+
// Create new session
|
|
228
|
+
const sessionResult = await conn.newSession({
|
|
229
|
+
cwd: input.cwd,
|
|
230
|
+
mcpServers: (input.mcpServers ?? []).map(s => ({
|
|
231
|
+
name: s.name,
|
|
232
|
+
command: s.command,
|
|
233
|
+
args: s.args ?? [],
|
|
234
|
+
env: s.env ?? [],
|
|
235
|
+
})),
|
|
236
|
+
});
|
|
237
|
+
process.stderr.write(`[acp-adapter] Session created: ${sessionResult.sessionId}\n`);
|
|
238
|
+
const session = {
|
|
239
|
+
tool: input.tool,
|
|
240
|
+
sessionId: sessionResult.sessionId,
|
|
241
|
+
sessionName: input.sessionName,
|
|
242
|
+
cwd: input.cwd,
|
|
243
|
+
child,
|
|
244
|
+
conn,
|
|
245
|
+
accumulator,
|
|
246
|
+
activePromise: null,
|
|
247
|
+
permissionMode,
|
|
248
|
+
};
|
|
249
|
+
this.sessions.set(input.sessionName, session);
|
|
250
|
+
return {
|
|
251
|
+
sessionId: sessionResult.sessionId,
|
|
252
|
+
sessionState: 'ready',
|
|
253
|
+
paneText: '',
|
|
254
|
+
lastSeenAt: new Date().toISOString(),
|
|
255
|
+
pid: child.pid ?? null,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
async startRun(input) {
|
|
259
|
+
const session = this.sessions.get(input.sessionName);
|
|
260
|
+
if (!session)
|
|
261
|
+
throw new Error(`ACP session not found: ${input.sessionName}`);
|
|
262
|
+
if (session.activePromise)
|
|
263
|
+
throw new Error(`Session ${input.sessionName} already has active run`);
|
|
264
|
+
session.accumulator.reset();
|
|
265
|
+
// Non-blocking prompt — store promise but don't await
|
|
266
|
+
session.activePromise = session.conn.prompt({
|
|
267
|
+
sessionId: session.sessionId,
|
|
268
|
+
prompt: [{ type: 'text', text: input.prompt }],
|
|
269
|
+
});
|
|
270
|
+
session.activePromise
|
|
271
|
+
.then((result) => {
|
|
272
|
+
session.accumulator.markComplete(result.stopReason ?? 'end_turn');
|
|
273
|
+
session.activePromise = null;
|
|
274
|
+
})
|
|
275
|
+
.catch((err) => {
|
|
276
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
277
|
+
process.stderr.write(`[acp] Prompt failed for ${input.sessionName}: ${msg}\n`);
|
|
278
|
+
session.accumulator.markComplete('failed');
|
|
279
|
+
session.activePromise = null;
|
|
280
|
+
});
|
|
281
|
+
return {
|
|
282
|
+
runId: `acp-${Date.now()}`,
|
|
283
|
+
runState: 'running',
|
|
284
|
+
paneText: '',
|
|
285
|
+
lastSeenAt: new Date().toISOString(),
|
|
286
|
+
pid: session.child.pid ?? null,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
async inspectSession(input) {
|
|
290
|
+
const session = this.sessions.get(input.sessionName);
|
|
291
|
+
// In-process session: direct check
|
|
292
|
+
if (session && isChildAlive(session.child)) {
|
|
293
|
+
return {
|
|
294
|
+
sessionState: session.activePromise ? 'busy' : 'ready',
|
|
295
|
+
paneText: session.accumulator.getRecentText(),
|
|
296
|
+
lastSeenAt: new Date().toISOString(),
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
// Cross-process fallback: check persisted PID liveness
|
|
300
|
+
if (input.pid && isPidAlive(input.pid)) {
|
|
301
|
+
return {
|
|
302
|
+
sessionState: 'busy', // PID alive but not our process — assume busy
|
|
303
|
+
paneText: '',
|
|
304
|
+
lastSeenAt: new Date().toISOString(),
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
return { sessionState: 'offline', paneText: '', lastSeenAt: new Date().toISOString() };
|
|
308
|
+
}
|
|
309
|
+
async inspectRun(input) {
|
|
310
|
+
if (!input.activeRun) {
|
|
311
|
+
return { runState: null, paneText: '', lastSeenAt: new Date().toISOString() };
|
|
312
|
+
}
|
|
313
|
+
const session = this.sessions.get(input.sessionName);
|
|
314
|
+
// In-process session: detailed status from accumulator
|
|
315
|
+
if (session && isChildAlive(session.child)) {
|
|
316
|
+
// (handled below)
|
|
317
|
+
}
|
|
318
|
+
else if (input.pid && isPidAlive(input.pid)) {
|
|
319
|
+
// Cross-process fallback: PID alive = running
|
|
320
|
+
return { runState: 'running', paneText: '', lastSeenAt: new Date().toISOString() };
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
return { runState: 'lost', paneText: '', lastSeenAt: new Date().toISOString() };
|
|
324
|
+
}
|
|
325
|
+
const acc = session.accumulator;
|
|
326
|
+
let runState;
|
|
327
|
+
if (!session.activePromise) {
|
|
328
|
+
// Prompt has returned
|
|
329
|
+
runState = acc.stopReason === 'end_turn' ? 'completed'
|
|
330
|
+
: acc.stopReason === 'cancelled' ? 'cancelled'
|
|
331
|
+
: 'failed';
|
|
332
|
+
}
|
|
333
|
+
else if (acc.hasPendingPermission) {
|
|
334
|
+
runState = 'needs_confirmation';
|
|
335
|
+
}
|
|
336
|
+
else if (acc.lastUpdateAt && acc.getRecentText().length > 0) {
|
|
337
|
+
// Idle detection: if agent has produced output but no updates for 60s,
|
|
338
|
+
// treat as completed. Some ACP adapters (e.g. codex-acp) may not
|
|
339
|
+
// resolve the prompt() call even after the agent finishes.
|
|
340
|
+
const idleMs = Date.now() - new Date(acc.lastUpdateAt).getTime();
|
|
341
|
+
if (idleMs > 60_000) {
|
|
342
|
+
acc.markComplete('end_turn');
|
|
343
|
+
session.activePromise = null;
|
|
344
|
+
runState = 'completed';
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
runState = 'running';
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
runState = 'running';
|
|
352
|
+
}
|
|
353
|
+
return {
|
|
354
|
+
runState,
|
|
355
|
+
paneText: acc.getRecentText(),
|
|
356
|
+
lastSeenAt: new Date().toISOString(),
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
subscribe(sessionName, listener) {
|
|
360
|
+
const session = this.sessions.get(sessionName);
|
|
361
|
+
if (!session)
|
|
362
|
+
return () => { };
|
|
363
|
+
session.accumulator.addListener(listener);
|
|
364
|
+
return () => session.accumulator.removeListener(listener);
|
|
365
|
+
}
|
|
366
|
+
async cancelRun(sessionName) {
|
|
367
|
+
const session = this.sessions.get(sessionName);
|
|
368
|
+
if (!session || !session.activePromise)
|
|
369
|
+
return;
|
|
370
|
+
try {
|
|
371
|
+
await session.conn.cancel({ sessionId: session.sessionId });
|
|
372
|
+
}
|
|
373
|
+
catch {
|
|
374
|
+
/* Agent may have already finished/crashed — safe to ignore */
|
|
375
|
+
}
|
|
376
|
+
// Mark accumulator complete so subscribers see cancellation and exit loop.
|
|
377
|
+
// activePromise will also settle naturally via the cancel response.
|
|
378
|
+
session.accumulator.markComplete('cancelled');
|
|
379
|
+
}
|
|
380
|
+
async stopSession(input) {
|
|
381
|
+
const session = this.sessions.get(input.sessionName);
|
|
382
|
+
if (!session)
|
|
383
|
+
return;
|
|
384
|
+
if (session.activePromise) {
|
|
385
|
+
try {
|
|
386
|
+
await session.conn.cancel({ sessionId: session.sessionId });
|
|
387
|
+
}
|
|
388
|
+
catch { /* Agent may already be dead */ }
|
|
389
|
+
}
|
|
390
|
+
await this.destroySession(session);
|
|
391
|
+
this.sessions.delete(input.sessionName);
|
|
392
|
+
}
|
|
393
|
+
async destroySession(session) {
|
|
394
|
+
const pid = session.child.pid;
|
|
395
|
+
const log = (msg) => process.stderr.write(`[acp-adapter] ${msg}\n`);
|
|
396
|
+
// Kill child + try to kill descendant processes
|
|
397
|
+
try {
|
|
398
|
+
session.child.kill('SIGTERM');
|
|
399
|
+
}
|
|
400
|
+
catch (e) {
|
|
401
|
+
log(`SIGTERM child failed: ${e instanceof Error ? e.message : e}`);
|
|
402
|
+
}
|
|
403
|
+
if (pid) {
|
|
404
|
+
try {
|
|
405
|
+
process.kill(pid, 'SIGTERM');
|
|
406
|
+
}
|
|
407
|
+
catch { /* already dead */ }
|
|
408
|
+
this.killDescendants(pid, 'SIGTERM');
|
|
409
|
+
}
|
|
410
|
+
await new Promise((resolve) => {
|
|
411
|
+
const timeout = setTimeout(() => {
|
|
412
|
+
try {
|
|
413
|
+
session.child.kill('SIGKILL');
|
|
414
|
+
}
|
|
415
|
+
catch (e) {
|
|
416
|
+
log(`SIGKILL child failed (pid=${pid}): ${e instanceof Error ? e.message : e}`);
|
|
417
|
+
}
|
|
418
|
+
if (pid) {
|
|
419
|
+
try {
|
|
420
|
+
process.kill(pid, 'SIGKILL');
|
|
421
|
+
}
|
|
422
|
+
catch (e) {
|
|
423
|
+
log(`SIGKILL pid=${pid} failed: ${e instanceof Error ? e.message : e}`);
|
|
424
|
+
}
|
|
425
|
+
this.killDescendants(pid, 'SIGKILL');
|
|
426
|
+
}
|
|
427
|
+
resolve();
|
|
428
|
+
}, 3_000);
|
|
429
|
+
session.child.once('exit', () => {
|
|
430
|
+
clearTimeout(timeout);
|
|
431
|
+
resolve();
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
/** Kill all child processes of a given PID (Linux: pgrep -P). */
|
|
436
|
+
killDescendants(parentPid, signal) {
|
|
437
|
+
try {
|
|
438
|
+
const out = execFileSync('pgrep', ['-P', String(parentPid)], { encoding: 'utf-8', timeout: 2000 });
|
|
439
|
+
for (const line of out.trim().split('\n')) {
|
|
440
|
+
const childPid = parseInt(line, 10);
|
|
441
|
+
if (childPid > 0) {
|
|
442
|
+
try {
|
|
443
|
+
process.kill(childPid, signal);
|
|
444
|
+
}
|
|
445
|
+
catch { /* already dead */ }
|
|
446
|
+
this.killDescendants(childPid, signal);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
catch { /* pgrep not found or no children — expected */ }
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
//# sourceMappingURL=sdk-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk-adapter.js","sourceRoot":"","sources":["../../src/internal/sdk-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAqB,YAAY,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAc9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAuB,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAIvD,wCAAwC;AACxC,SAAS,aAAa,CAAC,GAAW;IAChC,IAAI,CAAC;QAAC,YAAY,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,KAAK,CAAC;IAAC,CAAC;AACjG,CAAC;AAED,mEAAmE;AACnE,SAAS,YAAY,CAAC,SAAiB,EAAE,MAAc;IACrD,IAAI,aAAa,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IACtE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,cAAc,GAAuC;IACzD,MAAM,EAAE,YAAY,CAAC,kBAAkB,EAAE,uCAAuC,CAAC;CAClF,CAAC;AAEF,yEAAyE;AACzE,MAAM,UAAU,iBAAiB;IAC/B,MAAM,QAAQ,GAAG,EAAE,GAAG,cAAc,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,aAAa,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,aAAa,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QACzF,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YACzC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBACnD,MAAM,CAAC,GAAG,KAA8C,CAAC;gBACzD,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;oBACd,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;gBAC9D,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,2BAA2B,CAAC,CAAC;IACvC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAcD,SAAS,YAAY,CAAC,KAAmB;IACvC,OAAO,KAAK,CAAC,QAAQ,IAAI,IAAI,IAAI,KAAK,CAAC,UAAU,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;AAC7E,CAAC;AAED;;;;GAIG;AACH,SAAS,UAAU,CAAC,GAA8B;IAChD,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,OAAO,aAAa;IACP,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC5C,qBAAqB,CAAiB;IAEvD,YAAY,cAA+B;QACzC,IAAI,CAAC,qBAAqB;YACxB,cAAc,IAAK,OAAO,CAAC,GAAG,CAAC,mBAAsC,IAAI,aAAa,CAAC;IAC3F,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAAyB;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAEtD,IAAI,QAAQ,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACrE,OAAO;gBACL,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,YAAY,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;gBACvD,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC,aAAa,EAAE;gBAC9C,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACpC,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI;aAChC,CAAC;QACJ,CAAC;QAED,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;YACpC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC1C,CAAC;QAED,0BAA0B;QAC1B,MAAM,SAAS,GAAG,iBAAiB,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAElE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC;QAElI,mCAAmC;QACnC,uEAAuE;QACvE,iFAAiF;QACjF,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE;YACnD,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE;SACnD,CAAC,CAAC;QAEH,6EAA6E;QAC7E,+EAA+E;QAC/E,yDAAyD;QACzD,MAAM,YAAY,GAAG,UAAU,CAAC,GAAG,EAAE;YACnC,IAAI,CAAC;gBAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;QACrD,CAAC,EAAE,MAAM,CAAC,CAAC;QACX,YAAY,CAAC,KAAK,EAAE,CAAC;QAErB,IAAI,CAAC;YACH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC1C,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;gBACrC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,KAAK,CAAC,IAAI,iBAAiB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/G,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,YAAY,CAAC,YAAY,CAAC,CAAC;YAC3B,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,YAAY,CAAC,YAAY,CAAC,CAAC;QAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sCAAsC,KAAK,CAAC,GAAG,+BAA+B,CAAC,CAAC;QAErG,+FAA+F;QAC/F,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO;YACjC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,cAAc,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;YACtE,CAAC,CAAC,IAAI,CAAC;QACT,IAAI,QAAQ,GAAkB,IAAI,CAAC;QACnC,IAAI,aAAa,EAAE,CAAC;YAClB,IAAI,CAAC;gBACH,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;gBACnE,QAAQ,GAAG,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;gBACxC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;oBACzC,IAAI,CAAC;wBAAC,SAAS,CAAC,QAAS,EAAE,KAAK,CAAC,CAAC;oBAAC,CAAC;oBAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC;gBAChE,CAAC,CAAC,CAAC;gBACH,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;oBAClC,MAAM,QAAQ,GAAG,uCAAuC,IAAI,YAAY,MAAM,SAAS,KAAK,CAAC,GAAG,IAAI,CAAC;oBACrG,IAAI,CAAC;wBAAC,SAAS,CAAC,QAAS,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;oBAAC,CAAC;oBAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC;oBAC9E,IAAI,QAAQ,IAAI,IAAI;wBAAE,IAAI,CAAC;4BAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;wBAAC,CAAC;wBAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;gBACzE,CAAC,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,GAAiB,CAAC,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,GAAiB,CAAC,CAAC,CAAC;QACpD,CAAC;QAED,2CAA2C;QAC3C,MAAM,MAAM,GAAG,YAAY,CACzB,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,KAAM,CAA+B,EAC1D,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,MAAO,CAA+B,CAC5D,CAAC;QAEF,MAAM,WAAW,GAAG,IAAI,wBAAwB,EAAE,CAAC;QACnD,MAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,CAAC;QAClD,6CAA6C;QAC7C,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,WAAW,GAAG,GAAG,KAAK,CAAC,WAAW,QAAQ,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;YACjE,WAAW,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,WAAW,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,kBAAkB,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,cAAc,EAAE,CAAC,CAAC;QAC9E,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,cAAc,EAAE,CAAC,CAAC;QAE5E,MAAM,IAAI,GAAG,IAAI,oBAAoB,CACnC,GAAG,EAAE,CAAC,CAAC;YACL,aAAa,EAAE,KAAK,EAAE,MAAkC,EAAE,EAAE;gBAC1D,WAAW,CAAC,YAAY,CAAC,MAAM,CAAC,MAAa,CAAC,CAAC;YACjD,CAAC;YACD,iBAAiB,EAAE,KAAK,EAAE,MAAuC,EAAE,EAAE;gBACnE,WAAW,CAAC,oBAAoB,GAAG,IAAI,CAAC;gBACxC,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAa,EAAE,cAAc,CAAC,CAAC;gBAChE,WAAW,CAAC,oBAAoB,GAAG,KAAK,CAAC;gBACzC,OAAO,MAA0C,CAAC;YACpD,CAAC;YACD,YAAY,EAAE,KAAK,EAAE,MAAkC,EAAE,EAAE;gBACzD,OAAO,UAAU,CAAC,YAAY,CAAC,MAAa,CAAyC,CAAC;YACxF,CAAC;YACD,aAAa,EAAE,KAAK,EAAE,MAAmC,EAAE,EAAE;gBAC3D,OAAO,UAAU,CAAC,aAAa,CAAC,MAAa,CAA0C,CAAC;YAC1F,CAAC;YACD,cAAc,EAAE,KAAK,EAAE,MAAoC,EAAE,EAAE;gBAC7D,OAAO,WAAW,CAAC,cAAc,CAAC,MAAa,CAA2C,CAAC;YAC7F,CAAC;YACD,cAAc,EAAE,KAAK,EAAE,MAAoC,EAAE,EAAE;gBAC7D,OAAO,WAAW,CAAC,cAAc,CAAC,MAAa,CAA2C,CAAC;YAC7F,CAAC;YACD,mBAAmB,EAAE,KAAK,EAAE,MAAyC,EAAE,EAAE;gBACvE,OAAO,WAAW,CAAC,mBAAmB,CAAC,MAAa,CAAgD,CAAC;YACvG,CAAC;YACD,YAAY,EAAE,KAAK,EAAE,MAAkC,EAAE,EAAE;gBACzD,OAAO,WAAW,CAAC,YAAY,CAAC,MAAa,CAAyC,CAAC;YACzF,CAAC;YACD,eAAe,EAAE,KAAK,EAAE,MAAqC,EAAE,EAAE;gBAC/D,OAAO,WAAW,CAAC,eAAe,CAAC,MAAa,CAA4C,CAAC;YAC/F,CAAC;SACF,CAAC,EACF,MAAM,CACP,CAAC;QAEF,0BAA0B;QAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,KAAK,CAAC,IAAI,oBAAoB,CAAC,CAAC;QACnF,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC;YACxC,eAAe,EAAE,CAAC;YAClB,kBAAkB,EAAE;gBAClB,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;gBAC/C,QAAQ,EAAE,IAAI;aACf;SACF,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAElF,qBAAqB;QACrB,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC;YAC1C,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,UAAU,EAAE,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC7C,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;gBAClB,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE;aACjB,CAAC,CAAC;SACJ,CAAC,CAAC;QAEH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,aAAa,CAAC,SAAS,IAAI,CAAC,CAAC;QAEpF,MAAM,OAAO,GAAkB;YAC7B,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,SAAS,EAAE,aAAa,CAAC,SAAS;YAClC,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,KAAK;YACL,IAAI;YACJ,WAAW;YACX,aAAa,EAAE,IAAI;YACnB,cAAc;SACf,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAE9C,OAAO;YACL,SAAS,EAAE,aAAa,CAAC,SAAS;YAClC,YAAY,EAAE,OAAO;YACrB,QAAQ,EAAE,EAAE;YACZ,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACpC,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,IAAI;SACvB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAoB;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;QAC7E,IAAI,OAAO,CAAC,aAAa;YAAE,MAAM,IAAI,KAAK,CAAC,WAAW,KAAK,CAAC,WAAW,yBAAyB,CAAC,CAAC;QAElG,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;QAE5B,sDAAsD;QACtD,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;YAC1C,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;SAC/C,CAAC,CAAC;QAEH,OAAO,CAAC,aAAa;aAClB,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACf,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,IAAI,UAAU,CAAC,CAAC;YAClE,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;QAC/B,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,KAAK,CAAC,WAAW,KAAK,GAAG,IAAI,CAAC,CAAC;YAC/E,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YAC3C,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEL,OAAO;YACL,KAAK,EAAE,OAAO,IAAI,CAAC,GAAG,EAAE,EAAE;YAC1B,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,EAAE;YACZ,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACpC,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI;SAC/B,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,KAA0B;QAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAErD,mCAAmC;QACnC,IAAI,OAAO,IAAI,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3C,OAAO;gBACL,YAAY,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;gBACtD,QAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,aAAa,EAAE;gBAC7C,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACrC,CAAC;QACJ,CAAC;QAED,uDAAuD;QACvD,IAAI,KAAK,CAAC,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACvC,OAAO;gBACL,YAAY,EAAE,MAAM,EAAG,8CAA8C;gBACrE,QAAQ,EAAE,EAAE;gBACZ,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACrC,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;IACzF,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,KAAsB;QACrC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YACrB,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QAChF,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAErD,uDAAuD;QACvD,IAAI,OAAO,IAAI,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3C,kBAAkB;QACpB,CAAC;aAAM,IAAI,KAAK,CAAC,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9C,8CAA8C;YAC9C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QACrF,CAAC;aAAM,CAAC;YACN,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QAClF,CAAC;QAED,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC;QAChC,IAAI,QAAsB,CAAC;QAE3B,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAC3B,sBAAsB;YACtB,QAAQ,GAAG,GAAG,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC,CAAC,WAAW;gBACpD,CAAC,CAAC,GAAG,CAAC,UAAU,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW;oBAC9C,CAAC,CAAC,QAAQ,CAAC;QACf,CAAC;aAAM,IAAI,GAAG,CAAC,oBAAoB,EAAE,CAAC;YACpC,QAAQ,GAAG,oBAAoB,CAAC;QAClC,CAAC;aAAM,IAAI,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9D,uEAAuE;YACvE,iEAAiE;YACjE,2DAA2D;YAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;YACjE,IAAI,MAAM,GAAG,MAAM,EAAE,CAAC;gBACpB,GAAG,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;gBAC7B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;gBAC7B,QAAQ,GAAG,WAAW,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,QAAQ,GAAG,SAAS,CAAC;YACvB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,SAAS,CAAC;QACvB,CAAC;QAED,OAAO;YACL,QAAQ;YACR,QAAQ,EAAE,GAAG,CAAC,aAAa,EAAE;YAC7B,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACrC,CAAC;IACJ,CAAC;IAED,SAAS,CAAC,WAAmB,EAAE,QAAgE;QAC7F,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO;YAAE,OAAO,GAAG,EAAE,GAAc,CAAC,CAAC;QAC1C,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC1C,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,WAAmB;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa;YAAE,OAAO;QAC/C,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACP,8DAA8D;QAChE,CAAC;QACD,2EAA2E;QAC3E,oEAAoE;QACpE,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAuB;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;YAC9D,CAAC;YAAC,MAAM,CAAC,CAAC,+BAA+B,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,OAAsB;QACjD,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;QAC9B,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;QAC5E,gDAAgD;QAChD,IAAI,CAAC;YAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAAC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YAChD,GAAG,CAAC,yBAAyB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;YAClE,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACvC,CAAC;QACD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC9B,IAAI,CAAC;oBAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAAC,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBAChD,GAAG,CAAC,6BAA6B,GAAG,MAAM,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAClF,CAAC;gBACD,IAAI,GAAG,EAAE,CAAC;oBACR,IAAI,CAAC;wBAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;oBAAC,CAAC;oBAAC,OAAO,CAAC,EAAE,CAAC;wBAC/C,GAAG,CAAC,eAAe,GAAG,YAAY,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC1E,CAAC;oBACD,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;gBACvC,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC,EAAE,KAAK,CAAC,CAAC;YACV,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;gBAC9B,YAAY,CAAC,OAAO,CAAC,CAAC;gBACtB,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,iEAAiE;IACzD,eAAe,CAAC,SAAiB,EAAE,MAAsB;QAC/D,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACnG,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1C,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACpC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;oBACjB,IAAI,CAAC;wBAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;oBAAC,CAAC;oBAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;oBACpE,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBACzC,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,+CAA+C,CAAC,CAAC;IAC7D,CAAC;CACF"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
interface SessionUpdate {
|
|
2
|
+
sessionUpdate: string;
|
|
3
|
+
[key: string]: unknown;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Structured event emitted from accumulator as ACP session updates arrive.
|
|
7
|
+
* Consumed by daemon subscribeRun to stream to remote clients (Console chat).
|
|
8
|
+
*/
|
|
9
|
+
export type AccumulatorEvent = {
|
|
10
|
+
type: 'text';
|
|
11
|
+
text: string;
|
|
12
|
+
} | {
|
|
13
|
+
type: 'tool_use';
|
|
14
|
+
id: string;
|
|
15
|
+
title: string;
|
|
16
|
+
kind: string;
|
|
17
|
+
status: string;
|
|
18
|
+
} | {
|
|
19
|
+
type: 'tool_update';
|
|
20
|
+
id: string;
|
|
21
|
+
status: string;
|
|
22
|
+
} | {
|
|
23
|
+
type: 'usage';
|
|
24
|
+
used: number;
|
|
25
|
+
size: number;
|
|
26
|
+
} | {
|
|
27
|
+
type: 'complete';
|
|
28
|
+
stopReason: string;
|
|
29
|
+
};
|
|
30
|
+
export type AccumulatorListener = (event: AccumulatorEvent) => void;
|
|
31
|
+
export declare class SessionUpdateAccumulator {
|
|
32
|
+
private textChunks;
|
|
33
|
+
private toolCalls;
|
|
34
|
+
private logFile;
|
|
35
|
+
private listeners;
|
|
36
|
+
stopReason: string | null;
|
|
37
|
+
hasPendingPermission: boolean;
|
|
38
|
+
lastUpdateAt: string | null;
|
|
39
|
+
/** Set a log file path — events will be appended as human-readable lines. */
|
|
40
|
+
setLogFile(path: string): void;
|
|
41
|
+
reset(): void;
|
|
42
|
+
addListener(fn: AccumulatorListener): void;
|
|
43
|
+
/** Mark the run as complete and emit a complete event. Called by adapter after run settles. */
|
|
44
|
+
markComplete(stopReason: string): void;
|
|
45
|
+
removeListener(fn: AccumulatorListener): void;
|
|
46
|
+
private emit;
|
|
47
|
+
handleUpdate(update: SessionUpdate): void;
|
|
48
|
+
/** Recent text output, capped to maxChars (replaces capturePaneText). */
|
|
49
|
+
getRecentText(maxChars?: number): string;
|
|
50
|
+
/** Count of non-terminal (pending/in_progress) tool calls. */
|
|
51
|
+
get activeToolCalls(): number;
|
|
52
|
+
private appendLog;
|
|
53
|
+
}
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=session-accumulator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-accumulator.d.ts","sourceRoot":"","sources":["../../src/internal/session-accumulator.ts"],"names":[],"mappings":"AAkBA,UAAU,aAAa;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC7E;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAEpE,qBAAa,wBAAwB;IACnC,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,SAAS,CAAsE;IACvF,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,SAAS,CAAkC;IAEnD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IACjC,oBAAoB,UAAS;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEnC,6EAA6E;IAC7E,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK9B,KAAK,IAAI,IAAI;IAQb,WAAW,CAAC,EAAE,EAAE,mBAAmB,GAAG,IAAI;IAI1C,+FAA+F;IAC/F,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAKtC,cAAc,CAAC,EAAE,EAAE,mBAAmB,GAAG,IAAI;IAI7C,OAAO,CAAC,IAAI;IAUZ,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAkDzC,yEAAyE;IACzE,aAAa,CAAC,QAAQ,SAAO,GAAG,MAAM;IAKtC,8DAA8D;IAC9D,IAAI,eAAe,IAAI,MAAM,CAM5B;IAED,OAAO,CAAC,SAAS;CAIlB"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module acp-session-accumulator
|
|
3
|
+
* @description ACP 会话更新累加器,收集 Agent 进程的会话通知并提供结构化状态
|
|
4
|
+
*
|
|
5
|
+
* @author eddy
|
|
6
|
+
* @organization wykj
|
|
7
|
+
* @ownership wykj/eddy
|
|
8
|
+
*
|
|
9
|
+
* @created 2026-03-31
|
|
10
|
+
* @updated 2026-03-31
|
|
11
|
+
*
|
|
12
|
+
* @role adapter
|
|
13
|
+
* @layer provider
|
|
14
|
+
* @boundedContext acp
|
|
15
|
+
*/
|
|
16
|
+
import { appendFileSync, mkdirSync } from 'node:fs';
|
|
17
|
+
import { dirname } from 'node:path';
|
|
18
|
+
export class SessionUpdateAccumulator {
|
|
19
|
+
textChunks = [];
|
|
20
|
+
toolCalls = new Map();
|
|
21
|
+
logFile = null;
|
|
22
|
+
listeners = new Set();
|
|
23
|
+
stopReason = null;
|
|
24
|
+
hasPendingPermission = false;
|
|
25
|
+
lastUpdateAt = null;
|
|
26
|
+
/** Set a log file path — events will be appended as human-readable lines. */
|
|
27
|
+
setLogFile(path) {
|
|
28
|
+
this.logFile = path;
|
|
29
|
+
try {
|
|
30
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
catch { /* exists */ }
|
|
33
|
+
}
|
|
34
|
+
reset() {
|
|
35
|
+
this.textChunks = [];
|
|
36
|
+
this.toolCalls.clear();
|
|
37
|
+
this.stopReason = null;
|
|
38
|
+
this.hasPendingPermission = false;
|
|
39
|
+
this.lastUpdateAt = null;
|
|
40
|
+
}
|
|
41
|
+
addListener(fn) {
|
|
42
|
+
this.listeners.add(fn);
|
|
43
|
+
}
|
|
44
|
+
/** Mark the run as complete and emit a complete event. Called by adapter after run settles. */
|
|
45
|
+
markComplete(stopReason) {
|
|
46
|
+
this.stopReason = stopReason;
|
|
47
|
+
this.emit({ type: 'complete', stopReason });
|
|
48
|
+
}
|
|
49
|
+
removeListener(fn) {
|
|
50
|
+
this.listeners.delete(fn);
|
|
51
|
+
}
|
|
52
|
+
emit(event) {
|
|
53
|
+
for (const fn of this.listeners) {
|
|
54
|
+
try {
|
|
55
|
+
fn(event);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
/* listener error should not break accumulator */
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
handleUpdate(update) {
|
|
63
|
+
this.lastUpdateAt = new Date().toISOString();
|
|
64
|
+
const ts = this.lastUpdateAt.slice(11, 23); // HH:mm:ss.SSS
|
|
65
|
+
switch (update.sessionUpdate) {
|
|
66
|
+
case 'agent_message_chunk': {
|
|
67
|
+
const content = update.content;
|
|
68
|
+
if (content?.type === 'text' && content.text) {
|
|
69
|
+
this.textChunks.push(content.text);
|
|
70
|
+
this.appendLog(`${ts} [assistant] ${content.text}`);
|
|
71
|
+
this.emit({ type: 'text', text: content.text });
|
|
72
|
+
}
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
case 'tool_call': {
|
|
76
|
+
const id = update.toolCallId;
|
|
77
|
+
const title = update.title ?? '';
|
|
78
|
+
const kind = update.kind ?? 'other';
|
|
79
|
+
const status = update.status ?? 'pending';
|
|
80
|
+
this.toolCalls.set(id, { title, kind, status });
|
|
81
|
+
this.appendLog(`${ts} [tool:${kind}] ${title} (${status})`);
|
|
82
|
+
this.emit({ type: 'tool_use', id, title, kind, status });
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case 'tool_call_update': {
|
|
86
|
+
const id = update.toolCallId;
|
|
87
|
+
const existing = this.toolCalls.get(id);
|
|
88
|
+
const status = update.status ?? existing?.status ?? 'unknown';
|
|
89
|
+
if (existing) {
|
|
90
|
+
existing.status = status;
|
|
91
|
+
}
|
|
92
|
+
this.appendLog(`${ts} [tool_update] ${id} → ${status}`);
|
|
93
|
+
this.emit({ type: 'tool_update', id, status });
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
case 'usage_update': {
|
|
97
|
+
const used = update.used;
|
|
98
|
+
const size = update.size;
|
|
99
|
+
if (used != null && size != null) {
|
|
100
|
+
this.appendLog(`${ts} [usage] ${used}/${size} tokens`);
|
|
101
|
+
this.emit({ type: 'usage', used, size });
|
|
102
|
+
}
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
default:
|
|
106
|
+
// plan, agent_thought_chunk, available_commands_update, etc.
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** Recent text output, capped to maxChars (replaces capturePaneText). */
|
|
111
|
+
getRecentText(maxChars = 4000) {
|
|
112
|
+
const full = this.textChunks.join('');
|
|
113
|
+
return full.length > maxChars ? full.slice(-maxChars) : full;
|
|
114
|
+
}
|
|
115
|
+
/** Count of non-terminal (pending/in_progress) tool calls. */
|
|
116
|
+
get activeToolCalls() {
|
|
117
|
+
let count = 0;
|
|
118
|
+
for (const tc of this.toolCalls.values()) {
|
|
119
|
+
if (tc.status !== 'completed' && tc.status !== 'failed')
|
|
120
|
+
count++;
|
|
121
|
+
}
|
|
122
|
+
return count;
|
|
123
|
+
}
|
|
124
|
+
appendLog(line) {
|
|
125
|
+
if (!this.logFile)
|
|
126
|
+
return;
|
|
127
|
+
try {
|
|
128
|
+
appendFileSync(this.logFile, line + '\n');
|
|
129
|
+
}
|
|
130
|
+
catch { /* best effort */ }
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=session-accumulator.js.map
|