@opencoven/coven-code 0.0.3 → 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 +1 -1
- package/package.json +1 -1
- package/src/cli/execute.mjs +30 -168
- 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
|
@@ -147,7 +147,7 @@ rm -rf "$DEMO_HOME" # the script prints the exact path at the end
|
|
|
147
147
|
works without any account or API key.
|
|
148
148
|
|
|
149
149
|
```sh
|
|
150
|
-
node ./bin/coven-code.mjs --version # prints 0.0.
|
|
150
|
+
node ./bin/coven-code.mjs --version # prints 0.0.4
|
|
151
151
|
node ./bin/coven-code.mjs --help # full option and command reference
|
|
152
152
|
node ./bin/coven-code.mjs login # printable instructions (no token yet)
|
|
153
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
|
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',
|