@opencoven/coven-code 0.0.2 → 0.0.4
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 +1 -1
- package/docs/CLI.md +1 -1
- package/docs/DEMO.md +4 -1
- package/package.json +1 -1
- package/src/cli/execute.mjs +30 -168
- package/src/cli/slash-commands.mjs +20 -2
- package/src/cli/stream-json.mjs +109 -0
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ filtering and a details panel for commands, skills, and plugin actions.
|
|
|
34
34
|
|
|
35
35
|
```text
|
|
36
36
|
$ coven-code
|
|
37
|
-
Coven Code 0.0.
|
|
37
|
+
Coven Code 0.0.4
|
|
38
38
|
/Users/example/project
|
|
39
39
|
[chat] lane tools threads config help mode: smart effort: high
|
|
40
40
|
--------------------------------------------------------------------------------
|
package/docs/CLI.md
CHANGED
|
@@ -99,7 +99,7 @@ transcript, tabs, compact status line, command palette, slash-command menu, and
|
|
|
99
99
|
composer. It keeps a current local thread and accepts slash commands:
|
|
100
100
|
|
|
101
101
|
```text
|
|
102
|
-
Coven Code 0.0.
|
|
102
|
+
Coven Code 0.0.4
|
|
103
103
|
[chat] lane tools threads config help mode: smart effort: high
|
|
104
104
|
--------------------------------------------------------------------------------
|
|
105
105
|
Ready. Type a prompt or /help.
|
package/docs/DEMO.md
CHANGED
|
@@ -90,8 +90,11 @@ The menu accepts:
|
|
|
90
90
|
| -------- | -------------------------------------------------------- |
|
|
91
91
|
| `1`-`12` | run one section by number |
|
|
92
92
|
| `a` | run all sections in sequence, then print the scoreboard |
|
|
93
|
+
| `r` | replay the last section you ran |
|
|
93
94
|
| `t` | type your own prompt and run one execute turn |
|
|
94
95
|
| `s` | list the files the demo wrote into the sandbox HOME |
|
|
96
|
+
| `x` | open a real subshell inside the sandbox (`exit` returns) |
|
|
97
|
+
| `c` | copy the sandbox path to your clipboard |
|
|
95
98
|
| `l` | re-print the section table of contents (with `✓` marks) |
|
|
96
99
|
| `?` | show the menu help |
|
|
97
100
|
| `q` | quit (sandbox path printed so you can clean up or poke around) |
|
|
@@ -144,7 +147,7 @@ rm -rf "$DEMO_HOME" # the script prints the exact path at the end
|
|
|
144
147
|
works without any account or API key.
|
|
145
148
|
|
|
146
149
|
```sh
|
|
147
|
-
node ./bin/coven-code.mjs --version # prints 0.0.
|
|
150
|
+
node ./bin/coven-code.mjs --version # prints 0.0.4
|
|
148
151
|
node ./bin/coven-code.mjs --help # full option and command reference
|
|
149
152
|
node ./bin/coven-code.mjs login # printable instructions (no token yet)
|
|
150
153
|
node ./bin/coven-code.mjs login status # auth_status: logged_out
|
package/package.json
CHANGED
package/src/cli/execute.mjs
CHANGED
|
@@ -1,33 +1,24 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import { BUILTIN_TOOLS } from '../constants.mjs';
|
|
5
4
|
import { estimateUsage, fixtureAgentResponse } from '../agent/fixture.mjs';
|
|
6
|
-
import {
|
|
7
|
-
listActiveMcpServerEntries,
|
|
8
|
-
} from '../mcp/discover.mjs';
|
|
9
|
-
import { discoverMcpToolRows } from '../mcp/probe.mjs';
|
|
10
5
|
import {
|
|
11
6
|
loadPlugins,
|
|
12
7
|
runPluginEventHandlers,
|
|
13
8
|
} from '../plugins/discover.mjs';
|
|
14
9
|
import { discoverAgentFiles, firstGuidanceInDir } from '../commands/agents.mjs';
|
|
15
|
-
import {
|
|
16
|
-
isToolDisabled,
|
|
17
|
-
listToolboxTools,
|
|
18
|
-
toolKindForName,
|
|
19
|
-
} from '../tools/toolbox.mjs';
|
|
20
10
|
import { executePromptToolRequest } from '../tools/builtin/index.mjs';
|
|
21
11
|
import { toolResultContent } from '../tools/builtin/runtime.mjs';
|
|
22
12
|
import { persistThreadMessages, threadContinuationPrompt } from '../threads/store.mjs';
|
|
23
13
|
import { readEffectiveSettings } from '../settings/load.mjs';
|
|
24
14
|
import { expandFileReferences, expandThreadReferences } from './refs.mjs';
|
|
25
15
|
import { UsageError } from './parse.mjs';
|
|
26
|
-
import { reasoningEffortForMode } from './reasoning.mjs';
|
|
27
16
|
import { notifyAgentComplete } from './notifications.mjs';
|
|
28
17
|
import { globToRegex } from '../util/glob.mjs';
|
|
29
|
-
import {
|
|
18
|
+
import { emitJson } from '../util/fs.mjs';
|
|
30
19
|
import {
|
|
20
|
+
emitStreamJsonInit,
|
|
21
|
+
emitStreamJsonTurn,
|
|
31
22
|
streamJsonInputMessages,
|
|
32
23
|
streamJsonOutputUserContent,
|
|
33
24
|
streamJsonPermissionDenials,
|
|
@@ -60,83 +51,21 @@ export async function runExecute(parsed, stdin, options = {}) {
|
|
|
60
51
|
const result = turns.at(-1)?.result ?? '';
|
|
61
52
|
|
|
62
53
|
if (parsed.streamJson) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
...(await discoverMcpToolRows(activeMcpServers)).map(([name]) => name),
|
|
69
|
-
].filter((name) => !isToolDisabled(name, toolKindForName(name), parsed));
|
|
70
|
-
emitJson({
|
|
71
|
-
type: 'system',
|
|
72
|
-
subtype: 'init',
|
|
73
|
-
cwd: displayCwd(),
|
|
74
|
-
session_id: sessionId,
|
|
75
|
-
tools,
|
|
76
|
-
mcp_servers: activeMcpServers.map(({ name }) => ({ name, status: 'connected' })),
|
|
77
|
-
agent_mode: parsed.mode,
|
|
78
|
-
reasoning_effort: reasoningEffortForMode(parsed.mode, parsed.reasoningEffort),
|
|
54
|
+
await emitStreamJsonInit({
|
|
55
|
+
parsed,
|
|
56
|
+
plugins,
|
|
57
|
+
sessionId,
|
|
58
|
+
promptForMcpDiscovery: turns.map((turn) => turn.prompt).join('\n\n'),
|
|
79
59
|
});
|
|
80
60
|
for (const turn of turns) {
|
|
81
|
-
|
|
82
|
-
type: '
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
type: 'assistant',
|
|
90
|
-
message: {
|
|
91
|
-
type: 'message',
|
|
92
|
-
role: 'assistant',
|
|
93
|
-
content: [turn.toolRun.toolUse],
|
|
94
|
-
stop_reason: 'tool_use',
|
|
95
|
-
usage: estimateUsage(turn.prompt, JSON.stringify(turn.toolRun.toolUse.input)),
|
|
96
|
-
},
|
|
97
|
-
parent_tool_use_id: null,
|
|
98
|
-
session_id: sessionId,
|
|
99
|
-
});
|
|
100
|
-
for (const subagentMessage of turn.toolRun.subagentMessages ?? []) {
|
|
101
|
-
emitJson({
|
|
102
|
-
type: 'assistant',
|
|
103
|
-
message: {
|
|
104
|
-
type: 'message',
|
|
105
|
-
role: 'assistant',
|
|
106
|
-
content: assistantStreamContent(subagentMessage.text ?? '', parsed),
|
|
107
|
-
stop_reason: 'end_turn',
|
|
108
|
-
usage: estimateUsage(turn.prompt, subagentMessage.text ?? ''),
|
|
109
|
-
},
|
|
110
|
-
parent_tool_use_id: turn.toolRun.toolUse.id,
|
|
111
|
-
session_id: sessionId,
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
emitJson({
|
|
115
|
-
type: 'user',
|
|
116
|
-
message: {
|
|
117
|
-
role: 'user',
|
|
118
|
-
content: [{
|
|
119
|
-
type: 'tool_result',
|
|
120
|
-
tool_use_id: turn.toolRun.toolUse.id,
|
|
121
|
-
content: toolResultContent(turn.toolRun),
|
|
122
|
-
is_error: turn.toolRun.exitCode !== 0,
|
|
123
|
-
}],
|
|
124
|
-
},
|
|
125
|
-
parent_tool_use_id: toolRunParent(turn.toolRun, 'toolResultParentToolUseId', null),
|
|
126
|
-
session_id: sessionId,
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
emitJson({
|
|
130
|
-
type: 'assistant',
|
|
131
|
-
message: {
|
|
132
|
-
type: 'message',
|
|
133
|
-
role: 'assistant',
|
|
134
|
-
content: assistantStreamContent(turn.result, parsed),
|
|
135
|
-
stop_reason: 'end_turn',
|
|
136
|
-
usage: estimateUsage(turn.prompt, turn.result),
|
|
137
|
-
},
|
|
138
|
-
parent_tool_use_id: turn.toolRun ? toolRunParent(turn.toolRun, 'finalParentToolUseId', null) : null,
|
|
139
|
-
session_id: sessionId,
|
|
61
|
+
emitStreamJsonTurn({
|
|
62
|
+
userContent: [{ type: 'text', text: turn.prompt }],
|
|
63
|
+
promptText: turn.prompt,
|
|
64
|
+
toolRun: turn.toolRun,
|
|
65
|
+
result: turn.result,
|
|
66
|
+
parsed,
|
|
67
|
+
sessionId,
|
|
68
|
+
assistantParentToolUseId: turn.toolRun ? toolRunParent(turn.toolRun, 'finalParentToolUseId', null) : null,
|
|
140
69
|
});
|
|
141
70
|
}
|
|
142
71
|
emitJson(streamJsonResultMessage({
|
|
@@ -312,22 +241,11 @@ async function runStreamJsonInputExecute(parsed, stdin, options = {}, started =
|
|
|
312
241
|
const combinedPrompt = inputMessages.map((message) => message.text).filter(Boolean).join('\n\n');
|
|
313
242
|
const plugins = await loadPlugins(process.cwd());
|
|
314
243
|
await runSessionStartHandlers(plugins, sessionId);
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
...(await discoverMcpToolRows(activeMcpServers)).map(([name]) => name),
|
|
321
|
-
].filter((name) => !isToolDisabled(name, toolKindForName(name), parsed));
|
|
322
|
-
emitJson({
|
|
323
|
-
type: 'system',
|
|
324
|
-
subtype: 'init',
|
|
325
|
-
cwd: displayCwd(),
|
|
326
|
-
session_id: sessionId,
|
|
327
|
-
tools,
|
|
328
|
-
mcp_servers: activeMcpServers.map(({ name }) => ({ name, status: 'connected' })),
|
|
329
|
-
agent_mode: parsed.mode,
|
|
330
|
-
reasoning_effort: reasoningEffortForMode(parsed.mode, parsed.reasoningEffort),
|
|
244
|
+
await emitStreamJsonInit({
|
|
245
|
+
parsed,
|
|
246
|
+
plugins,
|
|
247
|
+
sessionId,
|
|
248
|
+
promptForMcpDiscovery: combinedPrompt,
|
|
331
249
|
});
|
|
332
250
|
|
|
333
251
|
const transcript = [];
|
|
@@ -356,67 +274,18 @@ async function runStreamJsonInputExecute(parsed, stdin, options = {}, started =
|
|
|
356
274
|
if (toolRun?.permissionDenials) permissionDenials.push(...toolRun.permissionDenials);
|
|
357
275
|
if ((toolRun?.exitCode ?? 0) !== 0) isError = true;
|
|
358
276
|
|
|
359
|
-
emitJson({
|
|
360
|
-
type: 'user',
|
|
361
|
-
...(input.steer ? { steer: true } : {}),
|
|
362
|
-
message: { role: 'user', content: streamJsonOutputUserContent(input.content) },
|
|
363
|
-
parent_tool_use_id: null,
|
|
364
|
-
session_id: sessionId,
|
|
365
|
-
});
|
|
366
277
|
if (toolRun?.toolUse) {
|
|
367
|
-
emitJson({
|
|
368
|
-
type: 'assistant',
|
|
369
|
-
message: {
|
|
370
|
-
type: 'message',
|
|
371
|
-
role: 'assistant',
|
|
372
|
-
content: [toolRun.toolUse],
|
|
373
|
-
stop_reason: 'tool_use',
|
|
374
|
-
usage: estimateUsage(input.text, JSON.stringify(toolRun.toolUse.input)),
|
|
375
|
-
},
|
|
376
|
-
parent_tool_use_id: null,
|
|
377
|
-
session_id: sessionId,
|
|
378
|
-
});
|
|
379
|
-
for (const subagentMessage of toolRun.subagentMessages ?? []) {
|
|
380
|
-
emitJson({
|
|
381
|
-
type: 'assistant',
|
|
382
|
-
message: {
|
|
383
|
-
type: 'message',
|
|
384
|
-
role: 'assistant',
|
|
385
|
-
content: assistantStreamContent(subagentMessage.text ?? '', parsed),
|
|
386
|
-
stop_reason: 'end_turn',
|
|
387
|
-
usage: estimateUsage(input.text, subagentMessage.text ?? ''),
|
|
388
|
-
},
|
|
389
|
-
parent_tool_use_id: toolRun.toolUse.id,
|
|
390
|
-
session_id: sessionId,
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
emitJson({
|
|
394
|
-
type: 'user',
|
|
395
|
-
message: {
|
|
396
|
-
role: 'user',
|
|
397
|
-
content: [{
|
|
398
|
-
type: 'tool_result',
|
|
399
|
-
tool_use_id: toolRun.toolUse.id,
|
|
400
|
-
content: toolResultContent(toolRun),
|
|
401
|
-
is_error: toolRun.exitCode !== 0,
|
|
402
|
-
}],
|
|
403
|
-
},
|
|
404
|
-
parent_tool_use_id: toolRunParent(toolRun, 'toolResultParentToolUseId', null),
|
|
405
|
-
session_id: sessionId,
|
|
406
|
-
});
|
|
407
278
|
parentToolUseId = toolRunParent(toolRun, 'finalParentToolUseId', null);
|
|
408
279
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
parent_tool_use_id: parentToolUseId,
|
|
419
|
-
session_id: sessionId,
|
|
280
|
+
emitStreamJsonTurn({
|
|
281
|
+
userContent: streamJsonOutputUserContent(input.content),
|
|
282
|
+
steer: input.steer,
|
|
283
|
+
promptText: input.text,
|
|
284
|
+
toolRun,
|
|
285
|
+
result,
|
|
286
|
+
parsed,
|
|
287
|
+
sessionId,
|
|
288
|
+
assistantParentToolUseId: parentToolUseId,
|
|
420
289
|
});
|
|
421
290
|
await runPluginEventHandlers(plugins.handlers['agent.end'], {
|
|
422
291
|
message: input.text,
|
|
@@ -453,13 +322,6 @@ async function runSessionStartHandlers(plugins, sessionId) {
|
|
|
453
322
|
});
|
|
454
323
|
}
|
|
455
324
|
|
|
456
|
-
function assistantStreamContent(result, parsed = {}) {
|
|
457
|
-
if (parsed.streamJsonThinking && readEffectiveSettings(parsed)['covenCode.thinking.enabled'] !== false) {
|
|
458
|
-
return [{ type: 'thinking', thinking: 'Using the local deterministic recreation.' }, { type: 'text', text: result }];
|
|
459
|
-
}
|
|
460
|
-
return [{ type: 'text', text: result }];
|
|
461
|
-
}
|
|
462
|
-
|
|
463
325
|
function modelPromptWithTranscript(turnPrompt, transcript, thread, parsed = {}) {
|
|
464
326
|
const context = transcript.length > 0
|
|
465
327
|
? `[conversation:${thread?.id ?? 'stream-json-input'}]\n${transcript
|
|
@@ -163,8 +163,8 @@ export async function buildSlashCommandCatalog(options = {}) {
|
|
|
163
163
|
const cwd = options.cwd ?? process.cwd();
|
|
164
164
|
const entries = [
|
|
165
165
|
...buildStaticSlashCommandCatalog(),
|
|
166
|
-
...
|
|
167
|
-
...await
|
|
166
|
+
...safeSkillSlashCommands(parsed, cwd),
|
|
167
|
+
...await safePluginSlashCommands(cwd),
|
|
168
168
|
];
|
|
169
169
|
return normalizeCatalog(entries);
|
|
170
170
|
} finally {
|
|
@@ -262,6 +262,24 @@ async function pluginSlashCommands(cwd) {
|
|
|
262
262
|
}));
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
+
function safeSkillSlashCommands(parsed, cwd) {
|
|
266
|
+
try {
|
|
267
|
+
return skillSlashCommands(parsed, cwd);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
console.error(`${CLI_NAME}: skill catalog unavailable: ${error?.message ?? error}`);
|
|
270
|
+
return [];
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async function safePluginSlashCommands(cwd) {
|
|
275
|
+
try {
|
|
276
|
+
return await pluginSlashCommands(cwd);
|
|
277
|
+
} catch (error) {
|
|
278
|
+
console.error(`${CLI_NAME}: plugin catalog unavailable: ${error?.message ?? error}`);
|
|
279
|
+
return [];
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
265
283
|
function normalizeCatalog(entries) {
|
|
266
284
|
const seen = new Set();
|
|
267
285
|
const catalog = [];
|
package/src/cli/stream-json.mjs
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { BUILTIN_TOOLS } from '../constants.mjs';
|
|
3
|
+
import { estimateUsage } from '../agent/fixture.mjs';
|
|
4
|
+
import { listActiveMcpServerEntries } from '../mcp/discover.mjs';
|
|
5
|
+
import { discoverMcpToolRows } from '../mcp/probe.mjs';
|
|
6
|
+
import { readEffectiveSettings } from '../settings/load.mjs';
|
|
7
|
+
import { isToolDisabled, listToolboxTools, toolKindForName } from '../tools/toolbox.mjs';
|
|
8
|
+
import { toolResultContent } from '../tools/builtin/runtime.mjs';
|
|
2
9
|
import { detectImageMediaType, imageMediaTypeExtension } from '../util/media.mjs';
|
|
10
|
+
import { displayCwd, emitJson } from '../util/fs.mjs';
|
|
3
11
|
import { UsageError } from './parse.mjs';
|
|
12
|
+
import { reasoningEffortForMode } from './reasoning.mjs';
|
|
4
13
|
import { imageMentionBlock } from './refs.mjs';
|
|
5
14
|
|
|
6
15
|
export function streamJsonInputMessages(prompt, stdin) {
|
|
@@ -90,6 +99,106 @@ export function streamJsonPermissionDenials(denials = []) {
|
|
|
90
99
|
});
|
|
91
100
|
}
|
|
92
101
|
|
|
102
|
+
export function assistantStreamContent(result, parsed = {}) {
|
|
103
|
+
if (parsed.streamJsonThinking && readEffectiveSettings(parsed)['covenCode.thinking.enabled'] !== false) {
|
|
104
|
+
return [{ type: 'thinking', thinking: 'Using the local deterministic recreation.' }, { type: 'text', text: result }];
|
|
105
|
+
}
|
|
106
|
+
return [{ type: 'text', text: result }];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export async function emitStreamJsonInit({ parsed, plugins, sessionId, promptForMcpDiscovery }) {
|
|
110
|
+
const activeMcpServers = listActiveMcpServerEntries(parsed, promptForMcpDiscovery);
|
|
111
|
+
const tools = [
|
|
112
|
+
...BUILTIN_TOOLS.map(([name]) => name),
|
|
113
|
+
...listToolboxTools(parsed).map((tool) => tool.name),
|
|
114
|
+
...plugins.tools.map((tool) => tool.name),
|
|
115
|
+
...(await discoverMcpToolRows(activeMcpServers)).map(([name]) => name),
|
|
116
|
+
].filter((name) => !isToolDisabled(name, toolKindForName(name), parsed));
|
|
117
|
+
emitJson({
|
|
118
|
+
type: 'system',
|
|
119
|
+
subtype: 'init',
|
|
120
|
+
cwd: displayCwd(),
|
|
121
|
+
session_id: sessionId,
|
|
122
|
+
tools,
|
|
123
|
+
mcp_servers: activeMcpServers.map(({ name }) => ({ name, status: 'connected' })),
|
|
124
|
+
agent_mode: parsed.mode,
|
|
125
|
+
reasoning_effort: reasoningEffortForMode(parsed.mode, parsed.reasoningEffort),
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function emitStreamJsonTurn({
|
|
130
|
+
userContent,
|
|
131
|
+
steer = false,
|
|
132
|
+
promptText,
|
|
133
|
+
toolRun,
|
|
134
|
+
result,
|
|
135
|
+
parsed,
|
|
136
|
+
sessionId,
|
|
137
|
+
assistantParentToolUseId,
|
|
138
|
+
}) {
|
|
139
|
+
emitJson({
|
|
140
|
+
type: 'user',
|
|
141
|
+
...(steer ? { steer: true } : {}),
|
|
142
|
+
message: { role: 'user', content: userContent },
|
|
143
|
+
parent_tool_use_id: null,
|
|
144
|
+
session_id: sessionId,
|
|
145
|
+
});
|
|
146
|
+
if (toolRun?.toolUse) {
|
|
147
|
+
emitJson({
|
|
148
|
+
type: 'assistant',
|
|
149
|
+
message: {
|
|
150
|
+
type: 'message',
|
|
151
|
+
role: 'assistant',
|
|
152
|
+
content: [toolRun.toolUse],
|
|
153
|
+
stop_reason: 'tool_use',
|
|
154
|
+
usage: estimateUsage(promptText, JSON.stringify(toolRun.toolUse.input)),
|
|
155
|
+
},
|
|
156
|
+
parent_tool_use_id: null,
|
|
157
|
+
session_id: sessionId,
|
|
158
|
+
});
|
|
159
|
+
for (const subagentMessage of toolRun.subagentMessages ?? []) {
|
|
160
|
+
emitJson({
|
|
161
|
+
type: 'assistant',
|
|
162
|
+
message: {
|
|
163
|
+
type: 'message',
|
|
164
|
+
role: 'assistant',
|
|
165
|
+
content: assistantStreamContent(subagentMessage.text ?? '', parsed),
|
|
166
|
+
stop_reason: 'end_turn',
|
|
167
|
+
usage: estimateUsage(promptText, subagentMessage.text ?? ''),
|
|
168
|
+
},
|
|
169
|
+
parent_tool_use_id: toolRun.toolUse.id,
|
|
170
|
+
session_id: sessionId,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
emitJson({
|
|
174
|
+
type: 'user',
|
|
175
|
+
message: {
|
|
176
|
+
role: 'user',
|
|
177
|
+
content: [{
|
|
178
|
+
type: 'tool_result',
|
|
179
|
+
tool_use_id: toolRun.toolUse.id,
|
|
180
|
+
content: toolResultContent(toolRun),
|
|
181
|
+
is_error: toolRun.exitCode !== 0,
|
|
182
|
+
}],
|
|
183
|
+
},
|
|
184
|
+
parent_tool_use_id: toolRunParent(toolRun, 'toolResultParentToolUseId', null),
|
|
185
|
+
session_id: sessionId,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
emitJson({
|
|
189
|
+
type: 'assistant',
|
|
190
|
+
message: {
|
|
191
|
+
type: 'message',
|
|
192
|
+
role: 'assistant',
|
|
193
|
+
content: assistantStreamContent(result, parsed),
|
|
194
|
+
stop_reason: 'end_turn',
|
|
195
|
+
usage: estimateUsage(promptText, result),
|
|
196
|
+
},
|
|
197
|
+
parent_tool_use_id: assistantParentToolUseId,
|
|
198
|
+
session_id: sessionId,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
93
202
|
export function streamJsonResultMessage({ started, isError, errorSubtype, numTurns, result, sessionId, usage, permissionDenials }) {
|
|
94
203
|
const common = {
|
|
95
204
|
type: 'result',
|