@cubicecho/agent-core 2.9.0 → 2.10.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 +19 -0
- package/dist/client.d.ts +41 -5
- package/dist/client.js +69 -21
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/llms.txt +5 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -585,6 +585,25 @@ OpenRouter `:free` suffix, a typo) would otherwise fetch the listing on every ca
|
|
|
585
585
|
same zero each time. Half a minute later it asks again, so a model pulled onto a box that has been
|
|
586
586
|
up a week is still picked up without a restart.
|
|
587
587
|
|
|
588
|
+
Both numbers are defaults. `configureClients` moves them for the process, the way `configureEvents`
|
|
589
|
+
and `configureHooks` do — a multi-tenant host raising the pool so tenants stop evicting each other,
|
|
590
|
+
a dev box shortening the miss window so a model it has just pulled shows up sooner:
|
|
591
|
+
|
|
592
|
+
```ts
|
|
593
|
+
import { configureClients } from "@cubicecho/agent-core";
|
|
594
|
+
|
|
595
|
+
configureClients({ maxClients: 256, listingMissMs: 2_000 });
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
A field left out, or given anything that is not a number above zero, keeps what it has, and the
|
|
599
|
+
call returns everything in force. Lowering `maxClients` below the pool's current size evicts down to
|
|
600
|
+
it at once, least recently used first. `resetClients` (and `resetAll`) puts the defaults back.
|
|
601
|
+
|
|
602
|
+
A host that keeps per-endpoint state of its own should key it on `endpointKey` — the JSON of the base
|
|
603
|
+
URL and the key, an absent key read as `NO_KEY` — rather than rebuilding that string, so the two
|
|
604
|
+
cannot drift. `endpointKey` holds the key in the clear; `endpointId`, its SHA-256 digest, is the one
|
|
605
|
+
that is safe to write down.
|
|
606
|
+
|
|
588
607
|
`resetAll` drops all four, and `reset.ts` names each seam separately for a test that wants one.
|
|
589
608
|
|
|
590
609
|
The latches can outlive the process as well, because otherwise every restart spends one refused
|
package/dist/client.d.ts
CHANGED
|
@@ -12,6 +12,36 @@ export declare const NO_KEY = "agent-core";
|
|
|
12
12
|
* @param config Read for `requestTimeoutSeconds` alone.
|
|
13
13
|
*/
|
|
14
14
|
export declare const timeoutMs: (config: Pick<Endpoint, "requestTimeoutSeconds">) => number | undefined;
|
|
15
|
+
/** What the client pool is held to across a process. Every field optional; see `configureClients`. */
|
|
16
|
+
export interface ClientPoolOptions {
|
|
17
|
+
/** How many endpoints' clients are kept at once. The least recently asked for goes first. */
|
|
18
|
+
maxClients?: number;
|
|
19
|
+
/**
|
|
20
|
+
* How long, in milliseconds, a model an endpoint did not list — or a server that answered
|
|
21
|
+
* without a served window — is taken at its word before the endpoint is asked again.
|
|
22
|
+
*/
|
|
23
|
+
listingMissMs?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Changes what the client pool is held to, for a process whose endpoints are not shaped like the
|
|
27
|
+
* deployments these defaults were chosen for.
|
|
28
|
+
*
|
|
29
|
+
* Module-level for the same reason `configureEvents` is: the pool is one module-level thing, and
|
|
30
|
+
* its size is a deployment's setting, said once at startup. A multi-tenant host keying on a key
|
|
31
|
+
* per user raises `maxClients` so its tenants stop evicting each other's connection pools; a dev
|
|
32
|
+
* box shortens `listingMissMs` so a model it has just pulled is seen sooner.
|
|
33
|
+
*
|
|
34
|
+
* A `maxClients` below the pool's current size evicts down to it at once, least recently asked
|
|
35
|
+
* for first, as the next `getClient` would have. A shorter `listingMissMs` applies to misses
|
|
36
|
+
* already remembered, since each is a timestamp compared against it when read.
|
|
37
|
+
*
|
|
38
|
+
* @param options The bounds to change. A field left out — or given anything that is not a number
|
|
39
|
+
* above zero — keeps what it has, so a half-built config narrows nothing. `Infinity` is a number
|
|
40
|
+
* above zero: as `maxClients` it lifts the bound, and as `listingMissMs` a miss is never asked
|
|
41
|
+
* about again until `resetClients`.
|
|
42
|
+
* @returns Everything in force afterwards, including what this call did not change.
|
|
43
|
+
*/
|
|
44
|
+
export declare function configureClients(options?: ClientPoolOptions): Required<ClientPoolOptions>;
|
|
15
45
|
/** How many idle windows the first chunk gets when `firstTokenSeconds` is not given. */
|
|
16
46
|
export declare const FIRST_TOKEN_FACTOR = 5;
|
|
17
47
|
/**
|
|
@@ -29,7 +59,7 @@ export declare const firstTokenMs: (config: Pick<Endpoint, "requestTimeoutSecond
|
|
|
29
59
|
* The pool is per *deployment*, not per request: what belongs in this map is an endpoint an
|
|
30
60
|
* operator configured, and everything cached in this package is bounded on that reading. A
|
|
31
61
|
* consumer that mints an API key per user still gets a working client, but it is churning
|
|
32
|
-
* connection pools rather than sharing them and holding every one of them — `
|
|
62
|
+
* connection pools rather than sharing them and holding every one of them — `maxClients` keeps
|
|
33
63
|
* that from being unbounded, and it is the point at which a client of your own, built and held
|
|
34
64
|
* per tenant, is the better answer than this.
|
|
35
65
|
*
|
|
@@ -43,7 +73,7 @@ export interface ModelInfo {
|
|
|
43
73
|
}
|
|
44
74
|
/**
|
|
45
75
|
* What counts as one endpoint, everywhere in this package that has to remember something about
|
|
46
|
-
* one —
|
|
76
|
+
* one — the model listings, `capabilities`, and the no-thinking hints in `side-task`.
|
|
47
77
|
*
|
|
48
78
|
* The URL and the key together, because the key is part of what is on the other end rather than
|
|
49
79
|
* only how it is paid for: a router is free to send two keys to two different backends, and then
|
|
@@ -51,7 +81,9 @@ export interface ModelInfo {
|
|
|
51
81
|
* endpoint with no key and one that passes `undefined` are one entry rather than two.
|
|
52
82
|
*
|
|
53
83
|
* Stringified rather than joined on a separator, for the reason `getClient` gives: no character
|
|
54
|
-
* is impossible in a URL or a key, and two endpoints must never collide on one entry.
|
|
84
|
+
* is impossible in a URL or a key, and two endpoints must never collide on one entry. A host
|
|
85
|
+
* keeping its own per-endpoint state keys it on this rather than on a copy of it, so the two
|
|
86
|
+
* cannot drift apart. It holds the key in the clear; `endpointId` is the one to write down.
|
|
55
87
|
*
|
|
56
88
|
* @param config Read for `baseUrl` and `apiKey` alone, and the key is optional here where
|
|
57
89
|
* `Endpoint` requires it — `capabilitiesFor` is handed a URL and maybe a key rather than a whole
|
|
@@ -67,7 +99,8 @@ export declare const endpointKey: (config: {
|
|
|
67
99
|
*
|
|
68
100
|
* What an endpoint refused is exported by `exportCapabilities` to be written into a settings row
|
|
69
101
|
* or a file, and a key inside that blob is a credential copied somewhere nobody meant to keep one.
|
|
70
|
-
* A digest identifies the same endpoint on the next boot without saying what the key was
|
|
102
|
+
* A digest identifies the same endpoint on the next boot without saying what the key was, and it
|
|
103
|
+
* is how a host finds its own endpoint's entry in a `CapabilitySnapshot`.
|
|
71
104
|
*
|
|
72
105
|
* @param config Read for `baseUrl` and `apiKey` alone, as `endpointKey` reads it.
|
|
73
106
|
*/
|
|
@@ -118,5 +151,8 @@ export declare function listModels(config: Endpoint): Promise<ModelInfo[]>;
|
|
|
118
151
|
export declare function contextLimitFor(config: Endpoint & {
|
|
119
152
|
model: string;
|
|
120
153
|
}, declared?: number): Promise<number>;
|
|
121
|
-
/**
|
|
154
|
+
/**
|
|
155
|
+
* Forgets every cached client and listing, and puts `configureClients` back to the defaults. For
|
|
156
|
+
* tests, and for a settings change under test.
|
|
157
|
+
*/
|
|
122
158
|
export declare function resetClients(): void;
|
package/dist/client.js
CHANGED
|
@@ -33,7 +33,7 @@ export const timeoutMs = (config) => {
|
|
|
33
33
|
*/
|
|
34
34
|
const clients = new Map();
|
|
35
35
|
/**
|
|
36
|
-
* How many endpoints' clients are kept at once.
|
|
36
|
+
* How many endpoints' clients are kept at once, until `configureClients` moves it.
|
|
37
37
|
*
|
|
38
38
|
* This is a backstop rather than a design. The key includes the API key, and every argument in
|
|
39
39
|
* this file for what bounds these caches is "a settings row's worth" — true of the deployments
|
|
@@ -47,6 +47,56 @@ const clients = new Map();
|
|
|
47
47
|
* constraint.
|
|
48
48
|
*/
|
|
49
49
|
const MAX_CLIENTS = 32;
|
|
50
|
+
/** How long a model an endpoint did not list stays unlisted before it is asked about again. */
|
|
51
|
+
const LISTING_MISS_MS = 30_000;
|
|
52
|
+
/** The numbers this module was written with. */
|
|
53
|
+
const CLIENT_DEFAULTS = {
|
|
54
|
+
maxClients: MAX_CLIENTS,
|
|
55
|
+
listingMissMs: LISTING_MISS_MS,
|
|
56
|
+
};
|
|
57
|
+
/** What is in force now. Read where it is used, so a change applies from the next call. */
|
|
58
|
+
let poolLimits = { ...CLIENT_DEFAULTS };
|
|
59
|
+
/**
|
|
60
|
+
* Drops the least recently asked-for clients until the pool fits. Nothing is closed on the way
|
|
61
|
+
* out: the SDK holds no handle a caller can release, and an evicted client is garbage once
|
|
62
|
+
* whatever request is still in flight on it has finished — dropping the reference is the whole
|
|
63
|
+
* of the eviction.
|
|
64
|
+
*/
|
|
65
|
+
const evict = () => {
|
|
66
|
+
for (const oldest of clients.keys()) {
|
|
67
|
+
if (clients.size <= poolLimits.maxClients)
|
|
68
|
+
break;
|
|
69
|
+
clients.delete(oldest);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Changes what the client pool is held to, for a process whose endpoints are not shaped like the
|
|
74
|
+
* deployments these defaults were chosen for.
|
|
75
|
+
*
|
|
76
|
+
* Module-level for the same reason `configureEvents` is: the pool is one module-level thing, and
|
|
77
|
+
* its size is a deployment's setting, said once at startup. A multi-tenant host keying on a key
|
|
78
|
+
* per user raises `maxClients` so its tenants stop evicting each other's connection pools; a dev
|
|
79
|
+
* box shortens `listingMissMs` so a model it has just pulled is seen sooner.
|
|
80
|
+
*
|
|
81
|
+
* A `maxClients` below the pool's current size evicts down to it at once, least recently asked
|
|
82
|
+
* for first, as the next `getClient` would have. A shorter `listingMissMs` applies to misses
|
|
83
|
+
* already remembered, since each is a timestamp compared against it when read.
|
|
84
|
+
*
|
|
85
|
+
* @param options The bounds to change. A field left out — or given anything that is not a number
|
|
86
|
+
* above zero — keeps what it has, so a half-built config narrows nothing. `Infinity` is a number
|
|
87
|
+
* above zero: as `maxClients` it lifts the bound, and as `listingMissMs` a miss is never asked
|
|
88
|
+
* about again until `resetClients`.
|
|
89
|
+
* @returns Everything in force afterwards, including what this call did not change.
|
|
90
|
+
*/
|
|
91
|
+
export function configureClients(options = {}) {
|
|
92
|
+
for (const [name, value] of Object.entries(options)) {
|
|
93
|
+
if (typeof value === "number" && value > 0) {
|
|
94
|
+
poolLimits[name] = value;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
evict();
|
|
98
|
+
return { ...poolLimits };
|
|
99
|
+
}
|
|
50
100
|
/** How many idle windows the first chunk gets when `firstTokenSeconds` is not given. */
|
|
51
101
|
export const FIRST_TOKEN_FACTOR = 5;
|
|
52
102
|
/**
|
|
@@ -70,7 +120,7 @@ export const firstTokenMs = (config) => {
|
|
|
70
120
|
* The pool is per *deployment*, not per request: what belongs in this map is an endpoint an
|
|
71
121
|
* operator configured, and everything cached in this package is bounded on that reading. A
|
|
72
122
|
* consumer that mints an API key per user still gets a working client, but it is churning
|
|
73
|
-
* connection pools rather than sharing them and holding every one of them — `
|
|
123
|
+
* connection pools rather than sharing them and holding every one of them — `maxClients` keeps
|
|
74
124
|
* that from being unbounded, and it is the point at which a client of your own, built and held
|
|
75
125
|
* per tenant, is the better answer than this.
|
|
76
126
|
*
|
|
@@ -92,14 +142,7 @@ export function getClient(config) {
|
|
|
92
142
|
}
|
|
93
143
|
const client = new OpenAI({ baseURL: config.baseUrl, apiKey, timeout, maxRetries: 0 });
|
|
94
144
|
clients.set(key, client);
|
|
95
|
-
|
|
96
|
-
// evicted client is garbage once whatever request is still in flight on it has finished —
|
|
97
|
-
// dropping the reference is the whole of the eviction.
|
|
98
|
-
for (const oldest of clients.keys()) {
|
|
99
|
-
if (clients.size <= MAX_CLIENTS)
|
|
100
|
-
break;
|
|
101
|
-
clients.delete(oldest);
|
|
102
|
-
}
|
|
145
|
+
evict();
|
|
103
146
|
return client;
|
|
104
147
|
}
|
|
105
148
|
/**
|
|
@@ -156,17 +199,15 @@ const listings = new Map();
|
|
|
156
199
|
* match the configured name, an OpenRouter `:free` suffix, a typo in a settings row — and there
|
|
157
200
|
* every call fetches the listing, re-reads it, finds the same absence and answers the same zero.
|
|
158
201
|
*
|
|
159
|
-
* Remembering the miss for a moment answers both: within `
|
|
202
|
+
* Remembering the miss for a moment answers both: within `listingMissMs` nobody is asked, and
|
|
160
203
|
* after it the endpoint is asked again, so an `ollama pull` on a box that has been up a week is
|
|
161
204
|
* picked up within the minute instead of at the next restart. Bounded by the (endpoint, model)
|
|
162
205
|
* pairs actually asked about, which is the bound the listings themselves have.
|
|
163
206
|
*/
|
|
164
207
|
const misses = new Map();
|
|
165
|
-
/** How long a model an endpoint did not list stays unlisted before it is asked about again. */
|
|
166
|
-
const LISTING_MISS_MS = 30_000;
|
|
167
208
|
/**
|
|
168
209
|
* What counts as one endpoint, everywhere in this package that has to remember something about
|
|
169
|
-
* one —
|
|
210
|
+
* one — the model listings, `capabilities`, and the no-thinking hints in `side-task`.
|
|
170
211
|
*
|
|
171
212
|
* The URL and the key together, because the key is part of what is on the other end rather than
|
|
172
213
|
* only how it is paid for: a router is free to send two keys to two different backends, and then
|
|
@@ -174,7 +215,9 @@ const LISTING_MISS_MS = 30_000;
|
|
|
174
215
|
* endpoint with no key and one that passes `undefined` are one entry rather than two.
|
|
175
216
|
*
|
|
176
217
|
* Stringified rather than joined on a separator, for the reason `getClient` gives: no character
|
|
177
|
-
* is impossible in a URL or a key, and two endpoints must never collide on one entry.
|
|
218
|
+
* is impossible in a URL or a key, and two endpoints must never collide on one entry. A host
|
|
219
|
+
* keeping its own per-endpoint state keys it on this rather than on a copy of it, so the two
|
|
220
|
+
* cannot drift apart. It holds the key in the clear; `endpointId` is the one to write down.
|
|
178
221
|
*
|
|
179
222
|
* @param config Read for `baseUrl` and `apiKey` alone, and the key is optional here where
|
|
180
223
|
* `Endpoint` requires it — `capabilitiesFor` is handed a URL and maybe a key rather than a whole
|
|
@@ -187,7 +230,8 @@ export const endpointKey = (config) => JSON.stringify([config.baseUrl, config.ap
|
|
|
187
230
|
*
|
|
188
231
|
* What an endpoint refused is exported by `exportCapabilities` to be written into a settings row
|
|
189
232
|
* or a file, and a key inside that blob is a credential copied somewhere nobody meant to keep one.
|
|
190
|
-
* A digest identifies the same endpoint on the next boot without saying what the key was
|
|
233
|
+
* A digest identifies the same endpoint on the next boot without saying what the key was, and it
|
|
234
|
+
* is how a host finds its own endpoint's entry in a `CapabilitySnapshot`.
|
|
191
235
|
*
|
|
192
236
|
* @param config Read for `baseUrl` and `apiKey` alone, as `endpointKey` reads it.
|
|
193
237
|
*/
|
|
@@ -196,7 +240,7 @@ export const endpointId = (config) => createHash("sha256").update(endpointKey(co
|
|
|
196
240
|
* Served windows found by asking a server's own API, keyed on endpoint and model together.
|
|
197
241
|
*
|
|
198
242
|
* A model's entry stays until `resetClients`, like a listing; a server that answered without one
|
|
199
|
-
* is asked again after `
|
|
243
|
+
* is asked again after `listingMissMs`, like a listing that did not name the model.
|
|
200
244
|
*/
|
|
201
245
|
const served = new Map();
|
|
202
246
|
/** Endpoints that answered both probes with a refusal, and are not asked again. */
|
|
@@ -246,7 +290,7 @@ export async function servedWindow(config) {
|
|
|
246
290
|
return 0;
|
|
247
291
|
const key = JSON.stringify([endpoint, config.model]);
|
|
248
292
|
const known = served.get(key);
|
|
249
|
-
if (known && (known.window > 0 || Date.now() - known.at <
|
|
293
|
+
if (known && (known.window > 0 || Date.now() - known.at < poolLimits.listingMissMs))
|
|
250
294
|
return known.window;
|
|
251
295
|
let window = 0;
|
|
252
296
|
try {
|
|
@@ -324,8 +368,8 @@ export async function contextLimitFor(config, declared = 0) {
|
|
|
324
368
|
const asked = misses.get(missKey);
|
|
325
369
|
// Asked again, but not on every call. A model that is never coming answers the same zero
|
|
326
370
|
// however often the endpoint is asked, and a caller sizing a window per turn pays a round
|
|
327
|
-
// trip for each of them; `
|
|
328
|
-
if (asked !== undefined && Date.now() - asked <
|
|
371
|
+
// trip for each of them; `listingMissMs` is how long that answer is allowed to stand.
|
|
372
|
+
if (asked !== undefined && Date.now() - asked < poolLimits.listingMissMs)
|
|
329
373
|
return 0;
|
|
330
374
|
// A failure is not remembered: an endpoint that was down when the last run started is not
|
|
331
375
|
// an endpoint with no models, and a window nobody could ask about is not a failed run.
|
|
@@ -346,8 +390,12 @@ export async function contextLimitFor(config, declared = 0) {
|
|
|
346
390
|
}
|
|
347
391
|
return listed()?.contextLength ?? 0;
|
|
348
392
|
}
|
|
349
|
-
/**
|
|
393
|
+
/**
|
|
394
|
+
* Forgets every cached client and listing, and puts `configureClients` back to the defaults. For
|
|
395
|
+
* tests, and for a settings change under test.
|
|
396
|
+
*/
|
|
350
397
|
export function resetClients() {
|
|
398
|
+
poolLimits = { ...CLIENT_DEFAULTS };
|
|
351
399
|
clients.clear();
|
|
352
400
|
listings.clear();
|
|
353
401
|
misses.clear();
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
export { type AgentLoopHooks, type AgentLoopOptions, type AgentLoopResult, buildBody, preselect, preview, resolveApiKey, runAgentLoop, type ToolCallOutcome, type ToolCallRequest, } from "./agent-loop.ts";
|
|
13
13
|
export { type Capabilities, capabilitiesFor, type ModelCapabilities, modelCapabilitiesFor, type NegotiateOptions, negotiate, resetCapabilities, } from "./capabilities.ts";
|
|
14
14
|
export type { CatalogServer } from "./catalog.ts";
|
|
15
|
-
export { contextLimitFor, FIRST_TOKEN_FACTOR, firstTokenMs, getClient, listModels, type ModelInfo, NO_KEY, resetClients, servedWindow, timeoutMs, } from "./client.ts";
|
|
15
|
+
export { type ClientPoolOptions, configureClients, contextLimitFor, endpointId, endpointKey, FIRST_TOKEN_FACTOR, firstTokenMs, getClient, listModels, type ModelInfo, NO_KEY, resetClients, servedWindow, timeoutMs, } from "./client.ts";
|
|
16
16
|
export { COMPACT_AT, type CompactionOptions, type CompactionPlan, compactTranscript, KEEP_RATIO, type PruneOptions, planCompaction, pruneToolResults, SUMMARY_LEAD, SUMMARY_PROMPT, summariser, summaryInput, } from "./compaction.ts";
|
|
17
17
|
export type { AgentConfig, Endpoint, ModelParams, RetryPolicy, ToolPolicy, } from "./config.ts";
|
|
18
18
|
export { errorMessage } from "./errors.ts";
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
export { buildBody, preselect, preview, resolveApiKey, runAgentLoop, } from "./agent-loop.js";
|
|
13
13
|
export { capabilitiesFor, modelCapabilitiesFor, negotiate, resetCapabilities, } from "./capabilities.js";
|
|
14
|
-
export { contextLimitFor, FIRST_TOKEN_FACTOR, firstTokenMs, getClient, listModels, NO_KEY, resetClients, servedWindow, timeoutMs, } from "./client.js";
|
|
14
|
+
export { configureClients, contextLimitFor, endpointId, endpointKey, FIRST_TOKEN_FACTOR, firstTokenMs, getClient, listModels, NO_KEY, resetClients, servedWindow, timeoutMs, } from "./client.js";
|
|
15
15
|
export { COMPACT_AT, compactTranscript, KEEP_RATIO, planCompaction, pruneToolResults, SUMMARY_LEAD, SUMMARY_PROMPT, summariser, summaryInput, } from "./compaction.js";
|
|
16
16
|
export { errorMessage } from "./errors.js";
|
|
17
17
|
export { configureEvents, emit, endRun, fold, history, resetEvents, watch, } from "./events.js";
|
package/llms.txt
CHANGED
|
@@ -44,14 +44,18 @@ The contract between whatever holds the tools and the loop that offers them to a
|
|
|
44
44
|
|
|
45
45
|
### client
|
|
46
46
|
|
|
47
|
+
- `ClientPoolOptions` (type) — What the client pool is held to across a process.
|
|
48
|
+
- `configureClients` — Changes what the client pool is held to, for a process whose endpoints are not shaped like the deployments these defaults were chosen for.
|
|
47
49
|
- `contextLimitFor` — How much a model will read, in tokens.
|
|
50
|
+
- `endpointId` — `endpointKey` hashed, for the remembered facts that can leave the process.
|
|
51
|
+
- `endpointKey` — What counts as one endpoint, everywhere in this package that has to remember something about one — the model listings, `capabilities`, and the no-thinking hints in `side-task`.
|
|
48
52
|
- `FIRST_TOKEN_FACTOR` — How many idle windows the first chunk gets when `firstTokenSeconds` is not given.
|
|
49
53
|
- `firstTokenMs` — The wait for a streamed turn's first chunk, in the SDK's spelling: `undefined` is no limit.
|
|
50
54
|
- `getClient` — The client for an endpoint, built once and kept.
|
|
51
55
|
- `listModels` — Asks an endpoint what it serves, and remembers the answer.
|
|
52
56
|
- `ModelInfo` (type) — A model an endpoint offers, and what it says the model will read.
|
|
53
57
|
- `NO_KEY` — The SDK insists on a non-empty key even where the server will not look at it.
|
|
54
|
-
- `resetClients` — Forgets every cached client and listing.
|
|
58
|
+
- `resetClients` — Forgets every cached client and listing, and puts `configureClients` back to the defaults.
|
|
55
59
|
- `servedWindow` — The window a local server is actually serving a model in, which its listing does not say.
|
|
56
60
|
- `timeoutMs` — Zero, less, or absent means no limit, which the SDK spells as `undefined`.
|
|
57
61
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cubicecho/agent-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.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",
|