zelari-code 0.2.2 → 0.6.2
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 +97 -2
- package/dist/agents/councilApi.js +7 -7
- package/dist/agents/councilApi.js.map +1 -1
- package/dist/agents/councilDirectives.js +3 -3
- package/dist/agents/promoteMember.js +2 -2
- package/dist/agents/roles.js +32 -32
- package/dist/agents/roles.js.map +1 -1
- package/dist/agents/skills/builtin/debugging.js +4 -4
- package/dist/agents/skills/builtin/debugging.js.map +1 -1
- package/dist/agents/skills/builtin/docs.js +13 -23
- package/dist/agents/skills/builtin/docs.js.map +1 -1
- package/dist/agents/skills/builtin/git-ops.js +3 -3
- package/dist/agents/skills/builtin/git-ops.js.map +1 -1
- package/dist/agents/skills/builtin/planning.js +4 -4
- package/dist/agents/skills/builtin/planning.js.map +1 -1
- package/dist/agents/skills/builtin/refactoring.js +3 -3
- package/dist/agents/skills/builtin/refactoring.js.map +1 -1
- package/dist/agents/skills/builtin/review.js +9 -9
- package/dist/agents/skills/builtin/review.js.map +1 -1
- package/dist/agents/skills/builtin/testing.js +3 -3
- package/dist/agents/skills/builtin/testing.js.map +1 -1
- package/dist/agents/tools.js +9 -2
- package/dist/agents/tools.js.map +1 -1
- package/dist/cli/app.js +94 -1861
- package/dist/cli/app.js.map +1 -1
- package/dist/cli/compaction.js.map +1 -1
- package/dist/cli/components/ChatStream.js +81 -14
- package/dist/cli/components/ChatStream.js.map +1 -1
- package/dist/cli/components/CollapsibleToolOutput.js +26 -3
- package/dist/cli/components/CollapsibleToolOutput.js.map +1 -1
- package/dist/cli/components/Header.js +20 -1
- package/dist/cli/components/Header.js.map +1 -1
- package/dist/cli/components/InputBar.js +34 -2
- package/dist/cli/components/InputBar.js.map +1 -1
- package/dist/cli/components/Sidebar.js +30 -10
- package/dist/cli/components/Sidebar.js.map +1 -1
- package/dist/cli/councilDispatcher.js +10 -2
- package/dist/cli/councilDispatcher.js.map +1 -1
- package/dist/cli/headless.js +137 -0
- package/dist/cli/headless.js.map +1 -0
- package/dist/cli/hooks/chatStats.js +28 -0
- package/dist/cli/hooks/chatStats.js.map +1 -0
- package/dist/cli/hooks/eventsToMessages.js +111 -0
- package/dist/cli/hooks/eventsToMessages.js.map +1 -0
- package/dist/cli/hooks/messageHelpers.js +125 -0
- package/dist/cli/hooks/messageHelpers.js.map +1 -0
- package/dist/cli/hooks/skillCompare.js +69 -0
- package/dist/cli/hooks/skillCompare.js.map +1 -0
- package/dist/cli/hooks/steer.js +28 -0
- package/dist/cli/hooks/steer.js.map +1 -0
- package/dist/cli/hooks/useBatchedMessages.js +67 -0
- package/dist/cli/hooks/useBatchedMessages.js.map +1 -0
- package/dist/cli/hooks/useChatTurn.js +363 -0
- package/dist/cli/hooks/useChatTurn.js.map +1 -0
- package/dist/cli/hooks/useSession.js +116 -0
- package/dist/cli/hooks/useSession.js.map +1 -0
- package/dist/cli/hooks/useSlashDispatch.js +303 -0
- package/dist/cli/hooks/useSlashDispatch.js.map +1 -0
- package/dist/cli/hooks/useTerminalSize.js +60 -0
- package/dist/cli/hooks/useTerminalSize.js.map +1 -0
- package/dist/cli/main.bundled.js +25212 -21722
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +86 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/provider/openai-compatible.js +9 -2
- package/dist/cli/provider/openai-compatible.js.map +1 -1
- package/dist/cli/runHeadless.js +160 -0
- package/dist/cli/runHeadless.js.map +1 -0
- package/dist/cli/sessionManager.js +47 -1
- package/dist/cli/sessionManager.js.map +1 -1
- package/dist/cli/skillSuggest.js +1 -1
- package/dist/cli/slashCommands.js +72 -3
- package/dist/cli/slashCommands.js.map +1 -1
- package/dist/cli/slashHandlers/branch.js +57 -0
- package/dist/cli/slashHandlers/branch.js.map +1 -0
- package/dist/cli/slashHandlers/git.js +40 -0
- package/dist/cli/slashHandlers/git.js.map +1 -0
- package/dist/cli/slashHandlers/promoteMember.js +25 -0
- package/dist/cli/slashHandlers/promoteMember.js.map +1 -0
- package/dist/cli/slashHandlers/provider.js +199 -0
- package/dist/cli/slashHandlers/provider.js.map +1 -0
- package/dist/cli/slashHandlers/skills.js +82 -0
- package/dist/cli/slashHandlers/skills.js.map +1 -0
- package/dist/cli/slashHandlers/transcript.js +13 -0
- package/dist/cli/slashHandlers/transcript.js.map +1 -0
- package/dist/cli/slashHandlers/updater.js +40 -0
- package/dist/cli/slashHandlers/updater.js.map +1 -0
- package/dist/cli/slashHandlers/workspace.js +118 -0
- package/dist/cli/slashHandlers/workspace.js.map +1 -0
- package/dist/cli/toolRegistry.js +17 -8
- package/dist/cli/toolRegistry.js.map +1 -1
- package/dist/cli/utils/duration.js +34 -0
- package/dist/cli/utils/duration.js.map +1 -0
- package/dist/cli/wizard/firstRun.js +63 -0
- package/dist/cli/wizard/firstRun.js.map +1 -0
- package/dist/cli/wizard/index.js +150 -0
- package/dist/cli/wizard/index.js.map +1 -0
- package/dist/cli/wizard/runWizard.js +137 -0
- package/dist/cli/wizard/runWizard.js.map +1 -0
- package/dist/cli/wizard/useWizardState.js +151 -0
- package/dist/cli/wizard/useWizardState.js.map +1 -0
- package/dist/cli/workspace/agentsMd.js +314 -0
- package/dist/cli/workspace/agentsMd.js.map +1 -0
- package/dist/cli/workspace/index.js +24 -0
- package/dist/cli/workspace/index.js.map +1 -0
- package/dist/cli/workspace/paths.js +88 -0
- package/dist/cli/workspace/paths.js.map +1 -0
- package/dist/cli/workspace/postCouncilHook.js +38 -0
- package/dist/cli/workspace/postCouncilHook.js.map +1 -0
- package/dist/cli/workspace/storage.js +392 -0
- package/dist/cli/workspace/storage.js.map +1 -0
- package/dist/cli/workspace/stubs.js +528 -0
- package/dist/cli/workspace/stubs.js.map +1 -0
- package/dist/cli/workspace/toolRegistry.js +61 -0
- package/dist/cli/workspace/toolRegistry.js.map +1 -0
- package/dist/cli/workspace/types.js +10 -0
- package/dist/cli/workspace/types.js.map +1 -0
- package/dist/main/core/tools/builtin/_walk.js +129 -0
- package/dist/main/core/tools/builtin/_walk.js.map +1 -0
- package/dist/main/core/tools/builtin/diff.js +477 -0
- package/dist/main/core/tools/builtin/diff.js.map +1 -0
- package/dist/main/core/tools/builtin/listFiles.js +5 -43
- package/dist/main/core/tools/builtin/listFiles.js.map +1 -1
- package/dist/main/core/tools/builtin/search.js +120 -28
- package/dist/main/core/tools/builtin/search.js.map +1 -1
- package/package.json +10 -2
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
// @ts-nocheck — pre-existing strict-mode type narrowing issues carried over
|
|
2
|
+
// from app.tsx. Runtime is correct; tighten signatures in a follow-up.
|
|
3
|
+
import { useState, useRef, useCallback } from 'react';
|
|
4
|
+
import { AgentHarness } from '@zelari/core/harness';
|
|
5
|
+
import { getMetricsLogger } from '../metrics.js';
|
|
6
|
+
import { openaiCompatibleProvider, providerFromEnv, providerConfigFor } from '../provider/openai-compatible.js';
|
|
7
|
+
import { providerFailover } from '../providerFailover.js';
|
|
8
|
+
import { resolveFailoverStream } from '../crossProviderFailover.js';
|
|
9
|
+
import { PROVIDERS } from '../keyStore.js';
|
|
10
|
+
import { createBuiltinToolRegistry } from '../toolRegistry.js';
|
|
11
|
+
import { appendOrExtendStreamingAssistant, appendSystem, appendToolStart, finalizeStreamingAssistant, updateToolMessageEnd, } from './messageHelpers.js';
|
|
12
|
+
import { computeSessionStatsDelta } from './chatStats.js';
|
|
13
|
+
export function useChatTurn(params) {
|
|
14
|
+
const { sessionId, writerRef, setMessages, commitStreaming, flushStreaming, setBusy, setSessionActive, setSessionStats } = params;
|
|
15
|
+
const harnessRef = useRef(null);
|
|
16
|
+
const [queueCount, setQueueCount] = useState(0);
|
|
17
|
+
const dispatchPrompt = useCallback(async (userText) => {
|
|
18
|
+
// v0.4.3 audit fix: provider resolution + harness construction now
|
|
19
|
+
// live INSIDE the try block. Previously, throws from providerFromEnv,
|
|
20
|
+
// resolveFailoverStream, or createBuiltinToolRegistry happened
|
|
21
|
+
// BEFORE the try (which only wrapped the stream loop), so the
|
|
22
|
+
// rejected promise escaped unhandled (useSlashDispatch doesn't
|
|
23
|
+
// try/catch its await either). The user saw a hang with no
|
|
24
|
+
// feedback instead of an actionable error message.
|
|
25
|
+
let envConfig;
|
|
26
|
+
let harness;
|
|
27
|
+
try {
|
|
28
|
+
envConfig = await providerFromEnv();
|
|
29
|
+
if (!envConfig) {
|
|
30
|
+
appendSystem(setMessages, 'OPENAI_API_KEY not set. Export it before running zelari-code.');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
setBusy(true);
|
|
34
|
+
const { registry: toolRegistry } = createBuiltinToolRegistry();
|
|
35
|
+
const baseProviderStream = openaiCompatibleProvider(envConfig);
|
|
36
|
+
const failoverResolution = await resolveFailoverStream({
|
|
37
|
+
failoverEnabled: process.env.ANATHEMA_FAILOVER !== '0',
|
|
38
|
+
envValue: process.env.ANATHEMA_FAILOVER_PROVIDER,
|
|
39
|
+
primaryProviderId: envConfig.providerId,
|
|
40
|
+
primary: baseProviderStream,
|
|
41
|
+
validProviderIds: PROVIDERS.map((p) => p.id),
|
|
42
|
+
lookupFallbackConfig: async (id) => providerConfigFor(id),
|
|
43
|
+
buildStream: (config) => openaiCompatibleProvider(config),
|
|
44
|
+
});
|
|
45
|
+
if (failoverResolution.warning) {
|
|
46
|
+
// Surface in the chat instead of console.warn: writes that bypass
|
|
47
|
+
// Ink force a full repaint of the TUI frame (visible flicker).
|
|
48
|
+
appendSystem(setMessages, `[failover] ${failoverResolution.warning}`);
|
|
49
|
+
}
|
|
50
|
+
const providerStream = failoverResolution.fallbackLabel
|
|
51
|
+
? providerFailover({
|
|
52
|
+
primary: baseProviderStream,
|
|
53
|
+
fallback: failoverResolution.fallback,
|
|
54
|
+
fallbackLabel: failoverResolution.fallbackLabel,
|
|
55
|
+
})
|
|
56
|
+
: providerFailover({
|
|
57
|
+
primary: baseProviderStream,
|
|
58
|
+
fallback: failoverResolution.fallback,
|
|
59
|
+
});
|
|
60
|
+
const cwd = process.cwd();
|
|
61
|
+
const toolList = toolRegistry.toOpenAITools().map((t) => `- ${t.function.name}: ${t.function.description}`).join('\n');
|
|
62
|
+
const systemPrompt = [
|
|
63
|
+
"You are Zelari Code, an interactive AI coding agent operating directly in the user's terminal.",
|
|
64
|
+
'',
|
|
65
|
+
'You ARE connected to this machine and have real tools to read, modify, and explore the codebase.',
|
|
66
|
+
"Never claim you lack filesystem or shell access — you have it. Use your tools instead of asking the user to paste file contents.",
|
|
67
|
+
'',
|
|
68
|
+
'# Working Directory',
|
|
69
|
+
`You are running in: ${cwd}`,
|
|
70
|
+
'All relative file paths are resolved against this directory. Always work with real files here.',
|
|
71
|
+
'',
|
|
72
|
+
'# Available Tools',
|
|
73
|
+
'You can call these tools. Use them to take action and gather information autonomously:',
|
|
74
|
+
toolList,
|
|
75
|
+
'',
|
|
76
|
+
'# Guidelines',
|
|
77
|
+
'- When the user asks you to write code, debug, or explore, be proactive: list files (bash: ls, list_files) and read key files (read_file) to understand the project instead of asking the user to paste file contents.',
|
|
78
|
+
"- Only invoke tools when they are necessary to answer the user's prompt. If the user is just saying hello or greeting them (e.g., \"ciao\", \"hello\"), simply greet them back and ask how you can help, without running any commands or tools.",
|
|
79
|
+
'- When you finish a task, briefly summarize what you did.',
|
|
80
|
+
].join('\n');
|
|
81
|
+
const harness = new AgentHarness({
|
|
82
|
+
model: envConfig.model,
|
|
83
|
+
provider: 'openai-compatible',
|
|
84
|
+
messages: [
|
|
85
|
+
{ role: 'system', content: systemPrompt },
|
|
86
|
+
{ role: 'user', content: userText },
|
|
87
|
+
],
|
|
88
|
+
tools: toolRegistry.toOpenAITools().map((t) => ({
|
|
89
|
+
name: t.function.name,
|
|
90
|
+
description: t.function.description,
|
|
91
|
+
parameters: t.function.parameters,
|
|
92
|
+
})),
|
|
93
|
+
toolRegistry,
|
|
94
|
+
providerStream,
|
|
95
|
+
cwd,
|
|
96
|
+
});
|
|
97
|
+
harnessRef.current = harness;
|
|
98
|
+
setQueueCount(harness.queueLength);
|
|
99
|
+
// Total assistant output across the whole turn — feeds the token/cost
|
|
100
|
+
// estimate fallback in computeSessionStatsDelta.
|
|
101
|
+
let assistantContent = '';
|
|
102
|
+
// Display buffer for the CURRENT streamed message only. Reset on every
|
|
103
|
+
// message_end: without this, the post-tool-call message re-rendered the
|
|
104
|
+
// full accumulated turn text, duplicating everything said before the
|
|
105
|
+
// tool ran.
|
|
106
|
+
let streamContent = '';
|
|
107
|
+
// tool_execution_end doesn't carry toolName — remember it from the
|
|
108
|
+
// matching start event (keyed by toolCallId) for metrics.
|
|
109
|
+
const toolNameById = new Map();
|
|
110
|
+
const metrics = getMetricsLogger();
|
|
111
|
+
let realUsage = null;
|
|
112
|
+
try {
|
|
113
|
+
for await (const event of harness.run()) {
|
|
114
|
+
if (event.type === 'message_end') {
|
|
115
|
+
if (event.usage)
|
|
116
|
+
realUsage = event.usage;
|
|
117
|
+
// Message boundary: drain buffered deltas, then seal the streamed
|
|
118
|
+
// bubble so the next message starts fresh instead of merging.
|
|
119
|
+
flushStreaming();
|
|
120
|
+
finalizeStreamingAssistant(setMessages);
|
|
121
|
+
streamContent = '';
|
|
122
|
+
}
|
|
123
|
+
if (event.type === 'queue_update') {
|
|
124
|
+
setQueueCount(harness.queueLength);
|
|
125
|
+
}
|
|
126
|
+
if (writerRef.current) {
|
|
127
|
+
await writerRef.current.append(event);
|
|
128
|
+
}
|
|
129
|
+
if (event.type === 'agent_end') {
|
|
130
|
+
metrics.record({
|
|
131
|
+
kind: 'run',
|
|
132
|
+
sessionId,
|
|
133
|
+
provider: envConfig.providerId,
|
|
134
|
+
model: envConfig.model,
|
|
135
|
+
latencyMs: event.durationMs,
|
|
136
|
+
ok: event.reason === 'stop',
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
else if (event.type === 'error') {
|
|
140
|
+
metrics.record({
|
|
141
|
+
kind: 'error',
|
|
142
|
+
sessionId,
|
|
143
|
+
provider: envConfig.providerId,
|
|
144
|
+
model: envConfig.model,
|
|
145
|
+
error: event.message,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
else if (event.type === 'tool_execution_end') {
|
|
149
|
+
metrics.record({
|
|
150
|
+
kind: 'tool',
|
|
151
|
+
sessionId,
|
|
152
|
+
provider: envConfig.providerId,
|
|
153
|
+
model: envConfig.model,
|
|
154
|
+
toolName: toolNameById.get(event.toolCallId) ?? 'unknown',
|
|
155
|
+
toolCallId: event.toolCallId,
|
|
156
|
+
durationMs: event.durationMs,
|
|
157
|
+
ok: !event.isError,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (event.type === 'message_delta') {
|
|
161
|
+
assistantContent += event.delta;
|
|
162
|
+
streamContent += event.delta;
|
|
163
|
+
// Route through the throttled setter so per-token deltas (50-200/sec)
|
|
164
|
+
// coalesce into ≤60 renders/sec instead of flickering the TUI.
|
|
165
|
+
// v0.5.0: forward the council member identity when present so
|
|
166
|
+
// the UI can render `🜂 Caronte: …` headers.
|
|
167
|
+
appendOrExtendStreamingAssistant(commitStreaming, streamContent, Date.now(), {
|
|
168
|
+
...(event.memberId ? { memberId: event.memberId } : {}),
|
|
169
|
+
...(event.memberName ? { memberName: event.memberName } : {}),
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
else if (event.type === 'error') {
|
|
173
|
+
flushStreaming();
|
|
174
|
+
appendSystem(setMessages, `[error] ${event.message}`, Date.now());
|
|
175
|
+
}
|
|
176
|
+
else if (event.type === 'tool_execution_start') {
|
|
177
|
+
toolNameById.set(event.toolCallId, event.toolName);
|
|
178
|
+
// Drain buffered deltas FIRST so the text streamed before the
|
|
179
|
+
// call renders above the tool line, not below it — then seal
|
|
180
|
+
// that bubble: it's complete once the model starts calling tools.
|
|
181
|
+
flushStreaming();
|
|
182
|
+
finalizeStreamingAssistant(setMessages);
|
|
183
|
+
appendToolStart(setMessages, event.toolName, event.toolCallId, event.args, event.ts);
|
|
184
|
+
}
|
|
185
|
+
else if (event.type === 'tool_execution_end') {
|
|
186
|
+
updateToolMessageEnd(setMessages, event.toolCallId, event.isError, event.durationMs, event.result);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
// Drain any buffered streaming deltas so the final assistant message
|
|
192
|
+
// is committed before busy flips to false (and the input re-enables).
|
|
193
|
+
flushStreaming();
|
|
194
|
+
finalizeStreamingAssistant(setMessages);
|
|
195
|
+
harnessRef.current = null;
|
|
196
|
+
setQueueCount(0);
|
|
197
|
+
setBusy(false);
|
|
198
|
+
setSessionStats((prev) => computeSessionStatsDelta(realUsage, userText, assistantContent, envConfig.model, prev));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
// v0.4.3 audit fix: catches throws from providerFromEnv /
|
|
203
|
+
// resolveFailoverStream / AgentHarness construction that were
|
|
204
|
+
// previously escaping the function unhandled. Surfaces the error
|
|
205
|
+
// to the chat instead of hanging silently.
|
|
206
|
+
// Flush first so any partial assistant content streamed before the
|
|
207
|
+
// throw is committed before the error message renders.
|
|
208
|
+
flushStreaming();
|
|
209
|
+
appendSystem(setMessages, `[dispatch error] ${err instanceof Error ? err.message : String(err)}`);
|
|
210
|
+
setBusy(false);
|
|
211
|
+
}
|
|
212
|
+
}, [sessionId, writerRef, setMessages, commitStreaming, flushStreaming, setBusy, setSessionActive, setSessionStats]);
|
|
213
|
+
const dispatchCouncilPrompt = useCallback(async (text) => {
|
|
214
|
+
await dispatchCouncilPromptImpl(text, {
|
|
215
|
+
sessionId,
|
|
216
|
+
writerRef,
|
|
217
|
+
setMessages,
|
|
218
|
+
commitStreaming,
|
|
219
|
+
flushStreaming,
|
|
220
|
+
setBusy,
|
|
221
|
+
setQueueCount,
|
|
222
|
+
});
|
|
223
|
+
}, [sessionId, writerRef, setMessages, commitStreaming, flushStreaming, setBusy, setQueueCount]);
|
|
224
|
+
return { dispatchPrompt, dispatchCouncilPrompt, harnessRef, queueCount, setQueueCount };
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* dispatchCouncilPrompt — multi-agent council dispatch.
|
|
228
|
+
*
|
|
229
|
+
* Surfaces tool_execution_start/end as 'tool' role messages so ChatStream
|
|
230
|
+
* renders CollapsibleToolOutput. Runs AGENTS.MD auto-maintenance after the
|
|
231
|
+
* council finishes (controlled by ZELARI_AGENTS_MD env var).
|
|
232
|
+
*
|
|
233
|
+
* Implementation lives outside the hook closure so it doesn't depend on the
|
|
234
|
+
* hook's identity for memoization. Callers receive a stable callback via the
|
|
235
|
+
* useChatTurn wrapper.
|
|
236
|
+
*/
|
|
237
|
+
async function dispatchCouncilPromptImpl(text, deps) {
|
|
238
|
+
const { sessionId, writerRef, setMessages, commitStreaming, flushStreaming, setBusy } = deps;
|
|
239
|
+
const envConfig = await providerFromEnv();
|
|
240
|
+
if (!envConfig) {
|
|
241
|
+
appendSystem(setMessages, 'OPENAI_API_KEY not set. Export it before invoking /council.');
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
setBusy(true);
|
|
245
|
+
// Import dynamically to avoid a circular dep at module-load time.
|
|
246
|
+
const { dispatchCouncil } = await import('../councilDispatcher.js');
|
|
247
|
+
const { createWorkspaceContext, createWorkspaceStubs } = await import('../workspace/stubs.js');
|
|
248
|
+
const { createWorkspaceToolRegistry } = await import('../workspace/toolRegistry.js');
|
|
249
|
+
const { setWorkspaceStubs } = await import('@zelari/core/skills');
|
|
250
|
+
const { runPostCouncilHook } = await import('../workspace/postCouncilHook.js');
|
|
251
|
+
const { FeedbackStore } = await import('../councilFeedback.js');
|
|
252
|
+
const { registry: councilToolRegistry } = createBuiltinToolRegistry();
|
|
253
|
+
const workspaceCtx = createWorkspaceContext();
|
|
254
|
+
const workspaceReg = createWorkspaceToolRegistry(workspaceCtx);
|
|
255
|
+
for (const name of workspaceReg.list()) {
|
|
256
|
+
const td = workspaceReg.get(name);
|
|
257
|
+
if (td)
|
|
258
|
+
councilToolRegistry.register(td);
|
|
259
|
+
}
|
|
260
|
+
setWorkspaceStubs(createWorkspaceStubs(workspaceCtx));
|
|
261
|
+
const councilFeedbackStore = new FeedbackStore();
|
|
262
|
+
try {
|
|
263
|
+
for await (const event of dispatchCouncil(text, {
|
|
264
|
+
apiKey: envConfig.apiKey,
|
|
265
|
+
model: envConfig.model,
|
|
266
|
+
provider: 'openai-compatible',
|
|
267
|
+
providerStream: openaiCompatibleProvider(envConfig),
|
|
268
|
+
sessionId,
|
|
269
|
+
tools: councilToolRegistry,
|
|
270
|
+
feedbackStore: councilFeedbackStore,
|
|
271
|
+
})) {
|
|
272
|
+
if (writerRef.current) {
|
|
273
|
+
await writerRef.current.append(event);
|
|
274
|
+
}
|
|
275
|
+
if (event.type === 'message_delta') {
|
|
276
|
+
// Coalesce streaming assistant content through the throttled setter so
|
|
277
|
+
// per-token deltas don't flicker the TUI (same as dispatchPrompt).
|
|
278
|
+
// v0.5.0: forward the council member identity when present so
|
|
279
|
+
// the UI can render `🜂 Caronte: …` headers above the streamed
|
|
280
|
+
// text. Extend the trailing streaming bubble only when it belongs
|
|
281
|
+
// to the SAME member — otherwise one specialist's text would be
|
|
282
|
+
// appended to (and attributed to) the previous one.
|
|
283
|
+
commitStreaming((prev) => {
|
|
284
|
+
const last = prev[prev.length - 1];
|
|
285
|
+
if (last &&
|
|
286
|
+
last.role === 'assistant' &&
|
|
287
|
+
last.id.startsWith('streaming-') &&
|
|
288
|
+
(last.memberId ?? null) === (event.memberId ?? null)) {
|
|
289
|
+
return [...prev.slice(0, -1), { ...last, content: last.content + event.delta }];
|
|
290
|
+
}
|
|
291
|
+
return [
|
|
292
|
+
...prev,
|
|
293
|
+
{
|
|
294
|
+
id: `streaming-${crypto.randomUUID()}`,
|
|
295
|
+
role: 'assistant',
|
|
296
|
+
content: event.delta,
|
|
297
|
+
ts: event.ts,
|
|
298
|
+
...(event.memberId ? { memberId: event.memberId } : {}),
|
|
299
|
+
...(event.memberName ? { memberName: event.memberName } : {}),
|
|
300
|
+
},
|
|
301
|
+
];
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
else if (event.type === 'message_end') {
|
|
305
|
+
// Member/turn boundary: drain buffered deltas and seal the bubble so
|
|
306
|
+
// the next streamed message starts fresh.
|
|
307
|
+
flushStreaming();
|
|
308
|
+
finalizeStreamingAssistant(setMessages);
|
|
309
|
+
}
|
|
310
|
+
else if (event.type === 'tool_execution_start') {
|
|
311
|
+
// Single 'tool' role message per invocation (CollapsibleToolOutput);
|
|
312
|
+
// the previous extra `▶ name(args)` system line duplicated it.
|
|
313
|
+
// Drain buffered deltas first so ordering matches reality, and seal
|
|
314
|
+
// the pre-tool bubble (complete once the member starts calling tools).
|
|
315
|
+
flushStreaming();
|
|
316
|
+
finalizeStreamingAssistant(setMessages);
|
|
317
|
+
appendToolStart(setMessages, event.toolName, event.toolCallId, event.args, event.ts);
|
|
318
|
+
}
|
|
319
|
+
else if (event.type === 'tool_execution_end') {
|
|
320
|
+
updateToolMessageEnd(setMessages, event.toolCallId, event.isError, event.durationMs, event.result);
|
|
321
|
+
}
|
|
322
|
+
else if (event.type === 'error') {
|
|
323
|
+
flushStreaming();
|
|
324
|
+
appendSystem(setMessages, `[error] ${event.message}`, event.ts);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
catch (err) {
|
|
329
|
+
// Flush any partial streamed content before the error message renders.
|
|
330
|
+
flushStreaming();
|
|
331
|
+
appendSystem(setMessages, `[council error] ${err instanceof Error ? err.message : String(err)}`, Date.now());
|
|
332
|
+
}
|
|
333
|
+
finally {
|
|
334
|
+
// Drain any buffered streaming deltas before status messages / busy flip,
|
|
335
|
+
// so the final council output is committed to the chat.
|
|
336
|
+
flushStreaming();
|
|
337
|
+
finalizeStreamingAssistant(setMessages);
|
|
338
|
+
try {
|
|
339
|
+
const hook = await runPostCouncilHook(workspaceCtx);
|
|
340
|
+
if (hook.ran && hook.changed) {
|
|
341
|
+
appendSystem(setMessages, `[agents.md] updated: ${hook.sections.length} section(s) changed (${hook.sections.join(', ')})`, Date.now());
|
|
342
|
+
}
|
|
343
|
+
else if (hook.ran && hook.reason) {
|
|
344
|
+
if (!hook.reason.includes('disabled')) {
|
|
345
|
+
appendSystem(setMessages, `[agents.md] ${hook.reason}`, Date.now());
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
catch {
|
|
350
|
+
// Best-effort — never block on AGENTS.MD errors.
|
|
351
|
+
}
|
|
352
|
+
setBusy(false);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Public wrapper that captures the dispatchCouncilPromptImpl dependencies
|
|
357
|
+
* from the useChatTurn closure. Returns a stable callback the App can wire
|
|
358
|
+
* into the InputBar onSubmit.
|
|
359
|
+
*/
|
|
360
|
+
export function makeCouncilDispatch(deps) {
|
|
361
|
+
return (text) => dispatchCouncilPromptImpl(text, deps);
|
|
362
|
+
}
|
|
363
|
+
//# sourceMappingURL=useChatTurn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useChatTurn.js","sourceRoot":"","sources":["../../../src/cli/hooks/useChatTurn.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// @ts-nocheck — pre-existing strict-mode type narrowing issues carried over
|
|
2
|
+
// from app.tsx. Runtime is correct; tighten signatures in a follow-up.
|
|
3
|
+
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
4
|
+
import { getCurrentSessionId, setCurrentSessionId, clearCurrentSessionId, newSessionId, ensureSessionDir, listSessions, loadSessionEvents, } from '../sessionManager.js';
|
|
5
|
+
import { SessionJsonlWriter } from '@zelari/core/harness';
|
|
6
|
+
import { eventsToMessages } from './eventsToMessages.js';
|
|
7
|
+
import { useBatchedMessages } from './useBatchedMessages.js';
|
|
8
|
+
export function useSession() {
|
|
9
|
+
const [sessionId, setSessionId] = useState('');
|
|
10
|
+
const [messages, setMessages] = useState([]);
|
|
11
|
+
const [sessionActive, setSessionActive] = useState(false);
|
|
12
|
+
const writerRef = useRef(null);
|
|
13
|
+
// Throttle layer over `messages`/`setMessages`. `commitStreaming` coalesces
|
|
14
|
+
// the per-token streaming deltas (the LLM emits ~50-200/sec) into at most
|
|
15
|
+
// one render per ~16ms, which lets `React.memo(ChatStream)` finally take
|
|
16
|
+
// effect. `setMessages` is the passthrough — non-streaming calls (bootstrap
|
|
17
|
+
// restore, /new reset, system/error messages) apply instantly.
|
|
18
|
+
const { commit: commitStreaming, flush: flushStreaming } = useBatchedMessages(messages, setMessages);
|
|
19
|
+
// Bootstrap on mount: resume current session or create new one.
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
let cancelled = false;
|
|
22
|
+
(async () => {
|
|
23
|
+
await ensureSessionDir();
|
|
24
|
+
let id = getCurrentSessionId();
|
|
25
|
+
let restoredMessages = [];
|
|
26
|
+
if (id) {
|
|
27
|
+
try {
|
|
28
|
+
const events = await loadSessionEvents(id);
|
|
29
|
+
if (!cancelled) {
|
|
30
|
+
restoredMessages = eventsToMessages(events);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Corrupt session — fall through to create new.
|
|
35
|
+
id = null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (!id) {
|
|
39
|
+
id = newSessionId();
|
|
40
|
+
setCurrentSessionId(id);
|
|
41
|
+
}
|
|
42
|
+
if (cancelled)
|
|
43
|
+
return;
|
|
44
|
+
writerRef.current = new SessionJsonlWriter(id);
|
|
45
|
+
setSessionId(id);
|
|
46
|
+
setMessages(restoredMessages);
|
|
47
|
+
if (restoredMessages.length > 0) {
|
|
48
|
+
setMessages((prev) => [
|
|
49
|
+
...prev,
|
|
50
|
+
{
|
|
51
|
+
id: crypto.randomUUID(),
|
|
52
|
+
role: 'system',
|
|
53
|
+
content: `[resume] loaded ${restoredMessages.length} messages from session ${id.slice(0, 8)}…`,
|
|
54
|
+
ts: Date.now(),
|
|
55
|
+
},
|
|
56
|
+
]);
|
|
57
|
+
setSessionActive(true);
|
|
58
|
+
}
|
|
59
|
+
})();
|
|
60
|
+
return () => {
|
|
61
|
+
cancelled = true;
|
|
62
|
+
// Fire-and-forget close on unmount.
|
|
63
|
+
void writerRef.current?.close();
|
|
64
|
+
};
|
|
65
|
+
}, []);
|
|
66
|
+
/**
|
|
67
|
+
* Dispatch /sessions, /resume <id>, /new commands.
|
|
68
|
+
* Returns the system message to surface in chat.
|
|
69
|
+
*/
|
|
70
|
+
const handleSessionKind = useCallback(async (kind, targetSessionId) => {
|
|
71
|
+
if (kind === 'session') {
|
|
72
|
+
try {
|
|
73
|
+
const sessions = await listSessions();
|
|
74
|
+
if (sessions.length === 0)
|
|
75
|
+
return '[sessions] no past sessions';
|
|
76
|
+
const lines = sessions.slice(0, 10).map((s) => {
|
|
77
|
+
const dt = new Date(s.mtimeMs).toISOString().replace('T', ' ').slice(0, 16);
|
|
78
|
+
return ` ${s.id.slice(0, 8)}… ${s.eventCount} events ${dt}`;
|
|
79
|
+
});
|
|
80
|
+
return `[sessions] showing ${Math.min(sessions.length, 10)} of ${sessions.length}:\n${lines.join('\n')}`;
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
return `[sessions] error: ${err instanceof Error ? err.message : String(err)}`;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (kind === 'resume' && targetSessionId) {
|
|
87
|
+
setCurrentSessionId(targetSessionId);
|
|
88
|
+
return `[resume] session ${targetSessionId.slice(0, 8)}… set as current — restart zelari-code to load it`;
|
|
89
|
+
}
|
|
90
|
+
if (kind === 'new') {
|
|
91
|
+
clearCurrentSessionId();
|
|
92
|
+
const id = newSessionId();
|
|
93
|
+
setCurrentSessionId(id);
|
|
94
|
+
writerRef.current?.close();
|
|
95
|
+
writerRef.current = new SessionJsonlWriter(id);
|
|
96
|
+
setSessionId(id);
|
|
97
|
+
setMessages([]);
|
|
98
|
+
setSessionActive(false);
|
|
99
|
+
return `[new] fresh session ${id.slice(0, 8)}… started`;
|
|
100
|
+
}
|
|
101
|
+
return `[${kind}] handled`;
|
|
102
|
+
}, []);
|
|
103
|
+
return {
|
|
104
|
+
sessionId,
|
|
105
|
+
setSessionId,
|
|
106
|
+
messages,
|
|
107
|
+
setMessages,
|
|
108
|
+
commitStreaming,
|
|
109
|
+
flushStreaming,
|
|
110
|
+
sessionActive,
|
|
111
|
+
setSessionActive,
|
|
112
|
+
writerRef,
|
|
113
|
+
handleSessionKind,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=useSession.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSession.js","sourceRoot":"","sources":["../../../src/cli/hooks/useSession.ts"],"names":[],"mappings":"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"}
|