@cubicecho/agent-core 2.18.0 → 2.19.0
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 +177 -3
- package/dist/agent-loop.d.ts +171 -11
- package/dist/agent-loop.js +77 -19
- package/dist/compaction.d.ts +27 -1
- package/dist/compaction.js +45 -12
- package/dist/events.d.ts +17 -4
- package/dist/hooks.d.ts +8 -2
- package/dist/hooks.js +8 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/ledger.d.ts +132 -0
- package/dist/ledger.js +166 -0
- package/dist/retry.d.ts +6 -0
- package/dist/retry.js +6 -2
- package/dist/stream.d.ts +11 -0
- package/dist/tool-loading.d.ts +17 -8
- package/dist/tool-loading.js +25 -8
- package/llms.txt +18 -2
- package/package.json +1 -1
package/dist/ledger.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { messageChars, messageTokens } from "./retry.js";
|
|
2
|
+
/** Whether two messages say the same thing, by identity first since most of a transcript is. */
|
|
3
|
+
const sameMessage = (a, b) => a === b || JSON.stringify(a) === JSON.stringify(b);
|
|
4
|
+
/** Whether a request sent everything the one before it did, in the same place, and then more. */
|
|
5
|
+
const appended = (previous, next) => {
|
|
6
|
+
const before = previous.tools ?? [];
|
|
7
|
+
const now = next.tools ?? [];
|
|
8
|
+
return (before.length === now.length &&
|
|
9
|
+
before.every((name, at) => name === now[at]) &&
|
|
10
|
+
previous.messages.length <= next.messages.length &&
|
|
11
|
+
previous.messages.every((message, at) => sameMessage(message, next.messages[at])));
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* The ledger with one more request on it, in the epoch the request before it says it belongs to.
|
|
15
|
+
*
|
|
16
|
+
* The epoch carries on only where the new request declared the same tools in the same order and
|
|
17
|
+
* sent every earlier message unchanged — the case in which the two prompts subtract. Anything else
|
|
18
|
+
* starts a new one: a fold, a prune, a system prompt that moved, and a tool array that grew, whose
|
|
19
|
+
* schema would otherwise be counted as the cost of the messages beside it. A request that reported
|
|
20
|
+
* no prompt records nothing, and neither does one that reaches no further than the last entry in
|
|
21
|
+
* the same epoch, so a retry or a continuation leaves the first reading standing.
|
|
22
|
+
*
|
|
23
|
+
* @param ledger The ledger so far. Not written to; handed back as it is when nothing is recorded.
|
|
24
|
+
* @param previous The request the ledger's last entry was recorded from — not merely the last one
|
|
25
|
+
* sent, so that a request which reported nothing is skipped over rather than compared against.
|
|
26
|
+
* `undefined` where that is not known, which starts a new epoch.
|
|
27
|
+
* @param next The request just answered.
|
|
28
|
+
*/
|
|
29
|
+
export function recordRequest(ledger, previous, next) {
|
|
30
|
+
if (!(next.prompt > 0))
|
|
31
|
+
return ledger;
|
|
32
|
+
const last = ledger.at(-1);
|
|
33
|
+
if (last && previous && appended(previous, next)) {
|
|
34
|
+
if (next.through <= last.through)
|
|
35
|
+
return ledger;
|
|
36
|
+
return [...ledger, { through: next.through, prompt: next.prompt, epoch: last.epoch }];
|
|
37
|
+
}
|
|
38
|
+
return [
|
|
39
|
+
...ledger,
|
|
40
|
+
{ through: next.through, prompt: next.prompt, epoch: last ? last.epoch + 1 : 0 },
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The ledger for a transcript that has been rewritten, keeping the boundaries the rewrite left
|
|
45
|
+
* standing.
|
|
46
|
+
*
|
|
47
|
+
* A difference inside an epoch stays true after the epoch ends, since the prefix the two requests
|
|
48
|
+
* shared cancels whatever became of it. So the entries that fall in the part of the transcript
|
|
49
|
+
* still at its head keep their place, the ones in the part still at its tail move with it, and
|
|
50
|
+
* only the ones in between — the messages a fold removed or a prune stubbed — are dropped. The
|
|
51
|
+
* tail's entries move to a later epoch as well, so no difference is read across the rewrite.
|
|
52
|
+
*
|
|
53
|
+
* @param ledger The ledger for `before`. Not written to.
|
|
54
|
+
* @param before The transcript the ledger's indexes are in.
|
|
55
|
+
* @param after The transcript that replaces it. One that only appended to `before`, or is the same
|
|
56
|
+
* array, hands the ledger back as it is.
|
|
57
|
+
*/
|
|
58
|
+
export function rebaseLedger(ledger, before, after) {
|
|
59
|
+
if (before === after)
|
|
60
|
+
return ledger;
|
|
61
|
+
const shortest = Math.min(before.length, after.length);
|
|
62
|
+
let head = 0;
|
|
63
|
+
while (head < shortest && sameMessage(before[head], after[head]))
|
|
64
|
+
head++;
|
|
65
|
+
if (head === before.length)
|
|
66
|
+
return ledger;
|
|
67
|
+
let tail = 0;
|
|
68
|
+
while (tail < shortest - head &&
|
|
69
|
+
sameMessage(before[before.length - 1 - tail], after[after.length - 1 - tail]))
|
|
70
|
+
tail++;
|
|
71
|
+
// The boundary just ahead of a kept tail stands too: what follows it is all still there. With
|
|
72
|
+
// no tail kept there is nothing left for it to be the start of.
|
|
73
|
+
const start = tail > 0 ? before.length - tail - 1 : before.length;
|
|
74
|
+
const shift = after.length - before.length;
|
|
75
|
+
return ledger.flatMap((entry) => entry.through < head
|
|
76
|
+
? [entry]
|
|
77
|
+
: entry.through >= start
|
|
78
|
+
? [{ ...entry, through: entry.through + shift, epoch: entry.epoch + 1 }]
|
|
79
|
+
: []);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Each measured message's share of its group's cost, by index. A group is the messages between two
|
|
83
|
+
* neighbouring entries of one epoch, and is left out — for the estimate to answer — where the
|
|
84
|
+
* difference is not above zero, where the entries are out of order, or where the transcript does
|
|
85
|
+
* not reach its end.
|
|
86
|
+
*/
|
|
87
|
+
function shares(ledger, messages) {
|
|
88
|
+
const out = new Map();
|
|
89
|
+
let floor = 0;
|
|
90
|
+
for (let at = 1; at < ledger.length; at++) {
|
|
91
|
+
const from = ledger[at - 1];
|
|
92
|
+
const to = ledger[at];
|
|
93
|
+
const tokens = to.prompt - from.prompt;
|
|
94
|
+
const start = from.through + 1;
|
|
95
|
+
const end = to.through + 1;
|
|
96
|
+
if (from.epoch !== to.epoch || !(tokens > 0))
|
|
97
|
+
continue;
|
|
98
|
+
if (start < floor || end <= start || end > messages.length)
|
|
99
|
+
continue;
|
|
100
|
+
floor = end;
|
|
101
|
+
const chars = [];
|
|
102
|
+
let total = 0;
|
|
103
|
+
for (let index = start; index < end; index++) {
|
|
104
|
+
chars.push(messageChars(messages[index]));
|
|
105
|
+
total += chars[index - start];
|
|
106
|
+
}
|
|
107
|
+
for (let index = start; index < end; index++) {
|
|
108
|
+
out.set(index, (tokens * chars[index - start]) / total);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return out;
|
|
112
|
+
}
|
|
113
|
+
/** The estimate for a message nothing measured, as the options ask for it. */
|
|
114
|
+
const fallback = ({ charsPerToken, estimate }) => estimate ?? ((message) => messageTokens(message, { charsPerToken }));
|
|
115
|
+
/**
|
|
116
|
+
* What the messages from `from` up to, not including, `to` cost the window, measured where the
|
|
117
|
+
* ledger can say and estimated where it cannot.
|
|
118
|
+
*
|
|
119
|
+
* Between two boundaries recorded in one epoch it is a subtraction and exact. A boundary falls
|
|
120
|
+
* after a question and after each step's tool results, never after an assistant message, so a
|
|
121
|
+
* stretch that starts or ends inside a group is given that group's measured total divided by
|
|
122
|
+
* character share — the way `contextTokens` divides a reported prompt — and messages no pair of
|
|
123
|
+
* entries covers fall back to the estimate: the ones before the first entry, the group either side
|
|
124
|
+
* of an epoch's end, and whatever has not been sent yet.
|
|
125
|
+
*
|
|
126
|
+
* A difference of zero or less is not trusted and is estimated instead. That is how a server
|
|
127
|
+
* reporting `prompt_tokens` net of its cache would show up, though one whose net counts still
|
|
128
|
+
* happened to rise would not be caught by it.
|
|
129
|
+
*
|
|
130
|
+
* @param ledger The ledger kept for `messages`.
|
|
131
|
+
* @param from The first message counted. Below zero counts from the start.
|
|
132
|
+
* @param to The first message not counted, as `slice` takes it. Past the end counts to the end.
|
|
133
|
+
* @param messages The transcript the ledger's indexes are in.
|
|
134
|
+
* @param options The estimate for what is not measured: a divisor, or a function of the caller's.
|
|
135
|
+
* @returns Whole tokens, rounded once over the stretch rather than per message.
|
|
136
|
+
*/
|
|
137
|
+
export function tokensBetween(ledger, from, to, messages, options = {}) {
|
|
138
|
+
const measured = shares(ledger, messages);
|
|
139
|
+
const estimate = fallback(options);
|
|
140
|
+
let total = 0;
|
|
141
|
+
for (let at = Math.max(0, from); at < Math.min(to, messages.length); at++) {
|
|
142
|
+
total += measured.get(at) ?? estimate(messages[at]);
|
|
143
|
+
}
|
|
144
|
+
return Math.round(total);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* A per-message cost for `planCompaction`'s `estimate`: the measured share where the ledger covers
|
|
148
|
+
* the message, the calibrated estimate where it does not.
|
|
149
|
+
*
|
|
150
|
+
* The planner asks about one message at a time, and nothing reports anything that fine, so a
|
|
151
|
+
* measured message is given its group's total by character share. The shares are not rounded,
|
|
152
|
+
* which is what makes a whole group of them add back up to the difference the server reported.
|
|
153
|
+
*
|
|
154
|
+
* @param ledger The ledger kept for `messages`.
|
|
155
|
+
* @param messages The transcript the plan will be made for. The function it returns knows a
|
|
156
|
+
* message by identity, so it has to be asked about these objects and not copies of them; one it
|
|
157
|
+
* does not know is estimated.
|
|
158
|
+
* @param options The estimate for what is not measured: a divisor, or a function of the caller's.
|
|
159
|
+
*/
|
|
160
|
+
export function estimateFrom(ledger, messages, options = {}) {
|
|
161
|
+
const estimate = fallback(options);
|
|
162
|
+
const measured = new Map();
|
|
163
|
+
for (const [at, tokens] of shares(ledger, messages))
|
|
164
|
+
measured.set(messages[at], tokens);
|
|
165
|
+
return (message) => measured.get(message) ?? estimate(message);
|
|
166
|
+
}
|
package/dist/retry.d.ts
CHANGED
|
@@ -44,6 +44,12 @@ export interface TokenEstimateOptions {
|
|
|
44
44
|
*/
|
|
45
45
|
charsPerToken?: number;
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* How many characters one message is worth: its keys, and its content in whichever shape.
|
|
49
|
+
*
|
|
50
|
+
* @param message The message as it will be sent.
|
|
51
|
+
*/
|
|
52
|
+
export declare function messageChars(message: OpenAI.ChatCompletionMessageParam): number;
|
|
47
53
|
/**
|
|
48
54
|
* How many characters a tool array is worth, measured once per array.
|
|
49
55
|
*
|
package/dist/retry.js
CHANGED
|
@@ -71,8 +71,12 @@ const REASONING_ALT_KEY = 15;
|
|
|
71
71
|
export const CHARS_PER_TOKEN = 4;
|
|
72
72
|
/** The divisor an option asked for, or the fallback when it asked for nothing usable. */
|
|
73
73
|
const divisor = (charsPerToken) => charsPerToken !== undefined && charsPerToken > 0 ? charsPerToken : CHARS_PER_TOKEN;
|
|
74
|
-
/**
|
|
75
|
-
|
|
74
|
+
/**
|
|
75
|
+
* How many characters one message is worth: its keys, and its content in whichever shape.
|
|
76
|
+
*
|
|
77
|
+
* @param message The message as it will be sent.
|
|
78
|
+
*/
|
|
79
|
+
export function messageChars(message) {
|
|
76
80
|
let chars = message.role.length + ENVELOPE;
|
|
77
81
|
const { content } = message;
|
|
78
82
|
if (typeof content === "string")
|
package/dist/stream.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type OpenAI from "openai";
|
|
2
|
+
import { type ContextBreakdown } from "./retry.ts";
|
|
2
3
|
import { type Fence } from "./thinking.ts";
|
|
3
4
|
/**
|
|
4
5
|
* Reading one streamed turn back into a message.
|
|
@@ -95,6 +96,16 @@ export interface TurnUsage {
|
|
|
95
96
|
* prompt, so this is what every change to the tool list costs the cache.
|
|
96
97
|
*/
|
|
97
98
|
toolSchemaTokens?: number;
|
|
99
|
+
/**
|
|
100
|
+
* What the request was made of, as `contextTokens` cuts it, filled by `runAgentLoop`. Shares of
|
|
101
|
+
* the prompt the turn's first request reported, summing to it, or an estimate where none was.
|
|
102
|
+
*
|
|
103
|
+
* Measured on the request as first built, with the tools as `toolSchemaTokens` measures them. A
|
|
104
|
+
* continued turn's `prompt` is every request's summed, so it is larger than this `total`; and
|
|
105
|
+
* where a refusal was answered with a lesser body, the prompt is that body's and the proportions
|
|
106
|
+
* are still the first one's.
|
|
107
|
+
*/
|
|
108
|
+
context?: ContextBreakdown;
|
|
98
109
|
}
|
|
99
110
|
/** One streamed turn, put back together into the shape a loop and a transcript work with. */
|
|
100
111
|
export interface Turn {
|
package/dist/tool-loading.d.ts
CHANGED
|
@@ -107,21 +107,30 @@ export declare function orderTools(tools: OpenAI.ChatCompletionTool[], order?: T
|
|
|
107
107
|
export declare const MAX_PER_LOAD = 12;
|
|
108
108
|
/**
|
|
109
109
|
* The most a conversation carries between turns. Bounds the tool array no matter how long the
|
|
110
|
-
* conversation runs;
|
|
110
|
+
* conversation runs; past it, the earliest-declared names this turn did not use fall off first.
|
|
111
111
|
*
|
|
112
112
|
* Only a multi-turn caller needs this — a run that starts from nothing each time has nothing to
|
|
113
113
|
* carry. See `carryOver`, which takes another number if this one is not yours.
|
|
114
114
|
*/
|
|
115
115
|
export declare const MAX_CARRIED = 16;
|
|
116
116
|
/**
|
|
117
|
-
* The tools to start the next turn with:
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
117
|
+
* The tools to start the next turn with: last turn's where they were, then what this turn used.
|
|
118
|
+
*
|
|
119
|
+
* Nothing carried moves. A template renders the tool array near the head of the prompt, and
|
|
120
|
+
* moving each used tool to the end — which this did until it was found in a local server's cache
|
|
121
|
+
* log — reordered the array between turns and re-prefilled the whole transcript from the first
|
|
122
|
+
* moved definition. Kept in place, the next turn's array is this one's with only the unused
|
|
123
|
+
* loads gone, a prefix of it when every load was used. Past `max`, dropping a name from the
|
|
124
|
+
* middle costs the cache from there, so it happens only when the cap forces it.
|
|
125
|
+
*
|
|
126
|
+
* @param previous Last turn's names, in the order they were declared.
|
|
127
|
+
* @param used What this turn called. Names not already carried are appended in the order given,
|
|
128
|
+
* so pass them in load order to keep them where the tool array had them.
|
|
129
|
+
* @param max How many to carry, defaulting to `MAX_CARRIED`. Past it, the earliest names not in
|
|
130
|
+
* `used` go first, then the earliest of all. At least one: a cap of zero is read as one, not as
|
|
131
|
+
* no cap and not as none.
|
|
123
132
|
*/
|
|
124
|
-
export declare
|
|
133
|
+
export declare function carryOver(previous: readonly string[], used: ReadonlySet<string>, max?: number): string[];
|
|
125
134
|
/**
|
|
126
135
|
* Resolves requested names against the catalogue, expanding trailing `*` wildcards.
|
|
127
136
|
*
|
package/dist/tool-loading.js
CHANGED
|
@@ -174,21 +174,38 @@ export function orderTools(tools, order = true) {
|
|
|
174
174
|
export const MAX_PER_LOAD = 12;
|
|
175
175
|
/**
|
|
176
176
|
* The most a conversation carries between turns. Bounds the tool array no matter how long the
|
|
177
|
-
* conversation runs;
|
|
177
|
+
* conversation runs; past it, the earliest-declared names this turn did not use fall off first.
|
|
178
178
|
*
|
|
179
179
|
* Only a multi-turn caller needs this — a run that starts from nothing each time has nothing to
|
|
180
180
|
* carry. See `carryOver`, which takes another number if this one is not yours.
|
|
181
181
|
*/
|
|
182
182
|
export const MAX_CARRIED = 16;
|
|
183
183
|
/**
|
|
184
|
-
* The tools to start the next turn with:
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
184
|
+
* The tools to start the next turn with: last turn's where they were, then what this turn used.
|
|
185
|
+
*
|
|
186
|
+
* Nothing carried moves. A template renders the tool array near the head of the prompt, and
|
|
187
|
+
* moving each used tool to the end — which this did until it was found in a local server's cache
|
|
188
|
+
* log — reordered the array between turns and re-prefilled the whole transcript from the first
|
|
189
|
+
* moved definition. Kept in place, the next turn's array is this one's with only the unused
|
|
190
|
+
* loads gone, a prefix of it when every load was used. Past `max`, dropping a name from the
|
|
191
|
+
* middle costs the cache from there, so it happens only when the cap forces it.
|
|
192
|
+
*
|
|
193
|
+
* @param previous Last turn's names, in the order they were declared.
|
|
194
|
+
* @param used What this turn called. Names not already carried are appended in the order given,
|
|
195
|
+
* so pass them in load order to keep them where the tool array had them.
|
|
196
|
+
* @param max How many to carry, defaulting to `MAX_CARRIED`. Past it, the earliest names not in
|
|
197
|
+
* `used` go first, then the earliest of all. At least one: a cap of zero is read as one, not as
|
|
198
|
+
* no cap and not as none.
|
|
190
199
|
*/
|
|
191
|
-
export
|
|
200
|
+
export function carryOver(previous, used, max = MAX_CARRIED) {
|
|
201
|
+
const next = [...previous, ...[...used].filter((name) => !previous.includes(name))];
|
|
202
|
+
const cap = Math.max(1, max);
|
|
203
|
+
while (next.length > cap) {
|
|
204
|
+
const stale = next.findIndex((name) => !used.has(name));
|
|
205
|
+
next.splice(stale === -1 ? 0 : stale, 1);
|
|
206
|
+
}
|
|
207
|
+
return next;
|
|
208
|
+
}
|
|
192
209
|
/**
|
|
193
210
|
* Resolves requested names against the catalogue, expanding trailing `*` wildcards.
|
|
194
211
|
*
|
package/llms.txt
CHANGED
|
@@ -15,14 +15,17 @@ The loop above a turn: send, run the tools the model asked for, send again, unti
|
|
|
15
15
|
|
|
16
16
|
- `AgentLoopHooks` (type) — The hooks a loop runs around one question.
|
|
17
17
|
- `AgentLoopOptions` (type) — What `runAgentLoop` takes.
|
|
18
|
+
- `AgentLoopRequest` (type) — One step's request as `onRequest` is handed it: what the model is about to read.
|
|
18
19
|
- `AgentLoopResult` (type) — What a finished loop hands back.
|
|
19
20
|
- `buildBody` — The one place a streamed request's body is decided from a config and what the endpoint and the model have refused.
|
|
20
21
|
- `preselect` — The tools a request is likely to need, picked by a small model before the run starts, or none.
|
|
21
22
|
- `preview` — A long tool argument or result cut to what a watcher needs, with the full length said.
|
|
22
23
|
- `resolveApiKey` — The key to send, where an endpoint may inherit one from the settings it overrides.
|
|
23
24
|
- `runAgentLoop` — Runs a question to its answer: one `runTurn` per step, the tools it asks for between them, until a turn asks for none.
|
|
25
|
+
- `StepWindow` (type) — How full the window is as a step is about to be sent, as `beforeStep` is told it.
|
|
24
26
|
- `ToolCallOutcome` (type) — What one tool call did, in the order the model asked.
|
|
25
|
-
- `ToolCallRequest` (type) — One call the model made, as `dispatch`
|
|
27
|
+
- `ToolCallRequest` (type) — One call the model made, as `dispatch` and `onToolCall` are handed it.
|
|
28
|
+
- `ToolCallResult` (type) — One call's whole answer, as `onToolResult` is handed it.
|
|
26
29
|
|
|
27
30
|
### calibration
|
|
28
31
|
|
|
@@ -163,6 +166,19 @@ Lifecycle hooks, from the host's side: what a session looks like to them, where
|
|
|
163
166
|
- `untrusted` — Fences text nobody trusted — a fetched page, an email, a submitted card, a tool result — so the model can see where it starts and ends and read it as data rather than as instructions.
|
|
164
167
|
- `withContext` — The request, with the hooks' context added to this turn's question.
|
|
165
168
|
|
|
169
|
+
### ledger
|
|
170
|
+
|
|
171
|
+
What stretches of a transcript cost, read off the prompt counts the server already reported.
|
|
172
|
+
|
|
173
|
+
- `estimateFrom` — A per-message cost for `planCompaction`'s `estimate`: the measured share where the ledger covers the message, the calibrated estimate where it does not.
|
|
174
|
+
- `LedgerEntry` (type) — One request's reported prompt, and how far into the transcript that request reached.
|
|
175
|
+
- `LedgerEstimateOptions` (type) — What `tokensBetween` and `estimateFrom` take besides the ledger and the transcript.
|
|
176
|
+
- `LedgerRequest` (type) — What `recordRequest` needs to know of one request.
|
|
177
|
+
- `rebaseLedger` — The ledger for a transcript that has been rewritten, keeping the boundaries the rewrite left standing.
|
|
178
|
+
- `recordRequest` — The ledger with one more request on it, in the epoch the request before it says it belongs to.
|
|
179
|
+
- `TokenLedger` (type) — A transcript's entries in the order their requests were sent, which is also by `through`.
|
|
180
|
+
- `tokensBetween` — What the messages from `from` up to, not including, `to` cost the window, measured where the ledger can say and estimated where it cannot.
|
|
181
|
+
|
|
166
182
|
### reset
|
|
167
183
|
|
|
168
184
|
- `resetAll` — Forgets everything this package remembers between calls.
|
|
@@ -300,7 +316,7 @@ Reading what a model meant by a tool call when it did not write one cleanly.
|
|
|
300
316
|
|
|
301
317
|
### tool-loading
|
|
302
318
|
|
|
303
|
-
- `carryOver` — The tools to start the next turn with:
|
|
319
|
+
- `carryOver` — The tools to start the next turn with: last turn's where they were, then what this turn used.
|
|
304
320
|
- `catalogList` — The catalogue as a plain grouped listing of names, loaded ones marked if asked.
|
|
305
321
|
- `catalogPrompt` — The catalogue block appended to the system prompt.
|
|
306
322
|
- `expandNames` — Resolves requested names against the catalogue, expanding trailing `*` wildcards.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cubicecho/agent-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.19.0",
|
|
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",
|