@yaklabs-ai/plugin-protocol 0.32.0 → 0.33.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 CHANGED
@@ -11,7 +11,7 @@ flow.
11
11
  ```json
12
12
  {
13
13
  "dependencies": {
14
- "@bonsai/plugin-protocol": "npm:@yaklabs-ai/plugin-protocol@^0.32.0"
14
+ "@bonsai/plugin-protocol": "npm:@yaklabs-ai/plugin-protocol@^0.33.0"
15
15
  }
16
16
  }
17
17
  ```
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@yaklabs-ai/plugin-protocol",
4
- "version": "0.32.0",
4
+ "version": "0.33.0",
5
5
  "target": "npm",
6
6
  "firstPartyLicense": "MIT",
7
7
  "bundled": [],
package/dist/index.d.ts CHANGED
@@ -2580,7 +2580,13 @@ declare const canonicalContributionSchemas: {
2580
2580
  localId: z.ZodString;
2581
2581
  title: z.ZodString;
2582
2582
  icon: z.ZodOptional<z.ZodString>;
2583
- placement: z.ZodOptional<z.ZodString>;
2583
+ button: z.ZodOptional<z.ZodEnum<{
2584
+ tabStrip: "tabStrip";
2585
+ }>>;
2586
+ menu: z.ZodOptional<z.ZodEnum<{
2587
+ help: "help";
2588
+ }>>;
2589
+ where: z.ZodOptional<z.ZodString>;
2584
2590
  }, z.core.$strict>;
2585
2591
  UiSlotContribution: z.ZodObject<{
2586
2592
  localId: z.ZodString;
@@ -2694,8 +2700,6 @@ declare const canonicalContributionSchemas: {
2694
2700
  "artifacts.preview": "artifacts.preview";
2695
2701
  "cost.read": "cost.read";
2696
2702
  "billing.read": "billing.read";
2697
- "context.read": "context.read";
2698
- "usage.read": "usage.read";
2699
2703
  "self-improvement.read": "self-improvement.read";
2700
2704
  "automations.read": "automations.read";
2701
2705
  "shared-artifacts.read": "shared-artifacts.read";
@@ -2715,8 +2719,6 @@ declare const canonicalContributionSchemas: {
2715
2719
  "artifacts.preview": "artifacts.preview";
2716
2720
  "cost.read": "cost.read";
2717
2721
  "billing.read": "billing.read";
2718
- "context.read": "context.read";
2719
- "usage.read": "usage.read";
2720
2722
  "self-improvement.read": "self-improvement.read";
2721
2723
  "automations.read": "automations.read";
2722
2724
  "shared-artifacts.read": "shared-artifacts.read";
@@ -2766,8 +2768,6 @@ declare const canonicalContributionSchemas: {
2766
2768
  "artifacts.preview": "artifacts.preview";
2767
2769
  "cost.read": "cost.read";
2768
2770
  "billing.read": "billing.read";
2769
- "context.read": "context.read";
2770
- "usage.read": "usage.read";
2771
2771
  "self-improvement.read": "self-improvement.read";
2772
2772
  "automations.read": "automations.read";
2773
2773
  "shared-artifacts.read": "shared-artifacts.read";
@@ -2804,8 +2804,6 @@ declare const canonicalContributionSchemas: {
2804
2804
  "artifacts.preview": "artifacts.preview";
2805
2805
  "cost.read": "cost.read";
2806
2806
  "billing.read": "billing.read";
2807
- "context.read": "context.read";
2808
- "usage.read": "usage.read";
2809
2807
  "self-improvement.read": "self-improvement.read";
2810
2808
  "automations.read": "automations.read";
2811
2809
  "shared-artifacts.read": "shared-artifacts.read";
@@ -2999,6 +2997,41 @@ export declare const CommandHandler: z.ZodDiscriminatedUnion<[z.ZodObject<{
2999
2997
 
3000
2998
  export declare type CommandHandler = z.infer<typeof CommandHandler>;
3001
2999
 
3000
+ export declare type CommandWhere = {
3001
+ readonly kind: "literal";
3002
+ readonly value: boolean;
3003
+ } | {
3004
+ readonly kind: "key";
3005
+ readonly key: CommandWhereKey;
3006
+ } | {
3007
+ readonly kind: "equals";
3008
+ readonly key: CommandWhereKey;
3009
+ readonly value: boolean | string;
3010
+ readonly negated: boolean;
3011
+ } | {
3012
+ readonly kind: "not";
3013
+ readonly operand: CommandWhere;
3014
+ } | {
3015
+ readonly kind: "and" | "or";
3016
+ readonly left: CommandWhere;
3017
+ readonly right: CommandWhere;
3018
+ };
3019
+
3020
+ export declare type CommandWhereKey = keyof typeof WHERE_KEY_TYPES;
3021
+
3022
+ export declare type CommandWhereParseResult = {
3023
+ readonly ok: true;
3024
+ readonly where: CommandWhere;
3025
+ } | {
3026
+ readonly ok: false;
3027
+ readonly message: string;
3028
+ };
3029
+
3030
+ /** The values a `where` reads. A key left out isn't known yet, for example while it loads. */
3031
+ export declare type CommandWhereValues = {
3032
+ readonly [K in CommandWhereKey]?: (typeof WHERE_KEY_TYPES)[K] extends "boolean" ? boolean : string;
3033
+ };
3034
+
3002
3035
  /**
3003
3036
  * Total order over claims, for deterministic projection and diffs. Compares the same fields
3004
3037
  * {@link sameClaim} compares, in a fixed order, so two claims that compare equal here are the same
@@ -3128,6 +3161,25 @@ export declare const CorpusResourceKind: z.ZodEnum<{
3128
3161
 
3129
3162
  export declare type CorpusResourceKind = z.infer<typeof CorpusResourceKind>;
3130
3163
 
3164
+ /**
3165
+ * Every plugin's declarations of one kind, each with the plugin that made it. Main and the window
3166
+ * each hold the plugins' `kay.ui` facts, and both read them through here. `contributes` crosses the
3167
+ * daemon, the protocol and main unread, so this is where it gets its type back.
3168
+ */
3169
+ export declare function declarationsOfKind<TPlugin extends {
3170
+ readonly contributes: Readonly<Record<string, unknown>>;
3171
+ }, K extends keyof UiContributes>(plugins: readonly TPlugin[], kind: K): readonly {
3172
+ readonly plugin: TPlugin;
3173
+ readonly declaration: NonNullable<UiContributes[K]>[number];
3174
+ }[];
3175
+
3176
+ /**
3177
+ * A declared command's full id. Neither part can contain `/`, so two plugins can't produce the same
3178
+ * one, and none can name an app command such as `session.interrupt`, which a plugin called `session`
3179
+ * could otherwise put a button on without implementing it.
3180
+ */
3181
+ export declare function declaredCommandId(pluginId: string, localId: string): string;
3182
+
3131
3183
  /**
3132
3184
  * The `compatibility` block as the check reads it. Structural rather than the parsed
3133
3185
  * `PluginCompatibilityManifest`, so a host can judge the block of a manifest whose other fields
@@ -3227,6 +3279,13 @@ export declare const EntityResolverContribution: z.ZodObject<{
3227
3279
 
3228
3280
  export declare type EntityResolverContribution = z.infer<typeof EntityResolverContribution>;
3229
3281
 
3282
+ /**
3283
+ * Whether a `where` holds. When the answer depends on a value not known yet the result is false,
3284
+ * so a button stays hidden while a value loads rather than flashing on: `true || app.channel == 'x'`
3285
+ * holds whatever the channel is, and `!(app.channel == 'x')` waits for it.
3286
+ */
3287
+ export declare function evaluateCommandWhere(where: CommandWhere, values: CommandWhereValues): boolean;
3288
+
3230
3289
  export declare const EventGrantRequest: z.ZodObject<{
3231
3290
  event: z.ZodString;
3232
3291
  operations: z.ZodArray<z.ZodEnum<{
@@ -4009,8 +4068,13 @@ export declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
4009
4068
  * 0.32.0 lets an app-data source declare its window store as data (#15891). `store` under
4010
4069
  * `contributes.dataSources` replaces a `kay.ui` data materializer, and a change too big for a live
4011
4070
  * update becomes a re-read of the snapshot. A plugin that declares a store declares ^0.32.0.
4071
+ *
4072
+ * 0.33.0 lets a plugin declare a window command with its button and menu item (#15903). `commands`
4073
+ * under `kay.ui` `contributes` names each command's title, icon file, `button`, `menu` and `where`,
4074
+ * and `api.implementCommand(localId, handler)` supplies what it does. `placement` is gone and `icon`
4075
+ * is now a file path: nothing ever read either. A plugin that declares a command declares ^0.33.0.
4012
4076
  */
4013
- export declare const KAY_PLUGIN_SDK_VERSION: "0.32.0";
4077
+ export declare const KAY_PLUGIN_SDK_VERSION: "0.33.0";
4014
4078
 
4015
4079
  export declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
4016
4080
 
@@ -5474,7 +5538,13 @@ export declare const KayPluginManifestV1: z.ZodObject<{
5474
5538
  localId: z.ZodString;
5475
5539
  title: z.ZodString;
5476
5540
  icon: z.ZodOptional<z.ZodString>;
5477
- placement: z.ZodOptional<z.ZodString>;
5541
+ button: z.ZodOptional<z.ZodEnum<{
5542
+ tabStrip: "tabStrip";
5543
+ }>>;
5544
+ menu: z.ZodOptional<z.ZodEnum<{
5545
+ help: "help";
5546
+ }>>;
5547
+ where: z.ZodOptional<z.ZodString>;
5478
5548
  }, z.core.$strict>>>;
5479
5549
  slots: z.ZodOptional<z.ZodArray<z.ZodObject<{
5480
5550
  localId: z.ZodString;
@@ -5562,8 +5632,6 @@ export declare const KayPluginManifestV1: z.ZodObject<{
5562
5632
  "artifacts.preview": "artifacts.preview";
5563
5633
  "cost.read": "cost.read";
5564
5634
  "billing.read": "billing.read";
5565
- "context.read": "context.read";
5566
- "usage.read": "usage.read";
5567
5635
  "self-improvement.read": "self-improvement.read";
5568
5636
  "automations.read": "automations.read";
5569
5637
  "shared-artifacts.read": "shared-artifacts.read";
@@ -5600,8 +5668,6 @@ export declare const KayPluginManifestV1: z.ZodObject<{
5600
5668
  "artifacts.preview": "artifacts.preview";
5601
5669
  "cost.read": "cost.read";
5602
5670
  "billing.read": "billing.read";
5603
- "context.read": "context.read";
5604
- "usage.read": "usage.read";
5605
5671
  "self-improvement.read": "self-improvement.read";
5606
5672
  "automations.read": "automations.read";
5607
5673
  "shared-artifacts.read": "shared-artifacts.read";
@@ -6449,8 +6515,6 @@ export declare const KayUiAppHostCapability: z.ZodEnum<{
6449
6515
  "artifacts.preview": "artifacts.preview";
6450
6516
  "cost.read": "cost.read";
6451
6517
  "billing.read": "billing.read";
6452
- "context.read": "context.read";
6453
- "usage.read": "usage.read";
6454
6518
  "self-improvement.read": "self-improvement.read";
6455
6519
  "automations.read": "automations.read";
6456
6520
  "shared-artifacts.read": "shared-artifacts.read";
@@ -6568,7 +6632,13 @@ export declare const KayUiTargetManifest: z.ZodObject<{
6568
6632
  localId: z.ZodString;
6569
6633
  title: z.ZodString;
6570
6634
  icon: z.ZodOptional<z.ZodString>;
6571
- placement: z.ZodOptional<z.ZodString>;
6635
+ button: z.ZodOptional<z.ZodEnum<{
6636
+ tabStrip: "tabStrip";
6637
+ }>>;
6638
+ menu: z.ZodOptional<z.ZodEnum<{
6639
+ help: "help";
6640
+ }>>;
6641
+ where: z.ZodOptional<z.ZodString>;
6572
6642
  }, z.core.$strict>>>;
6573
6643
  slots: z.ZodOptional<z.ZodArray<z.ZodObject<{
6574
6644
  localId: z.ZodString;
@@ -6656,8 +6726,6 @@ export declare const KayUiTargetManifest: z.ZodObject<{
6656
6726
  "artifacts.preview": "artifacts.preview";
6657
6727
  "cost.read": "cost.read";
6658
6728
  "billing.read": "billing.read";
6659
- "context.read": "context.read";
6660
- "usage.read": "usage.read";
6661
6729
  "self-improvement.read": "self-improvement.read";
6662
6730
  "automations.read": "automations.read";
6663
6731
  "shared-artifacts.read": "shared-artifacts.read";
@@ -6694,8 +6762,6 @@ export declare const KayUiTargetManifest: z.ZodObject<{
6694
6762
  "artifacts.preview": "artifacts.preview";
6695
6763
  "cost.read": "cost.read";
6696
6764
  "billing.read": "billing.read";
6697
- "context.read": "context.read";
6698
- "usage.read": "usage.read";
6699
6765
  "self-improvement.read": "self-improvement.read";
6700
6766
  "automations.read": "automations.read";
6701
6767
  "shared-artifacts.read": "shared-artifacts.read";
@@ -6886,6 +6952,12 @@ export declare function parseArtifactProvenanceCaptureContext(input: unknown): A
6886
6952
  /** Returns an owned value snapshot; callers must not attach live session references. */
6887
6953
  export declare function parseArtifactProvenanceEnvelope(input: unknown): ArtifactProvenanceEnvelopeV1;
6888
6954
 
6955
+ /**
6956
+ * Parses a declared command's `where`: `||`, `&&`, `!`, parentheses, `==`, `!=`, strings, `true`,
6957
+ * `false` and dotted keys, for example `account.signedIn || app.channel != 'production'`.
6958
+ */
6959
+ export declare function parseCommandWhere(source: string): CommandWhereParseResult;
6960
+
6889
6961
  /** A `MAJOR.MINOR.PATCH` version broken into its comparable parts. */
6890
6962
  export declare interface ParsedSemver {
6891
6963
  readonly major: number;
@@ -10772,8 +10844,6 @@ export declare const ResolvedKayUiApp: z.ZodObject<{
10772
10844
  "artifacts.preview": "artifacts.preview";
10773
10845
  "cost.read": "cost.read";
10774
10846
  "billing.read": "billing.read";
10775
- "context.read": "context.read";
10776
- "usage.read": "usage.read";
10777
10847
  "self-improvement.read": "self-improvement.read";
10778
10848
  "automations.read": "automations.read";
10779
10849
  "shared-artifacts.read": "shared-artifacts.read";
@@ -12066,8 +12136,6 @@ export declare const ResolvedPluginContractV1: z.ZodObject<{
12066
12136
  "artifacts.preview": "artifacts.preview";
12067
12137
  "cost.read": "cost.read";
12068
12138
  "billing.read": "billing.read";
12069
- "context.read": "context.read";
12070
- "usage.read": "usage.read";
12071
12139
  "self-improvement.read": "self-improvement.read";
12072
12140
  "automations.read": "automations.read";
12073
12141
  "shared-artifacts.read": "shared-artifacts.read";
@@ -13652,8 +13720,6 @@ export declare const UiAppCapabilities: z.ZodObject<{
13652
13720
  "artifacts.preview": "artifacts.preview";
13653
13721
  "cost.read": "cost.read";
13654
13722
  "billing.read": "billing.read";
13655
- "context.read": "context.read";
13656
- "usage.read": "usage.read";
13657
13723
  "self-improvement.read": "self-improvement.read";
13658
13724
  "automations.read": "automations.read";
13659
13725
  "shared-artifacts.read": "shared-artifacts.read";
@@ -13693,8 +13759,6 @@ export declare const UiAppContribution: z.ZodObject<{
13693
13759
  "artifacts.preview": "artifacts.preview";
13694
13760
  "cost.read": "cost.read";
13695
13761
  "billing.read": "billing.read";
13696
- "context.read": "context.read";
13697
- "usage.read": "usage.read";
13698
13762
  "self-improvement.read": "self-improvement.read";
13699
13763
  "automations.read": "automations.read";
13700
13764
  "shared-artifacts.read": "shared-artifacts.read";
@@ -13731,8 +13795,6 @@ export declare const UiAppContribution: z.ZodObject<{
13731
13795
  "artifacts.preview": "artifacts.preview";
13732
13796
  "cost.read": "cost.read";
13733
13797
  "billing.read": "billing.read";
13734
- "context.read": "context.read";
13735
- "usage.read": "usage.read";
13736
13798
  "self-improvement.read": "self-improvement.read";
13737
13799
  "automations.read": "automations.read";
13738
13800
  "shared-artifacts.read": "shared-artifacts.read";
@@ -13749,11 +13811,19 @@ export declare const UiCommandContribution: z.ZodObject<{
13749
13811
  localId: z.ZodString;
13750
13812
  title: z.ZodString;
13751
13813
  icon: z.ZodOptional<z.ZodString>;
13752
- placement: z.ZodOptional<z.ZodString>;
13814
+ button: z.ZodOptional<z.ZodEnum<{
13815
+ tabStrip: "tabStrip";
13816
+ }>>;
13817
+ menu: z.ZodOptional<z.ZodEnum<{
13818
+ help: "help";
13819
+ }>>;
13820
+ where: z.ZodOptional<z.ZodString>;
13753
13821
  }, z.core.$strict>;
13754
13822
 
13755
13823
  export declare type UiCommandContribution = z.infer<typeof UiCommandContribution>;
13756
13824
 
13825
+ declare type UiContributes = NonNullable<KayUiTargetManifest["contributes"]>;
13826
+
13757
13827
  export declare const UiEventSubscriptionContribution: z.ZodObject<{
13758
13828
  localId: z.ZodString;
13759
13829
  event: z.ZodString;
@@ -14174,6 +14244,12 @@ export declare type WebSessionGrantRequest = z.infer<typeof WebSessionGrantReque
14174
14244
  */
14175
14245
  export declare function webSessionPathWithinPrefix(pathname: string, pathPrefix: string): boolean;
14176
14246
 
14247
+ /** What a `where` expression can read, and the type of each. */
14248
+ declare const WHERE_KEY_TYPES: {
14249
+ readonly "account.signedIn": "boolean";
14250
+ readonly "app.channel": "string";
14251
+ };
14252
+
14177
14253
  /** Construct the exact claim row for one Whiteboard scope and operation. */
14178
14254
  export declare function whiteboardCapabilityClaim(operation: WhiteboardCapabilityOperation, scope: WhiteboardCapabilityScope, target?: "kay.agent"): WhiteboardCapabilityClaimV1;
14179
14255
 
package/dist/index.js CHANGED
@@ -13,7 +13,15 @@ var KAY_APP_DATA_READ_RESULT_MAX_BYTES = 16 * 1024 * 1024;
13
13
  // packages/plugin-protocol/dist/ui-icon-paths.js
14
14
  function declaredUiIconPaths(manifest) {
15
15
  const contributes = manifest.targets?.kay?.ui?.contributes;
16
- return (contributes?.railEntries ?? []).flatMap((entry) => entry.icon === void 0 ? [] : [{ label: `kay.ui rail entry '${entry.id}' icon`, path: entry.icon }]);
16
+ return [
17
+ ...(contributes?.railEntries ?? []).flatMap((entry) => entry.icon === void 0 ? [] : [{ label: `kay.ui rail entry '${entry.id}' icon`, path: entry.icon }]),
18
+ ...(contributes?.commands ?? []).flatMap((command) => command.icon === void 0 ? [] : [
19
+ {
20
+ label: `kay.ui command '${command.localId}' icon`,
21
+ path: command.icon
22
+ }
23
+ ])
24
+ ];
17
25
  }
18
26
 
19
27
  // packages/plugin-protocol/dist/approval-types.js
@@ -230,14 +238,15 @@ var JsonSchema = z4.record(z4.string(), JsonValue);
230
238
  var KAY_PLUGIN_MANIFEST_SIZE_CAP_BYTES = 1024 * 1024;
231
239
  var KAY_PLUGIN_PROTOCOL_VERSION = "kay.plugin.v1";
232
240
  var KAY_PLUGIN_PROTOCOL_PACKAGE_NAME = "@bonsai/plugin-protocol";
233
- var KAY_PLUGIN_SDK_VERSION = "0.32.0";
241
+ var KAY_PLUGIN_SDK_VERSION = "0.33.0";
234
242
  var KAY_PLUGIN_COMPATIBLE_SDK_VERSIONS = [
235
243
  "0.26.3",
236
244
  "0.27.1",
237
245
  "0.28.0",
238
246
  "0.29.0",
239
247
  "0.30.0",
240
- "0.31.0"
248
+ "0.31.0",
249
+ "0.32.0"
241
250
  ];
242
251
  var KAY_PLUGIN_TARGET_NAMES = [
243
252
  "kay.agent",
@@ -2823,6 +2832,165 @@ function createPluginEventsSchemas(canonical) {
2823
2832
  var { PluginEventLocalId, PluginEventUri, PluginEventTimestamp, PluginEventRelated, PluginEventPublishSource, PluginEventSource, PluginEventId, PluginEventPublishInput, PluginEventEnvelope } = createPluginEventsSchemas(false);
2824
2833
  var canonicalPluginEventSchemas = createPluginEventsSchemas(true);
2825
2834
 
2835
+ // packages/plugin-protocol/dist/declared-commands.js
2836
+ function declarationsOfKind(plugins, kind) {
2837
+ return plugins.flatMap((plugin) => (plugin.contributes[kind] ?? []).map((declaration) => ({
2838
+ plugin,
2839
+ declaration
2840
+ })));
2841
+ }
2842
+ function declaredCommandId(pluginId, localId) {
2843
+ return `${pluginId}/${localId}`;
2844
+ }
2845
+ var WHERE_KEY_TYPES = {
2846
+ "account.signedIn": "boolean",
2847
+ "app.channel": "string"
2848
+ };
2849
+ var TOKEN = /\s*(?:(\|\||&&|==|!=|!|\(|\))|'([^']*)'|"([^"]*)"|([A-Za-z][A-Za-z0-9]*(?:\.[A-Za-z][A-Za-z0-9]*)*))/y;
2850
+ function tokenize(source) {
2851
+ const tokens = [];
2852
+ TOKEN.lastIndex = 0;
2853
+ while (source.slice(TOKEN.lastIndex).trim() !== "") {
2854
+ const start = TOKEN.lastIndex;
2855
+ const match = TOKEN.exec(source);
2856
+ if (match === null) {
2857
+ throw new Error(`unexpected text at '${source.slice(start).trim()}'`);
2858
+ }
2859
+ const [, operator, single, double, word] = match;
2860
+ if (operator !== void 0)
2861
+ tokens.push({ kind: "operator", text: operator });
2862
+ else if (word !== void 0)
2863
+ tokens.push({ kind: "word", text: word });
2864
+ else
2865
+ tokens.push({ kind: "string", text: single ?? double ?? "" });
2866
+ }
2867
+ return tokens;
2868
+ }
2869
+ function isKey(text) {
2870
+ return Object.hasOwn(WHERE_KEY_TYPES, text);
2871
+ }
2872
+ function parseTokens(tokens) {
2873
+ let position = 0;
2874
+ const takeOperator = (text) => {
2875
+ const token = tokens[position];
2876
+ if (token?.kind !== "operator" || token.text !== text)
2877
+ return false;
2878
+ position += 1;
2879
+ return true;
2880
+ };
2881
+ const parseOr = () => {
2882
+ let left = parseAnd();
2883
+ while (takeOperator("||"))
2884
+ left = { kind: "or", left, right: parseAnd() };
2885
+ return left;
2886
+ };
2887
+ const parseAnd = () => {
2888
+ let left = parseNot();
2889
+ while (takeOperator("&&"))
2890
+ left = { kind: "and", left, right: parseNot() };
2891
+ return left;
2892
+ };
2893
+ const parseNot = () => takeOperator("!") ? { kind: "not", operand: parseNot() } : parseAtom();
2894
+ const parseAtom = () => {
2895
+ if (takeOperator("(")) {
2896
+ const inner = parseOr();
2897
+ if (!takeOperator(")"))
2898
+ throw new Error("missing ')'");
2899
+ return inner;
2900
+ }
2901
+ const token = tokens[position];
2902
+ if (token === void 0)
2903
+ throw new Error("the expression ends too soon");
2904
+ position += 1;
2905
+ if (token.kind === "word" && token.text === "true") {
2906
+ return { kind: "literal", value: true };
2907
+ }
2908
+ if (token.kind === "word" && token.text === "false") {
2909
+ return { kind: "literal", value: false };
2910
+ }
2911
+ if (token.kind !== "word")
2912
+ throw new Error(`unexpected '${token.text}'`);
2913
+ if (!isKey(token.text)) {
2914
+ throw new Error(`unknown key '${token.text}'; the keys are ${Object.keys(WHERE_KEY_TYPES).join(", ")}`);
2915
+ }
2916
+ return parseKeyAtom(token.text);
2917
+ };
2918
+ const parseKeyAtom = (key) => {
2919
+ const negated = takeOperator("!=");
2920
+ if (!negated && !takeOperator("==")) {
2921
+ if (WHERE_KEY_TYPES[key] !== "boolean") {
2922
+ throw new Error(`'${key}' must be compared, with == or !=`);
2923
+ }
2924
+ return { kind: "key", key };
2925
+ }
2926
+ const value = parseLiteral();
2927
+ if (typeof value !== WHERE_KEY_TYPES[key]) {
2928
+ throw new Error(`'${key}' compares to a ${WHERE_KEY_TYPES[key]}`);
2929
+ }
2930
+ return { kind: "equals", key, value, negated };
2931
+ };
2932
+ const parseLiteral = () => {
2933
+ const token = tokens[position];
2934
+ position += 1;
2935
+ if (token?.kind === "string")
2936
+ return token.text;
2937
+ if (token?.kind === "word" && token.text === "true")
2938
+ return true;
2939
+ if (token?.kind === "word" && token.text === "false")
2940
+ return false;
2941
+ throw new Error("expected a string, true or false after == or !=");
2942
+ };
2943
+ const where = parseOr();
2944
+ const extra = tokens[position];
2945
+ if (extra !== void 0)
2946
+ throw new Error(`unexpected '${extra.text}'`);
2947
+ return where;
2948
+ }
2949
+ function parseCommandWhere(source) {
2950
+ try {
2951
+ return { ok: true, where: parseTokens(tokenize(source)) };
2952
+ } catch (error) {
2953
+ return { ok: false, message: error.message };
2954
+ }
2955
+ }
2956
+ function resolve(where, values) {
2957
+ switch (where.kind) {
2958
+ case "literal":
2959
+ return where.value;
2960
+ case "key": {
2961
+ const value = values[where.key];
2962
+ return value === void 0 ? void 0 : value === true;
2963
+ }
2964
+ case "equals": {
2965
+ const value = values[where.key];
2966
+ if (value === void 0)
2967
+ return void 0;
2968
+ return value === where.value !== where.negated;
2969
+ }
2970
+ case "not": {
2971
+ const operand = resolve(where.operand, values);
2972
+ return operand === void 0 ? void 0 : !operand;
2973
+ }
2974
+ case "and": {
2975
+ const left = resolve(where.left, values);
2976
+ const right = resolve(where.right, values);
2977
+ if (left === false || right === false)
2978
+ return false;
2979
+ return left === void 0 || right === void 0 ? void 0 : true;
2980
+ }
2981
+ case "or": {
2982
+ const left = resolve(where.left, values);
2983
+ const right = resolve(where.right, values);
2984
+ if (left === true || right === true)
2985
+ return true;
2986
+ return left === void 0 || right === void 0 ? void 0 : false;
2987
+ }
2988
+ }
2989
+ }
2990
+ function evaluateCommandWhere(where, values) {
2991
+ return resolve(where, values) === true;
2992
+ }
2993
+
2826
2994
  // packages/plugin-protocol/dist/contributions.js
2827
2995
  var MCP_SERVER_LOCAL_HTTP_HOSTNAMES = /* @__PURE__ */ new Set(["localhost", "127.0.0.1"]);
2828
2996
  var MCP_SIGN_IN_SCHEME_KIND = {
@@ -3403,8 +3571,28 @@ function createContributionsSchemas(canonical) {
3403
3571
  const UiCommandContribution2 = z12.strictObject({
3404
3572
  localId: LocalContributionId2,
3405
3573
  title: NonEmptyString3,
3406
- icon: NonEmptyString3.optional(),
3407
- placement: NonEmptyString3.optional()
3574
+ icon: PackageAssetPath2.optional(),
3575
+ button: z12.enum(["tabStrip"]).optional(),
3576
+ menu: z12.enum(["help"]).optional(),
3577
+ where: NonEmptyString3.optional()
3578
+ }).superRefine((command, ctx) => {
3579
+ if (command.where === void 0)
3580
+ return;
3581
+ if (command.button === void 0) {
3582
+ ctx.addIssue({
3583
+ code: "custom",
3584
+ path: ["where"],
3585
+ message: `command ${command.localId} declares where without a button: where only decides when a button shows`
3586
+ });
3587
+ }
3588
+ const parsed = parseCommandWhere(command.where);
3589
+ if (!parsed.ok) {
3590
+ ctx.addIssue({
3591
+ code: "custom",
3592
+ path: ["where"],
3593
+ message: `command ${command.localId} has an invalid where: ${parsed.message}`
3594
+ });
3595
+ }
3408
3596
  });
3409
3597
  const UiSlotContribution2 = z12.strictObject({
3410
3598
  localId: LocalContributionId2,
@@ -3489,16 +3677,9 @@ function createContributionsSchemas(canonical) {
3489
3677
  "cost.read",
3490
3678
  // Server-rated organization billing, distinct from local/provider cost.
3491
3679
  "billing.read",
3492
- // Context, Skills, and Memory analytics reads (full snapshots via the capability broker).
3493
- "context.read",
3680
+ // Skills and Memory analytics reads (full snapshots via the capability broker).
3494
3681
  "skills.read",
3495
3682
  "memory.read",
3496
- // The "session trees" lens: root-session USD/token roll-ups from the
3497
- // typed usage-query surface (telemetry-unification RFC Phase 3, PR 3
3498
- // contract `docs/telemetry-lane-pr3-contracts.md`, amendment A7). Follows
3499
- // the `cost.read`/`context.read`/`skills.read`/`memory.read` convention -
3500
- // names the data (`usage`), not the tab that happens to render it.
3501
- "usage.read",
3502
3683
  // The self-improvement lens: reads the telemetry lane's self-improvement rollup
3503
3684
  // (memory/skill/notebook activity). Follows the same "names the data" convention.
3504
3685
  "self-improvement.read",
@@ -4217,9 +4398,7 @@ function createManifestSchemas(canonical) {
4217
4398
  */
4218
4399
  description: NonEmptyString3,
4219
4400
  // Display icons resolved relative to the package root and traversal-guarded
4220
- // by `PackageAssetPath`. This is a *raster/asset* icon - distinct from the
4221
- // *symbolic* `UiCommandContribution.icon` (an icon-set name), see LEXICON
4222
- // `icon`. By default the host treats the SVG as a mark and frames it, inset
4401
+ // by `PackageAssetPath`. By default the host treats the SVG as a mark and frames it, inset
4223
4402
  // on a white tile. An SVG whose artwork is already a complete tile (its own
4224
4403
  // background, edge to edge) says so with `data-icon-shape="tile"` on its
4225
4404
  // root `<svg>` element, and the host then draws it full-bleed in its tile
@@ -4438,6 +4617,7 @@ function createManifestSchemas(canonical) {
4438
4617
  presentationByUriModule.set(presentation.uriModule, presentation.localId);
4439
4618
  }
4440
4619
  }
4620
+ reportDuplicateLocalIds(ctx, ["targets", "kay", "ui", "contributes", "commands"], manifest.targets?.kay?.ui?.contributes?.commands, "ui command");
4441
4621
  reportDuplicateLocalIds(ctx, ["targets", "kay", "ui", "contributes", "referencePresentations"], manifest.targets?.kay?.ui?.contributes?.referencePresentations, "reference presentation");
4442
4622
  reportDuplicateLocalIds(ctx, ["targets", "kay", "app", "contributes", "eventDefinitions"], manifest.targets?.kay?.app?.contributes?.eventDefinitions, "plugin event definition");
4443
4623
  reportDuplicateLocalIds(ctx, ["targets", "kay", "app", "contributes", "contextContributors"], manifest.targets?.kay?.app?.contributes?.contextContributors, "context contributor");
@@ -6927,9 +7107,12 @@ export {
6927
7107
  compareClaims,
6928
7108
  compareSemver,
6929
7109
  configSectionKeysForManifest,
7110
+ declarationsOfKind,
7111
+ declaredCommandId,
6930
7112
  declaredUiIconPaths,
6931
7113
  dedupeClaims,
6932
7114
  deriveDirectoryPluginToolName,
7115
+ evaluateCommandWhere,
6933
7116
  finalizeArtifactProvenanceEnvelope,
6934
7117
  findSkillSuggestionCitations,
6935
7118
  hasClaim,
@@ -6951,6 +7134,7 @@ export {
6951
7134
  parseArtifactOutputUri,
6952
7135
  parseArtifactProvenanceCaptureContext,
6953
7136
  parseArtifactProvenanceEnvelope,
7137
+ parseCommandWhere,
6954
7138
  parseKayPluginManifestV1,
6955
7139
  parseKayUiAppPackageV1,
6956
7140
  parseKayUiBundleIndexV1,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaklabs-ai/plugin-protocol",
3
- "version": "0.32.0",
3
+ "version": "0.33.0",
4
4
  "description": "The Kay plugin manifest schema (`kay.plugin.v1`) — parse and validate a kay-plugin.json.",
5
5
  "author": "YakLabs",
6
6
  "type": "module",