toolnexus 0.24.0 → 0.26.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 +151 -1
- package/dist/acp.d.ts +37 -6
- package/dist/acp.js +239 -52
- package/dist/classifier.d.ts +189 -31
- package/dist/classifier.js +589 -30
- package/dist/client.d.ts +38 -8
- package/dist/client.js +102 -23
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/judge.d.ts +6 -3
- package/dist/judge.js +13 -1
- package/dist/mcp.d.ts +32 -7
- package/dist/mcp.js +125 -36
- package/dist/mcp2026/auth.d.ts +137 -0
- package/dist/mcp2026/auth.js +446 -0
- package/dist/mcp2026/client.d.ts +48 -0
- package/dist/mcp2026/client.js +160 -0
- package/dist/mcp2026/protocol.d.ts +54 -0
- package/dist/mcp2026/protocol.js +113 -0
- package/dist/mcp2026/skills.d.ts +5 -0
- package/dist/mcp2026/skills.js +25 -0
- package/dist/mcp2026/source.d.ts +86 -0
- package/dist/mcp2026/source.js +372 -0
- package/dist/mcp2026/stdio.d.ts +24 -0
- package/dist/mcp2026/stdio.js +99 -0
- package/dist/mcp2026/toolsearch.d.ts +5 -0
- package/dist/mcp2026/toolsearch.js +58 -0
- package/dist/mcphandler.d.ts +169 -0
- package/dist/mcphandler.js +1145 -0
- package/dist/mcpheader.d.ts +5 -0
- package/dist/mcpheader.js +18 -0
- package/dist/mcpserve.d.ts +24 -15
- package/dist/mcpserve.js +105 -2
- package/dist/mcpserverauth.d.ts +48 -0
- package/dist/mcpserverauth.js +203 -0
- package/dist/serve.js +7 -0
- package/dist/skill.d.ts +21 -0
- package/dist/skill.js +44 -0
- package/dist/toolkit.d.ts +20 -1
- package/dist/toolkit.js +25 -3
- package/dist/types.d.ts +22 -0
- package/package.json +4 -3
- package/src/acp.ts +258 -55
- package/src/classifier.ts +677 -46
- package/src/client.ts +130 -27
- package/src/index.ts +2 -0
- package/src/judge.ts +19 -4
- package/src/mcp.ts +162 -43
- package/src/mcp2026/auth.ts +473 -0
- package/src/mcp2026/client.ts +161 -0
- package/src/mcp2026/protocol.ts +135 -0
- package/src/mcp2026/skills.ts +22 -0
- package/src/mcp2026/source.ts +407 -0
- package/src/mcp2026/stdio.ts +102 -0
- package/src/mcp2026/toolsearch.ts +56 -0
- package/src/mcphandler.ts +1252 -0
- package/src/mcpheader.ts +19 -0
- package/src/mcpserve.ts +115 -2
- package/src/mcpserverauth.ts +216 -0
- package/src/serve.ts +7 -0
- package/src/skill.ts +50 -0
- package/src/toolkit.ts +31 -4
- package/src/types.ts +23 -0
package/dist/classifier.d.ts
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Classifier (SPEC.md §8B) — the contract for a JUDGMENT, as `Tool` is the contract for an
|
|
3
|
-
* ACTION. A System One model takes a state plus pre-declared, typed questions and returns
|
|
4
|
-
* calibrated answers with no free text. It has no messages, no tool calling and no streaming,
|
|
5
|
-
* so it never enters the §8 client loop.
|
|
6
|
-
*
|
|
7
|
-
* A classifier INTERPRETS; it never AUTHORISES. Schema validity is not correctness: a decision
|
|
8
|
-
* can be confidently wrong, and "cannot hallucinate" means only that the returned value is in
|
|
9
|
-
* the declared schema. Numeric limits, permission checks and allowlists stay in code. Nothing
|
|
10
|
-
* here is a security control.
|
|
11
|
-
*/
|
|
12
1
|
import type { Client } from "./client.js";
|
|
13
2
|
import { type ErrorInfo, type ErrorTier, type MetricEvent } from "./client.js";
|
|
14
3
|
/** The System One endpoint base. */
|
|
@@ -24,15 +13,50 @@ export declare const DEFAULT_BATCH_CONCURRENCY = 16;
|
|
|
24
13
|
/**
|
|
25
14
|
* A named BACKEND: `baseUrl`, `model` and `apiKeyEnv` are only jointly valid, so they travel as
|
|
26
15
|
* a UNIT (ADR 0027 D1). `jev-latest` is TypeSafe's spelling; the gateway spells the same model
|
|
27
|
-
* `typesafe/jev-1.
|
|
16
|
+
* `typesafe/jev-1.14`, and mixing the two is issue #91. `custom` is a self-hosted System One
|
|
17
|
+
* endpoint and requires `baseUrl` + `supports` (SPEC §8B "Backends, images, cache and validation").
|
|
28
18
|
*/
|
|
29
|
-
export type ClassifierBackend = "typesafe" | "openrouter";
|
|
30
|
-
/**
|
|
31
|
-
|
|
19
|
+
export type ClassifierBackend = "typesafe" | "openrouter" | "cloudflare" | "vercel" | "custom";
|
|
20
|
+
/** What a backend+model can take. DATA: a fail-fast for what the table says, never a claim about
|
|
21
|
+
* the vendor. Override per classifier with `ClassifierOptions.supports`. */
|
|
22
|
+
export interface ClassifierSupports {
|
|
23
|
+
images: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** One row of the backend table. */
|
|
26
|
+
export interface ClassifierBackendPreset {
|
|
27
|
+
/** `""` on `custom`, which requires `baseUrl`. May carry `${NAME}`, expanded at call time. */
|
|
32
28
|
baseUrl: string;
|
|
33
29
|
model: string;
|
|
34
30
|
apiKeyEnv: string;
|
|
35
|
-
}
|
|
31
|
+
/** `systemone`: POST {baseUrl}/systemone. `cloudflare`: POST {baseUrl}, `/ai/run` envelope. */
|
|
32
|
+
wire: "systemone" | "cloudflare";
|
|
33
|
+
/** Send `TypeSafe-Danger-Zone-Images: true` when a request carries images. */
|
|
34
|
+
imagesHeader: boolean;
|
|
35
|
+
/** The default support for a model on this backend; absent on `custom`. */
|
|
36
|
+
supports?: (model: string) => ClassifierSupports;
|
|
37
|
+
}
|
|
38
|
+
/** TypeSafe's required opt-in header for image ("danger zone") input. */
|
|
39
|
+
export declare const CLASSIFIER_IMAGES_HEADER = "TypeSafe-Danger-Zone-Images";
|
|
40
|
+
/** Image limits (docs.typesafe.ai/images): checked client-side, never resized. */
|
|
41
|
+
export declare const CLASSIFIER_IMAGE_MIN_SIDE = 280;
|
|
42
|
+
export declare const CLASSIFIER_IMAGE_MAX_SIDE = 1568;
|
|
43
|
+
export declare const CLASSIFIER_IMAGE_MAX_BYTES: number;
|
|
44
|
+
export declare const CLASSIFIER_REQUEST_IMAGE_BYTES: number;
|
|
45
|
+
/**
|
|
46
|
+
* The backend table (PROPOSED defaults, owner to confirm — design.md PD-1..PD-4). Vercel and
|
|
47
|
+
* Cloudflare-Jev images stay false until a live probe proves them.
|
|
48
|
+
*/
|
|
49
|
+
export declare const CLASSIFIER_BACKENDS: Readonly<Record<ClassifierBackend, Readonly<ClassifierBackendPreset>>>;
|
|
50
|
+
/**
|
|
51
|
+
* Raised BEFORE any network call when the backend table says the backend cannot take what the
|
|
52
|
+
* request carries. Message, exact: `classifier: <backend> (<model>) does not support <feature>`.
|
|
53
|
+
*/
|
|
54
|
+
export declare class ClassifierUnsupported extends Error {
|
|
55
|
+
readonly backend: string;
|
|
56
|
+
readonly model: string;
|
|
57
|
+
readonly feature: string;
|
|
58
|
+
constructor(backend: string, model: string, feature: string);
|
|
59
|
+
}
|
|
36
60
|
/** Client-side cap on a choice's named options (§8B). */
|
|
37
61
|
export declare const MAX_CHOICE_OPTIONS = 255;
|
|
38
62
|
/** Bounds of a score rubric (§8B). */
|
|
@@ -83,8 +107,25 @@ export interface ScoreQuestion {
|
|
|
83
107
|
instructions: string;
|
|
84
108
|
criteria: string[];
|
|
85
109
|
}
|
|
86
|
-
/** The
|
|
110
|
+
/** The modelled question types, discriminated by `type`. */
|
|
87
111
|
export type Question = NoulQuestion | ChoiceQuestion | ScoreQuestion;
|
|
112
|
+
/**
|
|
113
|
+
* The OPEN end of the question union (§8B): a System One type the library does not model (e.g.
|
|
114
|
+
* Jev 1.14 `box`), sent as written with no client-side limits. `type` must be non-empty.
|
|
115
|
+
*/
|
|
116
|
+
export interface RawQuestion {
|
|
117
|
+
type: string;
|
|
118
|
+
instructions: string;
|
|
119
|
+
/** Sent verbatim when present, absent otherwise. */
|
|
120
|
+
criteria?: unknown;
|
|
121
|
+
}
|
|
122
|
+
/** Every question `evaluate` accepts: the modelled three plus a raw one. */
|
|
123
|
+
export type AnyQuestion = Question | RawQuestion;
|
|
124
|
+
/** True when `q` is a raw question (its type is not noul/choice/score). Not a type guard: every
|
|
125
|
+
* modelled question is structurally a `RawQuestion` too. */
|
|
126
|
+
export declare function isRawQuestion(q: AnyQuestion): boolean;
|
|
127
|
+
/** A raw question, sent as written. */
|
|
128
|
+
export declare function raw(type: string, instructions: string, criteria?: unknown): RawQuestion;
|
|
88
129
|
/** A noul question. Pass `criteria` only when you mean it — absent ≠ empty on the wire. */
|
|
89
130
|
export declare function noul(instructions: string, criteria?: NoulCriteria): NoulQuestion;
|
|
90
131
|
/** A choice question. Every description must say what picking that option would MEAN. */
|
|
@@ -98,7 +139,7 @@ export declare function score(instructions: string, criteria: string[]): ScoreQu
|
|
|
98
139
|
*/
|
|
99
140
|
export declare function choiceOver(instructions: string, items: Record<string, string>): ChoiceQuestion;
|
|
100
141
|
/** The wire form of one question — the object itself, minus an absent `criteria`. */
|
|
101
|
-
export declare function questionWire(
|
|
142
|
+
export declare function questionWire(question: AnyQuestion): Record<string, unknown>;
|
|
102
143
|
/**
|
|
103
144
|
* Canonical JSON: object keys sorted recursively in CODE-UNIT (ASCII) order, arrays NEVER
|
|
104
145
|
* reordered, compact separators, and `<>&'"` plus non-ASCII transmitted raw.
|
|
@@ -120,7 +161,7 @@ export declare function canonicalJson(value: unknown): string;
|
|
|
120
161
|
* ways across our own seven runtimes). Do not re-widen this: a caller who needs their state
|
|
121
162
|
* pinned canonicalises it themselves before handing it over.
|
|
122
163
|
*/
|
|
123
|
-
export declare function canonicalRequest(model: string, questions: Record<string,
|
|
164
|
+
export declare function canonicalRequest(model: string, questions: Record<string, AnyQuestion>): string;
|
|
124
165
|
/** The probability that a statement holds. NO confidence: the number is the answer. */
|
|
125
166
|
export interface NoulAnswer {
|
|
126
167
|
type: "noul";
|
|
@@ -155,6 +196,18 @@ export interface ScoreAnswer {
|
|
|
155
196
|
* `Answer` (the suspension resolution) — same idea, different seam.
|
|
156
197
|
*/
|
|
157
198
|
export type DecisionAnswer = NoulAnswer | ChoiceAnswer | ScoreAnswer;
|
|
199
|
+
/**
|
|
200
|
+
* An answer of a type the library does not model (the open union, §8B). It may appear in
|
|
201
|
+
* `Decision.answers` at runtime (read it with `decision.raw(key)` or `isRawAnswer`); `value` is the
|
|
202
|
+
* whole answer object as decoded, `type` included. It is kept out of `DecisionAnswer` so existing
|
|
203
|
+
* `switch (a.type)` narrowing keeps compiling.
|
|
204
|
+
*/
|
|
205
|
+
export interface RawAnswer {
|
|
206
|
+
type: string;
|
|
207
|
+
value: Record<string, unknown>;
|
|
208
|
+
}
|
|
209
|
+
/** True when an answer is a raw (unmodelled-type) answer. */
|
|
210
|
+
export declare function isRawAnswer(a: unknown): a is RawAnswer;
|
|
158
211
|
/** The wire's usage block. `cost` is absent on some backends. */
|
|
159
212
|
export interface ClassifierUsage {
|
|
160
213
|
inputTokens: number;
|
|
@@ -178,6 +231,8 @@ export declare class Decision {
|
|
|
178
231
|
* BACKEND DOES NOT TRANSFER TO ANOTHER.
|
|
179
232
|
*/
|
|
180
233
|
readonly calibrated: boolean;
|
|
234
|
+
/** True when the decision came from `ClassifierOptions.cache` and no request was sent. */
|
|
235
|
+
readonly cached: boolean;
|
|
181
236
|
constructor(
|
|
182
237
|
/** What actually answered, which may be more specific than the model that was asked for. */
|
|
183
238
|
model: string, answers: Record<string, DecisionAnswer>, usage: ClassifierUsage,
|
|
@@ -186,7 +241,11 @@ export declare class Decision {
|
|
|
186
241
|
* unless it derived them from provider token probabilities. A THRESHOLD TUNED AGAINST ONE
|
|
187
242
|
* BACKEND DOES NOT TRANSFER TO ANOTHER.
|
|
188
243
|
*/
|
|
189
|
-
calibrated: boolean
|
|
244
|
+
calibrated: boolean,
|
|
245
|
+
/** True when the decision came from `ClassifierOptions.cache` and no request was sent. */
|
|
246
|
+
cached?: boolean);
|
|
247
|
+
/** Typed read of a raw (unmodelled-type) answer. Throws on an absent key or a modelled type. */
|
|
248
|
+
raw(key: string): RawAnswer;
|
|
190
249
|
/** Typed read. Throws (never returns undefined) on a wrong-type or absent key. */
|
|
191
250
|
noul(key: string): NoulAnswer;
|
|
192
251
|
choice(key: string): ChoiceAnswer;
|
|
@@ -210,7 +269,12 @@ export declare function nearUniform(probabilities: Record<string, number>): bool
|
|
|
210
269
|
* `nearUniform` is derived. A malformed answer is an error, never a repaired one (ADR 0020).
|
|
211
270
|
*/
|
|
212
271
|
export declare function decodeDecision(raw: unknown, fallbackModel: string): Decision;
|
|
213
|
-
/**
|
|
272
|
+
/**
|
|
273
|
+
* `"systemone" | "llm" | "custom" | "static"` — the same slot as the client's `style`.
|
|
274
|
+
*
|
|
275
|
+
* `"llm"` is DEPRECATED (ADR 0038 D3: System One is the single product wire). It keeps working
|
|
276
|
+
* byte-identically, as an alias, for at least one minor release; there is no runtime warning.
|
|
277
|
+
*/
|
|
214
278
|
export type ClassifierStyle = "systemone" | "llm" | "custom" | "static";
|
|
215
279
|
/**
|
|
216
280
|
* One entry of the `static` corpus. It is keyed on the canonical request AND the state: several
|
|
@@ -220,12 +284,12 @@ export type ClassifierStyle = "systemone" | "llm" | "custom" | "static";
|
|
|
220
284
|
*/
|
|
221
285
|
export interface RecordedDecision {
|
|
222
286
|
state: unknown;
|
|
223
|
-
questions: Record<string,
|
|
287
|
+
questions: Record<string, AnyQuestion>;
|
|
224
288
|
/** The recorded backend response body, verbatim. */
|
|
225
289
|
response: unknown;
|
|
226
290
|
}
|
|
227
291
|
/** The host's own backend (`style: "custom"`). Every wire option is ignored. */
|
|
228
|
-
export type EvaluateFn = (state: unknown, questions: Record<string,
|
|
292
|
+
export type EvaluateFn = (state: unknown, questions: Record<string, AnyQuestion>, signal?: AbortSignal) => Promise<Decision> | Decision;
|
|
229
293
|
/**
|
|
230
294
|
* Mirrors §8 `ClientOptions` field-for-field wherever a field makes sense, so a host that has
|
|
231
295
|
* configured one has configured the other.
|
|
@@ -233,7 +297,7 @@ export type EvaluateFn = (state: unknown, questions: Record<string, Question>, s
|
|
|
233
297
|
export interface ClassifierOptions {
|
|
234
298
|
/** Default `"systemone"`. */
|
|
235
299
|
style?: ClassifierStyle;
|
|
236
|
-
/** A named `
|
|
300
|
+
/** A named backend row (`"typesafe"` | `"openrouter"` | `"cloudflare"` | `"vercel"` | `"custom"`), set as a
|
|
237
301
|
* UNIT. Default `"typesafe"`. The three individual options still win where given, for a
|
|
238
302
|
* self-hosted origin — but a known-bad mixture is refused at construction, not 700 ms later
|
|
239
303
|
* as an "Unknown model" 400. */
|
|
@@ -277,12 +341,34 @@ export interface ClassifierOptions {
|
|
|
277
341
|
/** Emits `classifier.evaluate` events into the SAME §8 sink, and carries the
|
|
278
342
|
* degenerate-criteria warning as `classifier.warning`. */
|
|
279
343
|
onMetric?: (ev: MetricEvent) => void;
|
|
280
|
-
/** `style: "llm"` only — the §8 Client to emulate over.
|
|
344
|
+
/** `style: "llm"` only — the §8 Client to emulate over.
|
|
345
|
+
* @deprecated `style: "llm"` is deprecated (System One is the single wire); it still works. */
|
|
281
346
|
client?: Client;
|
|
282
347
|
/** `style: "custom"` only — the host's own function. */
|
|
283
348
|
evaluate?: EvaluateFn;
|
|
284
349
|
/** `style: "static"` only — the recorded corpus. */
|
|
285
350
|
decisions?: RecordedDecision[];
|
|
351
|
+
/** Overrides the backend table's support row for this classifier. Required with `backend: "custom"`. */
|
|
352
|
+
supports?: ClassifierSupports;
|
|
353
|
+
/** Opt-in answer cache (§8B). Absent ⇒ no caching. Consulted by style `systemone` only; only
|
|
354
|
+
* replies that pass `validateDecision` are stored. Methods may return values or Promises. */
|
|
355
|
+
cache?: ClassifierCache;
|
|
356
|
+
}
|
|
357
|
+
/** An injected answer cache. Values are opaque strings: the served model under a model key, the
|
|
358
|
+
* System One reply body under a decision key. */
|
|
359
|
+
export interface ClassifierCache {
|
|
360
|
+
get(key: string): string | undefined | null | Promise<string | undefined | null>;
|
|
361
|
+
set(key: string, value: string): void | Promise<void>;
|
|
362
|
+
}
|
|
363
|
+
/** One state's outcome from `states(...).evaluate`: exactly one of `decision` / `error` is set. */
|
|
364
|
+
export interface BatchResult {
|
|
365
|
+
decision?: Decision;
|
|
366
|
+
error?: Error;
|
|
367
|
+
}
|
|
368
|
+
/** A named question (`judge.noul(...)` etc. build these). */
|
|
369
|
+
export interface NamedClassifierQuestion {
|
|
370
|
+
name: string;
|
|
371
|
+
question: AnyQuestion;
|
|
286
372
|
}
|
|
287
373
|
/** The whole seam: one verb. */
|
|
288
374
|
export declare class Classifier {
|
|
@@ -292,6 +378,9 @@ export declare class Classifier {
|
|
|
292
378
|
private readonly model;
|
|
293
379
|
private readonly apiKeyEnv;
|
|
294
380
|
private readonly timeoutMs;
|
|
381
|
+
private readonly backend;
|
|
382
|
+
private readonly preset;
|
|
383
|
+
private readonly supports;
|
|
295
384
|
private readonly corpus;
|
|
296
385
|
/** The once-per-question-key set for the degenerate warning, so a per-turn judge does not
|
|
297
386
|
* flood the sink. */
|
|
@@ -301,14 +390,33 @@ export declare class Classifier {
|
|
|
301
390
|
* The whole contract: a state plus typed questions in, a Decision out. Questions are
|
|
302
391
|
* INDEPENDENT — one answer is never context for another.
|
|
303
392
|
*/
|
|
304
|
-
evaluate(state: unknown, questions: Record<string,
|
|
393
|
+
evaluate(state: unknown, questions: Record<string, AnyQuestion>, signal?: AbortSignal): Promise<Decision>;
|
|
394
|
+
/**
|
|
395
|
+
* Binds one state (a VALUE, not a session: nothing is sent until `evaluate`). Its `evaluate`
|
|
396
|
+
* runs the same path as `evaluate` PLUS fail-closed validation (`validateDecision`).
|
|
397
|
+
*/
|
|
398
|
+
state(value: unknown, opts?: {
|
|
399
|
+
signal?: AbortSignal;
|
|
400
|
+
}): {
|
|
401
|
+
evaluate(...questions: NamedClassifierQuestion[]): Promise<Decision>;
|
|
402
|
+
};
|
|
403
|
+
/**
|
|
404
|
+
* Binds a batch of states. Its `evaluate` runs `state(v).evaluate` per state, at most 16 in
|
|
405
|
+
* flight, and returns one `{decision | error}` per state IN ORDER. One state's failure never
|
|
406
|
+
* fails the batch; only a question-set error (duplicate name) throws, before any request.
|
|
407
|
+
*/
|
|
408
|
+
states(...values: unknown[]): {
|
|
409
|
+
evaluate(...questions: NamedClassifierQuestion[]): Promise<BatchResult[]>;
|
|
410
|
+
};
|
|
411
|
+
/** The one path. `validate` = fail closed on `validateDecision` (the value builders). */
|
|
412
|
+
private run;
|
|
305
413
|
/**
|
|
306
414
|
* The same questions over many states (SPEC §8B "Batch"). Each state goes through
|
|
307
415
|
* `evaluate`, at most `concurrency` (default 16) in flight; decisions come back in STATE
|
|
308
416
|
* order. Fails closed: the first failing state's index is named and no decisions return.
|
|
309
417
|
* No states is an error and sends nothing.
|
|
310
418
|
*/
|
|
311
|
-
evaluateBatch(states: readonly unknown[], questions: Record<string,
|
|
419
|
+
evaluateBatch(states: readonly unknown[], questions: Record<string, AnyQuestion>, opts?: {
|
|
312
420
|
signal?: AbortSignal;
|
|
313
421
|
concurrency?: number;
|
|
314
422
|
}): Promise<Decision[]>;
|
|
@@ -319,15 +427,18 @@ export declare class Classifier {
|
|
|
319
427
|
*/
|
|
320
428
|
private reportDegenerate;
|
|
321
429
|
/**
|
|
322
|
-
* Assembles the request: the canonical model + questions, plus
|
|
323
|
-
*
|
|
324
|
-
* bodyTransform → marshal).
|
|
430
|
+
* Assembles the request for the backend's wire: the canonical model + questions, plus the state
|
|
431
|
+
* (VERBATIM unless it carried content parts) and, on systemone, `assets`; then the §8 Gap 1
|
|
432
|
+
* pipeline in §8 order (base → requestParams merge → bodyTransform → marshal).
|
|
325
433
|
*/
|
|
326
434
|
private body;
|
|
327
435
|
/** Identifies a recorded decision by the canonical request AND the state. */
|
|
328
436
|
private staticKey;
|
|
329
437
|
private evaluateStatic;
|
|
330
|
-
|
|
438
|
+
/** Lift images, apply the support table and the limits — all before any request. */
|
|
439
|
+
private prepare;
|
|
440
|
+
/** The systemone style on every backend: lift, check, cache, post, decode. */
|
|
441
|
+
private evaluateWire;
|
|
331
442
|
/**
|
|
332
443
|
* The one POST, with the §8 retry budget, reusing the client's `ErrorInfo`/`ErrorTier`
|
|
333
444
|
* classifier and the `Retry-After` delay-seconds rule verbatim.
|
|
@@ -369,3 +480,50 @@ export declare function degenerateCriteria(criteria: Record<string, string>): st
|
|
|
369
480
|
* with, or `""` when the pairing is fine.
|
|
370
481
|
*/
|
|
371
482
|
export declare function backendMismatch(baseUrl: string, model: string): string;
|
|
483
|
+
/** §8B model key: which model an endpoint + requested model (alias) served last. */
|
|
484
|
+
export declare function classifierModelCacheKey(endpoint: string, model: string): string;
|
|
485
|
+
/** §8B decision key, on the SERVED model. No assets ⇒ the `assets` member is omitted. */
|
|
486
|
+
export declare function classifierDecisionCacheKey(endpoint: string, servedModel: string, state: unknown, assets: Record<string, unknown> | undefined, questions: Record<string, AnyQuestion>): string;
|
|
487
|
+
/** The canonical JSON a decision key hashes (exported for conformance tests). */
|
|
488
|
+
export declare function classifierDecisionCacheKeyBytes(endpoint: string, servedModel: string, state: unknown, assets: Record<string, unknown> | undefined, questions: Record<string, AnyQuestion>): string;
|
|
489
|
+
/**
|
|
490
|
+
* In-process TTL cache with a size cap (oldest-inserted out first). `ttlMs` 0 = no expiry; `max`
|
|
491
|
+
* 0 = unbounded. toolnexus persists nothing itself: implement `ClassifierCache` to persist.
|
|
492
|
+
*/
|
|
493
|
+
export declare class MemoryCache implements ClassifierCache {
|
|
494
|
+
readonly ttlMs: number;
|
|
495
|
+
readonly max: number;
|
|
496
|
+
private readonly now;
|
|
497
|
+
private readonly m;
|
|
498
|
+
constructor(ttlMs?: number, max?: number, now?: () => number);
|
|
499
|
+
get(key: string): string | undefined;
|
|
500
|
+
set(key: string, value: string): void;
|
|
501
|
+
get size(): number;
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* V1: fail closed on a reply that does not answer exactly the questions asked, within their
|
|
505
|
+
* schema. First failure wins, in the §8B order. Returns the error, or undefined when valid.
|
|
506
|
+
*/
|
|
507
|
+
export declare function validateDecision(questions: Record<string, AnyQuestion>, decision: {
|
|
508
|
+
answers: Record<string, unknown>;
|
|
509
|
+
}): Error | undefined;
|
|
510
|
+
/** jevx's INCLUSIVE cut-points (T1). They sit alongside `Bands` (exclusive), which stays the
|
|
511
|
+
* default of `ask` / `gate`. */
|
|
512
|
+
export interface Thresholds {
|
|
513
|
+
yes: number;
|
|
514
|
+
no: number;
|
|
515
|
+
minConfidence: number;
|
|
516
|
+
}
|
|
517
|
+
/** 0.8 / 0.2 / 0.6 (jevx's builtin profile). */
|
|
518
|
+
export declare const DEFAULT_THRESHOLDS: Readonly<Thresholds>;
|
|
519
|
+
/**
|
|
520
|
+
* The band of one answer under `Thresholds`: noul `p >= yes` ⇒ yes, `p <= no` ⇒ no, else
|
|
521
|
+
* uncertain; choice/score `confidence >= minConfidence` ⇒ yes, else uncertain. No near-uniform
|
|
522
|
+
* demotion (that is `Bands`' rule). A raw answer is uncertain.
|
|
523
|
+
*/
|
|
524
|
+
export declare function thresholdBand(answer: DecisionAnswer | RawAnswer, t?: Thresholds): "yes" | "no" | "uncertain";
|
|
525
|
+
/**
|
|
526
|
+
* Split a question set into chunks of `size`, keys in ASCII order. A helper, not automatic:
|
|
527
|
+
* joint calibration across a split is unproven, so the host decides to split and merges.
|
|
528
|
+
*/
|
|
529
|
+
export declare function chunkQuestions<Q extends AnyQuestion>(questions: Record<string, Q>, size: number): Record<string, Q>[];
|