@adecore/agents 0.39.0 → 0.40.1
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/async.d.ts +5 -0
- package/dist/async.js +13 -5
- package/dist/chat/acp-protocol.js +3 -5
- package/dist/chat/chat-core.js +0 -2
- package/dist/chat/chat-process.d.ts +1 -0
- package/dist/chat/chat-process.js +1 -1
- package/dist/chat/chat-session.js +6 -8
- package/dist/chat/claude-protocol.js +1 -6
- package/dist/chat/claude-transcript.js +1 -3
- package/dist/chat/codex-protocol.js +1 -6
- package/dist/chat/projector.js +1 -3
- package/dist/chat/request-summary.js +1 -3
- package/dist/coded-error.js +1 -5
- package/dist/context/argv.js +1 -2
- package/dist/context/verb.js +1 -3
- package/dist/error-text.d.ts +1 -0
- package/dist/error-text.js +4 -0
- package/dist/fields.d.ts +3 -0
- package/dist/fields.js +12 -0
- package/dist/fs.d.ts +1 -0
- package/dist/fs.js +8 -4
- package/dist/lineage.js +11 -5
- package/dist/messages/notice-store.js +3 -4
- package/dist/providers/accounts/acp-account.js +3 -20
- package/dist/providers/accounts/service.d.ts +1 -2
- package/dist/providers/accounts/service.js +5 -9
- package/dist/providers/accounts/status.js +1 -3
- package/dist/providers/acp-agent-state.js +1 -3
- package/dist/providers/claude.js +0 -1
- package/dist/providers/codex-models.json +3 -2
- package/dist/providers/codex.js +0 -1
- package/dist/providers/detect.js +1 -1
- package/dist/providers/shell-commands.js +1 -2
- package/dist/run-process.js +1 -3
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +5 -8
- package/dist/tasks/background-limit.js +3 -2
- package/dist/tasks/task-coordinator.js +11 -17
- package/dist/testing/watch.js +0 -1
- package/dist/usage/limits/monitor.js +1 -2
- package/dist/usage/prices-snapshot.json +8 -0
- package/dist/usage/readers/claude.js +3 -10
- package/dist/usage/readers/codex.js +2 -9
- package/dist/usage/readers/grok.js +3 -10
- package/dist/usage/readers/host-log.js +3 -10
- package/dist/usage/record.d.ts +2 -0
- package/dist/usage/record.js +13 -0
- package/package.json +6 -6
- package/src/async.ts +23 -5
- package/src/chat/acp-backend.ts +121 -0
- package/src/chat/acp-protocol.ts +172 -6
- package/src/chat/attachment-store.ts +21 -0
- package/src/chat/backend.ts +0 -2
- package/src/chat/bookmark-store.ts +23 -0
- package/src/chat/chat-core.ts +208 -7
- package/src/chat/chat-log.ts +19 -0
- package/src/chat/chat-process.ts +52 -1
- package/src/chat/chat-session.ts +401 -10
- package/src/chat/chat-store.ts +50 -0
- package/src/chat/chat-title.ts +9 -0
- package/src/chat/claude-backend.ts +50 -0
- package/src/chat/claude-protocol.ts +155 -8
- package/src/chat/claude-title.ts +10 -0
- package/src/chat/claude-transcript.ts +47 -4
- package/src/chat/codex-backend.ts +131 -0
- package/src/chat/codex-protocol.ts +180 -8
- package/src/chat/codex-thread.ts +23 -0
- package/src/chat/composer-preferences.ts +6 -0
- package/src/chat/context-breakdown.ts +11 -0
- package/src/chat/delta-coalescer.ts +8 -0
- package/src/chat/external-sessions.ts +28 -0
- package/src/chat/generated-image.ts +25 -0
- package/src/chat/index.ts +5 -0
- package/src/chat/input.ts +13 -0
- package/src/chat/json-rpc-transport.ts +28 -0
- package/src/chat/limit-resume.ts +13 -0
- package/src/chat/projector.ts +160 -4
- package/src/chat/readable-text.ts +3 -0
- package/src/chat/request-summary.ts +18 -4
- package/src/chat/subagent-projection.ts +3 -0
- package/src/chat/subagent-reader.ts +76 -0
- package/src/chat/subagent-settlement.ts +24 -0
- package/src/chat/thread-search.ts +13 -0
- package/src/chat/thread.ts +31 -0
- package/src/chat/ui-queries.ts +122 -0
- package/src/chat/ui-replies.ts +34 -0
- package/src/chat/visual-store.ts +49 -0
- package/src/chat/wake-chat.ts +3 -0
- package/src/client-sinks.ts +2 -0
- package/src/coded-error.ts +1 -5
- package/src/context/argv.ts +18 -2
- package/src/context/index.ts +1 -0
- package/src/context/refusal.ts +3 -0
- package/src/context/verb.ts +32 -4
- package/src/coordination/index.ts +10 -0
- package/src/error-text.ts +7 -0
- package/src/fields.ts +14 -0
- package/src/fs.ts +20 -4
- package/src/host/agent-host.ts +20 -0
- package/src/host/environment.ts +6 -0
- package/src/host/handlers.ts +18 -0
- package/src/host/memory-port.ts +4 -0
- package/src/host/wiring.ts +10 -0
- package/src/index.ts +1 -0
- package/src/lineage.ts +24 -5
- package/src/messages/deliver-message.ts +6 -0
- package/src/messages/deliver-notice.ts +13 -0
- package/src/messages/notice-store.ts +16 -4
- package/src/modes.ts +1 -0
- package/src/outbox/outbox-worker.ts +31 -0
- package/src/outbox/outbox.ts +5 -0
- package/src/providers/accounts/accounts.ts +36 -0
- package/src/providers/accounts/acp-account.ts +22 -27
- package/src/providers/accounts/launch.ts +4 -0
- package/src/providers/accounts/service.ts +110 -12
- package/src/providers/accounts/shadow-home.ts +10 -0
- package/src/providers/accounts/status.ts +13 -4
- package/src/providers/accounts/store.ts +25 -0
- package/src/providers/accounts/variables.ts +11 -1
- package/src/providers/acp-agent-state.ts +24 -3
- package/src/providers/acp-provider.ts +5 -0
- package/src/providers/acp-usage-log.ts +2 -0
- package/src/providers/catalog.ts +17 -0
- package/src/providers/claude.ts +10 -1
- package/src/providers/codex-models.json +3 -2
- package/src/providers/codex-rules.ts +3 -0
- package/src/providers/codex.ts +2 -1
- package/src/providers/detect.ts +6 -1
- package/src/providers/provider.ts +1 -1
- package/src/providers/registry.ts +18 -2
- package/src/providers/shell-commands.ts +37 -2
- package/src/record-directory.ts +19 -0
- package/src/run-process.ts +24 -3
- package/src/serializer.ts +3 -0
- package/src/skills.ts +73 -10
- package/src/tasks/background-limit.ts +9 -2
- package/src/tasks/end-children.ts +9 -0
- package/src/tasks/give-task.ts +8 -0
- package/src/tasks/task-coordinator.ts +81 -17
- package/src/tasks/task-store.ts +28 -0
- package/src/tasks/waiting-child.ts +21 -0
- package/src/tasks/wake-parent.ts +26 -0
- package/src/tasks/wiring.ts +22 -0
- package/src/testing/accounts.ts +2 -0
- package/src/testing/fake-acp-capture.ts +16 -0
- package/src/testing/fake-acp.ts +66 -0
- package/src/testing/fake-claude.ts +177 -0
- package/src/testing/fake-cli.ts +29 -0
- package/src/testing/fake-codex.ts +122 -0
- package/src/testing/manual-clock.ts +2 -0
- package/src/testing/watch.ts +7 -1
- package/src/title-file.ts +12 -0
- package/src/usage/accounts.ts +6 -0
- package/src/usage/aggregate.ts +19 -0
- package/src/usage/exchange.ts +12 -0
- package/src/usage/index-file.ts +27 -0
- package/src/usage/limits/monitor.ts +31 -3
- package/src/usage/limits/normalize.ts +30 -0
- package/src/usage/limits/probe.ts +17 -0
- package/src/usage/prices-snapshot.json +8 -0
- package/src/usage/pricing.ts +35 -0
- package/src/usage/projects.ts +8 -0
- package/src/usage/readers/claude.ts +12 -9
- package/src/usage/readers/codex.ts +40 -8
- package/src/usage/readers/grok.ts +17 -9
- package/src/usage/readers/host-log.ts +9 -9
- package/src/usage/record.ts +22 -0
- package/src/usage/roots.ts +6 -0
- package/src/usage/scanner.ts +61 -0
- package/src/usage/usage-service.ts +14 -0
- package/src/watch-seam.ts +8 -0
- package/src/windows-command.ts +12 -0
|
@@ -23,29 +23,35 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
23
23
|
const assistantText = (text: string): void => {
|
|
24
24
|
const id = `msg_${nonce}_${++messageCounter}`;
|
|
25
25
|
out({ type: 'stream_event', event: { type: 'message_start', message: { id, model } }, session_id: sessionId });
|
|
26
|
+
|
|
26
27
|
out({
|
|
27
28
|
type: 'stream_event',
|
|
28
29
|
event: { type: 'content_block_start', index: 0, content_block: { type: 'thinking', thinking: '' } },
|
|
29
30
|
session_id: sessionId
|
|
30
31
|
});
|
|
32
|
+
|
|
31
33
|
out({
|
|
32
34
|
type: 'stream_event',
|
|
33
35
|
event: { type: 'content_block_delta', index: 0, delta: { type: 'thinking_delta', thinking: 'weighing it' } },
|
|
34
36
|
session_id: sessionId
|
|
35
37
|
});
|
|
38
|
+
|
|
36
39
|
out({ type: 'stream_event', event: { type: 'content_block_stop', index: 0 }, session_id: sessionId });
|
|
37
40
|
out({ type: 'stream_event', event: { type: 'content_block_start', index: 1, content_block: { type: 'text', text: '' } }, session_id: sessionId });
|
|
38
41
|
const half = Math.ceil(text.length / 2);
|
|
42
|
+
|
|
39
43
|
out({
|
|
40
44
|
type: 'stream_event',
|
|
41
45
|
event: { type: 'content_block_delta', index: 1, delta: { type: 'text_delta', text: text.slice(0, half) } },
|
|
42
46
|
session_id: sessionId
|
|
43
47
|
});
|
|
48
|
+
|
|
44
49
|
out({
|
|
45
50
|
type: 'stream_event',
|
|
46
51
|
event: { type: 'content_block_delta', index: 1, delta: { type: 'text_delta', text: text.slice(half) } },
|
|
47
52
|
session_id: sessionId
|
|
48
53
|
});
|
|
54
|
+
|
|
49
55
|
// Every frame carries the uuid of its line in the transcript, which is what a fork is cut at.
|
|
50
56
|
out({
|
|
51
57
|
type: 'assistant',
|
|
@@ -53,12 +59,14 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
53
59
|
message: { id, model, role: 'assistant', content: [{ type: 'thinking', thinking: '' }], usage },
|
|
54
60
|
session_id: sessionId
|
|
55
61
|
});
|
|
62
|
+
|
|
56
63
|
out({
|
|
57
64
|
type: 'assistant',
|
|
58
65
|
uuid: `${id}-text`,
|
|
59
66
|
message: { id, model, role: 'assistant', content: [{ type: 'text', text }], usage },
|
|
60
67
|
session_id: sessionId
|
|
61
68
|
});
|
|
69
|
+
|
|
62
70
|
out({ type: 'stream_event', event: { type: 'message_stop' }, session_id: sessionId });
|
|
63
71
|
};
|
|
64
72
|
|
|
@@ -79,6 +87,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
79
87
|
// A request the API turned away: a synthetic message with the reason, then a result that failed without saying which error.
|
|
80
88
|
const refusal = (text: string, error: string, status: number): void => {
|
|
81
89
|
const id = `msg_${nonce}_${++messageCounter}`;
|
|
90
|
+
|
|
82
91
|
out({
|
|
83
92
|
type: 'assistant',
|
|
84
93
|
uuid: `${id}-text`,
|
|
@@ -87,6 +96,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
87
96
|
error,
|
|
88
97
|
session_id: sessionId
|
|
89
98
|
});
|
|
99
|
+
|
|
90
100
|
out({
|
|
91
101
|
type: 'result',
|
|
92
102
|
subtype: 'success',
|
|
@@ -111,6 +121,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
111
121
|
session_id: sessionId
|
|
112
122
|
});
|
|
113
123
|
};
|
|
124
|
+
|
|
114
125
|
const childResult = (toolUseId: string, content: string): void => {
|
|
115
126
|
out({
|
|
116
127
|
type: 'user',
|
|
@@ -119,10 +130,12 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
119
130
|
session_id: sessionId
|
|
120
131
|
});
|
|
121
132
|
};
|
|
133
|
+
|
|
122
134
|
child([{ type: 'tool_use', id: `${agentToolUseId}_read`, name: 'Read', input: { file_path: 'README.md' } }]);
|
|
123
135
|
childResult(`${agentToolUseId}_read`, '# Notes');
|
|
124
136
|
child([{ type: 'tool_use', id: `${agentToolUseId}_bash`, name: 'Bash', input: { command: 'ls', description: 'List files' } }]);
|
|
125
137
|
childResult(`${agentToolUseId}_bash`, 'README.md');
|
|
138
|
+
|
|
126
139
|
out({
|
|
127
140
|
type: 'system',
|
|
128
141
|
subtype: 'task_progress',
|
|
@@ -134,6 +147,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
134
147
|
last_tool_name: 'Bash',
|
|
135
148
|
session_id: sessionId
|
|
136
149
|
});
|
|
150
|
+
|
|
137
151
|
child([{ type: 'text', text: report }]);
|
|
138
152
|
};
|
|
139
153
|
|
|
@@ -151,11 +165,14 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
151
165
|
|
|
152
166
|
const settleTwo = (name: 'a-one' | 'a-two', stopped: boolean): void => {
|
|
153
167
|
const toolUseId = name === 'a-one' ? 'toolu_two_a' : 'toolu_two_b';
|
|
168
|
+
|
|
154
169
|
if (!openTwo.delete(name)) {
|
|
155
170
|
return;
|
|
156
171
|
}
|
|
172
|
+
|
|
157
173
|
if (stopped) {
|
|
158
174
|
out({ type: 'system', subtype: 'task_updated', task_id: name, patch: { status: 'killed', end_time: 0 }, session_id: sessionId });
|
|
175
|
+
|
|
159
176
|
out({
|
|
160
177
|
type: 'system',
|
|
161
178
|
subtype: 'task_notification',
|
|
@@ -167,6 +184,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
167
184
|
session_id: sessionId
|
|
168
185
|
});
|
|
169
186
|
}
|
|
187
|
+
|
|
170
188
|
out({
|
|
171
189
|
type: 'user',
|
|
172
190
|
message: {
|
|
@@ -175,6 +193,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
175
193
|
},
|
|
176
194
|
session_id: sessionId
|
|
177
195
|
});
|
|
196
|
+
|
|
178
197
|
if (openTwo.size === 0) {
|
|
179
198
|
assistantText('summarized B');
|
|
180
199
|
result();
|
|
@@ -184,6 +203,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
184
203
|
// The rest of a background agent once its request was answered: its call's result, its report, and the turn the CLI opens about it.
|
|
185
204
|
const finishBackgroundAgent = (command: string, allowed: boolean, message: string | undefined): void => {
|
|
186
205
|
const toolUseId = 'toolu_bgask';
|
|
206
|
+
|
|
187
207
|
out({
|
|
188
208
|
type: 'user',
|
|
189
209
|
message: {
|
|
@@ -200,13 +220,16 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
200
220
|
parent_tool_use_id: toolUseId,
|
|
201
221
|
session_id: sessionId
|
|
202
222
|
});
|
|
223
|
+
|
|
203
224
|
const report = allowed ? `the agent ran ${command}` : 'the agent could not run it';
|
|
225
|
+
|
|
204
226
|
out({
|
|
205
227
|
type: 'assistant',
|
|
206
228
|
message: { id: `msg_${nonce}_${++messageCounter}`, model, role: 'assistant', content: [{ type: 'text', text: report }], usage },
|
|
207
229
|
parent_tool_use_id: toolUseId,
|
|
208
230
|
session_id: sessionId
|
|
209
231
|
});
|
|
232
|
+
|
|
210
233
|
out({
|
|
211
234
|
type: 'system',
|
|
212
235
|
subtype: 'task_notification',
|
|
@@ -217,6 +240,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
217
240
|
summary: report,
|
|
218
241
|
session_id: sessionId
|
|
219
242
|
});
|
|
243
|
+
|
|
220
244
|
out({ type: 'system', subtype: 'init', session_id: sessionId, model, cwd: io.cwd, tools: ['Bash'], slash_commands: [], argv: args });
|
|
221
245
|
assistantText(report);
|
|
222
246
|
result();
|
|
@@ -225,11 +249,14 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
225
249
|
const handleUser = (text: string): void => {
|
|
226
250
|
if (text === 'crash') {
|
|
227
251
|
io.exit(1);
|
|
252
|
+
|
|
228
253
|
return;
|
|
229
254
|
}
|
|
255
|
+
|
|
230
256
|
// Two foreground subagents beside each other; the turn ends once both settled: a-two when the test runs what is put off, a-one by a `stop_task`.
|
|
231
257
|
if (text === 'two subagents') {
|
|
232
258
|
openTwo.add('a-one').add('a-two');
|
|
259
|
+
|
|
233
260
|
for (const [name, toolUseId] of [
|
|
234
261
|
['a-one', 'toolu_two_a'],
|
|
235
262
|
['a-two', 'toolu_two_b']
|
|
@@ -247,6 +274,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
247
274
|
},
|
|
248
275
|
session_id: sessionId
|
|
249
276
|
});
|
|
277
|
+
|
|
250
278
|
out({
|
|
251
279
|
type: 'system',
|
|
252
280
|
subtype: 'task_started',
|
|
@@ -261,21 +289,28 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
261
289
|
session_id: sessionId
|
|
262
290
|
});
|
|
263
291
|
}
|
|
292
|
+
|
|
264
293
|
io.later(() => settleTwo('a-two', false));
|
|
294
|
+
|
|
265
295
|
return;
|
|
266
296
|
}
|
|
297
|
+
|
|
267
298
|
if (text === 'crash loudly') {
|
|
268
299
|
io.err(`${'warming up\n'.repeat(2000)}Error: the fake lost its key\n at handleUser (fake-claude.ts)\n`);
|
|
269
300
|
io.exit(1);
|
|
301
|
+
|
|
270
302
|
return;
|
|
271
303
|
}
|
|
304
|
+
|
|
272
305
|
// Over stdio only: a process of the CLI's own, as a dev server an agent started would be.
|
|
273
306
|
if (text === 'start a grandchild') {
|
|
274
307
|
const grandchild = spawn('sleep', ['600'], { stdio: 'ignore' });
|
|
275
308
|
assistantText(`grandchild ${grandchild.pid}`);
|
|
276
309
|
result();
|
|
310
|
+
|
|
277
311
|
return;
|
|
278
312
|
}
|
|
313
|
+
|
|
279
314
|
/*
|
|
280
315
|
* A background agent that asks to run a command while the turn that launched it ends, framed the way Claude
|
|
281
316
|
* Code 2.1.282 sends it: the request names the agent's own call and its `agent_id`, the result of the turn
|
|
@@ -287,6 +322,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
287
322
|
const [first = '', ...rest] = text.split('\n');
|
|
288
323
|
const command = first.slice(20).trim() || 'ls';
|
|
289
324
|
const toolUseId = 'toolu_bgask';
|
|
325
|
+
|
|
290
326
|
out({
|
|
291
327
|
type: 'assistant',
|
|
292
328
|
message: {
|
|
@@ -300,6 +336,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
300
336
|
},
|
|
301
337
|
session_id: sessionId
|
|
302
338
|
});
|
|
339
|
+
|
|
303
340
|
out({
|
|
304
341
|
type: 'system',
|
|
305
342
|
subtype: 'task_started',
|
|
@@ -311,6 +348,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
311
348
|
task_type: 'local_agent',
|
|
312
349
|
session_id: sessionId
|
|
313
350
|
});
|
|
351
|
+
|
|
314
352
|
out({
|
|
315
353
|
type: 'user',
|
|
316
354
|
message: {
|
|
@@ -319,6 +357,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
319
357
|
},
|
|
320
358
|
session_id: sessionId
|
|
321
359
|
});
|
|
360
|
+
|
|
322
361
|
const ask = (): void => {
|
|
323
362
|
out({
|
|
324
363
|
type: 'assistant',
|
|
@@ -332,7 +371,9 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
332
371
|
parent_tool_use_id: toolUseId,
|
|
333
372
|
session_id: sessionId
|
|
334
373
|
});
|
|
374
|
+
|
|
335
375
|
backgroundAsk = { requestId: 'req-bg', command };
|
|
376
|
+
|
|
336
377
|
out({
|
|
337
378
|
type: 'control_request',
|
|
338
379
|
request_id: 'req-bg',
|
|
@@ -347,45 +388,62 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
347
388
|
}
|
|
348
389
|
});
|
|
349
390
|
};
|
|
391
|
+
|
|
350
392
|
if (rest.includes('late')) {
|
|
351
393
|
assistantText('the agent runs');
|
|
352
394
|
result();
|
|
353
395
|
io.later(ask);
|
|
396
|
+
|
|
354
397
|
return;
|
|
355
398
|
}
|
|
399
|
+
|
|
356
400
|
ask();
|
|
401
|
+
|
|
357
402
|
if (rest.includes('slow')) {
|
|
358
403
|
slow = true;
|
|
404
|
+
|
|
359
405
|
return;
|
|
360
406
|
}
|
|
407
|
+
|
|
361
408
|
assistantText('the agent runs');
|
|
362
409
|
result();
|
|
410
|
+
|
|
363
411
|
return;
|
|
364
412
|
}
|
|
413
|
+
|
|
365
414
|
// A line of its own, so a prompt with a task brief under it or a message above it still waits.
|
|
366
415
|
if (text.split('\n').some((line) => line === 'slow')) {
|
|
367
416
|
slow = true;
|
|
368
417
|
out({ type: 'stream_event', event: { type: 'message_start', message: { id: `msg_${nonce}_${++messageCounter}`, model } }, session_id: sessionId });
|
|
418
|
+
|
|
369
419
|
return;
|
|
370
420
|
}
|
|
421
|
+
|
|
371
422
|
// Lines of their own, as the two ways Claude Code 2.1.281 ends a turn it could not get an answer for.
|
|
372
423
|
const limit = text.split('\n').find((line) => line.startsWith('limit:'));
|
|
424
|
+
|
|
373
425
|
if (limit !== undefined) {
|
|
374
426
|
const resetsAt = Number(limit.slice(6));
|
|
427
|
+
|
|
375
428
|
out({
|
|
376
429
|
type: 'rate_limit_event',
|
|
377
430
|
rate_limit_info: { status: 'rejected', resetsAt, rateLimitType: 'five_hour', utilization: 1 },
|
|
378
431
|
uuid: `rate-${nonce}`,
|
|
379
432
|
session_id: sessionId
|
|
380
433
|
});
|
|
434
|
+
|
|
381
435
|
refusal("You've hit your session limit · resets 3pm", 'rate_limit', 429);
|
|
436
|
+
|
|
382
437
|
return;
|
|
383
438
|
}
|
|
439
|
+
|
|
384
440
|
// A line of its own as well: a tool call whose result is that many bytes, the way a long log or a big file reads back.
|
|
385
441
|
const output = text.split('\n').find((line) => line.startsWith('output:'));
|
|
442
|
+
|
|
386
443
|
if (output !== undefined) {
|
|
387
444
|
const bytes = Number(output.slice(7));
|
|
388
445
|
const toolUseId = `toolu_${nonce}_${++messageCounter}`;
|
|
446
|
+
|
|
389
447
|
out({
|
|
390
448
|
type: 'assistant',
|
|
391
449
|
message: {
|
|
@@ -397,7 +455,9 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
397
455
|
},
|
|
398
456
|
session_id: sessionId
|
|
399
457
|
});
|
|
458
|
+
|
|
400
459
|
const line = 'build step finished without warnings\n';
|
|
460
|
+
|
|
401
461
|
out({
|
|
402
462
|
type: 'user',
|
|
403
463
|
message: {
|
|
@@ -408,23 +468,31 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
408
468
|
},
|
|
409
469
|
session_id: sessionId
|
|
410
470
|
});
|
|
471
|
+
|
|
411
472
|
assistantText(`read ${bytes} bytes of build log`);
|
|
412
473
|
result();
|
|
474
|
+
|
|
413
475
|
return;
|
|
414
476
|
}
|
|
477
|
+
|
|
415
478
|
if (text.split('\n').includes('overloaded')) {
|
|
416
479
|
refusal('API Error: Repeated 529 Overloaded errors', 'overloaded', 529);
|
|
480
|
+
|
|
417
481
|
return;
|
|
418
482
|
}
|
|
483
|
+
|
|
419
484
|
if (text === 'compact') {
|
|
420
485
|
out({ type: 'system', subtype: 'compact_boundary', compact_metadata: { trigger: 'manual', pre_tokens: 5000 }, session_id: sessionId });
|
|
421
486
|
assistantText('compacted');
|
|
422
487
|
result();
|
|
488
|
+
|
|
423
489
|
return;
|
|
424
490
|
}
|
|
491
|
+
|
|
425
492
|
if (text.startsWith('ask:')) {
|
|
426
493
|
const question = text.slice(4).trim();
|
|
427
494
|
pendingQuestion = question;
|
|
495
|
+
|
|
428
496
|
out({
|
|
429
497
|
type: 'control_request',
|
|
430
498
|
request_id: 'req-q',
|
|
@@ -447,14 +515,17 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
447
515
|
tool_use_id: 'toolu_q'
|
|
448
516
|
}
|
|
449
517
|
});
|
|
518
|
+
|
|
450
519
|
return;
|
|
451
520
|
}
|
|
521
|
+
|
|
452
522
|
if (text.startsWith('write:')) {
|
|
453
523
|
const [path = '', ...rest] = text.slice(6).trim().split(' ');
|
|
454
524
|
const content = `${rest.join(' ')}\n`;
|
|
455
525
|
// Against the CLI's own folder: in a test the fake shares the test runner's working directory.
|
|
456
526
|
writeFileSync(resolve(io.cwd, path), content);
|
|
457
527
|
const id = `msg_${nonce}_${++messageCounter}`;
|
|
528
|
+
|
|
458
529
|
out({
|
|
459
530
|
type: 'assistant',
|
|
460
531
|
message: {
|
|
@@ -466,20 +537,26 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
466
537
|
},
|
|
467
538
|
session_id: sessionId
|
|
468
539
|
});
|
|
540
|
+
|
|
469
541
|
out({
|
|
470
542
|
type: 'user',
|
|
471
543
|
message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'toolu_write', content: `wrote ${path}`, is_error: false }] },
|
|
472
544
|
session_id: sessionId
|
|
473
545
|
});
|
|
546
|
+
|
|
474
547
|
assistantText('written');
|
|
475
548
|
result();
|
|
549
|
+
|
|
476
550
|
return;
|
|
477
551
|
}
|
|
552
|
+
|
|
478
553
|
// `delegate late:` sends the subagent's first work before `task_started`, an order the CLI does not promise to avoid.
|
|
479
554
|
const late = text.startsWith('delegate late:');
|
|
555
|
+
|
|
480
556
|
if (late || text.startsWith('delegate:')) {
|
|
481
557
|
const description = text.slice(text.indexOf(':') + 1).trim();
|
|
482
558
|
const report = '# Report\n\n- one\n- two';
|
|
559
|
+
|
|
483
560
|
out({
|
|
484
561
|
type: 'assistant',
|
|
485
562
|
message: {
|
|
@@ -498,6 +575,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
498
575
|
},
|
|
499
576
|
session_id: sessionId
|
|
500
577
|
});
|
|
578
|
+
|
|
501
579
|
const taskStarted = (): void => {
|
|
502
580
|
out({
|
|
503
581
|
type: 'system',
|
|
@@ -513,13 +591,17 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
513
591
|
session_id: sessionId
|
|
514
592
|
});
|
|
515
593
|
};
|
|
594
|
+
|
|
516
595
|
if (!late) {
|
|
517
596
|
taskStarted();
|
|
518
597
|
}
|
|
598
|
+
|
|
519
599
|
subagentWork('toolu_delegate', report);
|
|
600
|
+
|
|
520
601
|
if (late) {
|
|
521
602
|
taskStarted();
|
|
522
603
|
}
|
|
604
|
+
|
|
523
605
|
out({
|
|
524
606
|
type: 'user',
|
|
525
607
|
message: {
|
|
@@ -528,10 +610,13 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
528
610
|
},
|
|
529
611
|
session_id: sessionId
|
|
530
612
|
});
|
|
613
|
+
|
|
531
614
|
assistantText('summarized');
|
|
532
615
|
result();
|
|
616
|
+
|
|
533
617
|
return;
|
|
534
618
|
}
|
|
619
|
+
|
|
535
620
|
/*
|
|
536
621
|
* A background agent that opens a foreground one of its own, in the order Claude Code 2.1.282 streams it:
|
|
537
622
|
* the grandchild's call and result come as frames of its parent, its own steps not at all, and its
|
|
@@ -539,12 +624,15 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
539
624
|
*/
|
|
540
625
|
if (text.startsWith('nested:')) {
|
|
541
626
|
const summary = text.slice(7).trim() || 'done';
|
|
627
|
+
|
|
542
628
|
const task = (frame: Record<string, unknown>): void => {
|
|
543
629
|
out({ type: 'system', session_id: sessionId, ...frame });
|
|
544
630
|
};
|
|
631
|
+
|
|
545
632
|
const underMiddle = (message: Record<string, unknown>, type: 'assistant' | 'user'): void => {
|
|
546
633
|
out({ type, message, parent_tool_use_id: 'toolu_middle', session_id: sessionId });
|
|
547
634
|
};
|
|
635
|
+
|
|
548
636
|
out({
|
|
549
637
|
type: 'assistant',
|
|
550
638
|
message: {
|
|
@@ -563,6 +651,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
563
651
|
},
|
|
564
652
|
session_id: sessionId
|
|
565
653
|
});
|
|
654
|
+
|
|
566
655
|
task({
|
|
567
656
|
subtype: 'task_started',
|
|
568
657
|
task_id: 'a-middle',
|
|
@@ -574,6 +663,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
574
663
|
task_type: 'local_agent',
|
|
575
664
|
prompt: summary
|
|
576
665
|
});
|
|
666
|
+
|
|
577
667
|
out({
|
|
578
668
|
type: 'user',
|
|
579
669
|
message: {
|
|
@@ -582,8 +672,10 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
582
672
|
},
|
|
583
673
|
session_id: sessionId
|
|
584
674
|
});
|
|
675
|
+
|
|
585
676
|
assistantText('sent');
|
|
586
677
|
result();
|
|
678
|
+
|
|
587
679
|
io.later(() => {
|
|
588
680
|
underMiddle(
|
|
589
681
|
{
|
|
@@ -595,6 +687,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
595
687
|
},
|
|
596
688
|
'assistant'
|
|
597
689
|
);
|
|
690
|
+
|
|
598
691
|
task({
|
|
599
692
|
subtype: 'task_started',
|
|
600
693
|
task_id: 'a-leaf',
|
|
@@ -606,17 +699,22 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
606
699
|
task_type: 'local_agent',
|
|
607
700
|
prompt: 'echo PONG'
|
|
608
701
|
});
|
|
702
|
+
|
|
609
703
|
task({ subtype: 'task_updated', task_id: 'a-leaf', patch: { status: 'completed', end_time: 0 } });
|
|
610
704
|
task({ subtype: 'task_notification', task_id: 'a-leaf', tool_use_id: 'toolu_leaf', status: 'completed', output_file: '', summary: 'PONG' });
|
|
705
|
+
|
|
611
706
|
underMiddle(
|
|
612
707
|
{ role: 'user', content: [{ type: 'tool_result', tool_use_id: 'toolu_leaf', content: `PONG${agentFooter('a-leaf')}`, is_error: false }] },
|
|
613
708
|
'user'
|
|
614
709
|
);
|
|
710
|
+
|
|
615
711
|
underMiddle(
|
|
616
712
|
{ id: `msg_${nonce}_${++messageCounter}`, model, role: 'assistant', content: [{ type: 'text', text: `the leaf said PONG` }], usage },
|
|
617
713
|
'assistant'
|
|
618
714
|
);
|
|
715
|
+
|
|
619
716
|
task({ subtype: 'task_updated', task_id: 'a-middle', patch: { status: 'completed', end_time: 0 } });
|
|
717
|
+
|
|
620
718
|
task({
|
|
621
719
|
subtype: 'task_notification',
|
|
622
720
|
task_id: 'a-middle',
|
|
@@ -626,15 +724,19 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
626
724
|
summary,
|
|
627
725
|
usage: { total_tokens: 1500, tool_uses: 1, duration_ms: 250 }
|
|
628
726
|
});
|
|
727
|
+
|
|
629
728
|
out({ type: 'system', subtype: 'init', session_id: sessionId, model, cwd: io.cwd, tools: ['Bash'], slash_commands: [], argv: args });
|
|
630
729
|
assistantText(`done: ${summary}`);
|
|
631
730
|
result();
|
|
632
731
|
});
|
|
732
|
+
|
|
633
733
|
return;
|
|
634
734
|
}
|
|
735
|
+
|
|
635
736
|
if (text.startsWith('background:')) {
|
|
636
737
|
const summary = text.slice(11).trim() || 'done';
|
|
637
738
|
const id = `msg_${nonce}_${++messageCounter}`;
|
|
739
|
+
|
|
638
740
|
out({
|
|
639
741
|
type: 'assistant',
|
|
640
742
|
message: {
|
|
@@ -648,6 +750,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
648
750
|
},
|
|
649
751
|
session_id: sessionId
|
|
650
752
|
});
|
|
753
|
+
|
|
651
754
|
out({
|
|
652
755
|
type: 'system',
|
|
653
756
|
subtype: 'task_started',
|
|
@@ -659,6 +762,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
659
762
|
task_type: 'local_agent',
|
|
660
763
|
session_id: sessionId
|
|
661
764
|
});
|
|
765
|
+
|
|
662
766
|
out({
|
|
663
767
|
type: 'user',
|
|
664
768
|
message: {
|
|
@@ -667,12 +771,15 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
667
771
|
},
|
|
668
772
|
session_id: sessionId
|
|
669
773
|
});
|
|
774
|
+
|
|
670
775
|
assistantText('I will report back');
|
|
671
776
|
result();
|
|
777
|
+
|
|
672
778
|
// What the real CLI does after the turn ended: the subagent works on, and only later come a
|
|
673
779
|
// notification, a fresh init, an assistant message of its own and a result, with no user frame.
|
|
674
780
|
io.later(() => {
|
|
675
781
|
subagentWork('toolu_agent', `the subagent says: ${summary}`);
|
|
782
|
+
|
|
676
783
|
io.later(() => {
|
|
677
784
|
out({
|
|
678
785
|
type: 'system',
|
|
@@ -685,13 +792,16 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
685
792
|
usage: { total_tokens: 1500, tool_uses: 2, duration_ms: 250 },
|
|
686
793
|
session_id: sessionId
|
|
687
794
|
});
|
|
795
|
+
|
|
688
796
|
out({ type: 'system', subtype: 'init', session_id: sessionId, model, cwd: io.cwd, tools: ['Bash'], slash_commands: [], argv: args });
|
|
689
797
|
assistantText(`the subagent says: ${summary}`);
|
|
690
798
|
result();
|
|
691
799
|
});
|
|
692
800
|
});
|
|
801
|
+
|
|
693
802
|
return;
|
|
694
803
|
}
|
|
804
|
+
|
|
695
805
|
/*
|
|
696
806
|
* A background subagent that sends a command to the background and answers at once, the way Claude
|
|
697
807
|
* Code 2.1.282 runs one: its notification opens a turn with that answer while the command runs on.
|
|
@@ -703,6 +813,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
703
813
|
const command = text.split('\n')[0]!.slice(19).trim() || 'sleep 30';
|
|
704
814
|
const agentUse = 'toolu_cmd_agent';
|
|
705
815
|
const bashUse = 'toolu_cmd_bash';
|
|
816
|
+
|
|
706
817
|
const subagent = (content: unknown[]): void => {
|
|
707
818
|
out({
|
|
708
819
|
type: 'assistant',
|
|
@@ -711,6 +822,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
711
822
|
session_id: sessionId
|
|
712
823
|
});
|
|
713
824
|
};
|
|
825
|
+
|
|
714
826
|
const subagentResult = (toolUseId: string, content: string): void => {
|
|
715
827
|
out({
|
|
716
828
|
type: 'user',
|
|
@@ -719,6 +831,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
719
831
|
session_id: sessionId
|
|
720
832
|
});
|
|
721
833
|
};
|
|
834
|
+
|
|
722
835
|
const agentNotified = (summary: string): void => {
|
|
723
836
|
out({
|
|
724
837
|
type: 'system',
|
|
@@ -730,8 +843,10 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
730
843
|
usage: { total_tokens: 1500, tool_uses: 1, duration_ms: 250 },
|
|
731
844
|
session_id: sessionId
|
|
732
845
|
});
|
|
846
|
+
|
|
733
847
|
out({ type: 'system', subtype: 'init', session_id: sessionId, model, cwd: io.cwd, tools: ['Bash'], slash_commands: [], argv: args });
|
|
734
848
|
};
|
|
849
|
+
|
|
735
850
|
out({
|
|
736
851
|
type: 'assistant',
|
|
737
852
|
message: {
|
|
@@ -743,6 +858,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
743
858
|
},
|
|
744
859
|
session_id: sessionId
|
|
745
860
|
});
|
|
861
|
+
|
|
746
862
|
out({
|
|
747
863
|
type: 'system',
|
|
748
864
|
subtype: 'task_started',
|
|
@@ -754,6 +870,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
754
870
|
task_type: 'local_agent',
|
|
755
871
|
session_id: sessionId
|
|
756
872
|
});
|
|
873
|
+
|
|
757
874
|
out({
|
|
758
875
|
type: 'user',
|
|
759
876
|
message: {
|
|
@@ -762,10 +879,13 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
762
879
|
},
|
|
763
880
|
session_id: sessionId
|
|
764
881
|
});
|
|
882
|
+
|
|
765
883
|
assistantText('started');
|
|
766
884
|
result();
|
|
885
|
+
|
|
767
886
|
io.later(() => {
|
|
768
887
|
subagent([{ type: 'tool_use', id: bashUse, name: 'Bash', input: { command, run_in_background: true } }]);
|
|
888
|
+
|
|
769
889
|
out({
|
|
770
890
|
type: 'system',
|
|
771
891
|
subtype: 'task_started',
|
|
@@ -776,13 +896,16 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
776
896
|
is_backgrounded: true,
|
|
777
897
|
session_id: sessionId
|
|
778
898
|
});
|
|
899
|
+
|
|
779
900
|
subagentResult(bashUse, 'Command running in background with ID: b-cmd.');
|
|
780
901
|
subagent([{ type: 'text', text: 'Command started in the background.' }]);
|
|
781
902
|
agentNotified('Agent "Run it" finished');
|
|
782
903
|
assistantText('the subagent says: Command started in the background.');
|
|
783
904
|
result();
|
|
905
|
+
|
|
784
906
|
io.later(() => {
|
|
785
907
|
out({ type: 'system', subtype: 'task_updated', task_id: 'b-cmd', patch: { status: 'completed', end_time: 30000 }, session_id: sessionId });
|
|
908
|
+
|
|
786
909
|
out({
|
|
787
910
|
type: 'system',
|
|
788
911
|
subtype: 'task_notification',
|
|
@@ -793,6 +916,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
793
916
|
summary: `Background command "${command}" completed (exit code 0)`,
|
|
794
917
|
session_id: sessionId
|
|
795
918
|
});
|
|
919
|
+
|
|
796
920
|
subagent([{ type: 'tool_use', id: 'toolu_cmd_read', name: 'Read', input: { file_path: 'b-cmd.output' } }]);
|
|
797
921
|
subagentResult('toolu_cmd_read', 'DONE');
|
|
798
922
|
subagent([{ type: 'text', text: 'The command printed DONE.' }]);
|
|
@@ -801,24 +925,30 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
801
925
|
result();
|
|
802
926
|
});
|
|
803
927
|
});
|
|
928
|
+
|
|
804
929
|
return;
|
|
805
930
|
}
|
|
931
|
+
|
|
806
932
|
/*
|
|
807
933
|
* A two-phase workflow, framed the way Claude Code 2.1.282 streams one: the call answers at launch,
|
|
808
934
|
* and its agents send no frames of their own; only some progress frames carry a report of the whole run.
|
|
809
935
|
*/
|
|
810
936
|
if (text.startsWith('workflow:')) {
|
|
811
937
|
const summary = text.slice(9).trim() || 'Write a file, then read it';
|
|
938
|
+
|
|
812
939
|
const task = (frame: Record<string, unknown>): void => {
|
|
813
940
|
out({ type: 'system', task_id: 'wf-task', session_id: sessionId, ...frame });
|
|
814
941
|
};
|
|
942
|
+
|
|
815
943
|
const phases = [
|
|
816
944
|
{ type: 'workflow_phase', index: 1, title: 'Write' },
|
|
817
945
|
{ type: 'workflow_phase', index: 2, title: 'Read' }
|
|
818
946
|
];
|
|
947
|
+
|
|
819
948
|
const writer = { type: 'workflow_agent', index: 1, label: 'write-file', phaseIndex: 1, phaseTitle: 'Write', agentId: 'a-writer', startedAt: 1000 };
|
|
820
949
|
const reader = { type: 'workflow_agent', index: 2, label: 'read-file', phaseIndex: 2, phaseTitle: 'Read', agentId: 'a-reader', startedAt: 6000 };
|
|
821
950
|
const writerDone = { ...writer, state: 'done', lastToolName: 'Write', tokens: 16264, toolCalls: 1, durationMs: 5000 };
|
|
951
|
+
|
|
822
952
|
const progress = (description: string, report?: unknown[]): void => {
|
|
823
953
|
task({
|
|
824
954
|
subtype: 'task_progress',
|
|
@@ -830,6 +960,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
830
960
|
...(report === undefined ? {} : { workflow_progress: report })
|
|
831
961
|
});
|
|
832
962
|
};
|
|
963
|
+
|
|
833
964
|
out({
|
|
834
965
|
type: 'assistant',
|
|
835
966
|
message: {
|
|
@@ -841,13 +972,16 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
841
972
|
},
|
|
842
973
|
session_id: sessionId
|
|
843
974
|
});
|
|
975
|
+
|
|
844
976
|
out({
|
|
845
977
|
type: 'system',
|
|
846
978
|
subtype: 'background_tasks_changed',
|
|
847
979
|
tasks: [{ task_id: 'wf-task', task_type: 'local_workflow', description: summary }],
|
|
848
980
|
session_id: sessionId
|
|
849
981
|
});
|
|
982
|
+
|
|
850
983
|
task({ subtype: 'task_started', tool_use_id: 'toolu_wf', description: summary, task_type: 'local_workflow', workflow_name: 'write-and-read' });
|
|
984
|
+
|
|
851
985
|
out({
|
|
852
986
|
type: 'user',
|
|
853
987
|
message: {
|
|
@@ -863,15 +997,18 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
863
997
|
},
|
|
864
998
|
session_id: sessionId
|
|
865
999
|
});
|
|
1000
|
+
|
|
866
1001
|
progress('Write: write-file', [...phases, { ...writer, state: 'start' }]);
|
|
867
1002
|
assistantText('the workflow runs');
|
|
868
1003
|
result();
|
|
1004
|
+
|
|
869
1005
|
io.later(() => {
|
|
870
1006
|
progress('Write: write-file');
|
|
871
1007
|
progress('Read: read-file', [...phases, writerDone, { ...reader, state: 'start' }]);
|
|
872
1008
|
progress('Read: read-file', [...phases, writerDone, { ...reader, state: 'done', lastToolName: 'Read', durationMs: 4000 }]);
|
|
873
1009
|
out({ type: 'system', subtype: 'background_tasks_changed', tasks: [], session_id: sessionId });
|
|
874
1010
|
task({ subtype: 'task_updated', patch: { status: 'completed', end_time: 10000 } });
|
|
1011
|
+
|
|
875
1012
|
task({
|
|
876
1013
|
subtype: 'task_notification',
|
|
877
1014
|
tool_use_id: 'toolu_wf',
|
|
@@ -880,20 +1017,25 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
880
1017
|
summary: `Dynamic workflow "${summary}" completed`,
|
|
881
1018
|
usage: { total_tokens: 32403, tool_uses: 2, duration_ms: 9000 }
|
|
882
1019
|
});
|
|
1020
|
+
|
|
883
1021
|
out({ type: 'system', subtype: 'init', session_id: sessionId, model, cwd: io.cwd, tools: ['Bash'], slash_commands: [], argv: args });
|
|
884
1022
|
assistantText('the workflow is done');
|
|
885
1023
|
result();
|
|
886
1024
|
});
|
|
1025
|
+
|
|
887
1026
|
return;
|
|
888
1027
|
}
|
|
1028
|
+
|
|
889
1029
|
if (text.startsWith('run:')) {
|
|
890
1030
|
const command = text.slice(4).trim();
|
|
891
1031
|
const id = `msg_${nonce}_${++messageCounter}`;
|
|
1032
|
+
|
|
892
1033
|
out({
|
|
893
1034
|
type: 'assistant',
|
|
894
1035
|
message: { id, model, role: 'assistant', content: [{ type: 'tool_use', id: 'toolu_run', name: 'Bash', input: { command } }], usage },
|
|
895
1036
|
session_id: sessionId
|
|
896
1037
|
});
|
|
1038
|
+
|
|
897
1039
|
// The frames the real CLI emits around a long Bash call, in its order and shape.
|
|
898
1040
|
out({
|
|
899
1041
|
type: 'system',
|
|
@@ -905,6 +1047,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
905
1047
|
task_type: 'local_bash',
|
|
906
1048
|
session_id: sessionId
|
|
907
1049
|
});
|
|
1050
|
+
|
|
908
1051
|
out({
|
|
909
1052
|
type: 'tool_progress',
|
|
910
1053
|
tool_use_id: 'toolu_run',
|
|
@@ -914,6 +1057,7 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
914
1057
|
task_id: 'task-1',
|
|
915
1058
|
session_id: sessionId
|
|
916
1059
|
});
|
|
1060
|
+
|
|
917
1061
|
out({
|
|
918
1062
|
type: 'system',
|
|
919
1063
|
subtype: 'task_notification',
|
|
@@ -924,24 +1068,31 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
924
1068
|
summary: `Run ${command}`,
|
|
925
1069
|
session_id: sessionId
|
|
926
1070
|
});
|
|
1071
|
+
|
|
927
1072
|
out({
|
|
928
1073
|
type: 'user',
|
|
929
1074
|
message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'toolu_run', content: `ran: ${command}`, is_error: false }] },
|
|
930
1075
|
session_id: sessionId
|
|
931
1076
|
});
|
|
1077
|
+
|
|
932
1078
|
assistantText('done');
|
|
933
1079
|
result();
|
|
1080
|
+
|
|
934
1081
|
return;
|
|
935
1082
|
}
|
|
1083
|
+
|
|
936
1084
|
if (text.startsWith('tool:')) {
|
|
937
1085
|
const command = text.slice(5).trim();
|
|
938
1086
|
const id = `msg_${nonce}_${++messageCounter}`;
|
|
1087
|
+
|
|
939
1088
|
out({
|
|
940
1089
|
type: 'assistant',
|
|
941
1090
|
message: { id, model, role: 'assistant', content: [{ type: 'tool_use', id: 'toolu_1', name: 'Bash', input: { command } }], usage },
|
|
942
1091
|
session_id: sessionId
|
|
943
1092
|
});
|
|
1093
|
+
|
|
944
1094
|
pendingApproval = { command };
|
|
1095
|
+
|
|
945
1096
|
out({
|
|
946
1097
|
type: 'control_request',
|
|
947
1098
|
request_id: 'req-1',
|
|
@@ -956,14 +1107,18 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
956
1107
|
]
|
|
957
1108
|
}
|
|
958
1109
|
});
|
|
1110
|
+
|
|
959
1111
|
return;
|
|
960
1112
|
}
|
|
1113
|
+
|
|
961
1114
|
if (text === 'system?') {
|
|
962
1115
|
const at = args.indexOf('--append-system-prompt');
|
|
963
1116
|
assistantText(at >= 0 ? args[at + 1]! : 'none');
|
|
964
1117
|
result();
|
|
1118
|
+
|
|
965
1119
|
return;
|
|
966
1120
|
}
|
|
1121
|
+
|
|
967
1122
|
assistantText(`echo: ${text}`);
|
|
968
1123
|
result();
|
|
969
1124
|
};
|
|
@@ -972,31 +1127,40 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
972
1127
|
const inner = response.response as
|
|
973
1128
|
| { behavior?: string; message?: string; updatedInput?: { answers?: Record<string, string> }; updatedPermissions?: unknown[] }
|
|
974
1129
|
| undefined;
|
|
1130
|
+
|
|
975
1131
|
if (backgroundAsk !== null && response.request_id === backgroundAsk.requestId) {
|
|
976
1132
|
const { command } = backgroundAsk;
|
|
977
1133
|
backgroundAsk = null;
|
|
978
1134
|
finishBackgroundAgent(command, inner?.behavior === 'allow', inner?.message);
|
|
1135
|
+
|
|
979
1136
|
return;
|
|
980
1137
|
}
|
|
1138
|
+
|
|
981
1139
|
if (pendingQuestion) {
|
|
982
1140
|
const answer = inner?.updatedInput?.answers?.[pendingQuestion] ?? 'no answer';
|
|
983
1141
|
pendingQuestion = null;
|
|
984
1142
|
assistantText(`you chose ${answer}`);
|
|
985
1143
|
result();
|
|
1144
|
+
|
|
986
1145
|
return;
|
|
987
1146
|
}
|
|
1147
|
+
|
|
988
1148
|
const approval = pendingApproval;
|
|
989
1149
|
pendingApproval = null;
|
|
1150
|
+
|
|
990
1151
|
if (!approval) {
|
|
991
1152
|
return;
|
|
992
1153
|
}
|
|
1154
|
+
|
|
993
1155
|
if (inner?.behavior === 'allow') {
|
|
994
1156
|
const always = Array.isArray(inner.updatedPermissions) && inner.updatedPermissions.length > 0;
|
|
1157
|
+
|
|
995
1158
|
out({
|
|
996
1159
|
type: 'user',
|
|
997
1160
|
message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'toolu_1', content: `ran: ${approval.command}`, is_error: false }] },
|
|
998
1161
|
session_id: sessionId
|
|
999
1162
|
});
|
|
1163
|
+
|
|
1000
1164
|
assistantText(always ? 'done, remembered' : 'done');
|
|
1001
1165
|
} else {
|
|
1002
1166
|
out({
|
|
@@ -1004,8 +1168,10 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
1004
1168
|
message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'toolu_1', content: 'denied by user', is_error: true }] },
|
|
1005
1169
|
session_id: sessionId
|
|
1006
1170
|
});
|
|
1171
|
+
|
|
1007
1172
|
assistantText('denied');
|
|
1008
1173
|
}
|
|
1174
|
+
|
|
1009
1175
|
result();
|
|
1010
1176
|
};
|
|
1011
1177
|
|
|
@@ -1014,10 +1180,12 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
1014
1180
|
return {
|
|
1015
1181
|
onLine: (line) => {
|
|
1016
1182
|
const frame = JSON.parse(line) as Record<string, unknown>;
|
|
1183
|
+
|
|
1017
1184
|
if (frame.type === 'user') {
|
|
1018
1185
|
if (args.includes('--replay-user-messages') && typeof frame.uuid === 'string') {
|
|
1019
1186
|
out(frame);
|
|
1020
1187
|
}
|
|
1188
|
+
|
|
1021
1189
|
const message = frame.message as { content: Array<{ text: string }> };
|
|
1022
1190
|
handleUser(message.content[0]?.text ?? '');
|
|
1023
1191
|
} else if (frame.type === 'control_response') {
|
|
@@ -1025,9 +1193,11 @@ export function fakeClaude(io: FakeIo): FakeProgram {
|
|
|
1025
1193
|
} else if (frame.type === 'control_request') {
|
|
1026
1194
|
const request = frame.request as { subtype: string; task_id?: string };
|
|
1027
1195
|
out({ type: 'control_response', response: { subtype: 'success', request_id: frame.request_id, response: {} } });
|
|
1196
|
+
|
|
1028
1197
|
if (request.subtype === 'stop_task' && (request.task_id === 'a-one' || request.task_id === 'a-two')) {
|
|
1029
1198
|
settleTwo(request.task_id, true);
|
|
1030
1199
|
}
|
|
1200
|
+
|
|
1031
1201
|
if (request.subtype === 'interrupt' && slow) {
|
|
1032
1202
|
slow = false;
|
|
1033
1203
|
assistantText('[interrupted]');
|
|
@@ -1047,14 +1217,19 @@ export function claudeStoppingOnResume(sessionIds: ReadonlySet<string>, how: 'mi
|
|
|
1047
1217
|
return (io) => {
|
|
1048
1218
|
const resumeAt = io.argv.indexOf('--resume');
|
|
1049
1219
|
const sessionId = resumeAt >= 0 ? io.argv[resumeAt + 1] : undefined;
|
|
1220
|
+
|
|
1050
1221
|
if (sessionId === undefined || !sessionIds.has(sessionId)) {
|
|
1051
1222
|
return fakeClaude(io);
|
|
1052
1223
|
}
|
|
1224
|
+
|
|
1053
1225
|
if (how === 'exit') {
|
|
1054
1226
|
fakeClaude(io);
|
|
1227
|
+
|
|
1055
1228
|
return { onLine: () => io.exit(1) };
|
|
1056
1229
|
}
|
|
1230
|
+
|
|
1057
1231
|
const message = `No conversation found with session ID: ${sessionId}`;
|
|
1232
|
+
|
|
1058
1233
|
io.out({
|
|
1059
1234
|
type: 'result',
|
|
1060
1235
|
subtype: 'error_during_execution',
|
|
@@ -1069,8 +1244,10 @@ export function claudeStoppingOnResume(sessionIds: ReadonlySet<string>, how: 'mi
|
|
|
1069
1244
|
permission_denials: [],
|
|
1070
1245
|
errors: [message]
|
|
1071
1246
|
});
|
|
1247
|
+
|
|
1072
1248
|
io.err(`${message}\n`);
|
|
1073
1249
|
io.exit(1);
|
|
1250
|
+
|
|
1074
1251
|
return { onLine: () => undefined };
|
|
1075
1252
|
};
|
|
1076
1253
|
}
|