@cubicecho/agent-core 2.24.0 → 2.25.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 +10 -7
- package/dist/agent-loop.d.ts +84 -205
- package/dist/agent-loop.js +288 -597
- package/dist/calibration.d.ts +14 -10
- package/dist/calibration.js +30 -23
- package/dist/capabilities.d.ts +111 -42
- package/dist/capabilities.js +281 -138
- package/dist/client.d.ts +104 -35
- package/dist/client.js +205 -74
- package/dist/compaction.d.ts +103 -60
- package/dist/compaction.js +160 -86
- package/dist/config.d.ts +48 -12
- package/dist/config.js +20 -1
- package/dist/continuation.d.ts +24 -16
- package/dist/continuation.js +70 -44
- package/dist/digest.d.ts +7 -0
- package/dist/digest.js +18 -0
- package/dist/errors.d.ts +24 -15
- package/dist/errors.js +23 -15
- package/dist/events.d.ts +100 -63
- package/dist/events.js +250 -120
- package/dist/guards.d.ts +49 -4
- package/dist/guards.js +60 -5
- package/dist/hook-events.d.ts +21 -5
- package/dist/hook-events.js +23 -9
- package/dist/hooks.d.ts +96 -73
- package/dist/hooks.js +202 -116
- package/dist/index.d.ts +30 -26
- package/dist/index.js +29 -24
- package/dist/ledger.d.ts +62 -30
- package/dist/ledger.js +163 -56
- package/dist/platform.d.ts +15 -0
- package/dist/platform.js +15 -0
- package/dist/preselect.d.ts +223 -0
- package/dist/preselect.js +291 -0
- package/dist/request-body.d.ts +32 -0
- package/dist/request-body.js +47 -0
- package/dist/reset.d.ts +1 -0
- package/dist/reset.js +7 -6
- package/dist/retry.d.ts +44 -138
- package/dist/retry.js +83 -281
- package/dist/run-calls.d.ts +123 -0
- package/dist/run-calls.js +351 -0
- package/dist/run-turn.d.ts +36 -15
- package/dist/run-turn.js +74 -37
- package/dist/runtime.d.ts +23 -17
- package/dist/runtime.js +34 -24
- package/dist/schema-compat.d.ts +35 -18
- package/dist/schema-compat.js +346 -176
- package/dist/scope.d.ts +28 -5
- package/dist/scope.js +37 -10
- package/dist/side-task.d.ts +124 -40
- package/dist/side-task.js +186 -66
- package/dist/snapshot.d.ts +10 -5
- package/dist/snapshot.js +73 -30
- package/dist/spec.d.ts +56 -25
- package/dist/spec.js +494 -215
- package/dist/stream.d.ts +66 -16
- package/dist/stream.js +220 -97
- package/dist/thinking.d.ts +23 -8
- package/dist/thinking.js +92 -44
- package/dist/tokens.d.ts +164 -6
- package/dist/tokens.js +319 -6
- package/dist/tool-calls.d.ts +90 -17
- package/dist/tool-calls.js +207 -84
- package/dist/tool-loading.d.ts +101 -189
- package/dist/tool-loading.js +257 -371
- package/dist/wire.d.ts +81 -0
- package/dist/wire.js +73 -0
- package/llms.txt +76 -39
- package/package.json +4 -4
package/dist/tool-loading.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type OpenAI from
|
|
2
|
-
import type { CatalogServer } from
|
|
1
|
+
import type OpenAI from 'openai';
|
|
2
|
+
import type { CatalogServer } from './catalog.ts';
|
|
3
3
|
/**
|
|
4
4
|
* On-demand tool loading.
|
|
5
5
|
*
|
|
6
|
+
* @remarks
|
|
6
7
|
* A full tool definition is mostly JSON Schema, and it is sent on every request of every
|
|
7
8
|
* iteration whether or not the model wants it — a couple of connected servers can cost more
|
|
8
9
|
* tokens per request than the task's own prompt. So in on-demand mode the run starts with a
|
|
@@ -17,6 +18,7 @@ export declare const LOAD_TOOLS = "load_tools";
|
|
|
17
18
|
/**
|
|
18
19
|
* One object for the life of the process — the agent loop asks for it on every iteration.
|
|
19
20
|
*
|
|
21
|
+
* @remarks
|
|
20
22
|
* Frozen because it is shared: one mutable export reached by every consumer in the process
|
|
21
23
|
* means a caller that edits the description in place has edited it for all of them, in a place
|
|
22
24
|
* nobody would think to look for the change.
|
|
@@ -25,18 +27,28 @@ export declare const LOAD_TOOLS_DEFINITION: OpenAI.ChatCompletionTool;
|
|
|
25
27
|
/**
|
|
26
28
|
* The catalogue as a plain grouped listing of names, loaded ones marked if asked.
|
|
27
29
|
*
|
|
30
|
+
* @param catalog - The connected servers. Ones with no tools are dropped.
|
|
31
|
+
* @param [loaded] - Names to mark `(loaded)` rather than remove. Absent marks nothing, which keeps the
|
|
32
|
+
* listing the same text for the whole run.
|
|
33
|
+
* @returns Each server's label on a line ending in a colon, its tool names indented beneath, one
|
|
34
|
+
* server straight after another. Empty where no server has a tool.
|
|
35
|
+
*
|
|
36
|
+
* @remarks
|
|
28
37
|
* A server with no tools is dropped rather than titled: a pool hands one over whenever a
|
|
29
38
|
* server is connected but has nothing to offer, and a label with nothing under it reads as a
|
|
30
39
|
* listing that got cut off.
|
|
31
|
-
*
|
|
32
|
-
* @param catalog The connected servers. Ones with no tools are dropped.
|
|
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.
|
|
35
40
|
*/
|
|
36
41
|
export declare function catalogList(catalog: CatalogServer[], loaded?: ReadonlySet<string>): string;
|
|
37
42
|
/**
|
|
38
43
|
* The catalogue block appended to the system prompt. Names only — descriptions arrive on load.
|
|
39
44
|
*
|
|
45
|
+
* @param catalog - The connected servers. A catalogue with no tools in it produces an empty string.
|
|
46
|
+
* @param [loaded] - Names to mark `(loaded)`, for a caller that rebuilds its prompt per load and does
|
|
47
|
+
* not mind the cache. Absent marks nothing.
|
|
48
|
+
* @returns The heading, the instructions and the listing, with no blank line before or after — the
|
|
49
|
+
* caller separates it from its own prompt. Empty where there is nothing to list.
|
|
50
|
+
*
|
|
51
|
+
* @remarks
|
|
40
52
|
* `runAgentLoop` passes no `loaded`, so the block is the same text on every step. The system
|
|
41
53
|
* prompt is the head of the request, and marking each load there threw away the prompt cache for
|
|
42
54
|
* the whole transcript on every `load_tools` call. What is loaded is said where it does not move
|
|
@@ -47,32 +59,34 @@ export declare function catalogList(catalog: CatalogServer[], loaded?: ReadonlyS
|
|
|
47
59
|
* it was loaded, and the model loads again to get it back; hoisting them into a separate "already
|
|
48
60
|
* loaded" section splits a server's tools apart, and the model picks a sibling from the longer
|
|
49
61
|
* list instead.
|
|
50
|
-
*
|
|
51
|
-
* @param catalog The connected servers. A catalogue with no tools in it produces an empty string.
|
|
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.
|
|
54
62
|
*/
|
|
55
63
|
export declare function catalogPrompt(catalog: CatalogServer[], loaded?: ReadonlySet<string>): string;
|
|
56
64
|
/**
|
|
57
65
|
* The name a tool definition is called by, or `undefined` for one that is not a function.
|
|
58
66
|
*
|
|
67
|
+
* @param tool - The definition, as a request declares it.
|
|
68
|
+
* @returns The function's name as the definition spells it — an empty one comes back empty, not
|
|
69
|
+
* `undefined`.
|
|
70
|
+
*
|
|
71
|
+
* @remarks
|
|
59
72
|
* Undefined rather than empty, so a caller that skips such a tool and one that has to place it
|
|
60
73
|
* somewhere each say which they mean — a sort and a positional comparison want `?? ""`, a lookup
|
|
61
74
|
* by name wants the tool left out.
|
|
62
|
-
*
|
|
63
|
-
* @param tool The definition, as a request declares it.
|
|
64
75
|
*/
|
|
65
76
|
export declare const toolName: (tool: OpenAI.ChatCompletionTool) => string | undefined;
|
|
66
77
|
/**
|
|
67
78
|
* A tool array with newly loaded definitions appended, in the order they were loaded.
|
|
68
79
|
*
|
|
80
|
+
* @param previous - What the last request declared, `load_tools` included. Not written to.
|
|
81
|
+
* @param matched - The definitions to add. Ones whose name is already declared, here or earlier in
|
|
82
|
+
* this list, are skipped rather than moved. One that is not a function has no name to be
|
|
83
|
+
* skipped by, and is appended.
|
|
84
|
+
* @returns A new array, `previous` first — a copy even where nothing was added.
|
|
85
|
+
*
|
|
86
|
+
* @remarks
|
|
69
87
|
* Appended and never rebuilt from a set, so what a load adds is decided by the load and not by
|
|
70
88
|
* the shape of whatever collection the definitions came out of. Where the appended array ends up
|
|
71
89
|
* in the request is `orderTools`' business, which the loop applies after this.
|
|
72
|
-
*
|
|
73
|
-
* @param previous What the last request declared, `load_tools` included. Not written to.
|
|
74
|
-
* @param matched The definitions to add. Ones whose name is already declared, here or earlier in
|
|
75
|
-
* this list, are skipped rather than moved.
|
|
76
90
|
*/
|
|
77
91
|
export declare function loadedTools(previous: readonly OpenAI.ChatCompletionTool[], matched: readonly OpenAI.ChatCompletionTool[]): OpenAI.ChatCompletionTool[];
|
|
78
92
|
/**
|
|
@@ -83,6 +97,12 @@ export type ToolOrder = boolean | ((a: string, b: string) => number);
|
|
|
83
97
|
/**
|
|
84
98
|
* The tool array in a stable order, so the same set of tools renders the same way twice.
|
|
85
99
|
*
|
|
100
|
+
* @param tools - The definitions to order. Not written to.
|
|
101
|
+
* @param [order] - `true` for name order, `false` to leave it alone, or a comparator over the names.
|
|
102
|
+
* A tool that is not a function orders as the empty name.
|
|
103
|
+
* @returns `tools` itself when it is already in that order, so the common case copies nothing.
|
|
104
|
+
*
|
|
105
|
+
* @remarks
|
|
86
106
|
* A chat template renders the declared tools ahead of the system prompt, which makes the tool
|
|
87
107
|
* array the first thing a prompt cache has to match — and an array assembled from a map, from
|
|
88
108
|
* database rows, or from the order servers happened to connect in changes between processes and
|
|
@@ -94,16 +114,12 @@ export type ToolOrder = boolean | ((a: string, b: string) => number);
|
|
|
94
114
|
*
|
|
95
115
|
* `false` is for a caller that means its order: the model reads the array top to bottom, and a
|
|
96
116
|
* host may be putting what it wants reached for first at the front.
|
|
97
|
-
*
|
|
98
|
-
* @param tools The definitions to order. Not written to.
|
|
99
|
-
* @param order `true` for name order, `false` to leave it alone, or a comparator over the names.
|
|
100
|
-
* A tool that is not a function orders as the empty name.
|
|
101
|
-
* @returns `tools` itself when it is already in that order, so the common case copies nothing.
|
|
102
117
|
*/
|
|
103
118
|
export declare function orderTools(tools: OpenAI.ChatCompletionTool[], order?: ToolOrder): OpenAI.ChatCompletionTool[];
|
|
104
119
|
/**
|
|
105
120
|
* The most a single `load_tools` call may pull in.
|
|
106
121
|
*
|
|
122
|
+
* @remarks
|
|
107
123
|
* A wildcard like `gmail__*` matches 33 tools, and loading them all puts the model right back
|
|
108
124
|
* in the position on-demand loading exists to avoid — a tool array too large to choose from.
|
|
109
125
|
* Over-broad requests are refused with the matching names listed, so the next call can be
|
|
@@ -119,6 +135,7 @@ export declare const MAX_PER_LOAD = 12;
|
|
|
119
135
|
* The most a conversation carries between turns. Bounds the tool array no matter how long the
|
|
120
136
|
* conversation runs; past it, the earliest-declared names this turn did not use fall off first.
|
|
121
137
|
*
|
|
138
|
+
* @remarks
|
|
122
139
|
* Only a multi-turn caller needs this — a run that starts from nothing each time has nothing to
|
|
123
140
|
* carry. See `carryOver`, which takes another number if this one is not yours.
|
|
124
141
|
*/
|
|
@@ -126,34 +143,39 @@ export declare const MAX_CARRIED = 16;
|
|
|
126
143
|
/**
|
|
127
144
|
* The tools to start the next turn with: last turn's where they were, then what this turn used.
|
|
128
145
|
*
|
|
146
|
+
* @param previous - Last turn's names, in the order they were declared.
|
|
147
|
+
* @param used - What this turn called. Names not already carried are appended in the order given,
|
|
148
|
+
* so pass them in load order to keep them where the tool array had them.
|
|
149
|
+
* @param [max] - How many to carry. Past it, the earliest names not in
|
|
150
|
+
* `used` go first, then the earliest of all. At least one: a cap of zero is read as one, not as
|
|
151
|
+
* no cap and not as none.
|
|
152
|
+
* @returns The names to carry, as a new array no longer than the cap.
|
|
153
|
+
*
|
|
154
|
+
* @remarks
|
|
129
155
|
* Nothing carried moves. A template renders the tool array near the head of the prompt, and
|
|
130
156
|
* moving each used tool to the end — which this did until it was found in a local server's cache
|
|
131
157
|
* log — reordered the array between turns and re-prefilled the whole transcript from the first
|
|
132
158
|
* moved definition. Kept in place, the next turn's array is this one's with only the unused
|
|
133
159
|
* loads gone, a prefix of it when every load was used. Past `max`, dropping a name from the
|
|
134
160
|
* middle costs the cache from there, so it happens only when the cap forces it.
|
|
135
|
-
*
|
|
136
|
-
* @param previous Last turn's names, in the order they were declared.
|
|
137
|
-
* @param used What this turn called. Names not already carried are appended in the order given,
|
|
138
|
-
* so pass them in load order to keep them where the tool array had them.
|
|
139
|
-
* @param max How many to carry, defaulting to `MAX_CARRIED`. Past it, the earliest names not in
|
|
140
|
-
* `used` go first, then the earliest of all. At least one: a cap of zero is read as one, not as
|
|
141
|
-
* no cap and not as none.
|
|
142
161
|
*/
|
|
143
162
|
export declare function carryOver(previous: readonly string[], used: ReadonlySet<string>, max?: number): string[];
|
|
144
163
|
/**
|
|
145
164
|
* Resolves requested names against the catalogue, expanding trailing `*` wildcards.
|
|
146
165
|
*
|
|
166
|
+
* @param requested - What the model asked for. A trailing `*` expands.
|
|
167
|
+
* @param catalog - The servers to resolve against.
|
|
168
|
+
* @param [maxPerLoad] - The most this call may load. It comes back on
|
|
169
|
+
* the resolution so `loadResult` reports the same number rather than a second opinion of it.
|
|
170
|
+
* @returns The names that resolved, each once; the ones nothing matched; the asks too broad for
|
|
171
|
+
* any call, with what they matched; and the ones that only did not fit this call.
|
|
172
|
+
*
|
|
173
|
+
* @remarks
|
|
147
174
|
* Names are matched leniently. Catalogue entries are slug-qualified (`nas_fs__read_file`) and
|
|
148
175
|
* models routinely ask for the bare tool name, so an exact miss falls back to a suffix match
|
|
149
176
|
* on the `__` boundary — accepted only when it is unambiguous. Rejecting those outright just
|
|
150
177
|
* buys a wasted round trip while the model guesses the prefix, and pushes it toward
|
|
151
178
|
* shotgunning wildcards.
|
|
152
|
-
*
|
|
153
|
-
* @param requested What the model asked for. A trailing `*` expands.
|
|
154
|
-
* @param catalog The servers to resolve against.
|
|
155
|
-
* @param maxPerLoad The most this call may load, defaulting to `MAX_PER_LOAD`. It comes back on
|
|
156
|
-
* the resolution so `loadResult` reports the same number rather than a second opinion of it.
|
|
157
179
|
*/
|
|
158
180
|
export declare function expandNames(requested: string[], catalog: CatalogServer[], maxPerLoad?: number): {
|
|
159
181
|
matched: string[];
|
|
@@ -168,31 +190,39 @@ export declare function expandNames(requested: string[], catalog: CatalogServer[
|
|
|
168
190
|
/**
|
|
169
191
|
* What `load_tools` reports back: the descriptions, now that they are worth their tokens.
|
|
170
192
|
*
|
|
193
|
+
* @param expanded - What `expandNames` resolved: the matches, the misses, and the over-broad asks.
|
|
194
|
+
* @param catalog - The servers, read for the descriptions now worth their tokens.
|
|
195
|
+
* @param [loaded] - What was loaded before this call. Absent reports every match as newly loaded.
|
|
196
|
+
* @returns What the model reads, a blank line between each thing it is told: what was loaded with
|
|
197
|
+
* its descriptions, what already was, each over-broad ask with its matches, what did not fit this
|
|
198
|
+
* call, and what is not in the catalogue. `No tool names were given.` where there is none of them.
|
|
199
|
+
*
|
|
200
|
+
* @remarks
|
|
171
201
|
* A name that was loaded before this call is reported as already loaded rather than loaded
|
|
172
202
|
* again. The catalogue no longer marks what is loaded — see `catalogPrompt` — so this is where a
|
|
173
203
|
* model that asks twice finds out it need not have, and is told to call the tool instead.
|
|
174
|
-
*
|
|
175
|
-
* @param expanded What `expandNames` resolved: the matches, the misses, and the over-broad asks.
|
|
176
|
-
* @param catalog The servers, read for the descriptions now worth their tokens.
|
|
177
|
-
* @param loaded What was loaded before this call. Absent reports every match as newly loaded.
|
|
178
204
|
*/
|
|
179
205
|
export declare function loadResult({ matched, unknown, overBroad, deferred, maxPerLoad }: ReturnType<typeof expandNames>, catalog: CatalogServer[], loaded?: ReadonlySet<string>): string;
|
|
180
206
|
/**
|
|
181
207
|
* Whether the catalogue holds a tool by this name.
|
|
182
208
|
*
|
|
183
|
-
* @param catalog The connected servers and the tools each one offers.
|
|
184
|
-
* @param name An exact name. Nothing is prefixed, trimmed or fuzzily matched.
|
|
209
|
+
* @param catalog - The connected servers and the tools each one offers.
|
|
210
|
+
* @param name - An exact name. Nothing is prefixed, trimmed or fuzzily matched.
|
|
211
|
+
* @returns True where any server offers it, which no server of an empty catalogue does.
|
|
185
212
|
*/
|
|
186
213
|
export declare const inCatalog: (catalog: CatalogServer[], name: string) => boolean;
|
|
187
214
|
/**
|
|
188
215
|
* `load_tools` arguments, defensively — a model may send a bare string or a nested object.
|
|
189
216
|
*
|
|
190
|
-
* @param args The tool call's arguments, exactly as the model sent them.
|
|
217
|
+
* @param args - The tool call's arguments, exactly as the model sent them.
|
|
218
|
+
* @returns The names under `names`, or failing that `tools`, or `name`: a string as a list of one,
|
|
219
|
+
* an array less whatever in it is not a string, and anything else as none. Not trimmed.
|
|
191
220
|
*/
|
|
192
221
|
export declare function requestedNames(args: Record<string, unknown>): string[];
|
|
193
222
|
/**
|
|
194
223
|
* The one tool a proxied run reaches every catalogued tool through.
|
|
195
224
|
*
|
|
225
|
+
* @remarks
|
|
196
226
|
* Proxied discovery is on-demand loading with a tool array that never changes. On-demand mode
|
|
197
227
|
* declares each tool as it is loaded, and a chat template renders the tool array in the system
|
|
198
228
|
* turn, ahead of the whole conversation — so appending one definition there moves every token
|
|
@@ -208,6 +238,7 @@ export declare const CALL_TOOL = "call_tool";
|
|
|
208
238
|
* The whole tool array of a proxied run, `load_tools` then `call_tool`, frozen because it is
|
|
209
239
|
* shared.
|
|
210
240
|
*
|
|
241
|
+
* @remarks
|
|
211
242
|
* The load keeps `LOAD_TOOLS` as its name, so `requestedNames` and `expandNames` read its
|
|
212
243
|
* arguments as they do on demand; only what it promises differs, which is why it is not
|
|
213
244
|
* `LOAD_TOOLS_DEFINITION`. `call_tool`'s `arguments` says `additionalProperties: true` and has to:
|
|
@@ -220,52 +251,63 @@ export declare const PROXY_TOOLS: readonly OpenAI.ChatCompletionTool[];
|
|
|
220
251
|
* The catalogue block for a proxied run's system prompt, worded for `call_tool` rather than for a
|
|
221
252
|
* tool list.
|
|
222
253
|
*
|
|
254
|
+
* @param catalog - The connected servers. A catalogue with no tools in it produces an empty string.
|
|
255
|
+
* @returns The heading, the instructions and the listing, with no blank line before or after.
|
|
256
|
+
*
|
|
257
|
+
* @remarks
|
|
223
258
|
* `catalogPrompt` tells the model a loaded tool is in its tool list, which proxied is never true —
|
|
224
259
|
* a model told so looks for it there and calls it natively. The listing itself is the same, and
|
|
225
260
|
* like that one it is never marked, so the head of the prompt is one text for the whole session.
|
|
226
|
-
*
|
|
227
|
-
* @param catalog The connected servers. A catalogue with no tools in it produces an empty string.
|
|
228
261
|
*/
|
|
229
262
|
export declare function proxyCatalogPrompt(catalog: CatalogServer[]): string;
|
|
230
263
|
/**
|
|
231
264
|
* Whether a tool result is a proxied load carrying definitions, which is the only copy of them
|
|
232
265
|
* the model has.
|
|
233
266
|
*
|
|
267
|
+
* @param result - The tool message's text. A load that only pointed back or refused is not one.
|
|
268
|
+
* @returns True where the text opens as `proxyLoadResult` opens a result with a definition in it.
|
|
269
|
+
*
|
|
270
|
+
* @remarks
|
|
234
271
|
* On demand the definitions are in the tool array and a load's result only repeats their
|
|
235
272
|
* descriptions, so clearing it loses nothing. Proxied, the result is the schema, and
|
|
236
273
|
* `pruneToolResults` asks this before it stubs one. Told by how `proxyLoadResult` opens, the way
|
|
237
274
|
* a summary is told by `SUMMARY_LEAD`, because a `tool` message carries no tool name of its own.
|
|
238
|
-
*
|
|
239
|
-
* @param result The tool message's text. A load that only pointed back or refused is not one.
|
|
240
275
|
*/
|
|
241
276
|
export declare const holdsDefinitions: (result: string) => boolean;
|
|
242
277
|
/**
|
|
243
278
|
* What a proxied `load_tools` answers: each new tool's whole definition as a line of JSON, since
|
|
244
279
|
* the result is the only place the model will ever see it.
|
|
245
280
|
*
|
|
281
|
+
* @param resolved - What the call asked for, from `expandNames`.
|
|
282
|
+
* @param catalog - The servers, read for the refusals' wording.
|
|
283
|
+
* @param definitions - The definitions of `resolved.matched`, as many as the host has. Ones that
|
|
284
|
+
* are not functions are skipped.
|
|
285
|
+
* @param [loaded] - What was loaded before this call. Absent reports every match as newly loaded.
|
|
286
|
+
* @returns What the model reads, a blank line between each part: the count and one line of JSON
|
|
287
|
+
* per new definition, then what was already loaded, what has no definition, and the refusals.
|
|
288
|
+
* Never empty.
|
|
289
|
+
*
|
|
290
|
+
* @remarks
|
|
246
291
|
* A name loaded before this call is answered with a pointer back rather than its definition a
|
|
247
292
|
* second time, and one the catalogue lists but `definitions` does not hold is said to have none,
|
|
248
293
|
* so the model is not left waiting on a schema that is not coming. The refusals — too broad, over
|
|
249
294
|
* the per-call cap, not in the catalogue, nothing asked for — are `loadResult`'s, worded the same
|
|
250
295
|
* in both modes.
|
|
251
|
-
*
|
|
252
|
-
* @param resolved What the call asked for, from `expandNames`.
|
|
253
|
-
* @param catalog The servers, read for the refusals' wording.
|
|
254
|
-
* @param definitions The definitions of `resolved.matched`, as many as the host has. Ones that
|
|
255
|
-
* are not functions are skipped.
|
|
256
|
-
* @param loaded What was loaded before this call. Absent reports every match as newly loaded.
|
|
257
296
|
*/
|
|
258
297
|
export declare function proxyLoadResult(resolved: ReturnType<typeof expandNames>, catalog: CatalogServer[], definitions: readonly OpenAI.ChatCompletionTool[], loaded?: ReadonlySet<string>): string;
|
|
259
298
|
/**
|
|
260
299
|
* The tool a `call_tool` names and the arguments to run it with, or a throw the model can read.
|
|
261
300
|
*
|
|
301
|
+
* @param args - The `call_tool` call's own arguments, parsed. An absent `arguments` is no arguments.
|
|
302
|
+
* @param catalog - What may be called. The name is trimmed and then matched exactly.
|
|
303
|
+
* @returns The trimmed name, and the arguments as an object: the one the model passed, not a copy,
|
|
304
|
+
* or the one its JSON string parsed to.
|
|
305
|
+
*
|
|
306
|
+
* @remarks
|
|
262
307
|
* `arguments` arrives as an object when the model follows the schema and as a JSON string when it
|
|
263
308
|
* copies the shape of a native call instead; both are taken, since the intent is the same. A name
|
|
264
309
|
* outside the catalogue is refused here rather than handed to a dispatcher, which is what keeps
|
|
265
310
|
* `call_tool` from reaching anything the catalogue does not offer.
|
|
266
|
-
*
|
|
267
|
-
* @param args The `call_tool` call's own arguments, parsed. An absent `arguments` is no arguments.
|
|
268
|
-
* @param catalog What may be called. The name is trimmed and then matched exactly.
|
|
269
311
|
*/
|
|
270
312
|
export declare function proxiedCall(args: Record<string, unknown>, catalog: CatalogServer[]): {
|
|
271
313
|
name: string;
|
|
@@ -275,147 +317,17 @@ export declare function proxiedCall(args: Record<string, unknown>, catalog: Cata
|
|
|
275
317
|
* A tool call as a watcher should see it: a `call_tool` as the tool it ran, anything else as it
|
|
276
318
|
* is.
|
|
277
319
|
*
|
|
320
|
+
* @param name - The name the model called.
|
|
321
|
+
* @param input - The call's arguments as JSON text.
|
|
322
|
+
* @returns The inner name and its arguments as JSON text — the string itself where the model
|
|
323
|
+
* passed `arguments` as one.
|
|
324
|
+
*
|
|
325
|
+
* @remarks
|
|
278
326
|
* The transcript keeps the `call_tool` the model wrote, since the next request has to repeat it
|
|
279
327
|
* word for word to stay in the cache; only the display looks through it. Anything that does not
|
|
280
328
|
* parse as a proxied call is left as it came.
|
|
281
|
-
*
|
|
282
|
-
* @param name The name the model called.
|
|
283
|
-
* @param input The call's arguments as JSON text.
|
|
284
|
-
* @returns The inner name and its arguments as JSON text — the string itself where the model
|
|
285
|
-
* passed `arguments` as one.
|
|
286
329
|
*/
|
|
287
330
|
export declare function shownCall(name: string, input: string): {
|
|
288
331
|
name: string;
|
|
289
332
|
input: string;
|
|
290
333
|
};
|
|
291
|
-
/**
|
|
292
|
-
* The system prompt a preselector is given, holding it to the cap its answer will be held to.
|
|
293
|
-
*
|
|
294
|
-
* On-demand loading otherwise costs a round trip every run: the model reads the catalogue,
|
|
295
|
-
* calls `load_tools`, and only then can do the work. A small model reading the same catalogue
|
|
296
|
-
* usually names the right tools outright, so the task model finds them already loaded and
|
|
297
|
-
* starts working on its first step.
|
|
298
|
-
*
|
|
299
|
-
* A wrong guess is cheap — an unused definition is a few hundred tokens for one run — but a
|
|
300
|
-
* broad guess is not, so the same cap applies here as to a `load_tools` call.
|
|
301
|
-
*
|
|
302
|
-
* @param maxPerLoad The most to ask for, defaulting to `MAX_PER_LOAD`. Give `preselection` the
|
|
303
|
-
* same number: this one is what the preselector is told, and that one is what it is held to.
|
|
304
|
-
*/
|
|
305
|
-
export declare const preselectSystem: (maxPerLoad?: number) => string;
|
|
306
|
-
/**
|
|
307
|
-
* The shape a preselector's answer is held to where the server takes a schema: `{ tools: [...] }`.
|
|
308
|
-
*
|
|
309
|
-
* An object around the array rather than the array, because a structured answer's root has to be
|
|
310
|
-
* an object — OpenAI's strict mode and every tool-schema normaliser insist.
|
|
311
|
-
*/
|
|
312
|
-
export declare const PRESELECT_SCHEMA: {
|
|
313
|
-
type: string;
|
|
314
|
-
properties: {
|
|
315
|
-
tools: {
|
|
316
|
-
type: string;
|
|
317
|
-
items: {
|
|
318
|
-
type: string;
|
|
319
|
-
};
|
|
320
|
-
};
|
|
321
|
-
};
|
|
322
|
-
required: string[];
|
|
323
|
-
additionalProperties: boolean;
|
|
324
|
-
};
|
|
325
|
-
/** The preselection system prompt at the default cap, for a caller that never changes it. */
|
|
326
|
-
export declare const PRESELECT_SYSTEM: string;
|
|
327
|
-
/**
|
|
328
|
-
* The user message for a preselection call: the catalogue, then the request.
|
|
329
|
-
*
|
|
330
|
-
* @param catalog The connected servers, rendered as the name-only listing.
|
|
331
|
-
* @param prompt The request being planned for, truncated — choosing tools needs the shape of the
|
|
332
|
-
* ask, not all of it.
|
|
333
|
-
* @param maxPromptChars Where the request is cut, defaulting to 2000. A caller whose requests
|
|
334
|
-
* carry the part that names the work at the end wants a larger one, and pays for it in the
|
|
335
|
-
* preselector's prompt.
|
|
336
|
-
*/
|
|
337
|
-
export declare const preselectInput: (catalog: CatalogServer[], prompt: string, maxPromptChars?: number) => string;
|
|
338
|
-
/**
|
|
339
|
-
* Resolves a preselection against the catalogue: unknown names dropped, count capped.
|
|
340
|
-
*
|
|
341
|
-
* @param names What the preselector replied: `{ tools: [...] }` as `PRESELECT_SCHEMA` has it, or
|
|
342
|
-
* the bare array an older prompt asked for. Unvalidated: anything else gives none, and entries
|
|
343
|
-
* that are not strings are dropped.
|
|
344
|
-
* @param catalog The servers to resolve against.
|
|
345
|
-
* @param maxPerLoad The most to keep, defaulting to `MAX_PER_LOAD`. The same number
|
|
346
|
-
* `preselectSystem` was given, or the model is being held to a cap it was never told about.
|
|
347
|
-
*/
|
|
348
|
-
export declare function preselection(names: unknown, catalog: CatalogServer[], maxPerLoad?: number): string[];
|
|
349
|
-
/**
|
|
350
|
-
* The least a best match may score and still be acted on without a model.
|
|
351
|
-
*
|
|
352
|
-
* A BM25 score, so it is read against the shape of the corpus rather than as a percentage: a
|
|
353
|
-
* query term carried by half the catalogue is worth about 0.7, and one carried by a single tool
|
|
354
|
-
* about 3. One at this floor is therefore "something more distinctive than a word every other
|
|
355
|
-
* tool uses", which is the weakest evidence worth skipping a round trip on.
|
|
356
|
-
*
|
|
357
|
-
* A term is distinctive only against other terms, so a catalogue of three or four tools rarely
|
|
358
|
-
* clears it. That is the right answer rather than a gap: a catalogue that small is not costing
|
|
359
|
-
* enough tokens to be worth choosing from in the first place.
|
|
360
|
-
*/
|
|
361
|
-
export declare const KEYWORD_MIN_SCORE = 1;
|
|
362
|
-
/**
|
|
363
|
-
* How far the best unpicked tool must fall below the last picked one for the cut to count clean.
|
|
364
|
-
*
|
|
365
|
-
* Half. The cap is the only reason a hit is dropped, so a hit just underneath it scoring nearly
|
|
366
|
-
* as much as one just above means the ranking chose arbitrarily, which is exactly the case a
|
|
367
|
-
* model should be spent on.
|
|
368
|
-
*/
|
|
369
|
-
export declare const KEYWORD_DROPOFF = 0.5;
|
|
370
|
-
/** One tool's score against a request. */
|
|
371
|
-
export interface ToolMatch {
|
|
372
|
-
name: string;
|
|
373
|
-
/** Its BM25 score. Zero-scoring tools are not ranked at all. */
|
|
374
|
-
score: number;
|
|
375
|
-
}
|
|
376
|
-
/** What `preselectByKeywords` found. */
|
|
377
|
-
export interface KeywordPreselection {
|
|
378
|
-
/** The names, best first, capped at `maxPerLoad`. */
|
|
379
|
-
names: string[];
|
|
380
|
-
/** Whether the match is clear enough to run on without asking a model. */
|
|
381
|
-
confident: boolean;
|
|
382
|
-
/** Every tool that scored at all, best first — for a caller measuring its own threshold. */
|
|
383
|
-
ranked: ToolMatch[];
|
|
384
|
-
}
|
|
385
|
-
/** What `preselectByKeywords` takes besides the catalogue and the request. */
|
|
386
|
-
export interface KeywordPreselectOptions {
|
|
387
|
-
/** The most to pick, defaulting to `MAX_PER_LOAD`. The same cap the model is held to. */
|
|
388
|
-
maxPerLoad?: number;
|
|
389
|
-
/** The floor under a confident best match, defaulting to `KEYWORD_MIN_SCORE`. */
|
|
390
|
-
minScore?: number;
|
|
391
|
-
/** The gap a confident cut needs, defaulting to `KEYWORD_DROPOFF`. */
|
|
392
|
-
dropoff?: number;
|
|
393
|
-
/** Where the request is cut, defaulting to 2000 — the same head `preselectInput` reads. */
|
|
394
|
-
maxPromptChars?: number;
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* The tools a request's own words point at, ranked, and whether they point clearly enough.
|
|
398
|
-
*
|
|
399
|
-
* A preselection call costs a round trip to a model that is being asked to do term matching, and
|
|
400
|
-
* on a local box that is seconds before the run has started. For a catalogue of a few dozen tools
|
|
401
|
-
* the words usually decide it: a request that says "commit" and a tool called `git__commit` need
|
|
402
|
-
* no reasoning to connect.
|
|
403
|
-
*
|
|
404
|
-
* BM25 rather than counting shared words, because the ranking has to survive the words every tool
|
|
405
|
-
* uses. "list", "get" and "file" are in half the descriptions in a real catalogue, and a plain
|
|
406
|
-
* overlap count hands the top of the ranking to whichever tool has the longest description. The
|
|
407
|
-
* inverse document frequency makes a term worth what it distinguishes, and the length
|
|
408
|
-
* normalisation stops a wordy description from outscoring the tool actually named.
|
|
409
|
-
*
|
|
410
|
-
* `confident` is what a caller acts on, and it is deliberately hard to earn: something more
|
|
411
|
-
* distinctive than a word the whole catalogue shares has to have matched, and the tools left
|
|
412
|
-
* unpicked have to score well below the ones picked. Anything else is ambiguous, and ambiguous is
|
|
413
|
-
* what the model is for. Nothing matching is not confident either — the words cannot tell "this
|
|
414
|
-
* request needs no tools" from "these words are not in the catalogue".
|
|
415
|
-
*
|
|
416
|
-
* @param catalog The servers to choose from. Each tool is matched on its name, its server's label
|
|
417
|
-
* and its one-line description, which is everything the catalogue holds.
|
|
418
|
-
* @param prompt The request being planned for. Only its head is read, as in `preselectInput`.
|
|
419
|
-
* @param options The cap, the two confidence thresholds, and where the request is cut.
|
|
420
|
-
*/
|
|
421
|
-
export declare function preselectByKeywords(catalog: CatalogServer[], prompt: string, { maxPerLoad, minScore, dropoff, maxPromptChars, }?: KeywordPreselectOptions): KeywordPreselection;
|