@yaklabs-ai/plugin-sdk 0.13.7 → 0.13.9

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 CHANGED
@@ -13,7 +13,7 @@ it under the name your plugin code actually imports:
13
13
  ```json
14
14
  {
15
15
  "dependencies": {
16
- "@bonsai/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.13.7"
16
+ "@bonsai/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.13.9"
17
17
  }
18
18
  }
19
19
  ```
@@ -62,7 +62,7 @@ Every tool the entrypoint registers is declared in the manifest too:
62
62
  "description": "Greets people by name.",
63
63
  "version": "0.1.0",
64
64
  "namespace": "widgets",
65
- "compatibility": { "sdk": "^0.13.7" },
65
+ "compatibility": { "sdk": "^0.13.9" },
66
66
  "targets": {
67
67
  "kay": {
68
68
  "agent": {
@@ -128,11 +128,16 @@ naming both versions, instead of loading it and finding no `activate`.
128
128
  | `@bonsai/plugin-sdk/agent-conversation` | How a session's agent-to-agent traffic groups into conversations, from 0.13.7 |
129
129
  | `@bonsai/plugin-sdk/app-data` | The app-data size caps, on an entry with no other import, from 0.13.7 |
130
130
  | `@bonsai/plugin-sdk/vendored-mcp` | The kit for a plugin built on a vendor's hosted MCP server, from 0.13.7 |
131
+ | `@bonsai/plugin-sdk/system-one` | The types and error class for `api.systemOne` / `app.systemOne`, from 0.13.8 |
132
+ | `@bonsai/plugin-sdk/zod` | `z` (the host's in the daemon), on an entry with no other import, from 0.13.9 |
131
133
 
132
134
  A plugin that imports a subpath declares at least the version its row names (`^0.13.7` for the
133
- last four). `vendored-mcp` builds the plugin's URI module (its link cards and help); hosting the
134
- vendor's MCP server itself is a separate host decision, and Bonsai currently makes it only for
135
- its own bundled plugins.
135
+ four from 0.13.7, `^0.13.8` for `system-one`, `^0.13.9` for `zod`). `vendored-mcp` builds the plugin's URI module (its link cards and help); hosting the
136
+ vendor's MCP server itself is a separate host decision: Bonsai hosts it once a person approves
137
+ the plugin's `mcp.host-server` grant for that server's name and URL. A server that needs an OAuth
138
+ sign-in names one of the plugin's auth services in `authService`; that service must declare exactly
139
+ one `delegated` scheme, which Bonsai uses to sign the person in to the server. Bonsai declares that
140
+ scheme at runtime; the plugin's code must not declare it again.
136
141
 
137
142
  `kay-agent/host` is intentionally not published; it is Bonsai's own loading
138
143
  machinery, not an authoring API.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@yaklabs-ai/plugin-sdk",
4
- "version": "0.13.7",
4
+ "version": "0.13.9",
5
5
  "target": "npm",
6
6
  "firstPartyLicense": "MIT",
7
7
  "bundled": [
@@ -249,6 +249,12 @@ declare interface AuthAccount {
249
249
  readonly needsReconnect?: boolean;
250
250
  }
251
251
 
252
+ declare interface Availability {
253
+ readonly available: boolean;
254
+ readonly reason?: string;
255
+ readonly cause?: SystemOneFailureCause;
256
+ }
257
+
252
258
  declare interface BackgroundTaskAdoptOptions {
253
259
  readonly preferredId?: string;
254
260
  readonly toolCallId?: string;
@@ -593,6 +599,85 @@ declare function CyclicOptions(type: TCyclic): TSchemaOptions;
593
599
 
594
600
  declare type CyclicStackLength<Stack extends unknown[], MaxLength extends number, Buffer extends unknown[] = []> = (Stack extends [infer Left, ...infer Right] ? Buffer['length'] extends MaxLength ? false : CyclicStackLength<Right, MaxLength, [...Buffer, Left]> : true);
595
601
 
602
+ declare type DecideAnswerFor<Q> = Q extends DecideBoolQuestion ? DecideBoolAnswer : Q extends DecideChoiceQuestion<infer L> ? DecideChoiceAnswer<L> : Q extends DecideScoreQuestion ? DecideScoreAnswer : never;
603
+
604
+ declare interface DecideBoolAnswer {
605
+ readonly type: "bool";
606
+ /** P(yes), from 0 to 1. */
607
+ readonly probability: number;
608
+ }
609
+
610
+ /** A yes/no question. `criteria` says what yes and what no mean; omit it to leave both open. */
611
+ declare interface DecideBoolQuestion {
612
+ readonly type: "bool";
613
+ readonly instructions: DecideInstructions;
614
+ readonly criteria?: {
615
+ readonly true: string;
616
+ readonly false: string;
617
+ };
618
+ }
619
+
620
+ declare interface DecideChoiceAnswer<L extends string = string> {
621
+ readonly type: "choice";
622
+ readonly choice: L;
623
+ readonly confidence: number;
624
+ /** P(label) for every offered label. */
625
+ readonly probabilities: Readonly<Record<L, number>>;
626
+ }
627
+
628
+ /** A choice among labels. Each label maps to what it means; an empty string leaves it open. */
629
+ declare interface DecideChoiceQuestion<L extends string = string> {
630
+ readonly type: "choice";
631
+ readonly instructions: DecideInstructions;
632
+ readonly criteria: Readonly<Record<L, string>>;
633
+ }
634
+
635
+ /** What a question asks: text, or a JSON object the client sends as its JSON text. */
636
+ declare type DecideInstructions = string | object;
637
+
638
+ declare type DecideModelId = "jev" | "clef" | "clef-flash";
639
+
640
+ declare type DecideQuestion = DecideBoolQuestion | DecideChoiceQuestion | DecideScoreQuestion;
641
+
642
+ /** Questions keyed by the name each answer comes back under. */
643
+ declare type DecideQuestions = Readonly<Record<string, DecideQuestion>>;
644
+
645
+ declare interface DecideRequest<Q extends DecideQuestions = DecideQuestions> {
646
+ /** Defaults to `jev`. */
647
+ readonly model?: DecideModelId;
648
+ readonly state: DecideState;
649
+ readonly questions: Q;
650
+ }
651
+
652
+ declare interface DecideScoreAnswer {
653
+ readonly type: "score";
654
+ /** The expected level, from 0 to the number of levels minus one. */
655
+ readonly score: number;
656
+ readonly confidence: number;
657
+ }
658
+
659
+ /** A score over ordered levels: the first criterion scores 0, the next 1, and so on. */
660
+ declare interface DecideScoreQuestion {
661
+ readonly type: "score";
662
+ readonly instructions: DecideInstructions;
663
+ readonly criteria: readonly string[];
664
+ }
665
+
666
+ /**
667
+ * What a decide call reads. A JSON value is sent as JSON; every value must survive
668
+ * `JSON.stringify` unchanged.
669
+ */
670
+ declare type DecideState = string | object;
671
+
672
+ /** Every asked question has an answer of its own kind. */
673
+ declare interface Decision<Q extends DecideQuestions = DecideQuestions> {
674
+ readonly model: DecideModelId;
675
+ readonly answers: {
676
+ readonly [K in keyof Q]: DecideAnswerFor<Q[K]>;
677
+ };
678
+ readonly usage?: SystemOneTokenUsage;
679
+ }
680
+
596
681
  /** One skill entry from a plugin's manifest (`targets.kay.agent.contributes.skills`). */
597
682
  export declare interface DeclaredSkillContribution {
598
683
  readonly localId: string;
@@ -714,6 +799,8 @@ declare const DollarSign = "$";
714
799
 
715
800
  declare const Dot = ".";
716
801
 
802
+ declare type DurationUnit = "seconds" | "minutes" | "hours" | "days" | "weeks" | "months" | "years";
803
+
717
804
  declare const Element: (input: string) => [unknown, string] | [];
718
805
 
719
806
  declare const ElementBase: (input: string) => [unknown, string] | [];
@@ -748,6 +835,18 @@ declare function Enum<Values extends TEnumValue[]>(values: readonly [...Values],
748
835
  /** Creates an Enum type from a TypeScript enum declaration. */
749
836
  declare function Enum<Enum extends TTypeScriptEnumLike>(value: Enum, options?: TSchemaOptions): TEnum<TTypeScriptEnumToEnumValues<Enum>>;
750
837
 
838
+ declare interface EstimateDistribution<V> {
839
+ readonly value: V | null;
840
+ readonly mean?: V;
841
+ readonly median?: V;
842
+ readonly p10?: V;
843
+ readonly p90?: V;
844
+ /** P(value < min). */
845
+ readonly pBelow?: number;
846
+ /** P(value > max). */
847
+ readonly pAbove?: number;
848
+ }
849
+
751
850
  /** Applies an Evaluate action to a type. */
752
851
  declare function Evaluate<Type extends TSchema>(type: Type, options?: TSchemaOptions): TEvaluate<Type>;
753
852
 
@@ -925,13 +1024,135 @@ declare interface ExtensionPaths {
925
1024
  /** Applies an Extract action using the given types. */
926
1025
  declare function Extract_2<Left extends TSchema, Right extends TSchema>(left: Left, right: Right, options?: TSchemaOptions): TExtract<Left, Right>;
927
1026
 
1027
+ declare type ExtractAnswerFor<F> = F extends ExtractTextField ? ExtractValueAnswer<"text", string> : F extends ExtractNumberField ? ExtractValueAnswer<"number", number> : F extends ExtractDateTimeField ? ExtractValueAnswer<F["type"], string> : F extends ExtractDurationField ? ExtractValueAnswer<"duration", number> : F extends ExtractListField ? ExtractListAnswer<F["items"] extends "number" ? number : string> : F extends ExtractEstimateField ? ExtractEstimateAnswer<F["min"] extends string ? string : number> : F extends ExtractForecastField ? ExtractForecastAnswer : never;
1028
+
1029
+ /** `date` answers are ISO dates, `time` ISO times, `datetime` ISO date-times. */
1030
+ declare interface ExtractDateTimeField extends ExtractFieldBase {
1031
+ readonly type: "date" | "time" | "datetime";
1032
+ }
1033
+
928
1034
  /** Creates a deferred Extract action. */
929
1035
  declare function ExtractDeferred<Left extends TSchema, Right extends TSchema>(left: Left, right: Right, options?: TSchemaOptions): TExtractDeferred<Left, Right>;
930
1036
 
1037
+ declare interface ExtractDurationField extends ExtractFieldBase {
1038
+ readonly type: "duration";
1039
+ /** Seconds when omitted. */
1040
+ readonly unit?: DurationUnit;
1041
+ readonly integer?: boolean;
1042
+ readonly decimals?: number;
1043
+ }
1044
+
1045
+ declare interface ExtractEstimateAnswer<V = number | string> extends EstimateDistribution<V> {
1046
+ readonly type: "estimate";
1047
+ }
1048
+
1049
+ /** A distribution over one value. `min`/`max` are numbers, or ISO dates for a date estimate. */
1050
+ declare interface ExtractEstimateField extends ExtractFieldBase {
1051
+ readonly type: "estimate";
1052
+ readonly min: number | string;
1053
+ readonly max: number | string;
1054
+ /** Grid step: a positive number (days for a date estimate), `month` or `year`. */
1055
+ readonly step?: number | "month" | "year";
1056
+ readonly scale?: "linear" | "log";
1057
+ readonly unit?: string;
1058
+ }
1059
+
1060
+ declare type ExtractField = ExtractTextField | ExtractNumberField | ExtractDateTimeField | ExtractDurationField | ExtractListField | ExtractEstimateField | ExtractForecastField;
1061
+
1062
+ declare interface ExtractFieldBase {
1063
+ readonly instructions?: string;
1064
+ /** P(null) above which the value is null. Clairic's default is 0.5. */
1065
+ readonly nullThreshold?: number;
1066
+ }
1067
+
1068
+ /** Fields keyed by name. A name matches `^[A-Za-z_][A-Za-z0-9_.\-]{0,63}$`. */
1069
+ declare type ExtractFields = Readonly<Record<string, ExtractField>>;
1070
+
1071
+ declare interface ExtractForecastAnswer {
1072
+ readonly type: "forecast";
1073
+ /** One value per step; `null` when the state does not determine the forecast. */
1074
+ readonly value: readonly number[] | null;
1075
+ readonly steps: readonly EstimateDistribution<number>[];
1076
+ }
1077
+
1078
+ /** One distribution per future step. */
1079
+ declare interface ExtractForecastField extends ExtractFieldBase {
1080
+ readonly type: "forecast";
1081
+ readonly min: number;
1082
+ readonly max: number;
1083
+ /** Number of steps, 1 to 64. */
1084
+ readonly horizon: number;
1085
+ readonly interval?: ForecastInterval;
1086
+ readonly scale?: "linear" | "log";
1087
+ readonly unit?: string;
1088
+ }
1089
+
1090
+ declare interface Extraction<F extends ExtractFields = ExtractFields> {
1091
+ readonly model: ExtractModelId;
1092
+ readonly answers: {
1093
+ readonly [K in keyof F]: ExtractAnswerFor<F[K]>;
1094
+ };
1095
+ /** The state was cut to fit the model's context. */
1096
+ readonly truncated: boolean;
1097
+ readonly usage?: SystemOneTokenUsage;
1098
+ }
1099
+
1100
+ declare interface ExtractListAnswer<V> {
1101
+ readonly type: "list";
1102
+ readonly value: readonly V[] | null;
1103
+ readonly confidence?: number;
1104
+ /** One per item in `value`. */
1105
+ readonly confidences?: readonly number[];
1106
+ readonly spans?: readonly TextSpan[];
1107
+ }
1108
+
1109
+ declare interface ExtractListField extends ExtractFieldBase {
1110
+ readonly type: "list";
1111
+ readonly items: "text" | "number" | "date";
1112
+ readonly decimals?: number;
1113
+ }
1114
+
1115
+ declare type ExtractModelId = "clairic";
1116
+
1117
+ declare interface ExtractNumberField extends ExtractFieldBase {
1118
+ readonly type: "number";
1119
+ readonly unit?: string;
1120
+ readonly integer?: boolean;
1121
+ /** 0 to 6. */
1122
+ readonly decimals?: number;
1123
+ }
1124
+
1125
+ declare interface ExtractRequest<F extends ExtractFields = ExtractFields> {
1126
+ readonly model: ExtractModelId;
1127
+ /** Text only; JSON is not accepted. */
1128
+ readonly state: string;
1129
+ readonly fields: F;
1130
+ /** ISO date that anchors dates written without a year. */
1131
+ readonly referenceDate?: string;
1132
+ }
1133
+
1134
+ declare interface ExtractTextField extends ExtractFieldBase {
1135
+ readonly type: "text";
1136
+ }
1137
+
1138
+ declare interface ExtractValueAnswer<T extends "text" | "number" | "date" | "time" | "datetime" | "duration", V> {
1139
+ readonly type: T;
1140
+ /** `null` when the state does not determine the value. */
1141
+ readonly value: V | null;
1142
+ /** The best candidate even when `value` is null. */
1143
+ readonly guess?: V;
1144
+ readonly confidence?: number;
1145
+ readonly pNull?: number;
1146
+ readonly span?: TextSpan;
1147
+ readonly unit?: string;
1148
+ }
1149
+
931
1150
  declare const Factor: (input: string) => [unknown, string] | [];
932
1151
 
933
1152
  declare function FactorMapping(input: [unknown, unknown, unknown, unknown, unknown]): unknown;
934
1153
 
1154
+ declare type ForecastInterval = "step" | "minute" | "hour" | "day" | "week" | "month" | "quarter" | "year";
1155
+
935
1156
  /** Creates a Function type. */
936
1157
  declare function _Function_<Parameters extends TSchema[], ReturnType extends TSchema>(parameters: [...Parameters], returnType: ReturnType, options?: TSchemaOptions): TFunction<Parameters, ReturnType>;
937
1158
 
@@ -1812,6 +2033,15 @@ declare interface KayAgentPluginApi {
1812
2033
  * guard it with `if (api.withJev !== undefined)`.
1813
2034
  */
1814
2035
  readonly withJev: WithJev;
2036
+ /**
2037
+ * System One: fast, cheap judgment calls (`decide`) and typed field extraction (`extract`) on
2038
+ * small models (Jev, Clef, Clef Flash, Clairic). Each call is checked against `jev.use`; a call
2039
+ * that cannot be served or is not permitted throws a `SystemOneError` whose `cause.kind` says
2040
+ * why, so put the feature's cheaper path in the call's own `catch`. Always present, on every
2041
+ * host; a host with no System One throws `not-served`. Types: `@bonsai/plugin-sdk/system-one`
2042
+ * (SDK 0.13.8).
2043
+ */
2044
+ readonly systemOne: SystemOneClient;
1815
2045
  /**
1816
2046
  * The daemon's clock and the time zone the user is in, read together on each `snapshot()` call.
1817
2047
  * Always present and ungated: it confers no authority, since a plugin runs in the daemon's
@@ -4373,6 +4603,76 @@ declare const StringPattern = ".*";
4373
4603
  /** Creates a Symbol type. */
4374
4604
  declare function Symbol_2(options?: TSchemaOptions): TSymbol;
4375
4605
 
4606
+ declare interface SystemOneCallOptions {
4607
+ readonly signal?: AbortSignal;
4608
+ /** Bounds the whole call, retries included. */
4609
+ readonly timeoutMs?: number;
4610
+ /** What the call is for, carried to the host's usage accounting. Never sent to a provider. */
4611
+ readonly purpose?: string;
4612
+ }
4613
+
4614
+ declare interface SystemOneClient {
4615
+ decide<const Q extends DecideQuestions>(request: DecideRequest<Q>, options?: SystemOneCallOptions): Promise<Decision<Q>>;
4616
+ extract<const F extends ExtractFields>(request: ExtractRequest<F>, options?: SystemOneCallOptions): Promise<Extraction<F>>;
4617
+ /** Whether some provider in the current order can serve `(kind, model)`. Never rejects. */
4618
+ availability(kind: SystemOneKind, model?: SystemOneModelId): Promise<Availability>;
4619
+ }
4620
+
4621
+ /**
4622
+ * Why a call failed or a provider can't serve, as a closed set. Never prose, and never the
4623
+ * vendor's body: bodies can echo the request's state.
4624
+ */
4625
+ declare type SystemOneFailureCause = {
4626
+ readonly kind: "no-credential";
4627
+ } | {
4628
+ readonly kind: "credential-store";
4629
+ } | {
4630
+ readonly kind: "not-served";
4631
+ } | {
4632
+ readonly kind: "not-permitted";
4633
+ } | {
4634
+ readonly kind: "unknown-model";
4635
+ } | {
4636
+ readonly kind: "invalid-request";
4637
+ readonly detail: string;
4638
+ } | {
4639
+ readonly kind: "too-large";
4640
+ } | {
4641
+ readonly kind: "http";
4642
+ readonly status: number;
4643
+ } | {
4644
+ readonly kind: "transport";
4645
+ } | {
4646
+ readonly kind: "timeout";
4647
+ } | {
4648
+ readonly kind: "aborted";
4649
+ } | {
4650
+ readonly kind: "invalid-answer";
4651
+ };
4652
+
4653
+ /**
4654
+ * ---
4655
+ * responsibility: The data shapes of the System One surface: models, the decide and extract
4656
+ * vocabularies, providers, and the failure causes.
4657
+ * owns:
4658
+ * - The caller-facing question, field, answer, and result types, in Bonsai's own words
4659
+ * (`bool` for yes/no, camelCase options). The vendors' words (`noul`, snake_case) appear
4660
+ * only in `wire.ts`.
4661
+ * - {@link SystemOneProvider}, the seam a transport implements.
4662
+ * does_not_own:
4663
+ * - Which models exist (`models.ts`), how answers are checked (`wire.ts`), or how a provider is
4664
+ * picked (`system-one-client.ts`).
4665
+ * ---
4666
+ */
4667
+ declare type SystemOneKind = "decide" | "extract";
4668
+
4669
+ declare type SystemOneModelId = DecideModelId | ExtractModelId;
4670
+
4671
+ declare interface SystemOneTokenUsage {
4672
+ readonly inputTokens: number;
4673
+ readonly outputTokens: number;
4674
+ }
4675
+
4376
4676
  declare namespace T {
4377
4677
  export {
4378
4678
  Codec,
@@ -5417,6 +5717,9 @@ declare type TExtractType<Left extends TSchema, Right extends TSchema, Check ext
5417
5717
 
5418
5718
  declare type TExtractUnion<Left extends TSchema[], Right extends TSchema, Result extends TSchema[] = []> = (Left extends [infer Head extends TSchema, ...infer Tail extends TSchema[]] ? TExtractUnion<Tail, Right, [...Result, ...TExtractType<Head, Right>]> : Result);
5419
5719
 
5720
+ /** `[start, end)` character offsets into the state. */
5721
+ declare type TextSpan = readonly [number, number];
5722
+
5420
5723
  declare type TFactor<Input extends string> = (TKeyOf<Input> extends [infer _0, infer Input extends string] ? (TBase<Input> extends [infer _1, infer Input extends string] ? (TIndexArray<Input> extends [infer _2, infer Input extends string] ? (TExtends_2<Input> extends [infer _3, infer Input extends string] ? (TWith<Input> extends [infer _4, infer Input extends string] ? [[_0, _1, _2, _3, _4], Input] : []) : []) : []) : []) : []) extends [infer _0 extends [unknown, unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TFactorMapping<_0>, Input] : [];
5421
5724
 
5422
5725
  declare type TFactorExtends<Type extends T.TSchema, Extends extends unknown[]> = (Extends extends [infer Right extends T.TSchema, infer True extends T.TSchema, infer False extends T.TSchema] ? S_2.TConditionalDeferred<Type, Right, True, False> : Type);
@@ -741,6 +741,68 @@ function unavailableInteractionSurfaces(message) {
741
741
  };
742
742
  }
743
743
 
744
+ // packages/system-one/dist/errors.js
745
+ var SystemOneError = class extends Error {
746
+ cause;
747
+ kind;
748
+ model;
749
+ /** The provider that failed; absent when no provider was tried. */
750
+ providerId;
751
+ constructor(init) {
752
+ super(describe(init));
753
+ this.name = "SystemOneError";
754
+ this.cause = init.cause;
755
+ this.kind = init.kind;
756
+ this.model = init.model;
757
+ this.providerId = init.providerId;
758
+ }
759
+ };
760
+ function describe(init) {
761
+ const where = init.providerId === void 0 ? "" : ` on provider ${init.providerId}`;
762
+ const detail = init.cause.kind === "http" ? ` (HTTP ${init.cause.status})` : init.cause.kind === "invalid-request" ? ` (${init.cause.detail})` : "";
763
+ return `System One ${init.kind} on ${init.model}${where} failed: ${init.cause.kind}${detail}.`;
764
+ }
765
+
766
+ // packages/system-one/dist/models.js
767
+ var DEFAULT_DECIDE_MODEL = "jev";
768
+ var SYSTEM_ONE_LIMITS = {
769
+ /** The serialized request body, in bytes. */
770
+ maxBodyBytes: 64 * 1024,
771
+ maxQuestions: 64,
772
+ maxFields: 32,
773
+ minChoiceOptions: 2,
774
+ maxChoiceOptions: 255,
775
+ minScoreLevels: 2,
776
+ maxScoreLevels: 10,
777
+ maxForecastHorizon: 64
778
+ };
779
+
780
+ // packages/system-one/dist/unavailable.js
781
+ var NOT_SERVED = {
782
+ available: false,
783
+ reason: "This host has no System One models.",
784
+ cause: { kind: "not-served" }
785
+ };
786
+ function createUnavailableSystemOneClient() {
787
+ return {
788
+ decide(request) {
789
+ return Promise.reject(new SystemOneError({
790
+ kind: "decide",
791
+ model: request.model ?? DEFAULT_DECIDE_MODEL,
792
+ cause: { kind: "not-served" }
793
+ }));
794
+ },
795
+ extract(request) {
796
+ return Promise.reject(new SystemOneError({
797
+ kind: "extract",
798
+ model: request.model,
799
+ cause: { kind: "not-served" }
800
+ }));
801
+ },
802
+ availability: () => Promise.resolve(NOT_SERVED)
803
+ };
804
+ }
805
+
744
806
  // packages/plugin-sdk/dist/disclosure/probe-kay-agent-capabilities.js
745
807
  var inertResult = () => new Promise(() => {
746
808
  });
@@ -784,6 +846,8 @@ function createKayAgentProbeCapabilityHandles() {
784
846
  interceptToolCall: () => {
785
847
  },
786
848
  withJev: INERT_WITH_JEV,
849
+ // Throws `not-served` at once, the outcome a plugin's own `catch` already handles.
850
+ systemOne: createUnavailableSystemOneClient(),
787
851
  // Fire-and-forget on the real api too, so dropping is the inert shape: nothing to hang on.
788
852
  events: { publish: () => {
789
853
  } },