@yaklabs-ai/plugin-protocol 0.32.0 → 0.34.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.34.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.34.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";
@@ -2737,6 +2739,9 @@ declare const canonicalContributionSchemas: {
2737
2739
  primary: "primary";
2738
2740
  plugins: "plugins";
2739
2741
  }>>;
2742
+ panel: z.ZodOptional<z.ZodObject<{
2743
+ body: z.ZodString;
2744
+ }, z.core.$strict>>;
2740
2745
  }, z.core.$strict>;
2741
2746
  UiAppContribution: z.ZodObject<{
2742
2747
  localId: z.ZodString;
@@ -2766,8 +2771,6 @@ declare const canonicalContributionSchemas: {
2766
2771
  "artifacts.preview": "artifacts.preview";
2767
2772
  "cost.read": "cost.read";
2768
2773
  "billing.read": "billing.read";
2769
- "context.read": "context.read";
2770
- "usage.read": "usage.read";
2771
2774
  "self-improvement.read": "self-improvement.read";
2772
2775
  "automations.read": "automations.read";
2773
2776
  "shared-artifacts.read": "shared-artifacts.read";
@@ -2804,8 +2807,6 @@ declare const canonicalContributionSchemas: {
2804
2807
  "artifacts.preview": "artifacts.preview";
2805
2808
  "cost.read": "cost.read";
2806
2809
  "billing.read": "billing.read";
2807
- "context.read": "context.read";
2808
- "usage.read": "usage.read";
2809
2810
  "self-improvement.read": "self-improvement.read";
2810
2811
  "automations.read": "automations.read";
2811
2812
  "shared-artifacts.read": "shared-artifacts.read";
@@ -2999,6 +3000,41 @@ export declare const CommandHandler: z.ZodDiscriminatedUnion<[z.ZodObject<{
2999
3000
 
3000
3001
  export declare type CommandHandler = z.infer<typeof CommandHandler>;
3001
3002
 
3003
+ export declare type CommandWhere = {
3004
+ readonly kind: "literal";
3005
+ readonly value: boolean;
3006
+ } | {
3007
+ readonly kind: "key";
3008
+ readonly key: CommandWhereKey;
3009
+ } | {
3010
+ readonly kind: "equals";
3011
+ readonly key: CommandWhereKey;
3012
+ readonly value: boolean | string;
3013
+ readonly negated: boolean;
3014
+ } | {
3015
+ readonly kind: "not";
3016
+ readonly operand: CommandWhere;
3017
+ } | {
3018
+ readonly kind: "and" | "or";
3019
+ readonly left: CommandWhere;
3020
+ readonly right: CommandWhere;
3021
+ };
3022
+
3023
+ export declare type CommandWhereKey = keyof typeof WHERE_KEY_TYPES;
3024
+
3025
+ export declare type CommandWhereParseResult = {
3026
+ readonly ok: true;
3027
+ readonly where: CommandWhere;
3028
+ } | {
3029
+ readonly ok: false;
3030
+ readonly message: string;
3031
+ };
3032
+
3033
+ /** The values a `where` reads. A key left out isn't known yet, for example while it loads. */
3034
+ export declare type CommandWhereValues = {
3035
+ readonly [K in CommandWhereKey]?: (typeof WHERE_KEY_TYPES)[K] extends "boolean" ? boolean : string;
3036
+ };
3037
+
3002
3038
  /**
3003
3039
  * Total order over claims, for deterministic projection and diffs. Compares the same fields
3004
3040
  * {@link sameClaim} compares, in a fixed order, so two claims that compare equal here are the same
@@ -3128,6 +3164,25 @@ export declare const CorpusResourceKind: z.ZodEnum<{
3128
3164
 
3129
3165
  export declare type CorpusResourceKind = z.infer<typeof CorpusResourceKind>;
3130
3166
 
3167
+ /**
3168
+ * Every plugin's declarations of one kind, each with the plugin that made it. Main and the window
3169
+ * each hold the plugins' `kay.ui` facts, and both read them through here. `contributes` crosses the
3170
+ * daemon, the protocol and main unread, so this is where it gets its type back.
3171
+ */
3172
+ export declare function declarationsOfKind<TPlugin extends {
3173
+ readonly contributes: Readonly<Record<string, unknown>>;
3174
+ }, K extends keyof UiContributes>(plugins: readonly TPlugin[], kind: K): readonly {
3175
+ readonly plugin: TPlugin;
3176
+ readonly declaration: NonNullable<UiContributes[K]>[number];
3177
+ }[];
3178
+
3179
+ /**
3180
+ * A declared command's full id. Neither part can contain `/`, so two plugins can't produce the same
3181
+ * one, and none can name an app command such as `session.interrupt`, which a plugin called `session`
3182
+ * could otherwise put a button on without implementing it.
3183
+ */
3184
+ export declare function declaredCommandId(pluginId: string, localId: string): string;
3185
+
3131
3186
  /**
3132
3187
  * The `compatibility` block as the check reads it. Structural rather than the parsed
3133
3188
  * `PluginCompatibilityManifest`, so a host can judge the block of a manifest whose other fields
@@ -3227,6 +3282,13 @@ export declare const EntityResolverContribution: z.ZodObject<{
3227
3282
 
3228
3283
  export declare type EntityResolverContribution = z.infer<typeof EntityResolverContribution>;
3229
3284
 
3285
+ /**
3286
+ * Whether a `where` holds. When the answer depends on a value not known yet the result is false,
3287
+ * so a button stays hidden while a value loads rather than flashing on: `true || app.channel == 'x'`
3288
+ * holds whatever the channel is, and `!(app.channel == 'x')` waits for it.
3289
+ */
3290
+ export declare function evaluateCommandWhere(where: CommandWhere, values: CommandWhereValues): boolean;
3291
+
3230
3292
  export declare const EventGrantRequest: z.ZodObject<{
3231
3293
  event: z.ZodString;
3232
3294
  operations: z.ZodArray<z.ZodEnum<{
@@ -4009,8 +4071,17 @@ export declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
4009
4071
  * 0.32.0 lets an app-data source declare its window store as data (#15891). `store` under
4010
4072
  * `contributes.dataSources` replaces a `kay.ui` data materializer, and a change too big for a live
4011
4073
  * update becomes a re-read of the snapshot. A plugin that declares a store declares ^0.32.0.
4074
+ *
4075
+ * 0.33.0 lets a plugin declare a window command with its button and menu item (#15903). `commands`
4076
+ * under `kay.ui` `contributes` names each command's title, icon file, `button`, `menu` and `where`,
4077
+ * and `api.implementCommand(localId, handler)` supplies what it does. `placement` is gone and `icon`
4078
+ * is now a file path: nothing ever read either. A plugin that declares a command declares ^0.33.0.
4079
+ *
4080
+ * 0.34.0 lets a rail entry declare a sidebar (#15901). `panel.body` on a `railEntries` entry names
4081
+ * what fills it, either a `contextOnly` app in the plugin or a body the host ships. Additive: a rail
4082
+ * entry with no `panel` still opens its page alone. A plugin that declares a panel declares ^0.34.0.
4012
4083
  */
4013
- export declare const KAY_PLUGIN_SDK_VERSION: "0.32.0";
4084
+ export declare const KAY_PLUGIN_SDK_VERSION: "0.34.0";
4014
4085
 
4015
4086
  export declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
4016
4087
 
@@ -5474,7 +5545,13 @@ export declare const KayPluginManifestV1: z.ZodObject<{
5474
5545
  localId: z.ZodString;
5475
5546
  title: z.ZodString;
5476
5547
  icon: z.ZodOptional<z.ZodString>;
5477
- placement: z.ZodOptional<z.ZodString>;
5548
+ button: z.ZodOptional<z.ZodEnum<{
5549
+ tabStrip: "tabStrip";
5550
+ }>>;
5551
+ menu: z.ZodOptional<z.ZodEnum<{
5552
+ help: "help";
5553
+ }>>;
5554
+ where: z.ZodOptional<z.ZodString>;
5478
5555
  }, z.core.$strict>>>;
5479
5556
  slots: z.ZodOptional<z.ZodArray<z.ZodObject<{
5480
5557
  localId: z.ZodString;
@@ -5562,8 +5639,6 @@ export declare const KayPluginManifestV1: z.ZodObject<{
5562
5639
  "artifacts.preview": "artifacts.preview";
5563
5640
  "cost.read": "cost.read";
5564
5641
  "billing.read": "billing.read";
5565
- "context.read": "context.read";
5566
- "usage.read": "usage.read";
5567
5642
  "self-improvement.read": "self-improvement.read";
5568
5643
  "automations.read": "automations.read";
5569
5644
  "shared-artifacts.read": "shared-artifacts.read";
@@ -5600,8 +5675,6 @@ export declare const KayPluginManifestV1: z.ZodObject<{
5600
5675
  "artifacts.preview": "artifacts.preview";
5601
5676
  "cost.read": "cost.read";
5602
5677
  "billing.read": "billing.read";
5603
- "context.read": "context.read";
5604
- "usage.read": "usage.read";
5605
5678
  "self-improvement.read": "self-improvement.read";
5606
5679
  "automations.read": "automations.read";
5607
5680
  "shared-artifacts.read": "shared-artifacts.read";
@@ -5623,6 +5696,9 @@ export declare const KayPluginManifestV1: z.ZodObject<{
5623
5696
  primary: "primary";
5624
5697
  plugins: "plugins";
5625
5698
  }>>;
5699
+ panel: z.ZodOptional<z.ZodObject<{
5700
+ body: z.ZodString;
5701
+ }, z.core.$strict>>;
5626
5702
  }, z.core.$strict>>>;
5627
5703
  themes: z.ZodOptional<z.ZodArray<z.ZodObject<{
5628
5704
  localId: z.ZodString;
@@ -6449,8 +6525,6 @@ export declare const KayUiAppHostCapability: z.ZodEnum<{
6449
6525
  "artifacts.preview": "artifacts.preview";
6450
6526
  "cost.read": "cost.read";
6451
6527
  "billing.read": "billing.read";
6452
- "context.read": "context.read";
6453
- "usage.read": "usage.read";
6454
6528
  "self-improvement.read": "self-improvement.read";
6455
6529
  "automations.read": "automations.read";
6456
6530
  "shared-artifacts.read": "shared-artifacts.read";
@@ -6568,7 +6642,13 @@ export declare const KayUiTargetManifest: z.ZodObject<{
6568
6642
  localId: z.ZodString;
6569
6643
  title: z.ZodString;
6570
6644
  icon: z.ZodOptional<z.ZodString>;
6571
- placement: z.ZodOptional<z.ZodString>;
6645
+ button: z.ZodOptional<z.ZodEnum<{
6646
+ tabStrip: "tabStrip";
6647
+ }>>;
6648
+ menu: z.ZodOptional<z.ZodEnum<{
6649
+ help: "help";
6650
+ }>>;
6651
+ where: z.ZodOptional<z.ZodString>;
6572
6652
  }, z.core.$strict>>>;
6573
6653
  slots: z.ZodOptional<z.ZodArray<z.ZodObject<{
6574
6654
  localId: z.ZodString;
@@ -6656,8 +6736,6 @@ export declare const KayUiTargetManifest: z.ZodObject<{
6656
6736
  "artifacts.preview": "artifacts.preview";
6657
6737
  "cost.read": "cost.read";
6658
6738
  "billing.read": "billing.read";
6659
- "context.read": "context.read";
6660
- "usage.read": "usage.read";
6661
6739
  "self-improvement.read": "self-improvement.read";
6662
6740
  "automations.read": "automations.read";
6663
6741
  "shared-artifacts.read": "shared-artifacts.read";
@@ -6694,8 +6772,6 @@ export declare const KayUiTargetManifest: z.ZodObject<{
6694
6772
  "artifacts.preview": "artifacts.preview";
6695
6773
  "cost.read": "cost.read";
6696
6774
  "billing.read": "billing.read";
6697
- "context.read": "context.read";
6698
- "usage.read": "usage.read";
6699
6775
  "self-improvement.read": "self-improvement.read";
6700
6776
  "automations.read": "automations.read";
6701
6777
  "shared-artifacts.read": "shared-artifacts.read";
@@ -6717,6 +6793,9 @@ export declare const KayUiTargetManifest: z.ZodObject<{
6717
6793
  primary: "primary";
6718
6794
  plugins: "plugins";
6719
6795
  }>>;
6796
+ panel: z.ZodOptional<z.ZodObject<{
6797
+ body: z.ZodString;
6798
+ }, z.core.$strict>>;
6720
6799
  }, z.core.$strict>>>;
6721
6800
  themes: z.ZodOptional<z.ZodArray<z.ZodObject<{
6722
6801
  localId: z.ZodString;
@@ -6886,6 +6965,12 @@ export declare function parseArtifactProvenanceCaptureContext(input: unknown): A
6886
6965
  /** Returns an owned value snapshot; callers must not attach live session references. */
6887
6966
  export declare function parseArtifactProvenanceEnvelope(input: unknown): ArtifactProvenanceEnvelopeV1;
6888
6967
 
6968
+ /**
6969
+ * Parses a declared command's `where`: `||`, `&&`, `!`, parentheses, `==`, `!=`, strings, `true`,
6970
+ * `false` and dotted keys, for example `account.signedIn || app.channel != 'production'`.
6971
+ */
6972
+ export declare function parseCommandWhere(source: string): CommandWhereParseResult;
6973
+
6889
6974
  /** A `MAJOR.MINOR.PATCH` version broken into its comparable parts. */
6890
6975
  export declare interface ParsedSemver {
6891
6976
  readonly major: number;
@@ -10772,8 +10857,6 @@ export declare const ResolvedKayUiApp: z.ZodObject<{
10772
10857
  "artifacts.preview": "artifacts.preview";
10773
10858
  "cost.read": "cost.read";
10774
10859
  "billing.read": "billing.read";
10775
- "context.read": "context.read";
10776
- "usage.read": "usage.read";
10777
10860
  "self-improvement.read": "self-improvement.read";
10778
10861
  "automations.read": "automations.read";
10779
10862
  "shared-artifacts.read": "shared-artifacts.read";
@@ -12066,8 +12149,6 @@ export declare const ResolvedPluginContractV1: z.ZodObject<{
12066
12149
  "artifacts.preview": "artifacts.preview";
12067
12150
  "cost.read": "cost.read";
12068
12151
  "billing.read": "billing.read";
12069
- "context.read": "context.read";
12070
- "usage.read": "usage.read";
12071
12152
  "self-improvement.read": "self-improvement.read";
12072
12153
  "automations.read": "automations.read";
12073
12154
  "shared-artifacts.read": "shared-artifacts.read";
@@ -13652,8 +13733,6 @@ export declare const UiAppCapabilities: z.ZodObject<{
13652
13733
  "artifacts.preview": "artifacts.preview";
13653
13734
  "cost.read": "cost.read";
13654
13735
  "billing.read": "billing.read";
13655
- "context.read": "context.read";
13656
- "usage.read": "usage.read";
13657
13736
  "self-improvement.read": "self-improvement.read";
13658
13737
  "automations.read": "automations.read";
13659
13738
  "shared-artifacts.read": "shared-artifacts.read";
@@ -13693,8 +13772,6 @@ export declare const UiAppContribution: z.ZodObject<{
13693
13772
  "artifacts.preview": "artifacts.preview";
13694
13773
  "cost.read": "cost.read";
13695
13774
  "billing.read": "billing.read";
13696
- "context.read": "context.read";
13697
- "usage.read": "usage.read";
13698
13775
  "self-improvement.read": "self-improvement.read";
13699
13776
  "automations.read": "automations.read";
13700
13777
  "shared-artifacts.read": "shared-artifacts.read";
@@ -13731,8 +13808,6 @@ export declare const UiAppContribution: z.ZodObject<{
13731
13808
  "artifacts.preview": "artifacts.preview";
13732
13809
  "cost.read": "cost.read";
13733
13810
  "billing.read": "billing.read";
13734
- "context.read": "context.read";
13735
- "usage.read": "usage.read";
13736
13811
  "self-improvement.read": "self-improvement.read";
13737
13812
  "automations.read": "automations.read";
13738
13813
  "shared-artifacts.read": "shared-artifacts.read";
@@ -13749,11 +13824,19 @@ export declare const UiCommandContribution: z.ZodObject<{
13749
13824
  localId: z.ZodString;
13750
13825
  title: z.ZodString;
13751
13826
  icon: z.ZodOptional<z.ZodString>;
13752
- placement: z.ZodOptional<z.ZodString>;
13827
+ button: z.ZodOptional<z.ZodEnum<{
13828
+ tabStrip: "tabStrip";
13829
+ }>>;
13830
+ menu: z.ZodOptional<z.ZodEnum<{
13831
+ help: "help";
13832
+ }>>;
13833
+ where: z.ZodOptional<z.ZodString>;
13753
13834
  }, z.core.$strict>;
13754
13835
 
13755
13836
  export declare type UiCommandContribution = z.infer<typeof UiCommandContribution>;
13756
13837
 
13838
+ declare type UiContributes = NonNullable<KayUiTargetManifest["contributes"]>;
13839
+
13757
13840
  export declare const UiEventSubscriptionContribution: z.ZodObject<{
13758
13841
  localId: z.ZodString;
13759
13842
  event: z.ZodString;
@@ -13773,6 +13856,9 @@ export declare const UiRailEntryContribution: z.ZodObject<{
13773
13856
  primary: "primary";
13774
13857
  plugins: "plugins";
13775
13858
  }>>;
13859
+ panel: z.ZodOptional<z.ZodObject<{
13860
+ body: z.ZodString;
13861
+ }, z.core.$strict>>;
13776
13862
  }, z.core.$strict>;
13777
13863
 
13778
13864
  export declare type UiRailEntryContribution = z.infer<typeof UiRailEntryContribution>;
@@ -14174,6 +14260,12 @@ export declare type WebSessionGrantRequest = z.infer<typeof WebSessionGrantReque
14174
14260
  */
14175
14261
  export declare function webSessionPathWithinPrefix(pathname: string, pathPrefix: string): boolean;
14176
14262
 
14263
+ /** What a `where` expression can read, and the type of each. */
14264
+ declare const WHERE_KEY_TYPES: {
14265
+ readonly "account.signedIn": "boolean";
14266
+ readonly "app.channel": "string";
14267
+ };
14268
+
14177
14269
  /** Construct the exact claim row for one Whiteboard scope and operation. */
14178
14270
  export declare function whiteboardCapabilityClaim(operation: WhiteboardCapabilityOperation, scope: WhiteboardCapabilityScope, target?: "kay.agent"): WhiteboardCapabilityClaimV1;
14179
14271
 
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,16 @@ 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.34.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",
250
+ "0.33.0"
241
251
  ];
242
252
  var KAY_PLUGIN_TARGET_NAMES = [
243
253
  "kay.agent",
@@ -2823,6 +2833,165 @@ function createPluginEventsSchemas(canonical) {
2823
2833
  var { PluginEventLocalId, PluginEventUri, PluginEventTimestamp, PluginEventRelated, PluginEventPublishSource, PluginEventSource, PluginEventId, PluginEventPublishInput, PluginEventEnvelope } = createPluginEventsSchemas(false);
2824
2834
  var canonicalPluginEventSchemas = createPluginEventsSchemas(true);
2825
2835
 
2836
+ // packages/plugin-protocol/dist/declared-commands.js
2837
+ function declarationsOfKind(plugins, kind) {
2838
+ return plugins.flatMap((plugin) => (plugin.contributes[kind] ?? []).map((declaration) => ({
2839
+ plugin,
2840
+ declaration
2841
+ })));
2842
+ }
2843
+ function declaredCommandId(pluginId, localId) {
2844
+ return `${pluginId}/${localId}`;
2845
+ }
2846
+ var WHERE_KEY_TYPES = {
2847
+ "account.signedIn": "boolean",
2848
+ "app.channel": "string"
2849
+ };
2850
+ var TOKEN = /\s*(?:(\|\||&&|==|!=|!|\(|\))|'([^']*)'|"([^"]*)"|([A-Za-z][A-Za-z0-9]*(?:\.[A-Za-z][A-Za-z0-9]*)*))/y;
2851
+ function tokenize(source) {
2852
+ const tokens = [];
2853
+ TOKEN.lastIndex = 0;
2854
+ while (source.slice(TOKEN.lastIndex).trim() !== "") {
2855
+ const start = TOKEN.lastIndex;
2856
+ const match = TOKEN.exec(source);
2857
+ if (match === null) {
2858
+ throw new Error(`unexpected text at '${source.slice(start).trim()}'`);
2859
+ }
2860
+ const [, operator, single, double, word] = match;
2861
+ if (operator !== void 0)
2862
+ tokens.push({ kind: "operator", text: operator });
2863
+ else if (word !== void 0)
2864
+ tokens.push({ kind: "word", text: word });
2865
+ else
2866
+ tokens.push({ kind: "string", text: single ?? double ?? "" });
2867
+ }
2868
+ return tokens;
2869
+ }
2870
+ function isKey(text) {
2871
+ return Object.hasOwn(WHERE_KEY_TYPES, text);
2872
+ }
2873
+ function parseTokens(tokens) {
2874
+ let position = 0;
2875
+ const takeOperator = (text) => {
2876
+ const token = tokens[position];
2877
+ if (token?.kind !== "operator" || token.text !== text)
2878
+ return false;
2879
+ position += 1;
2880
+ return true;
2881
+ };
2882
+ const parseOr = () => {
2883
+ let left = parseAnd();
2884
+ while (takeOperator("||"))
2885
+ left = { kind: "or", left, right: parseAnd() };
2886
+ return left;
2887
+ };
2888
+ const parseAnd = () => {
2889
+ let left = parseNot();
2890
+ while (takeOperator("&&"))
2891
+ left = { kind: "and", left, right: parseNot() };
2892
+ return left;
2893
+ };
2894
+ const parseNot = () => takeOperator("!") ? { kind: "not", operand: parseNot() } : parseAtom();
2895
+ const parseAtom = () => {
2896
+ if (takeOperator("(")) {
2897
+ const inner = parseOr();
2898
+ if (!takeOperator(")"))
2899
+ throw new Error("missing ')'");
2900
+ return inner;
2901
+ }
2902
+ const token = tokens[position];
2903
+ if (token === void 0)
2904
+ throw new Error("the expression ends too soon");
2905
+ position += 1;
2906
+ if (token.kind === "word" && token.text === "true") {
2907
+ return { kind: "literal", value: true };
2908
+ }
2909
+ if (token.kind === "word" && token.text === "false") {
2910
+ return { kind: "literal", value: false };
2911
+ }
2912
+ if (token.kind !== "word")
2913
+ throw new Error(`unexpected '${token.text}'`);
2914
+ if (!isKey(token.text)) {
2915
+ throw new Error(`unknown key '${token.text}'; the keys are ${Object.keys(WHERE_KEY_TYPES).join(", ")}`);
2916
+ }
2917
+ return parseKeyAtom(token.text);
2918
+ };
2919
+ const parseKeyAtom = (key) => {
2920
+ const negated = takeOperator("!=");
2921
+ if (!negated && !takeOperator("==")) {
2922
+ if (WHERE_KEY_TYPES[key] !== "boolean") {
2923
+ throw new Error(`'${key}' must be compared, with == or !=`);
2924
+ }
2925
+ return { kind: "key", key };
2926
+ }
2927
+ const value = parseLiteral();
2928
+ if (typeof value !== WHERE_KEY_TYPES[key]) {
2929
+ throw new Error(`'${key}' compares to a ${WHERE_KEY_TYPES[key]}`);
2930
+ }
2931
+ return { kind: "equals", key, value, negated };
2932
+ };
2933
+ const parseLiteral = () => {
2934
+ const token = tokens[position];
2935
+ position += 1;
2936
+ if (token?.kind === "string")
2937
+ return token.text;
2938
+ if (token?.kind === "word" && token.text === "true")
2939
+ return true;
2940
+ if (token?.kind === "word" && token.text === "false")
2941
+ return false;
2942
+ throw new Error("expected a string, true or false after == or !=");
2943
+ };
2944
+ const where = parseOr();
2945
+ const extra = tokens[position];
2946
+ if (extra !== void 0)
2947
+ throw new Error(`unexpected '${extra.text}'`);
2948
+ return where;
2949
+ }
2950
+ function parseCommandWhere(source) {
2951
+ try {
2952
+ return { ok: true, where: parseTokens(tokenize(source)) };
2953
+ } catch (error) {
2954
+ return { ok: false, message: error.message };
2955
+ }
2956
+ }
2957
+ function resolve(where, values) {
2958
+ switch (where.kind) {
2959
+ case "literal":
2960
+ return where.value;
2961
+ case "key": {
2962
+ const value = values[where.key];
2963
+ return value === void 0 ? void 0 : value === true;
2964
+ }
2965
+ case "equals": {
2966
+ const value = values[where.key];
2967
+ if (value === void 0)
2968
+ return void 0;
2969
+ return value === where.value !== where.negated;
2970
+ }
2971
+ case "not": {
2972
+ const operand = resolve(where.operand, values);
2973
+ return operand === void 0 ? void 0 : !operand;
2974
+ }
2975
+ case "and": {
2976
+ const left = resolve(where.left, values);
2977
+ const right = resolve(where.right, values);
2978
+ if (left === false || right === false)
2979
+ return false;
2980
+ return left === void 0 || right === void 0 ? void 0 : true;
2981
+ }
2982
+ case "or": {
2983
+ const left = resolve(where.left, values);
2984
+ const right = resolve(where.right, values);
2985
+ if (left === true || right === true)
2986
+ return true;
2987
+ return left === void 0 || right === void 0 ? void 0 : false;
2988
+ }
2989
+ }
2990
+ }
2991
+ function evaluateCommandWhere(where, values) {
2992
+ return resolve(where, values) === true;
2993
+ }
2994
+
2826
2995
  // packages/plugin-protocol/dist/contributions.js
2827
2996
  var MCP_SERVER_LOCAL_HTTP_HOSTNAMES = /* @__PURE__ */ new Set(["localhost", "127.0.0.1"]);
2828
2997
  var MCP_SIGN_IN_SCHEME_KIND = {
@@ -3403,8 +3572,28 @@ function createContributionsSchemas(canonical) {
3403
3572
  const UiCommandContribution2 = z12.strictObject({
3404
3573
  localId: LocalContributionId2,
3405
3574
  title: NonEmptyString3,
3406
- icon: NonEmptyString3.optional(),
3407
- placement: NonEmptyString3.optional()
3575
+ icon: PackageAssetPath2.optional(),
3576
+ button: z12.enum(["tabStrip"]).optional(),
3577
+ menu: z12.enum(["help"]).optional(),
3578
+ where: NonEmptyString3.optional()
3579
+ }).superRefine((command, ctx) => {
3580
+ if (command.where === void 0)
3581
+ return;
3582
+ if (command.button === void 0) {
3583
+ ctx.addIssue({
3584
+ code: "custom",
3585
+ path: ["where"],
3586
+ message: `command ${command.localId} declares where without a button: where only decides when a button shows`
3587
+ });
3588
+ }
3589
+ const parsed = parseCommandWhere(command.where);
3590
+ if (!parsed.ok) {
3591
+ ctx.addIssue({
3592
+ code: "custom",
3593
+ path: ["where"],
3594
+ message: `command ${command.localId} has an invalid where: ${parsed.message}`
3595
+ });
3596
+ }
3408
3597
  });
3409
3598
  const UiSlotContribution2 = z12.strictObject({
3410
3599
  localId: LocalContributionId2,
@@ -3489,16 +3678,9 @@ function createContributionsSchemas(canonical) {
3489
3678
  "cost.read",
3490
3679
  // Server-rated organization billing, distinct from local/provider cost.
3491
3680
  "billing.read",
3492
- // Context, Skills, and Memory analytics reads (full snapshots via the capability broker).
3493
- "context.read",
3681
+ // Skills and Memory analytics reads (full snapshots via the capability broker).
3494
3682
  "skills.read",
3495
3683
  "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
3684
  // The self-improvement lens: reads the telemetry lane's self-improvement rollup
3503
3685
  // (memory/skill/notebook activity). Follows the same "names the data" convention.
3504
3686
  "self-improvement.read",
@@ -3548,7 +3730,8 @@ function createContributionsSchemas(canonical) {
3548
3730
  homeLocation: NonEmptyString3.optional(),
3549
3731
  shortcut: NonEmptyString3.optional(),
3550
3732
  order: z12.number().finite().optional(),
3551
- section: z12.enum(["primary", "plugins"]).optional()
3733
+ section: z12.enum(["primary", "plugins"]).optional(),
3734
+ panel: z12.strictObject({ body: LocalContributionId2 }).optional()
3552
3735
  });
3553
3736
  const UiAppFields = z12.strictObject({
3554
3737
  localId: LocalContributionId2,
@@ -4217,9 +4400,7 @@ function createManifestSchemas(canonical) {
4217
4400
  */
4218
4401
  description: NonEmptyString3,
4219
4402
  // 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
4403
+ // by `PackageAssetPath`. By default the host treats the SVG as a mark and frames it, inset
4223
4404
  // on a white tile. An SVG whose artwork is already a complete tile (its own
4224
4405
  // background, edge to edge) says so with `data-icon-shape="tile"` on its
4225
4406
  // root `<svg>` element, and the host then draws it full-bleed in its tile
@@ -4397,6 +4578,26 @@ function createManifestSchemas(canonical) {
4397
4578
  });
4398
4579
  }
4399
4580
  }
4581
+ for (const [index, entry] of (manifest.targets?.kay?.ui?.contributes?.railEntries ?? []).entries()) {
4582
+ const body = entry.panel?.body;
4583
+ const app = manifest.targets?.kay?.ui?.contributes?.apps?.find((candidate) => candidate.localId === body);
4584
+ if (app !== void 0 && app.contextOnly !== true) {
4585
+ ctx.addIssue({
4586
+ code: "custom",
4587
+ path: [
4588
+ "targets",
4589
+ "kay",
4590
+ "ui",
4591
+ "contributes",
4592
+ "railEntries",
4593
+ index,
4594
+ "panel",
4595
+ "body"
4596
+ ],
4597
+ message: `Rail entry ${entry.id} panel body ${app.localId} must be a contextOnly ui app`
4598
+ });
4599
+ }
4600
+ }
4400
4601
  const subscribedUiEvents = new Set(manifest.targets?.kay?.ui?.contributes?.eventSubscriptions?.map((subscription) => subscription.event) ?? []);
4401
4602
  const invokedUiEndpoints = new Set(manifest.permissions?.byTarget["kay.ui"]?.endpoints?.filter((grant) => grant.operations.includes("invoke")).map((grant) => grant.endpoint) ?? []);
4402
4603
  const uriModuleIds = new Set([
@@ -4438,6 +4639,7 @@ function createManifestSchemas(canonical) {
4438
4639
  presentationByUriModule.set(presentation.uriModule, presentation.localId);
4439
4640
  }
4440
4641
  }
4642
+ reportDuplicateLocalIds(ctx, ["targets", "kay", "ui", "contributes", "commands"], manifest.targets?.kay?.ui?.contributes?.commands, "ui command");
4441
4643
  reportDuplicateLocalIds(ctx, ["targets", "kay", "ui", "contributes", "referencePresentations"], manifest.targets?.kay?.ui?.contributes?.referencePresentations, "reference presentation");
4442
4644
  reportDuplicateLocalIds(ctx, ["targets", "kay", "app", "contributes", "eventDefinitions"], manifest.targets?.kay?.app?.contributes?.eventDefinitions, "plugin event definition");
4443
4645
  reportDuplicateLocalIds(ctx, ["targets", "kay", "app", "contributes", "contextContributors"], manifest.targets?.kay?.app?.contributes?.contextContributors, "context contributor");
@@ -6927,9 +7129,12 @@ export {
6927
7129
  compareClaims,
6928
7130
  compareSemver,
6929
7131
  configSectionKeysForManifest,
7132
+ declarationsOfKind,
7133
+ declaredCommandId,
6930
7134
  declaredUiIconPaths,
6931
7135
  dedupeClaims,
6932
7136
  deriveDirectoryPluginToolName,
7137
+ evaluateCommandWhere,
6933
7138
  finalizeArtifactProvenanceEnvelope,
6934
7139
  findSkillSuggestionCitations,
6935
7140
  hasClaim,
@@ -6951,6 +7156,7 @@ export {
6951
7156
  parseArtifactOutputUri,
6952
7157
  parseArtifactProvenanceCaptureContext,
6953
7158
  parseArtifactProvenanceEnvelope,
7159
+ parseCommandWhere,
6954
7160
  parseKayPluginManifestV1,
6955
7161
  parseKayUiAppPackageV1,
6956
7162
  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.34.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",