@yaklabs-ai/plugin-sdk 0.11.0 → 0.12.3

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/dist/kay-app.js CHANGED
@@ -1,4 +1,17 @@
1
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
+ };
2
15
  function createFallbackOnlyWithJev() {
3
16
  return async (_use, fallback, options = {}) => {
4
17
  if (typeof fallback !== "function") {
@@ -114,6 +127,10 @@ function grammarProblem(input) {
114
127
  return field === "" ? "`observe` takes an object with `detector`, `source`, `state`, and `questions`." : `\`${field}\` is missing or has the wrong type.`;
115
128
  }
116
129
  const { detector, source, questions } = shape.data;
130
+ const { state } = input;
131
+ if (typeof state !== "object" || state === null || Array.isArray(state)) {
132
+ return "`state` must be a JSON object.";
133
+ }
117
134
  if (!fits(detector.id, DETECTOR_ID)) {
118
135
  return "`detector.id` must be a lowercase slug of at most 64 characters: a-z and 0-9 in words joined by single hyphens.";
119
136
  }
@@ -316,6 +333,98 @@ var uriTextEditPayloadArms = z4.union([
316
333
  z4.array(oldNewEntry).min(1)
317
334
  ]);
318
335
 
336
+ // packages/herd-uri/dist/line-selector.js
337
+ var RAW_TOKEN = /^raw$/i;
338
+ function parseRangeListToken(token) {
339
+ if (token.length === 0)
340
+ return void 0;
341
+ const ranges = [];
342
+ for (const part of token.split(",")) {
343
+ const range = parseSingleRange(part);
344
+ if (range === void 0)
345
+ return void 0;
346
+ ranges.push(range);
347
+ }
348
+ return ranges;
349
+ }
350
+ function toInt(value) {
351
+ if (!/^\d+$/.test(value))
352
+ return void 0;
353
+ const n = Number.parseInt(value, 10);
354
+ return Number.isSafeInteger(n) && n >= 1 ? n : void 0;
355
+ }
356
+ function parseSingleRange(part) {
357
+ const plus = part.indexOf("+");
358
+ if (plus >= 0) {
359
+ const start2 = toInt(part.slice(0, plus));
360
+ const count = toInt(part.slice(plus + 1));
361
+ if (start2 === void 0 || count === void 0)
362
+ return void 0;
363
+ return { start: start2, end: start2 + count - 1 };
364
+ }
365
+ const dash = part.indexOf("-");
366
+ if (dash >= 0) {
367
+ const start2 = toInt(part.slice(0, dash));
368
+ const endRaw = part.slice(dash + 1);
369
+ if (start2 === void 0)
370
+ return void 0;
371
+ if (endRaw.length === 0)
372
+ return { start: start2, end: Number.POSITIVE_INFINITY };
373
+ const end = toInt(endRaw);
374
+ if (end === void 0 || end < start2)
375
+ return void 0;
376
+ return { start: start2, end };
377
+ }
378
+ const start = toInt(part);
379
+ if (start === void 0)
380
+ return void 0;
381
+ return { start, end: Number.POSITIVE_INFINITY };
382
+ }
383
+ function mergeRanges(ranges) {
384
+ const sorted = [...ranges].sort((a, b) => a.start - b.start);
385
+ const merged = [];
386
+ for (const range of sorted) {
387
+ const last = merged[merged.length - 1];
388
+ if (last !== void 0 && range.start <= last.end) {
389
+ if (range.end > last.end) {
390
+ merged[merged.length - 1] = { start: last.start, end: range.end };
391
+ }
392
+ continue;
393
+ }
394
+ merged.push(range);
395
+ }
396
+ return merged;
397
+ }
398
+ function parseLineSelector(input) {
399
+ let address = input;
400
+ let raw = false;
401
+ let ranges;
402
+ for (let i = 0; i < 2; i += 1) {
403
+ const colon = address.lastIndexOf(":");
404
+ if (colon < 0)
405
+ break;
406
+ const token = address.slice(colon + 1);
407
+ if (RAW_TOKEN.test(token)) {
408
+ if (raw)
409
+ break;
410
+ raw = true;
411
+ address = address.slice(0, colon);
412
+ continue;
413
+ }
414
+ const parsed = parseRangeListToken(token);
415
+ if (parsed === void 0)
416
+ break;
417
+ if (ranges !== void 0)
418
+ break;
419
+ ranges = parsed;
420
+ address = address.slice(0, colon);
421
+ }
422
+ return {
423
+ address,
424
+ selector: { ranges: ranges ? mergeRanges(ranges) : [], raw }
425
+ };
426
+ }
427
+
319
428
  // packages/herd-uri/dist/schema/to-json-schema.js
320
429
  import { z as z5 } from "zod";
321
430
  function toJsonSchema(schema) {
@@ -359,6 +468,20 @@ function payload(name, schema, options = {}) {
359
468
  };
360
469
  }
361
470
 
471
+ // packages/plugin-sdk/dist/kay-app/skills.js
472
+ function createUnavailableSkills(message) {
473
+ const unavailable = {
474
+ status: "unavailable",
475
+ reason: "not-available",
476
+ message
477
+ };
478
+ return {
479
+ list: async () => unavailable,
480
+ read: async () => unavailable,
481
+ history: async () => unavailable
482
+ };
483
+ }
484
+
362
485
  // packages/plugin-sdk/dist/kay-app/transcript-text.js
363
486
  function transcriptMessageTexts(entries) {
364
487
  return entries.flatMap((entry) => {
@@ -414,6 +537,7 @@ var KAY_APP_AUTOMATION_CONDITION_KINDS = [
414
537
  "delayed-occurrence"
415
538
  ];
416
539
  export {
540
+ JevCallError,
417
541
  KAY_APP_AUTOMATION_CONDITION_KINDS,
418
542
  KAY_APP_DATA_CHANGE_MAX_BYTES,
419
543
  KayAppWorkflowFailure,
@@ -426,8 +550,10 @@ export {
426
550
  UriValidationError,
427
551
  createFallbackOnlySignals,
428
552
  createFallbackOnlyWithJev,
553
+ createUnavailableSkills,
429
554
  invalidObservation,
430
555
  isRetryable,
556
+ parseLineSelector,
431
557
  payload,
432
558
  transcriptMessageText,
433
559
  transcriptMessageTexts,
package/dist/signals.d.ts CHANGED
@@ -1,10 +1,3 @@
1
- import type { ChoiceResponse } from '@typesafe-ai/sdk';
2
- import type { NoulResponse } from '@typesafe-ai/sdk';
3
- import type { Questions } from '@typesafe-ai/sdk';
4
- import type { ScoreResponse } from '@typesafe-ai/sdk';
5
-
6
- export { ChoiceResponse }
7
-
8
1
  /**
9
2
  * The `signals` a host with no Jev lane or no signals store binds: `observe` never touches the
10
3
  * network, answers `invalid` for an input that breaks the recorded-name grammar exactly as a
@@ -24,6 +17,87 @@ export declare function createFallbackOnlySignals(): KayAppSignals;
24
17
  */
25
18
  export declare function invalidObservation(input: KayAppSignalsObserveInput): KayAppSignalObservation | undefined;
26
19
 
20
+ declare type JevAnswer = JevBoolAnswer | JevChoiceAnswer | JevScoreAnswer;
21
+
22
+ declare interface JevBoolAnswer {
23
+ readonly type: "bool";
24
+ /** P(yes), from 0 to 1. */
25
+ readonly probability: number;
26
+ }
27
+
28
+ /** A yes/no question. `criteria` says what yes and what no mean; omit it to leave both open. */
29
+ declare interface JevBoolQuestion {
30
+ readonly type: "bool";
31
+ readonly instructions: string;
32
+ readonly criteria?: {
33
+ readonly true: string;
34
+ readonly false: string;
35
+ };
36
+ }
37
+
38
+ declare interface JevChoiceAnswer<L extends string = string> {
39
+ readonly type: "choice";
40
+ readonly choice: L;
41
+ readonly confidence: number;
42
+ /** P(label) for every offered label. */
43
+ readonly probabilities: Readonly<Record<L, number>>;
44
+ }
45
+
46
+ /** A choice among labels. Each label maps to what it means; an empty string leaves it open. */
47
+ declare interface JevChoiceQuestion<L extends string = string> {
48
+ readonly type: "choice";
49
+ readonly instructions: string;
50
+ readonly criteria: Readonly<Record<L, string>>;
51
+ }
52
+
53
+ declare type JevQuestion = JevBoolQuestion | JevChoiceQuestion | JevScoreQuestion;
54
+
55
+ /** A rubric: questions keyed by the name each answer comes back under. */
56
+ declare type JevQuestions = Readonly<Record<string, JevQuestion>>;
57
+
58
+ declare interface JevScoreAnswer {
59
+ readonly type: "score";
60
+ /** The expected score, from 0 to the number of rungs minus one. */
61
+ readonly score: number;
62
+ readonly confidence: number;
63
+ }
64
+
65
+ /** A score over ordered rungs: the first criterion scores 0, the next 1, and so on. */
66
+ declare interface JevScoreQuestion {
67
+ readonly type: "score";
68
+ readonly instructions: string;
69
+ readonly criteria: readonly string[];
70
+ }
71
+
72
+ /**
73
+ * ---
74
+ * responsibility: The plugin-facing CONTRACT for Jev typed-decision inference — the shape of
75
+ * `api.withJev` on both plugin SDK targets, the {@link JevClient} a `use` body receives, the
76
+ * question and answer vocabulary it speaks, and the fallback-only implementation a host
77
+ * without a Jev lane binds.
78
+ * owns:
79
+ * - {@link WithJev}, {@link WithJevOptions}, {@link createFallbackOnlyWithJev}.
80
+ * - {@link JevClient}, the {@link JevQuestion} and {@link JevAnswer} vocabulary, and
81
+ * {@link JevCallError}.
82
+ * does_not_own:
83
+ * - The wire. The host serves `classify` over whichever route the user's Jev provider order
84
+ * picks; a plugin never sees a vendor client, a vendor type, or a route.
85
+ * - Credential resolution, the `jev.use` decision, the Jev-branch budget, or usage accounting.
86
+ * Those are host-side (`@kay/agent-runtime`'s `kay/jev/`).
87
+ * ---
88
+ *
89
+ * The vocabulary is Kay's own (SDK 0.12.0). Before it, `use` received TypeSafe's `TypeSafeClient`
90
+ * and plugins coded against a vendor's types. It follows pi's classifier contract, which the host
91
+ * runs Jev through: a yes/no question is `bool` and answers a `probability`, every instruction and
92
+ * criterion is text, and the state is a JSON object.
93
+ */
94
+ /**
95
+ * The state a rubric reads: a JSON object, never text or an array. Every value must survive
96
+ * `JSON.stringify` unchanged (no functions or class instances), because it is sent as JSON.
97
+ * Typed as `object` so a state declared as an interface fits without an index signature.
98
+ */
99
+ declare type JevState = object;
100
+
27
101
  /** One stored signal: the answers exactly as Jev gave them, and where the observed turn is. */
28
102
  export declare interface KayAppSignal {
29
103
  /** Recording order: a higher id was recorded later. */
@@ -34,7 +108,7 @@ export declare interface KayAppSignal {
34
108
  readonly source: KayAppSignalSource;
35
109
  readonly recordedAtMs: number;
36
110
  /** Keyed by question name, full probability distributions included. */
37
- readonly answers: Readonly<Record<string, NoulResponse | ChoiceResponse | ScoreResponse>>;
111
+ readonly answers: Readonly<Record<string, KayAppSignalAnswer>>;
38
112
  /** The inference that produced the answers; absent when the host recorded only part of it. */
39
113
  readonly inference?: {
40
114
  readonly model: string;
@@ -46,6 +120,9 @@ export declare interface KayAppSignal {
46
120
  readonly inputDigest: string;
47
121
  }
48
122
 
123
+ /** One stored answer: a {@link JevAnswer}, or a yes/no answer recorded before SDK 0.12.0. */
124
+ export declare type KayAppSignalAnswer = JevAnswer | KayAppSignalNoulAnswer;
125
+
49
126
  /** One version of one detector, under one rubric, as the catalog lists it. */
50
127
  export declare interface KayAppSignalDetector {
51
128
  readonly pluginId: string;
@@ -56,16 +133,26 @@ export declare interface KayAppSignalDetector {
56
133
  * version mean the rubric was edited without a version bump.
57
134
  */
58
135
  readonly rubricDigest: string;
59
- readonly questions: Questions;
136
+ readonly questions: Readonly<Record<string, KayAppSignalRubricQuestion>>;
60
137
  readonly firstRecordedAtMs: number;
61
138
  readonly lastRecordedAtMs: number;
62
139
  }
63
140
 
141
+ /**
142
+ * A yes/no answer as rows recorded before SDK 0.12.0 carry it, in TypeSafe's vocabulary:
143
+ * `noul` is P(yes). Stored rows are never rewritten, so a reader still meets these.
144
+ */
145
+ export declare interface KayAppSignalNoulAnswer {
146
+ readonly type: "noul";
147
+ readonly noul: number;
148
+ }
149
+
64
150
  /**
65
151
  * The result of one observe call. `status` is the only field a caller must switch on:
66
152
  *
67
- * - `classified`: Jev answered; `answers`, `model`, and `usage` are the vendor's verbatim
68
- * response, and `stored` says whether the row landed in the durable store.
153
+ * - `classified`: Jev answered; `answers` (one {@link JevAnswer} per question), `model`, and
154
+ * `usage` are what the Jev call returned, and `stored` says whether the row landed in the
155
+ * durable store.
69
156
  * - `unavailable`: Jev could not answer (no key, refused grant, timeout, vendor error, or a
70
157
  * malformed response), or the host has no signals store at all (`reason: "no-store"`).
71
158
  * `reason` names the host's classification; no row is written, so the same input can be
@@ -116,6 +203,18 @@ export declare interface KayAppSignalPage {
116
203
  readonly nextCursor?: string;
117
204
  }
118
205
 
206
+ /**
207
+ * One question of a stored rubric, as the recording plugin wrote it. Rubrics recorded before
208
+ * SDK 0.12.0 use TypeSafe's vocabulary (`noul` for yes/no, and instructions or criteria that
209
+ * may be JSON rather than text), and a stored rubric is never rewritten, so only `type` is
210
+ * guaranteed.
211
+ */
212
+ export declare interface KayAppSignalRubricQuestion {
213
+ readonly type: string;
214
+ readonly instructions?: unknown;
215
+ readonly criteria?: unknown;
216
+ }
217
+
119
218
  /**
120
219
  * The plugin's signal door. `observe` runs the fused inference-and-record step; `list` and
121
220
  * `listDetectors` read recorded signals back. The plugin id is stamped by the host at the
@@ -238,16 +337,16 @@ export declare interface KayAppSignalsObserveInput {
238
337
  * transcript the source points at. So the projection must be a pure function of the
239
338
  * transcript and the detector version, or the row's evidence cannot be reproduced.
240
339
  */
241
- readonly state: unknown;
340
+ readonly state: JevState;
242
341
  /**
243
- * The typed questions to answer, as the vendor SDK accepts them. Stored once per digest. A
342
+ * The typed questions to answer. Stored once per digest. A
244
343
  * rubric asks 1 to 64 questions. Each name is an identifier (letters, digits, and `_`, not
245
344
  * starting with a digit), at most 64 characters, because a reader types it into a `where`
246
345
  * filter. A choice question offers at most {@link MAX_CHOICE_LABELS} labels, each 1 to 64
247
346
  * characters with no `,`, `@`, or control or invisible character (`\p{C}`), and no whitespace
248
347
  * but single spaces between words, so a reader can copy it back exactly from rendered text.
249
348
  */
250
- readonly questions: Questions;
349
+ readonly questions: JevQuestions;
251
350
  readonly options?: WithJevOptions;
252
351
  }
253
352
 
@@ -332,10 +431,6 @@ export declare interface KayAppSignalsSessionQuery {
332
431
  /** The most labels a recorded choice question may offer, and so the most one filter names. */
333
432
  export declare const MAX_CHOICE_LABELS = 64;
334
433
 
335
- export { NoulResponse }
336
-
337
- export { ScoreResponse }
338
-
339
434
  /**
340
435
  * The largest epoch-millisecond time a `Date` can hold (about the year 275,760). A time outside
341
436
  * 0 to this bound has no date to show, so neither `observe` nor a read window accepts one.
package/dist/signals.js CHANGED
@@ -53,6 +53,10 @@ function grammarProblem(input) {
53
53
  return field === "" ? "`observe` takes an object with `detector`, `source`, `state`, and `questions`." : `\`${field}\` is missing or has the wrong type.`;
54
54
  }
55
55
  const { detector, source, questions } = shape.data;
56
+ const { state } = input;
57
+ if (typeof state !== "object" || state === null || Array.isArray(state)) {
58
+ return "`state` must be a JSON object.";
59
+ }
56
60
  if (!fits(detector.id, DETECTOR_ID)) {
57
61
  return "`detector.id` must be a lowercase slug of at most 64 characters: a-z and 0-9 in words joined by single hyphens.";
58
62
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaklabs-ai/plugin-sdk",
3
- "version": "0.11.0",
3
+ "version": "0.12.3",
4
4
  "description": "The Kay plugin SDK — types and helpers for authoring a Kay directory plugin.",
5
5
  "author": "YakLabs",
6
6
  "type": "module",
@@ -51,8 +51,7 @@
51
51
  "skills"
52
52
  ],
53
53
  "dependencies": {
54
- "zod": "^4.0.0",
55
- "@typesafe-ai/sdk": "0.6.0"
54
+ "zod": "^4.0.0"
56
55
  },
57
56
  "publishConfig": {
58
57
  "registry": "https://registry.npmjs.org",