zelari-code 0.4.3 → 0.7.5
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 +42 -0
- package/bin/zelari-code.js +1 -1
- 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 +50 -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 +23 -13
- 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 +2 -9
- package/dist/agents/tools.js.map +1 -1
- package/dist/cli/app.js +72 -33
- package/dist/cli/app.js.map +1 -1
- package/dist/cli/compaction.js.map +1 -1
- package/dist/cli/components/ChatStream.js +43 -82
- package/dist/cli/components/ChatStream.js.map +1 -1
- package/dist/cli/components/CollapsibleToolOutput.js +8 -21
- package/dist/cli/components/CollapsibleToolOutput.js.map +1 -1
- package/dist/cli/components/Header.js +6 -18
- package/dist/cli/components/Header.js.map +1 -1
- package/dist/cli/components/LiveRegion.js +54 -0
- package/dist/cli/components/LiveRegion.js.map +1 -0
- package/dist/cli/components/Sidebar.js +33 -31
- package/dist/cli/components/Sidebar.js.map +1 -1
- package/dist/cli/components/StatusBar.js +42 -0
- package/dist/cli/components/StatusBar.js.map +1 -0
- package/dist/cli/components/ToolOutput.js +68 -0
- package/dist/cli/components/ToolOutput.js.map +1 -0
- package/dist/cli/components/toolFormat.js +195 -0
- package/dist/cli/components/toolFormat.js.map +1 -0
- package/dist/cli/councilDispatcher.js +1 -1
- package/dist/cli/councilDispatcher.js.map +1 -1
- package/dist/cli/grokOAuth.js +93 -75
- package/dist/cli/grokOAuth.js.map +1 -1
- package/dist/cli/headless.js +137 -0
- package/dist/cli/headless.js.map +1 -0
- package/dist/cli/hooks/chatState.js +139 -0
- package/dist/cli/hooks/chatState.js.map +1 -0
- package/dist/cli/hooks/eventsToMessages.js +42 -11
- package/dist/cli/hooks/eventsToMessages.js.map +1 -1
- package/dist/cli/hooks/messageHelpers.js +72 -15
- package/dist/cli/hooks/messageHelpers.js.map +1 -1
- package/dist/cli/hooks/useBatchedMessages.js +71 -0
- package/dist/cli/hooks/useBatchedMessages.js.map +1 -0
- package/dist/cli/hooks/useChatTurn.js +453 -84
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/hooks/useSession.js +24 -3
- package/dist/cli/hooks/useSession.js.map +1 -1
- package/dist/cli/hooks/useSlashDispatch.js +13 -2
- package/dist/cli/hooks/useSlashDispatch.js.map +1 -1
- package/dist/cli/main.bundled.js +10607 -7889
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +120 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/mcp/mcpClient.js +152 -0
- package/dist/cli/mcp/mcpClient.js.map +1 -0
- package/dist/cli/mcp/mcpManager.js +139 -0
- package/dist/cli/mcp/mcpManager.js.map +1 -0
- package/dist/cli/provider/openai-compatible.js +9 -2
- package/dist/cli/provider/openai-compatible.js.map +1 -1
- package/dist/cli/refreshRegistry.js +9 -6
- package/dist/cli/refreshRegistry.js.map +1 -1
- package/dist/cli/runHeadless.js +160 -0
- package/dist/cli/runHeadless.js.map +1 -0
- package/dist/cli/sessionManager.js +1 -1
- package/dist/cli/sessionManager.js.map +1 -1
- package/dist/cli/skillSuggest.js +1 -1
- package/dist/cli/skillsMd.js +155 -0
- package/dist/cli/skillsMd.js.map +1 -0
- package/dist/cli/slashHandlers/branch.js +11 -2
- package/dist/cli/slashHandlers/branch.js.map +1 -1
- package/dist/cli/slashHandlers/git.js +0 -75
- package/dist/cli/slashHandlers/git.js.map +1 -1
- package/dist/cli/slashHandlers/promoteMember.js +25 -0
- package/dist/cli/slashHandlers/promoteMember.js.map +1 -0
- package/dist/cli/slashHandlers/skills.js +16 -0
- package/dist/cli/slashHandlers/skills.js.map +1 -1
- 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/toolRegistry.js +37 -6
- package/dist/cli/toolRegistry.js.map +1 -1
- 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/paths.js +20 -13
- package/dist/cli/workspace/paths.js.map +1 -1
- package/dist/cli/workspace/storage.js +7 -3
- package/dist/cli/workspace/storage.js.map +1 -1
- package/dist/cli/workspace/stubs.js +122 -44
- package/dist/cli/workspace/stubs.js.map +1 -1
- package/dist/cli/workspace/toolRegistry.js +2 -2
- package/dist/cli/workspace/toolRegistry.js.map +1 -1
- package/dist/cli/workspace/workspaceSummary.js +255 -0
- package/dist/cli/workspace/workspaceSummary.js.map +1 -0
- package/dist/main/core/AgentHarness.js +36 -7
- package/dist/main/core/AgentHarness.js.map +1 -1
- package/dist/main/core/tools/builtin/listFiles.js +43 -5
- package/dist/main/core/tools/builtin/listFiles.js.map +1 -1
- package/dist/main/core/tools/builtin/search.js +28 -120
- package/dist/main/core/tools/builtin/search.js.map +1 -1
- package/package.json +6 -1
- package/dist/cli/oauthCallbackServer.js +0 -207
- package/dist/cli/oauthCallbackServer.js.map +0 -1
- package/dist/main/core/tools/builtin/_walk.js +0 -129
- package/dist/main/core/tools/builtin/_walk.js.map +0 -1
- package/dist/main/core/tools/builtin/diff.js +0 -477
- package/dist/main/core/tools/builtin/diff.js.map +0 -1
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* headless — non-interactive CLI mode for CI/CD and scripting.
|
|
3
|
+
*
|
|
4
|
+
* Bypasses Ink entirely. Reads `--task <prompt>`, runs the prompt
|
|
5
|
+
* through the same dispatch path the TUI uses, and serializes the
|
|
6
|
+
* resulting events as one JSON object per line (NDJSON) on stdout.
|
|
7
|
+
*
|
|
8
|
+
* Exit codes:
|
|
9
|
+
* 0 — task completed successfully (last `agent_end.reason === 'completed'`)
|
|
10
|
+
* 1 — user error (missing task, missing API key, invalid flag)
|
|
11
|
+
* 2 — runtime error (provider failure, council exception)
|
|
12
|
+
* 3 — task errored (the agent run itself emitted `agent_end.reason === 'error'`)
|
|
13
|
+
*
|
|
14
|
+
* @public
|
|
15
|
+
* @since 0.5.0
|
|
16
|
+
*/
|
|
17
|
+
import { PROVIDERS, resolveApiKeyWithMeta } from './keyStore.js';
|
|
18
|
+
import { getActiveProvider, getModelForProvider } from './providerConfig.js';
|
|
19
|
+
import { openaiCompatibleProvider } from './provider/openai-compatible.js';
|
|
20
|
+
const HELP_TEXT = `zelari-code --headless --task <prompt> [--output json|plain] [--council] [--provider <id>] [--model <name>]
|
|
21
|
+
|
|
22
|
+
Non-interactive mode. Streams BrainEvents as NDJSON to stdout (one JSON
|
|
23
|
+
object per line) or as plain text (just the assistant message text).
|
|
24
|
+
|
|
25
|
+
Exit codes:
|
|
26
|
+
0 completed
|
|
27
|
+
1 user error (bad flags, missing API key, ...)
|
|
28
|
+
2 runtime error (provider failure, council exception)
|
|
29
|
+
3 agent run errored
|
|
30
|
+
`;
|
|
31
|
+
/**
|
|
32
|
+
* Parse argv for --headless options. Returns null options when
|
|
33
|
+
* --headless is not present (caller should fall through to TUI mode).
|
|
34
|
+
*/
|
|
35
|
+
export function parseHeadlessFlags(argv) {
|
|
36
|
+
if (!argv.includes('--headless')) {
|
|
37
|
+
return { options: null };
|
|
38
|
+
}
|
|
39
|
+
let task;
|
|
40
|
+
let output = 'json';
|
|
41
|
+
let useCouncil = false;
|
|
42
|
+
let provider;
|
|
43
|
+
let model;
|
|
44
|
+
for (let i = 0; i < argv.length; i++) {
|
|
45
|
+
const arg = argv[i];
|
|
46
|
+
if (arg === '--headless')
|
|
47
|
+
continue;
|
|
48
|
+
if (arg === '--output') {
|
|
49
|
+
const next = argv[i + 1];
|
|
50
|
+
if (next === 'json' || next === 'plain') {
|
|
51
|
+
output = next;
|
|
52
|
+
i++;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
return {
|
|
56
|
+
options: null,
|
|
57
|
+
error: `--output requires 'json' or 'plain', got '${next ?? '(missing)'}'`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else if (arg === '--task') {
|
|
62
|
+
task = argv[i + 1];
|
|
63
|
+
i++;
|
|
64
|
+
}
|
|
65
|
+
else if (arg === '--council') {
|
|
66
|
+
useCouncil = true;
|
|
67
|
+
}
|
|
68
|
+
else if (arg === '--provider') {
|
|
69
|
+
provider = argv[i + 1];
|
|
70
|
+
i++;
|
|
71
|
+
}
|
|
72
|
+
else if (arg === '--model') {
|
|
73
|
+
model = argv[i + 1];
|
|
74
|
+
i++;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (!task || task.trim().length === 0) {
|
|
78
|
+
return { options: null, error: '--headless requires --task <prompt>' };
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
options: { task, output, useCouncil, provider, model },
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Print the headless help text to stdout (caller prints to stderr for errors).
|
|
86
|
+
*/
|
|
87
|
+
export function printHeadlessHelp() {
|
|
88
|
+
// eslint-disable-next-line no-console
|
|
89
|
+
console.log(HELP_TEXT);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Resolve the API key for a provider; returns null with a reason
|
|
93
|
+
* when the key is missing. Used to fail fast with a clear error
|
|
94
|
+
* instead of failing mid-stream.
|
|
95
|
+
*/
|
|
96
|
+
export async function resolveHeadlessKey(providerId) {
|
|
97
|
+
const spec = PROVIDERS.find((p) => p.id === providerId);
|
|
98
|
+
if (!spec) {
|
|
99
|
+
return { error: `unknown provider: '${providerId}'` };
|
|
100
|
+
}
|
|
101
|
+
const resolved = await resolveApiKeyWithMeta(providerId);
|
|
102
|
+
if (!resolved || !resolved.apiKey) {
|
|
103
|
+
return {
|
|
104
|
+
error: `no API key for provider '${providerId}'.\n` +
|
|
105
|
+
`Set the env var ${spec.envVar} or save a key via /login.`,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// baseUrl lives in providerConfig (customEndpoints) not on StoredKey.
|
|
109
|
+
// Imported lazily to avoid a circular dep at module load.
|
|
110
|
+
const { getCustomEndpoint } = await import('./providerConfig.js');
|
|
111
|
+
const customBase = getCustomEndpoint(providerId);
|
|
112
|
+
return {
|
|
113
|
+
apiKey: resolved.apiKey,
|
|
114
|
+
...(customBase ? { baseUrl: customBase } : {}),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Determine the effective provider + model for a headless run.
|
|
119
|
+
* Prefers explicit --provider/--model flags, then the active
|
|
120
|
+
* provider from provider.json, then 'openai-compatible' as a
|
|
121
|
+
* last resort.
|
|
122
|
+
*/
|
|
123
|
+
export function resolveHeadlessProvider(opts) {
|
|
124
|
+
const provider = opts.provider ?? getActiveProvider().id;
|
|
125
|
+
const model = opts.model ?? getModelForProvider(provider);
|
|
126
|
+
return { provider, model };
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Emit one NDJSON line to stdout. Use process.stdout.write directly
|
|
130
|
+
* to avoid the console.log trailing newline (NDJSON convention is
|
|
131
|
+
* one JSON object per line, no extra whitespace).
|
|
132
|
+
*/
|
|
133
|
+
export function emitEvent(event) {
|
|
134
|
+
process.stdout.write(JSON.stringify(event) + '\n');
|
|
135
|
+
}
|
|
136
|
+
export { openaiCompatibleProvider };
|
|
137
|
+
//# sourceMappingURL=headless.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headless.js","sourceRoot":"","sources":["../../src/cli/headless.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAqB3E,MAAM,SAAS,GAAG;;;;;;;;;;CAUjB,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAuB;IACxD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,IAAI,IAAwB,CAAC;IAC7B,IAAI,MAAM,GAAqB,MAAM,CAAC;IACtC,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,QAA4B,CAAC;IACjC,IAAI,KAAyB,CAAC;IAE9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,YAAY;YAAE,SAAS;QACnC,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACzB,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACxC,MAAM,GAAG,IAAI,CAAC;gBACd,CAAC,EAAE,CAAC;YACN,CAAC;iBAAM,CAAC;gBACN,OAAO;oBACL,OAAO,EAAE,IAAI;oBACb,KAAK,EAAE,6CAA6C,IAAI,IAAI,WAAW,GAAG;iBAC3E,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACnB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YAC/B,UAAU,GAAG,IAAI,CAAC;QACpB,CAAC;aAAM,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YAChC,QAAQ,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACvB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7B,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACpB,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IAED,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,qCAAqC,EAAE,CAAC;IACzE,CAAC;IAED,OAAO;QACL,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE;KACvD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,UAAkB;IAGzD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC;IACxD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,KAAK,EAAE,sBAAsB,UAAU,GAAG,EAAE,CAAC;IACxD,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,UAAU,CAAC,CAAC;IACzD,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QAClC,OAAO;YACL,KAAK,EACH,4BAA4B,UAAU,MAAM;gBAC5C,mBAAmB,IAAI,CAAC,MAAM,4BAA4B;SAC7D,CAAC;IACJ,CAAC;IACD,sEAAsE;IACtE,0DAA0D;IAC1D,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;IAClE,MAAM,UAAU,GAAG,iBAAiB,CAAC,UAAmB,CAAC,CAAC;IAC1D,OAAO;QACL,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/C,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAqB;IAI3D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,iBAAiB,EAAE,CAAC,EAAE,CAAC;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,mBAAmB,CAAC,QAAiB,CAAC,CAAC;IACnE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;AACrD,CAAC;AAED,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { formatToolSummary } from '../components/toolFormat.js';
|
|
2
|
+
export const EMPTY_LIVE = { streaming: null, runningTools: [] };
|
|
3
|
+
/**
|
|
4
|
+
* Append a finalized message (system/user/sealed-assistant/completed-tool).
|
|
5
|
+
* Pure helper — callers pass the setter they want to target (the
|
|
6
|
+
* `finalized` setter in production, a plain array setter in tests).
|
|
7
|
+
*/
|
|
8
|
+
export function pushFinalized(setFinalized, message) {
|
|
9
|
+
setFinalized((prev) => [...prev, message]);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Update or start the streaming assistant bubble in `live`.
|
|
13
|
+
*
|
|
14
|
+
* - If `live.streaming` exists and (for council) belongs to the same member,
|
|
15
|
+
* replace its content with `fullContent` (the streaming caller always
|
|
16
|
+
* passes full accumulated content, not a delta).
|
|
17
|
+
* - Otherwise create a new streaming bubble stamped with the member context.
|
|
18
|
+
*
|
|
19
|
+
* `setLive` accepts a functional updater so the throttle layer
|
|
20
|
+
* (`useBatchedMessages`-style) can compose multiple updates without reading
|
|
21
|
+
* stale state.
|
|
22
|
+
*/
|
|
23
|
+
export function setStreaming(setLive, fullContent, ts, memberContext) {
|
|
24
|
+
setLive((prev) => {
|
|
25
|
+
const cur = prev.streaming;
|
|
26
|
+
if (cur &&
|
|
27
|
+
cur.role === 'assistant' &&
|
|
28
|
+
(cur.memberId ?? null) === (memberContext?.memberId ?? null)) {
|
|
29
|
+
return { ...prev, streaming: { ...cur, content: fullContent, ts } };
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
...prev,
|
|
33
|
+
streaming: {
|
|
34
|
+
id: `streaming-${crypto.randomUUID()}`,
|
|
35
|
+
role: 'assistant',
|
|
36
|
+
content: fullContent,
|
|
37
|
+
ts,
|
|
38
|
+
...(memberContext?.memberId ? { memberId: memberContext.memberId } : {}),
|
|
39
|
+
...(memberContext?.memberName ? { memberName: memberContext.memberName } : {}),
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Move `live.streaming` (if any) into `finalized`, sealing it. Drops the
|
|
46
|
+
* `streaming-` id prefix so the next bubble starts fresh. Idempotent: a no-op
|
|
47
|
+
* when nothing is streaming.
|
|
48
|
+
*
|
|
49
|
+
* This is the seal point fired on `message_end` and before a tool call: the
|
|
50
|
+
* bubble is complete and can be printed once into scrollback.
|
|
51
|
+
*/
|
|
52
|
+
export function finalizeStreaming(setFinalized, setLive) {
|
|
53
|
+
setLive((prev) => {
|
|
54
|
+
const cur = prev.streaming;
|
|
55
|
+
if (!cur || !cur.id.startsWith('streaming-'))
|
|
56
|
+
return prev;
|
|
57
|
+
const sealed = { ...cur, id: cur.id.slice('streaming-'.length) };
|
|
58
|
+
setFinalized((fin) => [...fin, sealed]);
|
|
59
|
+
return { ...prev, streaming: null };
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Max chars of tool result kept in memory for the printed body.
|
|
64
|
+
*
|
|
65
|
+
* v0.7.3: raised from 600 to 8000. The 600-char cut happened BEFORE
|
|
66
|
+
* formatToolResult could parse the JSON envelope — truncated JSON no longer
|
|
67
|
+
* parses, so every long bash/read_file result fell back to the raw escaped
|
|
68
|
+
* envelope (the ugly boxes in the 2026-07-02 live test). Display truncation
|
|
69
|
+
* is line-based in the formatter (ZELARI_TOOL_OUTPUT_LINES); this constant is
|
|
70
|
+
* only a memory bound.
|
|
71
|
+
*/
|
|
72
|
+
export const TOOL_RESULT_PREVIEW_CHARS = 8000;
|
|
73
|
+
/** Max chars of the JSON args preview shown on the tool summary line. */
|
|
74
|
+
export const TOOL_ARGS_PREVIEW_CHARS = 120;
|
|
75
|
+
/**
|
|
76
|
+
* Register a tool invocation in `live.runningTools`. The summary (args
|
|
77
|
+
* preview) is computed once; the result body is filled in by
|
|
78
|
+
* {@link completeTool} on `tool_execution_end`.
|
|
79
|
+
*/
|
|
80
|
+
export function startTool(setLive, toolName, toolCallId, args, ts) {
|
|
81
|
+
// v0.7.1 (B2): human-readable summary instead of raw-JSON args.
|
|
82
|
+
const argsPreview = formatToolSummary(toolName, args);
|
|
83
|
+
setLive((prev) => ({
|
|
84
|
+
...prev,
|
|
85
|
+
runningTools: [
|
|
86
|
+
...prev.runningTools,
|
|
87
|
+
{
|
|
88
|
+
id: crypto.randomUUID(),
|
|
89
|
+
role: 'tool',
|
|
90
|
+
content: argsPreview,
|
|
91
|
+
ts,
|
|
92
|
+
toolName,
|
|
93
|
+
toolCallId,
|
|
94
|
+
toolOk: undefined,
|
|
95
|
+
toolDurationMs: undefined,
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Mark a running tool as done and move it into `finalized`. Removes it from
|
|
102
|
+
* `live.runningTools` (by `toolCallId`) and appends the completed message —
|
|
103
|
+
* with its result body — to `finalized`.
|
|
104
|
+
*
|
|
105
|
+
* v0.7.3: the previous signature took a `live` snapshot (from `liveRef`) and
|
|
106
|
+
* removed by INDEX inside the functional updater. `liveRef` only updates on
|
|
107
|
+
* render, so for fast tools (start+end within one frame) the snapshot missed
|
|
108
|
+
* the just-started tool (end event dropped → tool stuck in the live region)
|
|
109
|
+
* or, with two ends in one frame, removed the WRONG element. The lookup now
|
|
110
|
+
* happens inside the `setLive` updater against the CURRENT state, keyed by
|
|
111
|
+
* toolCallId — same cross-setter pattern as {@link finalizeStreaming}.
|
|
112
|
+
*
|
|
113
|
+
* No-op if the toolCallId is unknown (defensive against duplicate end events).
|
|
114
|
+
*/
|
|
115
|
+
export function completeTool(setFinalized, setLive, toolCallId, isError, durationMs, result) {
|
|
116
|
+
setLive((prev) => {
|
|
117
|
+
const tool = prev.runningTools.find((t) => t.toolCallId === toolCallId && t.toolDurationMs === undefined);
|
|
118
|
+
if (!tool)
|
|
119
|
+
return prev;
|
|
120
|
+
const completed = {
|
|
121
|
+
...tool,
|
|
122
|
+
toolOk: !isError,
|
|
123
|
+
toolDurationMs: durationMs,
|
|
124
|
+
...(result !== undefined
|
|
125
|
+
? {
|
|
126
|
+
toolResult: result.length > TOOL_RESULT_PREVIEW_CHARS
|
|
127
|
+
? `${result.slice(0, TOOL_RESULT_PREVIEW_CHARS)}…`
|
|
128
|
+
: result,
|
|
129
|
+
}
|
|
130
|
+
: {}),
|
|
131
|
+
};
|
|
132
|
+
setFinalized((fin) => [...fin, completed]);
|
|
133
|
+
return {
|
|
134
|
+
...prev,
|
|
135
|
+
runningTools: prev.runningTools.filter((t) => t !== tool),
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=chatState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chatState.js","sourceRoot":"","sources":["../../../src/cli/hooks/chatState.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,29 +26,60 @@ export function eventsToMessages(events) {
|
|
|
26
26
|
out.push({ id: assistantId, role: 'assistant', content: assistantBuffer, ts: e.ts });
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
else if (e.type === 'message_end') {
|
|
30
|
+
// Message boundary: the next streamed message gets its own bubble,
|
|
31
|
+
// matching the live UI (which finalizes on message_end).
|
|
32
|
+
assistantBuffer = '';
|
|
33
|
+
assistantId = '';
|
|
34
|
+
}
|
|
29
35
|
else if (e.type === 'tool_execution_start') {
|
|
30
36
|
// v0.4.3 audit fix: the v3-W event schema renamed `tool_call` →
|
|
31
37
|
// `tool_execution_start` and added the `args` field. The old branches
|
|
32
38
|
// here silently dropped every tool invocation during session resume.
|
|
39
|
+
// v0.6.2: restored as a `role: 'tool'` message so the resumed
|
|
40
|
+
// transcript renders the tool box, same as the live UI.
|
|
33
41
|
assistantBuffer = '';
|
|
34
42
|
assistantId = '';
|
|
35
|
-
const argsPreview = JSON.stringify(e.args)
|
|
43
|
+
const argsPreview = JSON.stringify(e.args)?.slice(0, 120) ?? '';
|
|
36
44
|
out.push({
|
|
37
45
|
id: crypto.randomUUID(),
|
|
38
|
-
role: '
|
|
39
|
-
content:
|
|
46
|
+
role: 'tool',
|
|
47
|
+
content: argsPreview,
|
|
40
48
|
ts: e.ts,
|
|
49
|
+
toolName: e.toolName,
|
|
50
|
+
toolCallId: e.toolCallId,
|
|
41
51
|
});
|
|
42
52
|
}
|
|
43
53
|
else if (e.type === 'tool_execution_end') {
|
|
44
|
-
// v0.
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
54
|
+
// v0.6.2: update the matching start message in place (the event does
|
|
55
|
+
// NOT carry toolName — the old code rendered "[tool_result] undefined").
|
|
56
|
+
const end = e;
|
|
57
|
+
let matched = false;
|
|
58
|
+
for (let i = out.length - 1; i >= 0; i--) {
|
|
59
|
+
const m = out[i];
|
|
60
|
+
if (m.role === 'tool' && m.toolCallId === end.toolCallId && m.toolDurationMs === undefined) {
|
|
61
|
+
// v0.6.2 audit LOW-5: append `…` on truncation to match the
|
|
62
|
+
// live path (messageHelpers.appendToolEnd behavior).
|
|
63
|
+
const raw = typeof end.result === 'string' ? end.result : '';
|
|
64
|
+
const truncated = raw.length > 600 ? `${raw.slice(0, 600)}…` : raw;
|
|
65
|
+
out[i] = {
|
|
66
|
+
...m,
|
|
67
|
+
toolOk: !end.isError,
|
|
68
|
+
toolDurationMs: end.durationMs,
|
|
69
|
+
...(raw.length > 0 ? { toolResult: truncated } : {}),
|
|
70
|
+
};
|
|
71
|
+
matched = true;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (!matched) {
|
|
76
|
+
out.push({
|
|
77
|
+
id: crypto.randomUUID(),
|
|
78
|
+
role: 'system',
|
|
79
|
+
content: `[tool_result] ${end.toolCallId} → ${end.isError ? 'error' : 'ok'}`,
|
|
80
|
+
ts: e.ts,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
52
83
|
}
|
|
53
84
|
else if (e.type === 'agent_start') {
|
|
54
85
|
out.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventsToMessages.js","sourceRoot":"","sources":["../../../src/cli/hooks/eventsToMessages.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAA6B;IAC5D,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,IAAI,eAAe,GAAG,EAAE,CAAC;IACzB,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YAC/B,IAAI,WAAW,KAAK,EAAE;gBAAE,WAAW,GAAG,WAAW,YAAY,EAAE,EAAE,CAAC;YAClE,eAAe,IAAI,CAAC,CAAC,KAAK,CAAC;YAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACjC,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,EAAE,KAAK,WAAW,EAAE,CAAC;gBACjE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;YAC9D,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvF,CAAC;QACH,CAAC;aAAM,IAAI,CAAC,CAAC,IAAI,KAAK,sBAAsB,EAAE,CAAC;YAC7C,gEAAgE;YAChE,sEAAsE;YACtE,qEAAqE;YACrE,eAAe,GAAG,EAAE,CAAC;YACrB,WAAW,GAAG,EAAE,CAAC;YACjB,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAE,CAAuB,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"eventsToMessages.js","sourceRoot":"","sources":["../../../src/cli/hooks/eventsToMessages.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { formatToolSummary } from '../components/toolFormat.js';
|
|
1
2
|
/**
|
|
2
3
|
* Helpers for building ChatMessage instances in the most common shapes.
|
|
3
4
|
*
|
|
@@ -29,8 +30,12 @@ export function appendUser(setMessages, content, ts = Date.now()) {
|
|
|
29
30
|
* Append or extend the streaming assistant message. If the last message is
|
|
30
31
|
* already a streaming assistant message, append `delta` to its content;
|
|
31
32
|
* otherwise create a new one with a stable streaming id.
|
|
33
|
+
*
|
|
34
|
+
* When `memberName` is set (council-sourced messages), it's stamped on
|
|
35
|
+
* the message so the visible-reasoning UI can render `🜂 Caronte: …`
|
|
36
|
+
* headers above the streamed text.
|
|
32
37
|
*/
|
|
33
|
-
export function appendOrExtendStreamingAssistant(setMessages, fullContent, ts) {
|
|
38
|
+
export function appendOrExtendStreamingAssistant(setMessages, fullContent, ts, memberContext) {
|
|
34
39
|
setMessages((prev) => {
|
|
35
40
|
const last = prev[prev.length - 1];
|
|
36
41
|
if (last && last.role === 'assistant' && last.id.startsWith('streaming-')) {
|
|
@@ -38,23 +43,54 @@ export function appendOrExtendStreamingAssistant(setMessages, fullContent, ts) {
|
|
|
38
43
|
}
|
|
39
44
|
return [
|
|
40
45
|
...prev,
|
|
41
|
-
{
|
|
46
|
+
{
|
|
47
|
+
id: `streaming-${crypto.randomUUID()}`,
|
|
48
|
+
role: 'assistant',
|
|
49
|
+
content: fullContent,
|
|
50
|
+
ts,
|
|
51
|
+
...(memberContext?.memberId ? { memberId: memberContext.memberId } : {}),
|
|
52
|
+
...(memberContext?.memberName ? { memberName: memberContext.memberName } : {}),
|
|
53
|
+
},
|
|
42
54
|
];
|
|
43
55
|
});
|
|
44
56
|
}
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Max chars of tool result kept for the body. v0.7.3: raised 600 → 8000 to
|
|
59
|
+
* match chatState.ts — the 600-char cut chopped the JSON envelope before
|
|
60
|
+
* formatToolResult could parse it, forcing the raw-escaped fallback.
|
|
61
|
+
*/
|
|
62
|
+
export const TOOL_RESULT_PREVIEW_CHARS = 8000;
|
|
63
|
+
/** Max chars of the JSON args preview shown on the tool summary line. */
|
|
64
|
+
export const TOOL_ARGS_PREVIEW_CHARS = 120;
|
|
65
|
+
/**
|
|
66
|
+
* Append a tool invocation as a `role: 'tool'` message so ChatStream renders
|
|
67
|
+
* it via the live region's tool rendering (one status line per invocation, updated in
|
|
68
|
+
* place by {@link updateToolMessageEnd}) instead of loose system lines.
|
|
69
|
+
*/
|
|
70
|
+
export function appendToolStart(setMessages, toolName, toolCallId, args, ts) {
|
|
71
|
+
// v0.7.1 (B2): human-readable summary instead of raw-JSON args (which cut
|
|
72
|
+
// mid-string like {"path":"…","content":"Scrivi una spiegazione estrema…").
|
|
73
|
+
const argsPreview = formatToolSummary(toolName, args);
|
|
74
|
+
setMessages((prev) => [
|
|
75
|
+
...prev,
|
|
76
|
+
{
|
|
77
|
+
id: crypto.randomUUID(),
|
|
78
|
+
role: 'tool',
|
|
79
|
+
content: argsPreview,
|
|
80
|
+
ts,
|
|
81
|
+
toolName,
|
|
82
|
+
toolCallId,
|
|
83
|
+
toolOk: undefined,
|
|
84
|
+
toolDurationMs: undefined,
|
|
85
|
+
},
|
|
86
|
+
]);
|
|
55
87
|
}
|
|
56
|
-
/**
|
|
57
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Update the matching `tool_execution_start` message with its end status.
|
|
90
|
+
* The summary (args preview) is kept; the result is stored separately as the
|
|
91
|
+
* expandable body. Failed invocations auto-expand in ChatStream.
|
|
92
|
+
*/
|
|
93
|
+
export function updateToolMessageEnd(setMessages, toolCallId, isError, durationMs, result) {
|
|
58
94
|
setMessages((prev) => {
|
|
59
95
|
for (let i = prev.length - 1; i >= 0; i--) {
|
|
60
96
|
const m = prev[i];
|
|
@@ -64,7 +100,13 @@ export function updateToolMessageEnd(setMessages, toolCallId, isError, durationM
|
|
|
64
100
|
...m,
|
|
65
101
|
toolOk: !isError,
|
|
66
102
|
toolDurationMs: durationMs,
|
|
67
|
-
|
|
103
|
+
...(result !== undefined
|
|
104
|
+
? {
|
|
105
|
+
toolResult: result.length > TOOL_RESULT_PREVIEW_CHARS
|
|
106
|
+
? `${result.slice(0, TOOL_RESULT_PREVIEW_CHARS)}…`
|
|
107
|
+
: result,
|
|
108
|
+
}
|
|
109
|
+
: {}),
|
|
68
110
|
};
|
|
69
111
|
return updated;
|
|
70
112
|
}
|
|
@@ -72,4 +114,19 @@ export function updateToolMessageEnd(setMessages, toolCallId, isError, durationM
|
|
|
72
114
|
return prev;
|
|
73
115
|
});
|
|
74
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Seal the trailing streaming assistant message (if any) by dropping its
|
|
119
|
+
* `streaming-` id prefix. Called on `message_end` so the NEXT assistant
|
|
120
|
+
* message in the same turn (e.g. after a tool call) starts a fresh bubble
|
|
121
|
+
* instead of being merged into — or duplicated over — the previous one.
|
|
122
|
+
*/
|
|
123
|
+
export function finalizeStreamingAssistant(setMessages) {
|
|
124
|
+
setMessages((prev) => {
|
|
125
|
+
const last = prev[prev.length - 1];
|
|
126
|
+
if (last && last.role === 'assistant' && last.id.startsWith('streaming-')) {
|
|
127
|
+
return [...prev.slice(0, -1), { ...last, id: last.id.slice('streaming-'.length) }];
|
|
128
|
+
}
|
|
129
|
+
return prev;
|
|
130
|
+
});
|
|
131
|
+
}
|
|
75
132
|
//# sourceMappingURL=messageHelpers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messageHelpers.js","sourceRoot":"","sources":["../../../src/cli/hooks/messageHelpers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"messageHelpers.js","sourceRoot":"","sources":["../../../src/cli/hooks/messageHelpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
export function useBatchedMessages(state, setState, cadenceMs = 16) {
|
|
3
|
+
// Composed pending updater, or `null` when nothing is buffered.
|
|
4
|
+
const pendingRef = useRef(null);
|
|
5
|
+
// Active throttle-window timer handle, or `null` when not throttling.
|
|
6
|
+
const timerRef = useRef(null);
|
|
7
|
+
/**
|
|
8
|
+
* Apply the current pending updater to state, ignoring/clearing the timer.
|
|
9
|
+
* Used as the synchronous public drain (stream end) and internally.
|
|
10
|
+
*/
|
|
11
|
+
const flush = useCallback(() => {
|
|
12
|
+
if (timerRef.current !== null) {
|
|
13
|
+
clearTimeout(timerRef.current);
|
|
14
|
+
timerRef.current = null;
|
|
15
|
+
}
|
|
16
|
+
const pending = pendingRef.current;
|
|
17
|
+
pendingRef.current = null;
|
|
18
|
+
if (pending !== null) {
|
|
19
|
+
setState(pending);
|
|
20
|
+
}
|
|
21
|
+
}, [setState]);
|
|
22
|
+
const commit = useCallback((update) => {
|
|
23
|
+
// Type guard: SetStateAction<S> = S | ((prev: S) => S). Because a generic
|
|
24
|
+
// S may itself be a function type, `typeof x === 'function'` doesn't
|
|
25
|
+
// narrow; resolve via a guarded call helper instead.
|
|
26
|
+
const apply = (action, prev) => typeof action === 'function' ? action(prev) : action;
|
|
27
|
+
// Compose this update onto any pending one, preserving arrival order.
|
|
28
|
+
const head = pendingRef.current;
|
|
29
|
+
pendingRef.current =
|
|
30
|
+
head === null
|
|
31
|
+
? update
|
|
32
|
+
: (s) => {
|
|
33
|
+
const intermediate = apply(head, s);
|
|
34
|
+
return apply(update, intermediate);
|
|
35
|
+
};
|
|
36
|
+
if (timerRef.current === null) {
|
|
37
|
+
// Leading edge: not currently throttling. Flush immediately so the
|
|
38
|
+
// first token renders with no latency, then open a throttle window.
|
|
39
|
+
const leading = pendingRef.current;
|
|
40
|
+
pendingRef.current = null;
|
|
41
|
+
if (leading !== null) {
|
|
42
|
+
setState(leading);
|
|
43
|
+
}
|
|
44
|
+
timerRef.current = setTimeout(() => {
|
|
45
|
+
timerRef.current = null;
|
|
46
|
+
// Trailing edge: flush anything that accumulated during the window
|
|
47
|
+
// as a single render. Do NOT re-arm — the next commit starts a new
|
|
48
|
+
// leading edge.
|
|
49
|
+
const tail = pendingRef.current;
|
|
50
|
+
pendingRef.current = null;
|
|
51
|
+
if (tail !== null) {
|
|
52
|
+
setState(tail);
|
|
53
|
+
}
|
|
54
|
+
}, cadenceMs);
|
|
55
|
+
}
|
|
56
|
+
// else: inside a throttle window — the trailing handler above will
|
|
57
|
+
// catch the buffered update when the window closes.
|
|
58
|
+
}, [cadenceMs, setState]);
|
|
59
|
+
// On unmount: cancel any pending timer. Do NOT flush — teardown means the
|
|
60
|
+
// display is going away, and persisted state lives in the JSONL writer.
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
return () => {
|
|
63
|
+
if (timerRef.current !== null) {
|
|
64
|
+
clearTimeout(timerRef.current);
|
|
65
|
+
timerRef.current = null;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}, []);
|
|
69
|
+
return { state, commit, flush, setState };
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=useBatchedMessages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBatchedMessages.js","sourceRoot":"","sources":["../../../src/cli/hooks/useBatchedMessages.ts"],"names":[],"mappings":"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"}
|