@yaklabs-ai/plugin-sdk 0.13.10 → 0.14.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 +2 -2
- package/THIRD-PARTY-INVENTORY.json +1 -1
- package/dist/disclosure.d.ts +3 -172
- package/dist/disclosure.js +0 -2
- package/dist/kay-agent-testing.d.ts +4 -173
- package/dist/kay-agent-testing.js +0 -6
- package/dist/kay-agent.d.ts +24 -220
- package/dist/kay-agent.js +0 -76
- package/dist/kay-app-session-summary.d.ts +7041 -0
- package/dist/kay-app-session-summary.js +949 -0
- package/dist/kay-app.d.ts +181 -238
- package/dist/kay-app.js +1 -77
- package/dist/signals.d.ts +57 -81
- package/dist/signals.js +1 -1
- package/package.json +5 -5
- package/skills/directory-plugin-authoring/SKILL.md +1 -1
- package/dist/jev.d.ts +0 -203
- package/dist/jev.js +0 -77
package/dist/signals.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The `signals` a host with no
|
|
2
|
+
* The `signals` a host with no System One or no signals store binds: `observe` never touches the
|
|
3
3
|
* network, answers `invalid` for an input that breaks the recorded-name grammar exactly as a
|
|
4
4
|
* real host would, and otherwise `unavailable` with `stored: false`; both reads answer
|
|
5
5
|
* `unavailable` with reason `no-store`. So a caller's result handling does not change with host
|
|
@@ -10,35 +10,25 @@ export declare function createFallbackOnlySignals(): KayAppSignals;
|
|
|
10
10
|
/** The engine over one plugin's `observe` (normally `app.signals.observe`). */
|
|
11
11
|
export declare function createSignalEngine(observe: KayAppSignals["observe"]): SignalEngine;
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
* The `invalid` observation `observe` answers when a name in `input` breaks the recorded-name
|
|
15
|
-
* grammar, or `undefined` when every name can be recorded. A reader later types these names into
|
|
16
|
-
* an address or a `where` filter, so a row that broke the grammar would be unaddressable or
|
|
17
|
-
* unfilterable forever: the grammars are on {@link KayAppSignalsDetectorInput},
|
|
18
|
-
* {@link KayAppSignalSource}, and {@link KayAppSignalsObserveInput}. Checked first, before any
|
|
19
|
-
* digest, grant, store, or Jev call, by the host and by {@link createFallbackOnlySignals} alike.
|
|
20
|
-
*/
|
|
21
|
-
export declare function invalidObservation(input: KayAppSignalsObserveInput): KayAppSignalObservation | undefined;
|
|
13
|
+
declare type DecideAnswer = DecideBoolAnswer | DecideChoiceAnswer | DecideScoreAnswer;
|
|
22
14
|
|
|
23
|
-
declare
|
|
24
|
-
|
|
25
|
-
declare interface JevBoolAnswer {
|
|
15
|
+
declare interface DecideBoolAnswer {
|
|
26
16
|
readonly type: "bool";
|
|
27
17
|
/** P(yes), from 0 to 1. */
|
|
28
18
|
readonly probability: number;
|
|
29
19
|
}
|
|
30
20
|
|
|
31
21
|
/** A yes/no question. `criteria` says what yes and what no mean; omit it to leave both open. */
|
|
32
|
-
declare interface
|
|
22
|
+
declare interface DecideBoolQuestion {
|
|
33
23
|
readonly type: "bool";
|
|
34
|
-
readonly instructions:
|
|
24
|
+
readonly instructions: DecideInstructions;
|
|
35
25
|
readonly criteria?: {
|
|
36
26
|
readonly true: string;
|
|
37
27
|
readonly false: string;
|
|
38
28
|
};
|
|
39
29
|
}
|
|
40
30
|
|
|
41
|
-
declare interface
|
|
31
|
+
declare interface DecideChoiceAnswer<L extends string = string> {
|
|
42
32
|
readonly type: "choice";
|
|
43
33
|
readonly choice: L;
|
|
44
34
|
readonly confidence: number;
|
|
@@ -47,59 +37,43 @@ declare interface JevChoiceAnswer<L extends string = string> {
|
|
|
47
37
|
}
|
|
48
38
|
|
|
49
39
|
/** A choice among labels. Each label maps to what it means; an empty string leaves it open. */
|
|
50
|
-
declare interface
|
|
40
|
+
declare interface DecideChoiceQuestion<L extends string = string> {
|
|
51
41
|
readonly type: "choice";
|
|
52
|
-
readonly instructions:
|
|
42
|
+
readonly instructions: DecideInstructions;
|
|
53
43
|
readonly criteria: Readonly<Record<L, string>>;
|
|
54
44
|
}
|
|
55
45
|
|
|
56
|
-
|
|
46
|
+
/** What a question asks: text, or a JSON object the client sends as its JSON text. */
|
|
47
|
+
declare type DecideInstructions = string | object;
|
|
48
|
+
|
|
49
|
+
declare type DecideQuestion = DecideBoolQuestion | DecideChoiceQuestion | DecideScoreQuestion;
|
|
57
50
|
|
|
58
|
-
/**
|
|
59
|
-
declare type
|
|
51
|
+
/** Questions keyed by the name each answer comes back under. */
|
|
52
|
+
declare type DecideQuestions = Readonly<Record<string, DecideQuestion>>;
|
|
60
53
|
|
|
61
|
-
declare interface
|
|
54
|
+
declare interface DecideScoreAnswer {
|
|
62
55
|
readonly type: "score";
|
|
63
|
-
/** The expected
|
|
56
|
+
/** The expected level, from 0 to the number of levels minus one. */
|
|
64
57
|
readonly score: number;
|
|
65
58
|
readonly confidence: number;
|
|
66
59
|
}
|
|
67
60
|
|
|
68
|
-
/** A score over ordered
|
|
69
|
-
declare interface
|
|
61
|
+
/** A score over ordered levels: the first criterion scores 0, the next 1, and so on. */
|
|
62
|
+
declare interface DecideScoreQuestion {
|
|
70
63
|
readonly type: "score";
|
|
71
|
-
readonly instructions:
|
|
64
|
+
readonly instructions: DecideInstructions;
|
|
72
65
|
readonly criteria: readonly string[];
|
|
73
66
|
}
|
|
74
67
|
|
|
75
68
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* - {@link WithJev}, {@link WithJevOptions}, {@link createFallbackOnlyWithJev}.
|
|
83
|
-
* - {@link JevClient}, the {@link JevQuestion} and {@link JevAnswer} vocabulary, and
|
|
84
|
-
* {@link JevCallError}.
|
|
85
|
-
* does_not_own:
|
|
86
|
-
* - The wire. The host serves `classify` over whichever route the user's Jev provider order
|
|
87
|
-
* picks; a plugin never sees a vendor client, a vendor type, or a route.
|
|
88
|
-
* - Credential resolution, the `jev.use` decision, the Jev-branch budget, or usage accounting.
|
|
89
|
-
* Those are host-side (`@bonsai/agent-runtime`'s `kay/jev/`).
|
|
90
|
-
* ---
|
|
91
|
-
*
|
|
92
|
-
* The vocabulary is Bonsai's own (SDK 0.12.0). Before it, `use` received TypeSafe's `TypeSafeClient`
|
|
93
|
-
* and plugins coded against a vendor's types. It follows pi's classifier contract, which the host
|
|
94
|
-
* runs Jev through: a yes/no question is `bool` and answers a `probability`, every instruction and
|
|
95
|
-
* criterion is text, and the state is a JSON object.
|
|
96
|
-
*/
|
|
97
|
-
/**
|
|
98
|
-
* The state a rubric reads: a JSON object, never text or an array. Every value must survive
|
|
99
|
-
* `JSON.stringify` unchanged (no functions or class instances), because it is sent as JSON.
|
|
100
|
-
* Typed as `object` so a state declared as an interface fits without an index signature.
|
|
69
|
+
* The `invalid` observation `observe` answers when a name in `input` breaks the recorded-name
|
|
70
|
+
* grammar, or `undefined` when every name can be recorded. A reader later types these names into
|
|
71
|
+
* an address or a `where` filter, so a row that broke the grammar would be unaddressable or
|
|
72
|
+
* unfilterable forever: the grammars are on {@link KayAppSignalsDetectorInput},
|
|
73
|
+
* {@link KayAppSignalSource}, and {@link KayAppSignalsObserveInput}. Checked first, before any
|
|
74
|
+
* digest, grant, store, or Jev call, by the host and by {@link createFallbackOnlySignals} alike.
|
|
101
75
|
*/
|
|
102
|
-
declare
|
|
76
|
+
export declare function invalidObservation(input: KayAppSignalsObserveInput): KayAppSignalObservation | undefined;
|
|
103
77
|
|
|
104
78
|
/** One stored signal: the answers exactly as Jev gave them, and where the observed turn is. */
|
|
105
79
|
export declare interface KayAppSignal {
|
|
@@ -127,8 +101,8 @@ export declare interface KayAppSignal {
|
|
|
127
101
|
readonly inputDigest: string;
|
|
128
102
|
}
|
|
129
103
|
|
|
130
|
-
/** One stored answer: a {@link
|
|
131
|
-
export declare type KayAppSignalAnswer =
|
|
104
|
+
/** One stored answer: a {@link DecideAnswer}, or a yes/no answer recorded before SDK 0.12.0. */
|
|
105
|
+
export declare type KayAppSignalAnswer = DecideAnswer | KayAppSignalNoulAnswer;
|
|
132
106
|
|
|
133
107
|
/** One version of one detector, under one rubric, as the catalog lists it. */
|
|
134
108
|
export declare interface KayAppSignalDetector {
|
|
@@ -157,7 +131,7 @@ export declare interface KayAppSignalNoulAnswer {
|
|
|
157
131
|
/**
|
|
158
132
|
* The result of one observe call. `status` is the only field a caller must switch on:
|
|
159
133
|
*
|
|
160
|
-
* - `classified`: Jev answered; `answers` (one {@link
|
|
134
|
+
* - `classified`: Jev answered; `answers` (one {@link DecideAnswer} per question), `model`, and
|
|
161
135
|
* `usage` are what the Jev call returned, and `stored` says whether the row landed in the
|
|
162
136
|
* durable store.
|
|
163
137
|
* - `unavailable`: Jev could not answer (no key, refused grant, timeout, vendor error, or a
|
|
@@ -206,6 +180,25 @@ export declare interface KayAppSignalObservation {
|
|
|
206
180
|
readonly recordedAtMs: number;
|
|
207
181
|
}
|
|
208
182
|
|
|
183
|
+
/** Per-call knobs for {@link KayAppSignals.observe}. Every field is optional; the host applies its
|
|
184
|
+
* own default budget when none is given, so the Jev branch is never unbounded. */
|
|
185
|
+
export declare interface KayAppSignalObserveOptions {
|
|
186
|
+
/**
|
|
187
|
+
* Explicit cancellation. Always propagates as a rejection, because an aborted call means
|
|
188
|
+
* "stop", not "record nothing and carry on".
|
|
189
|
+
*/
|
|
190
|
+
readonly signal?: AbortSignal;
|
|
191
|
+
/** Bounds the Jev branch alone, measured from the call. */
|
|
192
|
+
readonly timeoutMs?: number;
|
|
193
|
+
/**
|
|
194
|
+
* Absolute epoch-ms hard deadline for the whole call. A deadline already passed rejects (like
|
|
195
|
+
* `signal`); one still ahead derives the Jev branch's budget from it.
|
|
196
|
+
*/
|
|
197
|
+
readonly deadlineAt?: number;
|
|
198
|
+
/** Attribution slug for host usage accounting. Never sent to Jev. */
|
|
199
|
+
readonly purpose?: string;
|
|
200
|
+
}
|
|
201
|
+
|
|
209
202
|
/** One page of signals, oldest recorded first. */
|
|
210
203
|
export declare interface KayAppSignalPage {
|
|
211
204
|
readonly signals: readonly KayAppSignal[];
|
|
@@ -370,7 +363,7 @@ export declare interface KayAppSignalsObserveInput {
|
|
|
370
363
|
* transcript the source points at. So the projection must be a pure function of the
|
|
371
364
|
* transcript and the detector version, or the row's evidence cannot be reproduced.
|
|
372
365
|
*/
|
|
373
|
-
readonly state:
|
|
366
|
+
readonly state: KayAppSignalState;
|
|
374
367
|
/**
|
|
375
368
|
* The typed questions to answer. Stored once per digest. A
|
|
376
369
|
* rubric asks 1 to 64 questions. Each name is an identifier (letters, digits, and `_`, not
|
|
@@ -379,8 +372,8 @@ export declare interface KayAppSignalsObserveInput {
|
|
|
379
372
|
* characters with no `,`, `@`, or control or invisible character (`\p{C}`), and no whitespace
|
|
380
373
|
* but single spaces between words, so a reader can copy it back exactly from rendered text.
|
|
381
374
|
*/
|
|
382
|
-
readonly questions:
|
|
383
|
-
readonly options?:
|
|
375
|
+
readonly questions: DecideQuestions;
|
|
376
|
+
readonly options?: KayAppSignalObserveOptions;
|
|
384
377
|
}
|
|
385
378
|
|
|
386
379
|
/**
|
|
@@ -461,6 +454,9 @@ export declare interface KayAppSignalsSessionQuery {
|
|
|
461
454
|
readonly limit?: number;
|
|
462
455
|
}
|
|
463
456
|
|
|
457
|
+
/** The state a signal's questions are asked over: any object, projected from the transcript. */
|
|
458
|
+
export declare type KayAppSignalState = object;
|
|
459
|
+
|
|
464
460
|
/**
|
|
465
461
|
* What a signal is about, named by the recording plugin. The host stores both values and never
|
|
466
462
|
* interprets them. A signal recorded without a subject has none; every reader treats it as before.
|
|
@@ -517,13 +513,13 @@ export declare interface SignalDefinition<I> {
|
|
|
517
513
|
readonly version: string;
|
|
518
514
|
/** What this signal is about, e.g. `turn`: a lowercase slug, stored on the row. */
|
|
519
515
|
readonly subjectKind: string;
|
|
520
|
-
readonly questions:
|
|
516
|
+
readonly questions: DecideQuestions;
|
|
521
517
|
/**
|
|
522
518
|
* The state Jev reads for this subject, or `undefined` when the subject carries nothing this
|
|
523
519
|
* signal can judge (no row is recorded). Must be a pure function of the subject: the row keeps
|
|
524
520
|
* only its digest.
|
|
525
521
|
*/
|
|
526
|
-
readonly project: (input: I) =>
|
|
522
|
+
readonly project: (input: I) => KayAppSignalState | undefined;
|
|
527
523
|
/**
|
|
528
524
|
* The subject's identity across sessions. Required with `maxAgeMs`; without it a row is tied
|
|
529
525
|
* to its own anchor only.
|
|
@@ -561,7 +557,7 @@ export declare interface SignalEngine {
|
|
|
561
557
|
* `source` anchors every row to the transcript; `options` is passed to every observe, with
|
|
562
558
|
* `purpose` set to `signals/<id>`.
|
|
563
559
|
*/
|
|
564
|
-
evaluate<I>(definitions: readonly SignalDefinition<I>[], input: I, source: KayAppSignalSource, options?:
|
|
560
|
+
evaluate<I>(definitions: readonly SignalDefinition<I>[], input: I, source: KayAppSignalSource, options?: KayAppSignalObserveOptions): Promise<readonly SignalEvaluation[]>;
|
|
565
561
|
}
|
|
566
562
|
|
|
567
563
|
/**
|
|
@@ -611,24 +607,4 @@ export declare interface SignalUpstream<I> {
|
|
|
611
607
|
readonly pass: readonly KayAppSignalsAnswerFilter[];
|
|
612
608
|
}
|
|
613
609
|
|
|
614
|
-
/** Per-call knobs for {@link WithJev}. Every field is optional; the host applies its own default
|
|
615
|
-
* budget when none is given, so the Jev branch is never unbounded. */
|
|
616
|
-
declare interface WithJevOptions {
|
|
617
|
-
/**
|
|
618
|
-
* Explicit cancellation. Always propagates as a rejection; never substituted with `fallback`,
|
|
619
|
-
* because an aborted call means "stop", not "use the cheaper path".
|
|
620
|
-
*/
|
|
621
|
-
readonly signal?: AbortSignal;
|
|
622
|
-
/** Bounds the Jev branch alone, measured from the call. */
|
|
623
|
-
readonly timeoutMs?: number;
|
|
624
|
-
/**
|
|
625
|
-
* Absolute epoch-ms hard deadline for the WHOLE call, `fallback` included. A deadline already
|
|
626
|
-
* passed rejects (like `signal`); one still ahead derives the Jev branch's budget from it and
|
|
627
|
-
* keeps a small reserve so `fallback` has a window to run.
|
|
628
|
-
*/
|
|
629
|
-
readonly deadlineAt?: number;
|
|
630
|
-
/** Attribution slug for host usage accounting. Never sent to Jev. */
|
|
631
|
-
readonly purpose?: string;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
610
|
export { }
|
package/dist/signals.js
CHANGED
|
@@ -120,7 +120,7 @@ function createFallbackOnlySignals() {
|
|
|
120
120
|
return {
|
|
121
121
|
observe: (input) => Promise.resolve(invalidObservation(input) ?? {
|
|
122
122
|
status: "unavailable",
|
|
123
|
-
reason: "no-
|
|
123
|
+
reason: "no-system-one",
|
|
124
124
|
detector: { ...input.detector, rubricDigest: "" },
|
|
125
125
|
source: input.source,
|
|
126
126
|
stored: false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yaklabs-ai/plugin-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "The Kay plugin SDK — types and helpers for authoring a Kay directory plugin.",
|
|
5
5
|
"author": "YakLabs",
|
|
6
6
|
"type": "module",
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
"types": "./dist/kay-app.d.ts",
|
|
18
18
|
"default": "./dist/kay-app.js"
|
|
19
19
|
},
|
|
20
|
+
"./kay-app/session-summary": {
|
|
21
|
+
"types": "./dist/kay-app-session-summary.d.ts",
|
|
22
|
+
"default": "./dist/kay-app-session-summary.js"
|
|
23
|
+
},
|
|
20
24
|
"./fs": {
|
|
21
25
|
"types": "./dist/fs.d.ts",
|
|
22
26
|
"default": "./dist/fs.js"
|
|
@@ -29,10 +33,6 @@
|
|
|
29
33
|
"types": "./dist/disclosure.d.ts",
|
|
30
34
|
"default": "./dist/disclosure.js"
|
|
31
35
|
},
|
|
32
|
-
"./jev": {
|
|
33
|
-
"types": "./dist/jev.d.ts",
|
|
34
|
-
"default": "./dist/jev.js"
|
|
35
|
-
},
|
|
36
36
|
"./signals": {
|
|
37
37
|
"types": "./dist/signals.d.ts",
|
|
38
38
|
"default": "./dist/signals.js"
|
|
@@ -101,7 +101,7 @@ a plugin you install yourself.
|
|
|
101
101
|
## The SDK resolution contract
|
|
102
102
|
|
|
103
103
|
- Plugin source imports `@bonsai/plugin-sdk/<subpath>` as a **bare specifier**
|
|
104
|
-
(`@bonsai/plugin-sdk/kay-agent`, `/kay-agent/testing`, `/kay-app`, `/disclosure`, `/fs`,
|
|
104
|
+
(`@bonsai/plugin-sdk/kay-agent`, `/kay-agent/testing`, `/kay-app`, `/disclosure`, `/fs`,
|
|
105
105
|
`/signals`, `/phase-shift`, `/time`, `/transcript`, `/transcript-review`, `/agent-conversation`,
|
|
106
106
|
`/app-data`, `/vendored-mcp`, `/system-one`, `/zod` — only declared exports exist). Take `z`
|
|
107
107
|
from the SDK (`/kay-agent`, or `/zod` in code a page also loads), never from `zod` itself.
|
package/dist/jev.d.ts
DELETED
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The `withJev` a host with no Jev lane binds: `use` is never called, no client is ever built,
|
|
3
|
-
* and no network is ever touched. It keeps the cancellation contract identical to the real
|
|
4
|
-
* wrapper's so a caller's `signal`/`deadlineAt` handling does not change with host composition.
|
|
5
|
-
*
|
|
6
|
-
* Deliberately here rather than in the runtime: this is the DEFAULT for the SDK's own host
|
|
7
|
-
* factory, which cannot import the runtime uphill. The runtime also delegates fallback execution
|
|
8
|
-
* here, so both paths share cancellation, deadline enforcement, and cleanup.
|
|
9
|
-
*/
|
|
10
|
-
export declare function createFallbackOnlyWithJev(): WithJev;
|
|
11
|
-
|
|
12
|
-
export declare type JevAnswer = JevBoolAnswer | JevChoiceAnswer | JevScoreAnswer;
|
|
13
|
-
|
|
14
|
-
/** The answer shape one question gets back. */
|
|
15
|
-
export declare type JevAnswerFor<Q> = Q extends JevBoolQuestion ? JevBoolAnswer : Q extends JevChoiceQuestion<infer L> ? JevChoiceAnswer<L> : Q extends JevScoreQuestion ? JevScoreAnswer : never;
|
|
16
|
-
|
|
17
|
-
export declare interface JevBoolAnswer {
|
|
18
|
-
readonly type: "bool";
|
|
19
|
-
/** P(yes), from 0 to 1. */
|
|
20
|
-
readonly probability: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** A yes/no question. `criteria` says what yes and what no mean; omit it to leave both open. */
|
|
24
|
-
export declare interface JevBoolQuestion {
|
|
25
|
-
readonly type: "bool";
|
|
26
|
-
readonly instructions: string;
|
|
27
|
-
readonly criteria?: {
|
|
28
|
-
readonly true: string;
|
|
29
|
-
readonly false: string;
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* The one error `classify` rejects with. It carries a classification, never the provider's own
|
|
35
|
-
* message or body: those can echo the request state, and this error reaches logs.
|
|
36
|
-
*/
|
|
37
|
-
export declare class JevCallError extends Error {
|
|
38
|
-
readonly transport: JevTransport;
|
|
39
|
-
readonly kind: JevCallErrorKind;
|
|
40
|
-
/** The final attempt's HTTP status, when a response arrived. */
|
|
41
|
-
readonly status: number | undefined;
|
|
42
|
-
constructor(init: {
|
|
43
|
-
readonly transport: JevTransport;
|
|
44
|
-
readonly kind: JevCallErrorKind;
|
|
45
|
-
readonly status?: number | undefined;
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Why a Jev call failed, as a closed set:
|
|
51
|
-
*
|
|
52
|
-
* - `http`: the route answered with an error status (`status` says which).
|
|
53
|
-
* - `too-large`: the route refused the request's size (413, or a 400 naming the token limit).
|
|
54
|
-
* - `network`: no response arrived.
|
|
55
|
-
* - `aborted`: the call was cancelled.
|
|
56
|
-
* - `invalid-answer`: the route answered, but not with an answer for every asked question.
|
|
57
|
-
*/
|
|
58
|
-
export declare type JevCallErrorKind = "http" | "too-large" | "network" | "aborted" | "invalid-answer";
|
|
59
|
-
|
|
60
|
-
export declare interface JevChoiceAnswer<L extends string = string> {
|
|
61
|
-
readonly type: "choice";
|
|
62
|
-
readonly choice: L;
|
|
63
|
-
readonly confidence: number;
|
|
64
|
-
/** P(label) for every offered label. */
|
|
65
|
-
readonly probabilities: Readonly<Record<L, number>>;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** A choice among labels. Each label maps to what it means; an empty string leaves it open. */
|
|
69
|
-
export declare interface JevChoiceQuestion<L extends string = string> {
|
|
70
|
-
readonly type: "choice";
|
|
71
|
-
readonly instructions: string;
|
|
72
|
-
readonly criteria: Readonly<Record<L, string>>;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/** One answered request: every asked question has an answer of its own kind. */
|
|
76
|
-
export declare interface JevClassification<Q extends JevQuestions = JevQuestions> {
|
|
77
|
-
/** The Jev model the host asked. */
|
|
78
|
-
readonly model: string;
|
|
79
|
-
readonly answers: {
|
|
80
|
-
readonly [K in keyof Q]: JevAnswerFor<Q[K]>;
|
|
81
|
-
};
|
|
82
|
-
/** Token counts, when the route reported them. */
|
|
83
|
-
readonly usage?: {
|
|
84
|
-
readonly inputTokens: number;
|
|
85
|
-
readonly outputTokens: number;
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export declare interface JevClassifyRequest<Q extends JevQuestions = JevQuestions> {
|
|
90
|
-
readonly state: JevState;
|
|
91
|
-
readonly questions: Q;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* The Jev client a `use` body receives. `classify` either resolves with an answer for every
|
|
96
|
-
* asked question, each of its question's kind, or rejects with a {@link JevCallError}; it never
|
|
97
|
-
* resolves with a partial or substituted answer.
|
|
98
|
-
*/
|
|
99
|
-
export declare interface JevClient {
|
|
100
|
-
classify<const Q extends JevQuestions>(request: JevClassifyRequest<Q>, options?: {
|
|
101
|
-
readonly signal?: AbortSignal;
|
|
102
|
-
}): Promise<JevClassification<Q>>;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export declare type JevQuestion = JevBoolQuestion | JevChoiceQuestion | JevScoreQuestion;
|
|
106
|
-
|
|
107
|
-
/** A rubric: questions keyed by the name each answer comes back under. */
|
|
108
|
-
export declare type JevQuestions = Readonly<Record<string, JevQuestion>>;
|
|
109
|
-
|
|
110
|
-
export declare interface JevScoreAnswer {
|
|
111
|
-
readonly type: "score";
|
|
112
|
-
/** The expected score, from 0 to the number of rungs minus one. */
|
|
113
|
-
readonly score: number;
|
|
114
|
-
readonly confidence: number;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** A score over ordered rungs: the first criterion scores 0, the next 1, and so on. */
|
|
118
|
-
export declare interface JevScoreQuestion {
|
|
119
|
-
readonly type: "score";
|
|
120
|
-
readonly instructions: string;
|
|
121
|
-
readonly criteria: readonly string[];
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* ---
|
|
126
|
-
* responsibility: The plugin-facing CONTRACT for Jev typed-decision inference — the shape of
|
|
127
|
-
* `api.withJev` on both plugin SDK targets, the {@link JevClient} a `use` body receives, the
|
|
128
|
-
* question and answer vocabulary it speaks, and the fallback-only implementation a host
|
|
129
|
-
* without a Jev lane binds.
|
|
130
|
-
* owns:
|
|
131
|
-
* - {@link WithJev}, {@link WithJevOptions}, {@link createFallbackOnlyWithJev}.
|
|
132
|
-
* - {@link JevClient}, the {@link JevQuestion} and {@link JevAnswer} vocabulary, and
|
|
133
|
-
* {@link JevCallError}.
|
|
134
|
-
* does_not_own:
|
|
135
|
-
* - The wire. The host serves `classify` over whichever route the user's Jev provider order
|
|
136
|
-
* picks; a plugin never sees a vendor client, a vendor type, or a route.
|
|
137
|
-
* - Credential resolution, the `jev.use` decision, the Jev-branch budget, or usage accounting.
|
|
138
|
-
* Those are host-side (`@bonsai/agent-runtime`'s `kay/jev/`).
|
|
139
|
-
* ---
|
|
140
|
-
*
|
|
141
|
-
* The vocabulary is Bonsai's own (SDK 0.12.0). Before it, `use` received TypeSafe's `TypeSafeClient`
|
|
142
|
-
* and plugins coded against a vendor's types. It follows pi's classifier contract, which the host
|
|
143
|
-
* runs Jev through: a yes/no question is `bool` and answers a `probability`, every instruction and
|
|
144
|
-
* criterion is text, and the state is a JSON object.
|
|
145
|
-
*/
|
|
146
|
-
/**
|
|
147
|
-
* The state a rubric reads: a JSON object, never text or an array. Every value must survive
|
|
148
|
-
* `JSON.stringify` unchanged (no functions or class instances), because it is sent as JSON.
|
|
149
|
-
* Typed as `object` so a state declared as an interface fits without an index signature.
|
|
150
|
-
*/
|
|
151
|
-
export declare type JevState = object;
|
|
152
|
-
|
|
153
|
-
/** The route a Jev call took: the user's own TypeSafe key, or Bonsai's hosted gateway. */
|
|
154
|
-
export declare type JevTransport = "direct" | "hosted";
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Run `use` against a live Jev client, falling back to `fallback` whenever Jev cannot serve the
|
|
158
|
-
* call. The wrapper exists so a feature can ASK for a typed decision without ever depending on
|
|
159
|
-
* one: `fallback` is required, and it runs whenever no provider in the user's Jev provider
|
|
160
|
-
* order holds a usable credential, the user has not granted `jev.use`, the branch exceeds its budget, `use` throws, or
|
|
161
|
-
* `use` declines by returning `undefined`. With valid options, this rejects on an explicit
|
|
162
|
-
* `signal` abort, reaching `deadlineAt`, or `fallback` itself throwing.
|
|
163
|
-
*
|
|
164
|
-
* ALWAYS PRESENT on the plugin API, on every host. A host that composed no Jev lane binds
|
|
165
|
-
* {@link createFallbackOnlyWithJev}, so a caller never branches on availability — branching is
|
|
166
|
-
* exactly how a fallback gets skipped.
|
|
167
|
-
*
|
|
168
|
-
* `jev` is a {@link JevClient} on the host's Jev model. It is valid only for the duration of
|
|
169
|
-
* the callback: a reference retained past `use`'s scope is refused at the transport, and an
|
|
170
|
-
* in-flight request is aborted when the call stops waiting.
|
|
171
|
-
* The callback itself is ABANDONED, not interrupted — a host cannot stop arbitrary JavaScript
|
|
172
|
-
* that is already running, so `use` must not perform side effects it would mind completing
|
|
173
|
-
* unobserved. The same applies to a running fallback: abort/deadline stops waiting for it but
|
|
174
|
-
* cannot interrupt its JavaScript.
|
|
175
|
-
*/
|
|
176
|
-
export declare type WithJev = <T>(
|
|
177
|
-
/** Return `undefined` to decline (the fallback runs). A feature whose real result can itself be
|
|
178
|
-
* `undefined` should return `null` or its own wrapper type instead. */
|
|
179
|
-
use: (jev: JevClient) => T | undefined | PromiseLike<T | undefined>,
|
|
180
|
-
/** Required. The behaviour the feature has without Jev. */
|
|
181
|
-
fallback: () => T | PromiseLike<T>, options?: WithJevOptions) => Promise<T>;
|
|
182
|
-
|
|
183
|
-
/** Per-call knobs for {@link WithJev}. Every field is optional; the host applies its own default
|
|
184
|
-
* budget when none is given, so the Jev branch is never unbounded. */
|
|
185
|
-
export declare interface WithJevOptions {
|
|
186
|
-
/**
|
|
187
|
-
* Explicit cancellation. Always propagates as a rejection; never substituted with `fallback`,
|
|
188
|
-
* because an aborted call means "stop", not "use the cheaper path".
|
|
189
|
-
*/
|
|
190
|
-
readonly signal?: AbortSignal;
|
|
191
|
-
/** Bounds the Jev branch alone, measured from the call. */
|
|
192
|
-
readonly timeoutMs?: number;
|
|
193
|
-
/**
|
|
194
|
-
* Absolute epoch-ms hard deadline for the WHOLE call, `fallback` included. A deadline already
|
|
195
|
-
* passed rejects (like `signal`); one still ahead derives the Jev branch's budget from it and
|
|
196
|
-
* keeps a small reserve so `fallback` has a window to run.
|
|
197
|
-
*/
|
|
198
|
-
readonly deadlineAt?: number;
|
|
199
|
-
/** Attribution slug for host usage accounting. Never sent to Jev. */
|
|
200
|
-
readonly purpose?: string;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export { }
|
package/dist/jev.js
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
// packages/plugin-sdk/dist/jev.js
|
|
2
|
-
var JevCallError = class extends Error {
|
|
3
|
-
transport;
|
|
4
|
-
kind;
|
|
5
|
-
/** The final attempt's HTTP status, when a response arrived. */
|
|
6
|
-
status;
|
|
7
|
-
constructor(init) {
|
|
8
|
-
super(`Jev call failed on the ${init.transport} route: ${init.kind}${init.status === void 0 ? "" : ` (HTTP ${init.status})`}.`);
|
|
9
|
-
this.name = "JevCallError";
|
|
10
|
-
this.transport = init.transport;
|
|
11
|
-
this.kind = init.kind;
|
|
12
|
-
this.status = init.status;
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
function createFallbackOnlyWithJev() {
|
|
16
|
-
return async (_use, fallback, options = {}) => {
|
|
17
|
-
if (typeof fallback !== "function") {
|
|
18
|
-
throw new TypeError("withJev requires a `fallback` function as its second argument.");
|
|
19
|
-
}
|
|
20
|
-
const { signal, deadlineAt } = options;
|
|
21
|
-
if (deadlineAt !== void 0 && !Number.isFinite(deadlineAt)) {
|
|
22
|
-
throw new TypeError("withJev's `deadlineAt` must be a finite epoch-ms timestamp.");
|
|
23
|
-
}
|
|
24
|
-
const assertWithinBoundaries = () => {
|
|
25
|
-
if (signal?.aborted === true) {
|
|
26
|
-
throw signal.reason ?? new DOMException("Aborted", "AbortError");
|
|
27
|
-
}
|
|
28
|
-
if (deadlineAt !== void 0 && Date.now() >= deadlineAt) {
|
|
29
|
-
throw new Error("withJev's deadline has passed.");
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
assertWithinBoundaries();
|
|
33
|
-
let timer;
|
|
34
|
-
let onAbort;
|
|
35
|
-
const stopped = new Promise((_resolve, reject) => {
|
|
36
|
-
if (signal !== void 0) {
|
|
37
|
-
onAbort = () => reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
|
|
38
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
39
|
-
}
|
|
40
|
-
if (deadlineAt !== void 0) {
|
|
41
|
-
const checkDeadline = () => {
|
|
42
|
-
const remaining = deadlineAt - Date.now();
|
|
43
|
-
if (remaining <= 0) {
|
|
44
|
-
reject(new Error("withJev's deadline has passed."));
|
|
45
|
-
} else {
|
|
46
|
-
timer = setTimeout(checkDeadline, Math.min(remaining, 2147483647));
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
checkDeadline();
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
try {
|
|
53
|
-
const result = await Promise.race([
|
|
54
|
-
Promise.resolve().then(() => {
|
|
55
|
-
assertWithinBoundaries();
|
|
56
|
-
return fallback();
|
|
57
|
-
}),
|
|
58
|
-
stopped
|
|
59
|
-
]);
|
|
60
|
-
assertWithinBoundaries();
|
|
61
|
-
return result;
|
|
62
|
-
} catch (error) {
|
|
63
|
-
assertWithinBoundaries();
|
|
64
|
-
throw error;
|
|
65
|
-
} finally {
|
|
66
|
-
if (timer !== void 0)
|
|
67
|
-
clearTimeout(timer);
|
|
68
|
-
if (signal !== void 0 && onAbort !== void 0) {
|
|
69
|
-
signal.removeEventListener("abort", onAbort);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
export {
|
|
75
|
-
JevCallError,
|
|
76
|
-
createFallbackOnlyWithJev
|
|
77
|
-
};
|