@cubicecho/agent-core 2.8.0 → 2.8.1
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 +4 -1
- package/dist/agent-loop.d.ts +4 -3
- package/dist/agent-loop.js +20 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/tool-loading.d.ts +34 -8
- package/dist/tool-loading.js +59 -14
- package/llms.txt +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -307,7 +307,10 @@ Found calls are run as `call_recovered_0` onward, the text is what is left, `onT
|
|
|
307
307
|
result see the turn that way, and a notice says so, since the real fix is the server's parser.
|
|
308
308
|
|
|
309
309
|
With `toolDiscovery: "ondemand"` and a catalogue, the request declares `load_tools` and what has
|
|
310
|
-
been loaded, and the catalogue rides on the system prompt
|
|
310
|
+
been loaded, appended in the order it was loaded, and the catalogue rides on the system prompt
|
|
311
|
+
unmarked, the same text on every step. Marking loads there rewrote the head of the prompt and lost
|
|
312
|
+
the prompt cache for the whole transcript on each one; a model that loads a tool twice is told in
|
|
313
|
+
the `load_tools` result that it already has it. A model that calls
|
|
311
314
|
a catalogued tool without loading it first is right about what it wants, and gets it loaded and
|
|
312
315
|
run. A preselection shapes the first step alone: those tools, no catalogue, no `load_tools` —
|
|
313
316
|
a model with the menu still in front of it shops, reloading what it has or picking a sibling —
|
package/dist/agent-loop.d.ts
CHANGED
|
@@ -192,9 +192,10 @@ export interface AgentLoopResult {
|
|
|
192
192
|
* whatever `runTurn` throws — `ContextOverflow` among them, however it was found out.
|
|
193
193
|
*
|
|
194
194
|
* On-demand loading is handled here, `load_tools` and all: the catalogue rides on the system
|
|
195
|
-
* prompt
|
|
196
|
-
*
|
|
197
|
-
* `maxTokens` is said so as a notice,
|
|
195
|
+
* prompt unchanged from step to step, loaded tools are appended to the tool array in load order,
|
|
196
|
+
* a catalogued tool called without being loaded is loaded and run rather than refused, and a
|
|
197
|
+
* preselection shapes the first step. A turn cut off at `maxTokens` is said so as a notice,
|
|
198
|
+
* because it otherwise reads exactly like a finished one.
|
|
198
199
|
*
|
|
199
200
|
* @param options The config, transcript, tools and dispatcher, plus the optional hooks, events
|
|
200
201
|
* and cancellation. See `AgentLoopOptions`.
|
package/dist/agent-loop.js
CHANGED
|
@@ -6,7 +6,7 @@ import { runTurn } from "./run-turn.js";
|
|
|
6
6
|
import { relaxTools, sanitizeTools } from "./schema-compat.js";
|
|
7
7
|
import { askJson, tryAsk } from "./side-task.js";
|
|
8
8
|
import { parseToolArguments, recoverToolCalls } from "./tool-calls.js";
|
|
9
|
-
import { catalogPrompt, expandNames, inCatalog, LOAD_TOOLS, LOAD_TOOLS_DEFINITION, loadResult, MAX_PER_LOAD, PRESELECT_SCHEMA, preselectInput, preselection, preselectSystem, requestedNames, } from "./tool-loading.js";
|
|
9
|
+
import { catalogPrompt, expandNames, inCatalog, LOAD_TOOLS, LOAD_TOOLS_DEFINITION, loadedTools, loadResult, MAX_PER_LOAD, PRESELECT_SCHEMA, preselectInput, preselection, preselectSystem, requestedNames, } from "./tool-loading.js";
|
|
10
10
|
/**
|
|
11
11
|
* The loop above a turn: send, run the tools the model asked for, send again, until it stops
|
|
12
12
|
* asking.
|
|
@@ -130,9 +130,10 @@ const accumulate = (total, turn) => {
|
|
|
130
130
|
* whatever `runTurn` throws — `ContextOverflow` among them, however it was found out.
|
|
131
131
|
*
|
|
132
132
|
* On-demand loading is handled here, `load_tools` and all: the catalogue rides on the system
|
|
133
|
-
* prompt
|
|
134
|
-
*
|
|
135
|
-
* `maxTokens` is said so as a notice,
|
|
133
|
+
* prompt unchanged from step to step, loaded tools are appended to the tool array in load order,
|
|
134
|
+
* a catalogued tool called without being loaded is loaded and run rather than refused, and a
|
|
135
|
+
* preselection shapes the first step. A turn cut off at `maxTokens` is said so as a notice,
|
|
136
|
+
* because it otherwise reads exactly like a finished one.
|
|
136
137
|
*
|
|
137
138
|
* @param options The config, transcript, tools and dispatcher, plus the optional hooks, events
|
|
138
139
|
* and cancellation. See `AgentLoopOptions`.
|
|
@@ -150,7 +151,15 @@ export async function runAgentLoop(options) {
|
|
|
150
151
|
for (const name of preselected)
|
|
151
152
|
loaded.add(name);
|
|
152
153
|
const used = new Set();
|
|
153
|
-
const
|
|
154
|
+
const definitions = new Map();
|
|
155
|
+
for (const tool of tools) {
|
|
156
|
+
if (tool.type === "function" && !definitions.has(tool.function.name)) {
|
|
157
|
+
definitions.set(tool.function.name, tool);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// In the order the names are given, not the order of `tools`: `loaded` is a set, which iterates
|
|
161
|
+
// in the order things were added, so a load appends and never reshuffles what went before.
|
|
162
|
+
const byName = (names) => [...names].flatMap((name) => definitions.get(name) ?? []);
|
|
154
163
|
let messages = [...options.messages];
|
|
155
164
|
// Held by reference rather than by index, so a `beforeStep` that folds the head into a summary
|
|
156
165
|
// moves the question without losing it — and one that summarises the question away takes the
|
|
@@ -176,9 +185,12 @@ export async function runAgentLoop(options) {
|
|
|
176
185
|
const declared = routed
|
|
177
186
|
? byName(new Set(preselected))
|
|
178
187
|
: onDemand
|
|
179
|
-
? [LOAD_TOOLS_DEFINITION,
|
|
188
|
+
? loadedTools([LOAD_TOOLS_DEFINITION], byName(loaded))
|
|
180
189
|
: tools;
|
|
181
|
-
|
|
190
|
+
// Unmarked, so the system prompt is the same text on every step and a load does not throw
|
|
191
|
+
// away the cache for the whole transcript. What is loaded is said in `declared` and in the
|
|
192
|
+
// `load_tools` result instead. The preselected first step is the one exception, by design.
|
|
193
|
+
const prompt = onDemand && !routed ? `${system}\n\n${catalogPrompt(catalog)}`.trim() : system;
|
|
182
194
|
const request = [
|
|
183
195
|
...(prompt ? [{ role: "system", content: prompt }] : []),
|
|
184
196
|
...withContext(messages, question ? messages.indexOf(question) : -1, gathered.context, hooks?.preface),
|
|
@@ -293,9 +305,9 @@ export async function runAgentLoop(options) {
|
|
|
293
305
|
throw unreadable;
|
|
294
306
|
if (onDemand && name === LOAD_TOOLS) {
|
|
295
307
|
const resolved = expandNames(requestedNames(args), catalog);
|
|
308
|
+
content = loadResult(resolved, catalog, loaded);
|
|
296
309
|
for (const hit of resolved.matched)
|
|
297
310
|
loaded.add(hit);
|
|
298
|
-
content = loadResult(resolved, catalog);
|
|
299
311
|
ok = resolved.matched.length > 0;
|
|
300
312
|
}
|
|
301
313
|
else {
|
package/dist/index.d.ts
CHANGED
|
@@ -28,4 +28,4 @@ export { type Produced, type StreamTurnOptions, streamTurn, type Turn, type Turn
|
|
|
28
28
|
export { ALL_FENCES, DEFAULT_FENCES, type Fence, FenceSplitter, type FenceSplitterOptions, type Split, stripThinking, THINK_FENCE, } from "./thinking.ts";
|
|
29
29
|
export { estimateTokens } from "./tokens.ts";
|
|
30
30
|
export { parseToolArguments, recoverToolCalls, ToolArgumentsError, type ToolCall, } from "./tool-calls.ts";
|
|
31
|
-
export { carryOver, catalogList, catalogPrompt, expandNames, inCatalog, LOAD_TOOLS, LOAD_TOOLS_DEFINITION, loadResult, MAX_CARRIED, MAX_PER_LOAD, PRESELECT_SCHEMA, PRESELECT_SYSTEM, preselectInput, preselection, preselectSystem, requestedNames, } from "./tool-loading.ts";
|
|
31
|
+
export { carryOver, catalogList, catalogPrompt, expandNames, inCatalog, LOAD_TOOLS, LOAD_TOOLS_DEFINITION, loadedTools, loadResult, MAX_CARRIED, MAX_PER_LOAD, PRESELECT_SCHEMA, PRESELECT_SYSTEM, preselectInput, preselection, preselectSystem, requestedNames, } from "./tool-loading.ts";
|
package/dist/index.js
CHANGED
|
@@ -26,4 +26,4 @@ export { streamTurn, } from "./stream.js";
|
|
|
26
26
|
export { ALL_FENCES, DEFAULT_FENCES, FenceSplitter, stripThinking, THINK_FENCE, } from "./thinking.js";
|
|
27
27
|
export { estimateTokens } from "./tokens.js";
|
|
28
28
|
export { parseToolArguments, recoverToolCalls, ToolArgumentsError, } from "./tool-calls.js";
|
|
29
|
-
export { carryOver, catalogList, catalogPrompt, expandNames, inCatalog, LOAD_TOOLS, LOAD_TOOLS_DEFINITION, loadResult, MAX_CARRIED, MAX_PER_LOAD, PRESELECT_SCHEMA, PRESELECT_SYSTEM, preselectInput, preselection, preselectSystem, requestedNames, } from "./tool-loading.js";
|
|
29
|
+
export { carryOver, catalogList, catalogPrompt, expandNames, inCatalog, LOAD_TOOLS, LOAD_TOOLS_DEFINITION, loadedTools, loadResult, MAX_CARRIED, MAX_PER_LOAD, PRESELECT_SCHEMA, PRESELECT_SYSTEM, preselectInput, preselection, preselectSystem, requestedNames, } from "./tool-loading.js";
|
package/dist/tool-loading.d.ts
CHANGED
|
@@ -23,28 +23,49 @@ export declare const LOAD_TOOLS = "load_tools";
|
|
|
23
23
|
*/
|
|
24
24
|
export declare const LOAD_TOOLS_DEFINITION: OpenAI.ChatCompletionTool;
|
|
25
25
|
/**
|
|
26
|
-
* The catalogue as a plain grouped listing of names, loaded ones marked.
|
|
26
|
+
* The catalogue as a plain grouped listing of names, loaded ones marked if asked.
|
|
27
27
|
*
|
|
28
28
|
* A server with no tools is dropped rather than titled: a pool hands one over whenever a
|
|
29
29
|
* server is connected but has nothing to offer, and a label with nothing under it reads as a
|
|
30
30
|
* listing that got cut off.
|
|
31
31
|
*
|
|
32
32
|
* @param catalog The connected servers. Ones with no tools are dropped.
|
|
33
|
-
* @param loaded Names
|
|
33
|
+
* @param loaded Names to mark `(loaded)` rather than remove. Absent marks nothing, which keeps the
|
|
34
|
+
* listing the same text for the whole run.
|
|
34
35
|
*/
|
|
35
36
|
export declare function catalogList(catalog: CatalogServer[], loaded?: ReadonlySet<string>): string;
|
|
36
37
|
/**
|
|
37
38
|
* The catalogue block appended to the system prompt. Names only — descriptions arrive on load.
|
|
38
39
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* the
|
|
40
|
+
* `runAgentLoop` passes no `loaded`, so the block is the same text on every step. The system
|
|
41
|
+
* prompt is the head of the request, and marking each load there threw away the prompt cache for
|
|
42
|
+
* the whole transcript on every `load_tools` call. What is loaded is said where it does not move
|
|
43
|
+
* the prefix instead: in the tool array, appended in load order (`loadedTools`), and in the
|
|
44
|
+
* `load_tools` result, which answers a repeat load with "already loaded" (`loadResult`).
|
|
45
|
+
*
|
|
46
|
+
* Loaded tools are never removed from the list. That reads as the tool having vanished the moment
|
|
47
|
+
* it was loaded, and the model loads again to get it back; hoisting them into a separate "already
|
|
48
|
+
* loaded" section splits a server's tools apart, and the model picks a sibling from the longer
|
|
49
|
+
* list instead.
|
|
43
50
|
*
|
|
44
51
|
* @param catalog The connected servers. A catalogue with no tools in it produces an empty string.
|
|
45
|
-
* @param loaded Names
|
|
52
|
+
* @param loaded Names to mark `(loaded)`, for a caller that rebuilds its prompt per load and does
|
|
53
|
+
* not mind the cache. Absent marks nothing.
|
|
46
54
|
*/
|
|
47
55
|
export declare function catalogPrompt(catalog: CatalogServer[], loaded?: ReadonlySet<string>): string;
|
|
56
|
+
/**
|
|
57
|
+
* A tool array with newly loaded definitions appended, in the order they were loaded.
|
|
58
|
+
*
|
|
59
|
+
* Never re-sorted and never rebuilt from a set. A template renders the tool array into the
|
|
60
|
+
* prompt near its head, and a load that moved an earlier definition moved everything after it,
|
|
61
|
+
* so the cache was lost from there on every load; appended, the definitions already sent stay
|
|
62
|
+
* a prefix of the new array.
|
|
63
|
+
*
|
|
64
|
+
* @param previous What the last request declared, `load_tools` included. Not written to.
|
|
65
|
+
* @param matched The definitions to add. Ones whose name is already declared, here or earlier in
|
|
66
|
+
* this list, are skipped rather than moved.
|
|
67
|
+
*/
|
|
68
|
+
export declare function loadedTools(previous: readonly OpenAI.ChatCompletionTool[], matched: readonly OpenAI.ChatCompletionTool[]): OpenAI.ChatCompletionTool[];
|
|
48
69
|
/**
|
|
49
70
|
* The most a single `load_tools` call may pull in.
|
|
50
71
|
*
|
|
@@ -103,10 +124,15 @@ export declare function expandNames(requested: string[], catalog: CatalogServer[
|
|
|
103
124
|
/**
|
|
104
125
|
* What `load_tools` reports back: the descriptions, now that they are worth their tokens.
|
|
105
126
|
*
|
|
127
|
+
* A name that was loaded before this call is reported as already loaded rather than loaded
|
|
128
|
+
* again. The catalogue no longer marks what is loaded — see `catalogPrompt` — so this is where a
|
|
129
|
+
* model that asks twice finds out it need not have, and is told to call the tool instead.
|
|
130
|
+
*
|
|
106
131
|
* @param expanded What `expandNames` resolved: the matches, the misses, and the over-broad asks.
|
|
107
132
|
* @param catalog The servers, read for the descriptions now worth their tokens.
|
|
133
|
+
* @param loaded What was loaded before this call. Absent reports every match as newly loaded.
|
|
108
134
|
*/
|
|
109
|
-
export declare function loadResult({ matched, unknown, overBroad, deferred, maxPerLoad }: ReturnType<typeof expandNames>, catalog: CatalogServer[]): string;
|
|
135
|
+
export declare function loadResult({ matched, unknown, overBroad, deferred, maxPerLoad }: ReturnType<typeof expandNames>, catalog: CatalogServer[], loaded?: ReadonlySet<string>): string;
|
|
110
136
|
/**
|
|
111
137
|
* Whether the catalogue holds a tool by this name.
|
|
112
138
|
*
|
package/dist/tool-loading.js
CHANGED
|
@@ -49,14 +49,15 @@ export const LOAD_TOOLS_DEFINITION = deepFreeze({
|
|
|
49
49
|
},
|
|
50
50
|
});
|
|
51
51
|
/**
|
|
52
|
-
* The catalogue as a plain grouped listing of names, loaded ones marked.
|
|
52
|
+
* The catalogue as a plain grouped listing of names, loaded ones marked if asked.
|
|
53
53
|
*
|
|
54
54
|
* A server with no tools is dropped rather than titled: a pool hands one over whenever a
|
|
55
55
|
* server is connected but has nothing to offer, and a label with nothing under it reads as a
|
|
56
56
|
* listing that got cut off.
|
|
57
57
|
*
|
|
58
58
|
* @param catalog The connected servers. Ones with no tools are dropped.
|
|
59
|
-
* @param loaded Names
|
|
59
|
+
* @param loaded Names to mark `(loaded)` rather than remove. Absent marks nothing, which keeps the
|
|
60
|
+
* listing the same text for the whole run.
|
|
60
61
|
*/
|
|
61
62
|
export function catalogList(catalog, loaded) {
|
|
62
63
|
return catalog
|
|
@@ -70,13 +71,20 @@ export function catalogList(catalog, loaded) {
|
|
|
70
71
|
/**
|
|
71
72
|
* The catalogue block appended to the system prompt. Names only — descriptions arrive on load.
|
|
72
73
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* the
|
|
74
|
+
* `runAgentLoop` passes no `loaded`, so the block is the same text on every step. The system
|
|
75
|
+
* prompt is the head of the request, and marking each load there threw away the prompt cache for
|
|
76
|
+
* the whole transcript on every `load_tools` call. What is loaded is said where it does not move
|
|
77
|
+
* the prefix instead: in the tool array, appended in load order (`loadedTools`), and in the
|
|
78
|
+
* `load_tools` result, which answers a repeat load with "already loaded" (`loadResult`).
|
|
79
|
+
*
|
|
80
|
+
* Loaded tools are never removed from the list. That reads as the tool having vanished the moment
|
|
81
|
+
* it was loaded, and the model loads again to get it back; hoisting them into a separate "already
|
|
82
|
+
* loaded" section splits a server's tools apart, and the model picks a sibling from the longer
|
|
83
|
+
* list instead.
|
|
77
84
|
*
|
|
78
85
|
* @param catalog The connected servers. A catalogue with no tools in it produces an empty string.
|
|
79
|
-
* @param loaded Names
|
|
86
|
+
* @param loaded Names to mark `(loaded)`, for a caller that rebuilds its prompt per load and does
|
|
87
|
+
* not mind the cache. Absent marks nothing.
|
|
80
88
|
*/
|
|
81
89
|
export function catalogPrompt(catalog, loaded) {
|
|
82
90
|
const list = catalogList(catalog, loaded);
|
|
@@ -88,14 +96,39 @@ export function catalogPrompt(catalog, loaded) {
|
|
|
88
96
|
"# Tool catalogue",
|
|
89
97
|
"",
|
|
90
98
|
"These tools exist but are not loaded. Call `load_tools` with the names you need, then call",
|
|
91
|
-
"them on the step after. Names are descriptive; load a tool to see its parameters. A
|
|
92
|
-
"
|
|
93
|
-
"
|
|
99
|
+
"them on the step after. Names are descriptive; load a tool to see its parameters. A tool",
|
|
100
|
+
"already in your tool list is loaded — call it directly, do not load it again. Do not load",
|
|
101
|
+
"tools the task does not need, and do not mention this mechanism in your answer.",
|
|
94
102
|
"",
|
|
95
103
|
list,
|
|
96
104
|
].join("\n");
|
|
97
105
|
}
|
|
98
106
|
const flatten = (catalog) => catalog.flatMap((server) => server.tools);
|
|
107
|
+
/**
|
|
108
|
+
* A tool array with newly loaded definitions appended, in the order they were loaded.
|
|
109
|
+
*
|
|
110
|
+
* Never re-sorted and never rebuilt from a set. A template renders the tool array into the
|
|
111
|
+
* prompt near its head, and a load that moved an earlier definition moved everything after it,
|
|
112
|
+
* so the cache was lost from there on every load; appended, the definitions already sent stay
|
|
113
|
+
* a prefix of the new array.
|
|
114
|
+
*
|
|
115
|
+
* @param previous What the last request declared, `load_tools` included. Not written to.
|
|
116
|
+
* @param matched The definitions to add. Ones whose name is already declared, here or earlier in
|
|
117
|
+
* this list, are skipped rather than moved.
|
|
118
|
+
*/
|
|
119
|
+
export function loadedTools(previous, matched) {
|
|
120
|
+
const nameOf = (tool) => tool.type === "function" ? tool.function.name : undefined;
|
|
121
|
+
const declared = new Set(previous.map(nameOf));
|
|
122
|
+
const tools = [...previous];
|
|
123
|
+
for (const tool of matched) {
|
|
124
|
+
const name = nameOf(tool);
|
|
125
|
+
if (name !== undefined && declared.has(name))
|
|
126
|
+
continue;
|
|
127
|
+
declared.add(name);
|
|
128
|
+
tools.push(tool);
|
|
129
|
+
}
|
|
130
|
+
return tools;
|
|
131
|
+
}
|
|
99
132
|
/**
|
|
100
133
|
* The most a single `load_tools` call may pull in.
|
|
101
134
|
*
|
|
@@ -201,17 +234,29 @@ export function expandNames(requested, catalog, maxPerLoad = MAX_PER_LOAD) {
|
|
|
201
234
|
/**
|
|
202
235
|
* What `load_tools` reports back: the descriptions, now that they are worth their tokens.
|
|
203
236
|
*
|
|
237
|
+
* A name that was loaded before this call is reported as already loaded rather than loaded
|
|
238
|
+
* again. The catalogue no longer marks what is loaded — see `catalogPrompt` — so this is where a
|
|
239
|
+
* model that asks twice finds out it need not have, and is told to call the tool instead.
|
|
240
|
+
*
|
|
204
241
|
* @param expanded What `expandNames` resolved: the matches, the misses, and the over-broad asks.
|
|
205
242
|
* @param catalog The servers, read for the descriptions now worth their tokens.
|
|
243
|
+
* @param loaded What was loaded before this call. Absent reports every match as newly loaded.
|
|
206
244
|
*/
|
|
207
|
-
export function loadResult({ matched, unknown, overBroad, deferred, maxPerLoad }, catalog) {
|
|
245
|
+
export function loadResult({ matched, unknown, overBroad, deferred, maxPerLoad }, catalog, loaded) {
|
|
208
246
|
const byName = new Map(flatten(catalog).map((tool) => [tool.name, tool.description]));
|
|
209
247
|
const lines = [];
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
248
|
+
const fresh = matched.filter((name) => !loaded?.has(name));
|
|
249
|
+
const again = matched.filter((name) => loaded?.has(name));
|
|
250
|
+
if (fresh.length) {
|
|
251
|
+
lines.push(`Loaded ${fresh.length} tool(s); they are callable on your next step.`, "");
|
|
252
|
+
for (const name of fresh)
|
|
213
253
|
lines.push(`${name}: ${byName.get(name) ?? ""}`.trim());
|
|
214
254
|
}
|
|
255
|
+
if (again.length) {
|
|
256
|
+
if (lines.length)
|
|
257
|
+
lines.push("");
|
|
258
|
+
lines.push(`Already loaded and in your tool list: ${again.join(", ")}. Call them directly; do not load them again.`);
|
|
259
|
+
}
|
|
215
260
|
for (const { name, hits } of overBroad) {
|
|
216
261
|
if (lines.length)
|
|
217
262
|
lines.push("");
|
package/llms.txt
CHANGED
|
@@ -231,12 +231,13 @@ Reading what a model meant by a tool call when it did not write one cleanly.
|
|
|
231
231
|
### tool-loading
|
|
232
232
|
|
|
233
233
|
- `carryOver` — The tools to start the next turn with: recently used, newest last, capped.
|
|
234
|
-
- `catalogList` — The catalogue as a plain grouped listing of names, loaded ones marked.
|
|
234
|
+
- `catalogList` — The catalogue as a plain grouped listing of names, loaded ones marked if asked.
|
|
235
235
|
- `catalogPrompt` — The catalogue block appended to the system prompt.
|
|
236
236
|
- `expandNames` — Resolves requested names against the catalogue, expanding trailing `*` wildcards.
|
|
237
237
|
- `inCatalog` — Whether the catalogue holds a tool by this name.
|
|
238
238
|
- `LOAD_TOOLS` — On-demand tool loading.
|
|
239
239
|
- `LOAD_TOOLS_DEFINITION` — One object for the life of the process — the agent loop asks for it on every iteration.
|
|
240
|
+
- `loadedTools` — A tool array with newly loaded definitions appended, in the order they were loaded.
|
|
240
241
|
- `loadResult` — What `load_tools` reports back: the descriptions, now that they are worth their tokens.
|
|
241
242
|
- `MAX_CARRIED` — The most a conversation carries between turns.
|
|
242
243
|
- `MAX_PER_LOAD` — The most a single `load_tools` call may pull in.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cubicecho/agent-core",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.1",
|
|
4
4
|
"description": "The endpoint-agnostic half of an OpenAI-compatible agent loop: tool-schema compatibility, on-demand tool loading, one-shot side tasks, run events, and a pooled client.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openai",
|