zelari-code 2.0.0-alpha.4 โ 2.0.0-alpha.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 +2 -2
- package/dist/cli/headlessHistorySeed.test.js +158 -0
- package/dist/cli/headlessHistorySeed.test.js.map +1 -0
- package/dist/cli/headlessSpine.js +87 -1
- package/dist/cli/headlessSpine.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +22 -2
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/main.bundled.js +664 -574
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/providerConfig.js +58 -49
- package/dist/cli/providerConfig.js.map +1 -1
- package/dist/cli/providerConfig.test.js +85 -0
- package/dist/cli/providerConfig.test.js.map +1 -0
- package/dist/cli/runHeadless.js +29 -42
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/sessionReplayInvariant.test.js +187 -0
- package/dist/cli/sessionReplayInvariant.test.js.map +1 -0
- package/dist/cli/sessionSpine.js +28 -0
- package/dist/cli/sessionSpine.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ By **[Anathema Studio](https://anathema-studio.com/)** ยท
|
|
|
42
42
|
|
|
43
43
|
๐ **[Full user guide (IT)](./docs/GUIDA.md)** โ install, TUI, slash commands, council, skills, workspace, headless, MCP, Desktop.
|
|
44
44
|
|
|
45
|
-
**Zelari Code** is an open-source **AI council coding agent** for the terminal: a multi-agent pipeline (Caronte, Nettuno, Gerione, Plutone, Minosse, Lucifero), a **kraken** super-agent (default; aliases `agent`/`single`) that can spawn explore/general/verify tentacles, and optional **zelari** missions that loop until a deliverable is done. It ships a rich TUI (Ink + React), slash commands, plan/build phases, and provider-agnostic LLM streaming (OpenAI-compatible, xAI Grok, ChatGPT, Anthropic, GLM/Z.AI, MiniMax, DeepSeek). OAuth via `/login grok`, `/login chatgpt`, `/login anthropic`. The reusable runtime is published as **[`@zelari/core`](https://www.npmjs.com/package/@zelari/core)** (Apache-2.0).
|
|
45
|
+
**Zelari Code** is an open-source **AI council coding agent** for the terminal: a multi-agent pipeline (Caronte, Nettuno, Gerione, Plutone, Minosse, Lucifero), a **kraken** super-agent (default; aliases `agent`/`single`) that can spawn explore/general/verify tentacles, and optional **zelari** missions that loop until a deliverable is done. It ships a rich TUI (Ink + React), slash commands, plan/build phases, and provider-agnostic LLM streaming (OpenAI-compatible, xAI Grok, ChatGPT, Anthropic, GLM/Z.AI, MiniMax, DeepSeek). OAuth via `/login grok`, `/login chatgpt`, `/login anthropic`. The reusable runtime is published as **[`@zelari/core`](https://www.npmjs.com/package/@zelari/core)** (Apache-2.0).
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
48
|
npm install -g zelari-code
|
|
@@ -295,7 +295,7 @@ Disable auto-check: `ANATHEMA_DEV=1 zelari-code`
|
|
|
295
295
|
## Architecture
|
|
296
296
|
|
|
297
297
|
```
|
|
298
|
-
zelari-code (CLI, Apache-2.0)
|
|
298
|
+
zelari-code (CLI, Apache-2.0)
|
|
299
299
|
โโโ src/cli/ # Ink TUI, providers, workspace, wizard, MCP, SSH, serve
|
|
300
300
|
โ โโโ components/ # ChatStream, InputBar, Sidebar, StatusBar, โฆ
|
|
301
301
|
โ โโโ slashHandlers/ # /provider, /workspace, /kraken, /trust, โฆ
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* headlessHistorySeed โ Exit-1/E1.2 canonical model-context path.
|
|
3
|
+
*
|
|
4
|
+
* Proves: legacy `--history` is imported one-shot into a fresh spine log,
|
|
5
|
+
* prior turns are then derived from events (never re-imported), resume
|
|
6
|
+
* ignores fresh legacy input, and a disabled spine falls back to the
|
|
7
|
+
* filtered legacy seed (declared discrete fallback).
|
|
8
|
+
*/
|
|
9
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
10
|
+
import { promises as fs } from 'node:fs';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import os from 'node:os';
|
|
13
|
+
import { openHeadlessSpine, seedHeadlessModelHistory } from './headlessSpine.js';
|
|
14
|
+
import { readSessionLog, resolveSessionsDir } from '@zelari/core/session';
|
|
15
|
+
let tmp;
|
|
16
|
+
beforeEach(async () => {
|
|
17
|
+
tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'zelari-history-seed-'));
|
|
18
|
+
});
|
|
19
|
+
afterEach(async () => {
|
|
20
|
+
delete process.env.ZELARI_SESSION_SPINE;
|
|
21
|
+
await fs.rm(tmp, { recursive: true, force: true });
|
|
22
|
+
});
|
|
23
|
+
const legacy = [
|
|
24
|
+
{ role: 'user', content: 'build the login form' },
|
|
25
|
+
{
|
|
26
|
+
role: 'assistant',
|
|
27
|
+
content: '<think>plan</think>Done โ see ---QUESTION---\ncontinue?',
|
|
28
|
+
},
|
|
29
|
+
{ role: 'system', content: 'stale system' },
|
|
30
|
+
{ role: 'tool', content: '{"ok":true}' },
|
|
31
|
+
];
|
|
32
|
+
function eventsPath(sessionId) {
|
|
33
|
+
return path.join(resolveSessionsDir({ baseDir: tmp }), sessionId, 'events.jsonl');
|
|
34
|
+
}
|
|
35
|
+
describe('seedHeadlessModelHistory', () => {
|
|
36
|
+
it('imports legacy --history one-shot and returns the derived seed', async () => {
|
|
37
|
+
const handle = await openHeadlessSpine({
|
|
38
|
+
sessionId: 'seed-1',
|
|
39
|
+
baseDir: tmp,
|
|
40
|
+
quiet: true,
|
|
41
|
+
});
|
|
42
|
+
const seed = await seedHeadlessModelHistory(handle, legacy);
|
|
43
|
+
expect(seed.source).toBe('spine-import');
|
|
44
|
+
expect(seed.importedCount).toBe(2);
|
|
45
|
+
// system/tool dropped; <think> + ---QUESTION--- preserved (binding policy)
|
|
46
|
+
expect(seed.history).toHaveLength(2);
|
|
47
|
+
expect(seed.history[0]).toEqual({ role: 'user', content: 'build the login form' });
|
|
48
|
+
expect(seed.history[1]?.role).toBe('assistant');
|
|
49
|
+
expect(seed.history[1]?.content).toContain('<think>plan</think>');
|
|
50
|
+
expect(seed.history[1]?.content).toContain('---QUESTION---');
|
|
51
|
+
// The imported turns are in the log โ model-visible โบ logged (P1).
|
|
52
|
+
const report = await readSessionLog(eventsPath('seed-1'));
|
|
53
|
+
const texts = report.events
|
|
54
|
+
.filter((e) => e.kind === 'user.message' || e.kind === 'assistant.message')
|
|
55
|
+
.map((e) => e.data.text);
|
|
56
|
+
expect(texts).toEqual(['build the login form', seed.history[1].content]);
|
|
57
|
+
const imported = report.events.find((e) => e.kind === 'assistant.message');
|
|
58
|
+
expect((imported?.data).imported).toBe('legacy-history');
|
|
59
|
+
await handle.close('test-end');
|
|
60
|
+
});
|
|
61
|
+
it('derives from the log on resume and ignores new legacy input', async () => {
|
|
62
|
+
const first = await openHeadlessSpine({
|
|
63
|
+
sessionId: 'seed-2',
|
|
64
|
+
baseDir: tmp,
|
|
65
|
+
quiet: true,
|
|
66
|
+
});
|
|
67
|
+
const s1 = await seedHeadlessModelHistory(first, [
|
|
68
|
+
{ role: 'user', content: 'u-first' },
|
|
69
|
+
{ role: 'assistant', content: 'a-first' },
|
|
70
|
+
]);
|
|
71
|
+
expect(s1.source).toBe('spine-import');
|
|
72
|
+
await first.close('test-end');
|
|
73
|
+
const resumed = await openHeadlessSpine({
|
|
74
|
+
sessionId: 'seed-2',
|
|
75
|
+
baseDir: tmp,
|
|
76
|
+
quiet: true,
|
|
77
|
+
});
|
|
78
|
+
const s2 = await seedHeadlessModelHistory(resumed, [
|
|
79
|
+
{ role: 'user', content: 'u-second-should-be-ignored' },
|
|
80
|
+
]);
|
|
81
|
+
expect(s2.source).toBe('spine');
|
|
82
|
+
expect(s2.importedCount).toBe(0);
|
|
83
|
+
expect(s2.history.map((m) => m.content)).toEqual(['u-first', 'a-first']);
|
|
84
|
+
await resumed.close('test-end');
|
|
85
|
+
});
|
|
86
|
+
it('falls back to the filtered legacy seed when the spine is disabled', async () => {
|
|
87
|
+
process.env.ZELARI_SESSION_SPINE = '0';
|
|
88
|
+
const handle = await openHeadlessSpine({
|
|
89
|
+
sessionId: 'seed-3',
|
|
90
|
+
baseDir: tmp,
|
|
91
|
+
quiet: true,
|
|
92
|
+
});
|
|
93
|
+
const seed = await seedHeadlessModelHistory(handle, legacy);
|
|
94
|
+
expect(seed.source).toBe('legacy-fallback');
|
|
95
|
+
expect(seed.importedCount).toBe(0);
|
|
96
|
+
expect(seed.history.map((m) => m.role)).toEqual(['user', 'assistant']);
|
|
97
|
+
await handle.close('test-end');
|
|
98
|
+
});
|
|
99
|
+
it('returns an empty seed for a fresh log with no legacy history', async () => {
|
|
100
|
+
const handle = await openHeadlessSpine({
|
|
101
|
+
sessionId: 'seed-4',
|
|
102
|
+
baseDir: tmp,
|
|
103
|
+
quiet: true,
|
|
104
|
+
});
|
|
105
|
+
const seed = await seedHeadlessModelHistory(handle);
|
|
106
|
+
expect(seed).toEqual({ history: [], importedCount: 0, source: 'spine' });
|
|
107
|
+
await handle.close('test-end');
|
|
108
|
+
});
|
|
109
|
+
it('keeps model-surface events in conversation order (invariant)', async () => {
|
|
110
|
+
const handle = await openHeadlessSpine({
|
|
111
|
+
sessionId: 'seed-5',
|
|
112
|
+
baseDir: tmp,
|
|
113
|
+
quiet: true,
|
|
114
|
+
});
|
|
115
|
+
const plain = [
|
|
116
|
+
{ role: 'user', content: 'plain user' },
|
|
117
|
+
{ role: 'assistant', content: 'plain assistant' },
|
|
118
|
+
];
|
|
119
|
+
const seed = await seedHeadlessModelHistory(handle, plain);
|
|
120
|
+
expect(seed.source).toBe('spine-import');
|
|
121
|
+
const report = await readSessionLog(eventsPath('seed-5'));
|
|
122
|
+
const kinds = report.events.map((e) => e.kind);
|
|
123
|
+
expect(kinds.indexOf('user.message')).toBeLessThan(kinds.indexOf('assistant.message'));
|
|
124
|
+
// Clean text round-trips byte-identical through import โ derive.
|
|
125
|
+
expect(seed.history).toEqual(plain);
|
|
126
|
+
await handle.close('test-end');
|
|
127
|
+
});
|
|
128
|
+
it('derivedModelSeed: compacted โ user, tool results dropped (shared policy)', async () => {
|
|
129
|
+
const handle = await openHeadlessSpine({
|
|
130
|
+
sessionId: 'seed-6',
|
|
131
|
+
baseDir: tmp,
|
|
132
|
+
quiet: true,
|
|
133
|
+
});
|
|
134
|
+
await seedHeadlessModelHistory(handle, [{ role: 'user', content: 'u1' }]);
|
|
135
|
+
// A compaction event lands on the spine (TUI /compact or budget policy).
|
|
136
|
+
handle.spine.mirrorBrainEvent({
|
|
137
|
+
type: 'session_compacted',
|
|
138
|
+
summary: 'sum-of-old-turns',
|
|
139
|
+
});
|
|
140
|
+
await handle.spine.flush();
|
|
141
|
+
const afterCompact = await seedHeadlessModelHistory(handle, []);
|
|
142
|
+
expect(afterCompact.source).toBe('spine');
|
|
143
|
+
expect(afterCompact.history.map((m) => `${m.role}:${m.content}`)).toContain('user:sum-of-old-turns');
|
|
144
|
+
// Tool results derive as orphans (no assistant tool_calls block) and
|
|
145
|
+
// must NOT reach the model seed.
|
|
146
|
+
handle.spine.mirrorBrainEvent({
|
|
147
|
+
type: 'tool_execution_end',
|
|
148
|
+
toolCallId: 'call-1',
|
|
149
|
+
result: 'raw tool output',
|
|
150
|
+
isError: false,
|
|
151
|
+
});
|
|
152
|
+
await handle.spine.flush();
|
|
153
|
+
const afterTool = await seedHeadlessModelHistory(handle, []);
|
|
154
|
+
expect(afterTool.history.some((m) => m.role === 'tool')).toBe(false);
|
|
155
|
+
await handle.close('test-end');
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
//# sourceMappingURL=headlessHistorySeed.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headlessHistorySeed.test.js","sourceRoot":"","sources":["../../src/cli/headlessHistorySeed.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { cleanAgentContent } from '@zelari/core';
|
|
2
|
+
import { exportSessionJson, SessionStore, resolveSessionsDir, derivedToAgentMessages, } from '@zelari/core/session';
|
|
2
3
|
import { deriveMissionState } from '@zelari/core/mission';
|
|
3
4
|
import { resolveProfile, toolManifestHash } from '@zelari/core/runtime';
|
|
4
5
|
import { SessionSpineMirror } from './sessionSpine.js';
|
|
@@ -99,4 +100,89 @@ export async function missionStateFromSpine(sessionId, baseDir) {
|
|
|
99
100
|
return null;
|
|
100
101
|
}
|
|
101
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Exit-1/E1.2 โ the session spine is the model-context source of truth.
|
|
105
|
+
*
|
|
106
|
+
* Call this BEFORE `handle.userMessage(task)` so the derived history
|
|
107
|
+
* excludes the current turn.
|
|
108
|
+
*
|
|
109
|
+
* - Fresh log + legacy `--history` โ import each turn as spine events
|
|
110
|
+
* (one-shot migration), then derive from events.
|
|
111
|
+
* - Existing log (resume) โ derive from events; legacy input is ignored
|
|
112
|
+
* (spine wins over the 1.x rolling JSON).
|
|
113
|
+
* - Degraded / disabled spine (ZELARI_SESSION_SPINE=0) โ declared discrete
|
|
114
|
+
* fallback to the filtered legacy seed, i.e. the pre-spine behavior.
|
|
115
|
+
*/
|
|
116
|
+
export async function seedHeadlessModelHistory(handle, legacy) {
|
|
117
|
+
const mirror = handle.spine;
|
|
118
|
+
const legacySeed = filterLegacySeed(legacy);
|
|
119
|
+
if (mirror.status !== 'active') {
|
|
120
|
+
return { history: legacySeed, importedCount: 0, source: 'legacy-fallback' };
|
|
121
|
+
}
|
|
122
|
+
const existing = await mirror.derivedPriorTurns();
|
|
123
|
+
if (existing && existing.length > 0) {
|
|
124
|
+
return { history: derivedModelSeed(existing), importedCount: 0, source: 'spine' };
|
|
125
|
+
}
|
|
126
|
+
if (legacySeed.length === 0) {
|
|
127
|
+
return { history: [], importedCount: 0, source: 'spine' };
|
|
128
|
+
}
|
|
129
|
+
for (const m of legacySeed) {
|
|
130
|
+
if (m.role === 'user') {
|
|
131
|
+
mirror.userMessage(m.content);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
mirror.assistantMessage(m.content, { imported: 'legacy-history' });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
await mirror.flush();
|
|
138
|
+
const derived = (await mirror.derivedPriorTurns()) ?? [];
|
|
139
|
+
return {
|
|
140
|
+
history: derivedModelSeed(derived),
|
|
141
|
+
importedCount: legacySeed.length,
|
|
142
|
+
source: 'spine-import',
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/** Same seed policy as the pre-spine path: user/assistant, scrubbed, non-empty. */
|
|
146
|
+
function filterLegacySeed(legacy) {
|
|
147
|
+
return (legacy ?? [])
|
|
148
|
+
.filter((m) => m.role === 'user' || m.role === 'assistant')
|
|
149
|
+
.map((m) => m.role === 'assistant' && m.content
|
|
150
|
+
? {
|
|
151
|
+
role: 'assistant',
|
|
152
|
+
content: cleanAgentContent(m.content, {
|
|
153
|
+
stripQuestion: false,
|
|
154
|
+
stripThink: false,
|
|
155
|
+
}),
|
|
156
|
+
}
|
|
157
|
+
: { role: m.role, content: m.content ?? '' })
|
|
158
|
+
.filter((m) => (m.content ?? '').trim().length > 0);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* DerivedMessage[] โ harness seed (Exit-1 shared policy, headless + TUI).
|
|
162
|
+
*
|
|
163
|
+
* - user/assistant pass through (assistant scrubbed with the binding
|
|
164
|
+
* policy: keep <think> and ---QUESTION--- blocks);
|
|
165
|
+
* - compacted summaries (system role) map to a user message โ the 1.x
|
|
166
|
+
* store's own convention โ so pre-compaction context survives without
|
|
167
|
+
* a mid-stream system message;
|
|
168
|
+
* - tool results are dropped: derived results carry no paired assistant
|
|
169
|
+
* tool_calls block (deriveMessages default), which providers reject.
|
|
170
|
+
*/
|
|
171
|
+
export function derivedModelSeed(derived) {
|
|
172
|
+
return derivedToAgentMessages(derived)
|
|
173
|
+
.map((m) => m.role === 'system'
|
|
174
|
+
? { role: 'user', content: m.content }
|
|
175
|
+
: m)
|
|
176
|
+
.map((m) => m.role === 'assistant' && m.content
|
|
177
|
+
? {
|
|
178
|
+
role: 'assistant',
|
|
179
|
+
content: cleanAgentContent(m.content, {
|
|
180
|
+
stripQuestion: false,
|
|
181
|
+
stripThink: false,
|
|
182
|
+
}),
|
|
183
|
+
}
|
|
184
|
+
: m)
|
|
185
|
+
.filter((m) => m.role === 'user' || m.role === 'assistant')
|
|
186
|
+
.filter((m) => (m.content ?? '').trim().length > 0);
|
|
187
|
+
}
|
|
102
188
|
//# sourceMappingURL=headlessSpine.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headlessSpine.js","sourceRoot":"","sources":["../../src/cli/headlessSpine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"headlessSpine.js","sourceRoot":"","sources":["../../src/cli/headlessSpine.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,7 @@ import { collectKrakenTurnMetrics, markRepairSucceeded, markRepairTriggered, res
|
|
|
20
20
|
import { krakenSelectionPlaybook } from "../kraken/selectionPlaybook.js";
|
|
21
21
|
import { buildKrakenRepairPrompt } from "../kraken/completionGate.js";
|
|
22
22
|
import { evaluateStrictBuildGate, strictGateEventPayload } from "../kraken/verificationBridge.js";
|
|
23
|
+
import { derivedModelSeed } from "../headlessSpine.js";
|
|
23
24
|
import { createPermissionAskHandler } from "./permissionPicker.js";
|
|
24
25
|
import { armPickerTimeout, askUserTimeoutMs } from "./askUserTimeout.js";
|
|
25
26
|
import { defaultPermissionPolicy } from "../safety/toolPermissions.js";
|
|
@@ -89,6 +90,25 @@ export function useChatTurn(params) {
|
|
|
89
90
|
const anchored = maybeAnchorShortAnswer(userText);
|
|
90
91
|
const effectiveUserText = anchored ?? userText;
|
|
91
92
|
// 2.0 spine: the user prompt is model-visible โ log it (the 1.x JSONL never did).
|
|
93
|
+
// Exit-1/E1.3: the model context is spine-derived โ the same canonical
|
|
94
|
+
// path as headless (seedHeadlessModelHistory / derivedModelSeed).
|
|
95
|
+
// Derive BEFORE the current user prompt is logged so the seed
|
|
96
|
+
// excludes this turn. The in-process rolling store stays the
|
|
97
|
+
// declared fallback (degraded/disabled spine, or a spine log still
|
|
98
|
+
// empty while the store carries replayed 1.x history) and keeps
|
|
99
|
+
// feeding render + budget heuristics.
|
|
100
|
+
let historyForModel;
|
|
101
|
+
{
|
|
102
|
+
const mirror = writerRef.current?.spine ?? null;
|
|
103
|
+
let spineSeed = null;
|
|
104
|
+
if (mirror && mirror.status === "active") {
|
|
105
|
+
const derived = await mirror.derivedPriorTurns();
|
|
106
|
+
if (derived && derived.length > 0) {
|
|
107
|
+
spineSeed = derivedModelSeed(derived);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
historyForModel = spineSeed ?? getHistory();
|
|
111
|
+
}
|
|
92
112
|
writerRef.current?.spine?.userMessage(effectiveUserText);
|
|
93
113
|
// Local-CLI provider (Slice B): opt-in via ZELARI_LOCAL_CLI=claude|codex|...
|
|
94
114
|
// No API key needed โ the CLI is authenticated on its own. Permission
|
|
@@ -268,7 +288,7 @@ export function useChatTurn(params) {
|
|
|
268
288
|
});
|
|
269
289
|
void writerRef.current?.append(compactionEvent);
|
|
270
290
|
}
|
|
271
|
-
historySeedLen =
|
|
291
|
+
historySeedLen = historyForModel.length;
|
|
272
292
|
// v0.7.3: surface the council plan (if any) to the single agent too.
|
|
273
293
|
// The plan lives in .zelari/plan.json but the agent had no idea it
|
|
274
294
|
// existed โ users had to paste task-file paths by hand. Best-effort:
|
|
@@ -552,7 +572,7 @@ export function useChatTurn(params) {
|
|
|
552
572
|
// v1.8.0: shared rolling history (agent/council/zelari) so short
|
|
553
573
|
// answers bind to prior ---QUESTION--- blocks. Possibly empty
|
|
554
574
|
// when ZELARI_HISTORY_TURNS=0.
|
|
555
|
-
...
|
|
575
|
+
...historyForModel,
|
|
556
576
|
{ role: "user", content: effectiveUserText },
|
|
557
577
|
],
|
|
558
578
|
tools: toolRegistry.toOpenAITools().map((t) => ({
|