@yaklabs-ai/plugin-sdk 0.35.0 → 0.36.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
@@ -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.35.0"
16
+ "@bonsai/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.36.0"
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.35.0" },
65
+ "compatibility": { "sdk": "^0.36.0" },
66
66
  "targets": {
67
67
  "kay": {
68
68
  "agent": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@yaklabs-ai/plugin-sdk",
4
- "version": "0.35.0",
4
+ "version": "0.36.0",
5
5
  "target": "npm",
6
6
  "firstPartyLicense": "MIT",
7
7
  "bundled": [
@@ -2385,8 +2385,13 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2385
2385
  * names one of the plugin's `rows` data sources, an optional `where` and a plural `label`.
2386
2386
  * `app.skills` gains `listPendingSuggestions` and `subscribeSuggestions` under `skills.read`. A plugin
2387
2387
  * that declares a badge declares ^0.35.0.
2388
+ *
2389
+ * 0.36.0 lets a plugin declare its pages and which page an address opens (#15897, #15898). `pages`
2390
+ * under `kay.ui` `contributes` names each page's title, icon file, companion status and opened
2391
+ * event. A reference presentation that opens a page gains `scheme` and `addresses`, and may leave
2392
+ * out `uriModule` when another layer serves the address. A plugin using these declares ^0.36.0.
2388
2393
  */
2389
- declare const KAY_PLUGIN_SDK_VERSION: "0.35.0";
2394
+ declare const KAY_PLUGIN_SDK_VERSION: "0.36.0";
2390
2395
 
2391
2396
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2392
2397
 
@@ -9873,12 +9878,13 @@ declare interface UriPatternInit {
9873
9878
  */
9874
9879
  readonly hostname?: string;
9875
9880
  /**
9876
- * Slash-delimited path pattern. A final capture may use `:name*` to consume
9877
- * the remaining path segments, preserving `/` in the captured value. Unless the pattern itself
9878
- * ends in `/`, an input path ending in one `/` matches as if the slash were absent, so
9879
- * `threads/t1/` is `threads/t1` (captures and official spelling included) and a lone `/` after a
9880
- * host is the empty path; a doubled `//` is never dropped, nor the root path of an address with
9881
- * no host (`bfs:///`).
9881
+ * Slash-delimited path pattern, starting with `/`. `""` matches only an address with no path. A
9882
+ * final capture may use `:name*` to consume the remaining path segments, preserving `/` in the
9883
+ * captured value. A capture may end in a literal extension: `:name.md` matches `billing.md` and
9884
+ * captures `billing`. Unless the pattern itself ends in `/`, an input path ending in one `/`
9885
+ * matches as if the slash were absent, so `threads/t1/` is `threads/t1` (captures and official
9886
+ * spelling included) and a lone `/` after a host is the empty path; a doubled `//` is never
9887
+ * dropped, nor the root path of an address with no host (`bfs:///`).
9882
9888
  */
9883
9889
  readonly pathname?: string;
9884
9890
  /** `&`-delimited query pattern; `""` matches only an address with no query. */
@@ -2439,8 +2439,13 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2439
2439
  * names one of the plugin's `rows` data sources, an optional `where` and a plural `label`.
2440
2440
  * `app.skills` gains `listPendingSuggestions` and `subscribeSuggestions` under `skills.read`. A plugin
2441
2441
  * that declares a badge declares ^0.35.0.
2442
+ *
2443
+ * 0.36.0 lets a plugin declare its pages and which page an address opens (#15897, #15898). `pages`
2444
+ * under `kay.ui` `contributes` names each page's title, icon file, companion status and opened
2445
+ * event. A reference presentation that opens a page gains `scheme` and `addresses`, and may leave
2446
+ * out `uriModule` when another layer serves the address. A plugin using these declares ^0.36.0.
2442
2447
  */
2443
- declare const KAY_PLUGIN_SDK_VERSION: "0.35.0";
2448
+ declare const KAY_PLUGIN_SDK_VERSION: "0.36.0";
2444
2449
 
2445
2450
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2446
2451
 
@@ -5647,7 +5652,20 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
5647
5652
  referencePresentations: z.ZodOptional<z.ZodArray<z.ZodObject<{
5648
5653
  localId: z.ZodString;
5649
5654
  globalId: z.ZodString;
5650
- uriModule: z.ZodString;
5655
+ uriModule: z.ZodOptional<z.ZodString>;
5656
+ schemes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5657
+ addresses: z.ZodOptional<z.ZodArray<z.ZodObject<{
5658
+ pattern: z.ZodObject<{
5659
+ protocol: z.ZodString;
5660
+ hostname: z.ZodString;
5661
+ pathname: z.ZodOptional<z.ZodString>;
5662
+ search: z.ZodOptional<z.ZodString>;
5663
+ }, z.core.$strict>;
5664
+ objectId: z.ZodOptional<z.ZodString>;
5665
+ open: z.ZodOptional<z.ZodObject<{
5666
+ kind: z.ZodLiteral<"none">;
5667
+ }, z.core.$strict>>;
5668
+ }, z.core.$strict>>>;
5651
5669
  resourceKind: z.ZodString;
5652
5670
  open: z.ZodDiscriminatedUnion<[z.ZodObject<{
5653
5671
  kind: z.ZodLiteral<"working-document">;
@@ -5711,6 +5729,7 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
5711
5729
  "sessions.create": "sessions.create";
5712
5730
  "artifacts.read": "artifacts.read";
5713
5731
  "artifacts.preview": "artifacts.preview";
5732
+ "markdown.document-view": "markdown.document-view";
5714
5733
  "cost.read": "cost.read";
5715
5734
  "billing.read": "billing.read";
5716
5735
  "skills.read": "skills.read";
@@ -10944,12 +10963,13 @@ declare interface UriPatternInit {
10944
10963
  */
10945
10964
  readonly hostname?: string;
10946
10965
  /**
10947
- * Slash-delimited path pattern. A final capture may use `:name*` to consume
10948
- * the remaining path segments, preserving `/` in the captured value. Unless the pattern itself
10949
- * ends in `/`, an input path ending in one `/` matches as if the slash were absent, so
10950
- * `threads/t1/` is `threads/t1` (captures and official spelling included) and a lone `/` after a
10951
- * host is the empty path; a doubled `//` is never dropped, nor the root path of an address with
10952
- * no host (`bfs:///`).
10966
+ * Slash-delimited path pattern, starting with `/`. `""` matches only an address with no path. A
10967
+ * final capture may use `:name*` to consume the remaining path segments, preserving `/` in the
10968
+ * captured value. A capture may end in a literal extension: `:name.md` matches `billing.md` and
10969
+ * captures `billing`. Unless the pattern itself ends in `/`, an input path ending in one `/`
10970
+ * matches as if the slash were absent, so `threads/t1/` is `threads/t1` (captures and official
10971
+ * spelling included) and a lone `/` after a host is the empty path; a doubled `//` is never
10972
+ * dropped, nor the root path of an address with no host (`bfs:///`).
10953
10973
  */
10954
10974
  readonly pathname?: string;
10955
10975
  /** `&`-delimited query pattern; `""` matches only an address with no query. */
@@ -2714,8 +2714,13 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2714
2714
  * names one of the plugin's `rows` data sources, an optional `where` and a plural `label`.
2715
2715
  * `app.skills` gains `listPendingSuggestions` and `subscribeSuggestions` under `skills.read`. A plugin
2716
2716
  * that declares a badge declares ^0.35.0.
2717
+ *
2718
+ * 0.36.0 lets a plugin declare its pages and which page an address opens (#15897, #15898). `pages`
2719
+ * under `kay.ui` `contributes` names each page's title, icon file, companion status and opened
2720
+ * event. A reference presentation that opens a page gains `scheme` and `addresses`, and may leave
2721
+ * out `uriModule` when another layer serves the address. A plugin using these declares ^0.36.0.
2717
2722
  */
2718
- declare const KAY_PLUGIN_SDK_VERSION: "0.35.0";
2723
+ declare const KAY_PLUGIN_SDK_VERSION: "0.36.0";
2719
2724
 
2720
2725
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2721
2726
 
@@ -11195,12 +11200,13 @@ declare interface UriPatternInit {
11195
11200
  */
11196
11201
  readonly hostname?: string;
11197
11202
  /**
11198
- * Slash-delimited path pattern. A final capture may use `:name*` to consume
11199
- * the remaining path segments, preserving `/` in the captured value. Unless the pattern itself
11200
- * ends in `/`, an input path ending in one `/` matches as if the slash were absent, so
11201
- * `threads/t1/` is `threads/t1` (captures and official spelling included) and a lone `/` after a
11202
- * host is the empty path; a doubled `//` is never dropped, nor the root path of an address with
11203
- * no host (`bfs:///`).
11203
+ * Slash-delimited path pattern, starting with `/`. `""` matches only an address with no path. A
11204
+ * final capture may use `:name*` to consume the remaining path segments, preserving `/` in the
11205
+ * captured value. A capture may end in a literal extension: `:name.md` matches `billing.md` and
11206
+ * captures `billing`. Unless the pattern itself ends in `/`, an input path ending in one `/`
11207
+ * matches as if the slash were absent, so `threads/t1/` is `threads/t1` (captures and official
11208
+ * spelling included) and a lone `/` after a host is the empty path; a doubled `//` is never
11209
+ * dropped, nor the root path of an address with no host (`bfs:///`).
11204
11210
  */
11205
11211
  readonly pathname?: string;
11206
11212
  /** `&`-delimited query pattern; `""` matches only an address with no query. */
package/dist/kay-agent.js CHANGED
@@ -2,7 +2,7 @@
2
2
  var SCHEME_RE = /^([a-z][a-z0-9+.-]*):\/\//i;
3
3
  var CAPTURE_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
4
4
  var REST_CAPTURE_RE = /^:([A-Za-z_][A-Za-z0-9_]*)\*$/;
5
- var CONSTRAINED_CAPTURE_RE = /^([A-Za-z_][A-Za-z0-9_]*)(?:\((.*)\))?$/;
5
+ var CONSTRAINED_CAPTURE_RE = /^([A-Za-z_][A-Za-z0-9_]*)(?:\((.*)\))?(\.[A-Za-z0-9]+)?$/;
6
6
  var MAX_CAPTURE_CONSTRAINT_LENGTH = 64;
7
7
  function compileUriClaim(claim) {
8
8
  if (claim.kind === "scheme") {
@@ -144,8 +144,10 @@ function compileParts(value, separator, options = {}) {
144
144
  const constraint = match[2];
145
145
  if (constraint !== void 0)
146
146
  assertSupportedConstraint(constraint);
147
+ const suffix = match[3];
147
148
  return {
148
149
  capture,
150
+ ...suffix !== void 0 ? { suffix } : {},
149
151
  ...constraint !== void 0 ? { constraint: new RegExp(`^(?:${constraint})$`) } : {}
150
152
  };
151
153
  }
@@ -165,8 +167,11 @@ function matchRoute(pattern, input) {
165
167
  if (pattern.hostname !== void 0 && !matchParts(pattern.hostname, input.hostname, isLoneCapture(pattern.hostname) ? void 0 : ".", captures, true)) {
166
168
  return void 0;
167
169
  }
168
- if (pattern.pathname !== void 0 && !matchParts(pattern.pathname, pattern.pathnameEndsInSlash === true ? input.pathname : withoutTrailingSlash(input), "/", captures)) {
169
- return void 0;
170
+ if (pattern.pathname !== void 0) {
171
+ const pathname = pattern.pathnameEndsInSlash === true ? input.pathname : withoutTrailingSlash(input);
172
+ if (pattern.pathname.length === 0 ? pathname !== "" : !matchParts(pattern.pathname, pathname, "/", captures)) {
173
+ return void 0;
174
+ }
170
175
  }
171
176
  if (pattern.search !== void 0 && (pattern.search.length === 0 ? input.search !== "" : !matchParts(pattern.search, input.search, "&", captures))) {
172
177
  return void 0;
@@ -200,7 +205,11 @@ function matchParts(pattern, value, separator, captures, foldLiterals = false) {
200
205
  return false;
201
206
  const actual = parts[partIndex];
202
207
  if (expected.capture !== void 0) {
203
- const decoded = safeDecode(actual);
208
+ const { suffix } = expected;
209
+ if (suffix !== void 0 && (!actual.endsWith(suffix) || actual.length === suffix.length)) {
210
+ return false;
211
+ }
212
+ const decoded = safeDecode(suffix === void 0 ? actual : actual.slice(0, -suffix.length));
204
213
  if (expected.constraint !== void 0 && !expected.constraint.test(decoded)) {
205
214
  return false;
206
215
  }
package/dist/kay-app.d.ts CHANGED
@@ -2676,8 +2676,13 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2676
2676
  * names one of the plugin's `rows` data sources, an optional `where` and a plural `label`.
2677
2677
  * `app.skills` gains `listPendingSuggestions` and `subscribeSuggestions` under `skills.read`. A plugin
2678
2678
  * that declares a badge declares ^0.35.0.
2679
+ *
2680
+ * 0.36.0 lets a plugin declare its pages and which page an address opens (#15897, #15898). `pages`
2681
+ * under `kay.ui` `contributes` names each page's title, icon file, companion status and opened
2682
+ * event. A reference presentation that opens a page gains `scheme` and `addresses`, and may leave
2683
+ * out `uriModule` when another layer serves the address. A plugin using these declares ^0.36.0.
2679
2684
  */
2680
- declare const KAY_PLUGIN_SDK_VERSION: "0.35.0";
2685
+ declare const KAY_PLUGIN_SDK_VERSION: "0.36.0";
2681
2686
 
2682
2687
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2683
2688
 
@@ -15980,12 +15985,13 @@ declare interface UriPatternInit {
15980
15985
  */
15981
15986
  readonly hostname?: string;
15982
15987
  /**
15983
- * Slash-delimited path pattern. A final capture may use `:name*` to consume
15984
- * the remaining path segments, preserving `/` in the captured value. Unless the pattern itself
15985
- * ends in `/`, an input path ending in one `/` matches as if the slash were absent, so
15986
- * `threads/t1/` is `threads/t1` (captures and official spelling included) and a lone `/` after a
15987
- * host is the empty path; a doubled `//` is never dropped, nor the root path of an address with
15988
- * no host (`bfs:///`).
15988
+ * Slash-delimited path pattern, starting with `/`. `""` matches only an address with no path. A
15989
+ * final capture may use `:name*` to consume the remaining path segments, preserving `/` in the
15990
+ * captured value. A capture may end in a literal extension: `:name.md` matches `billing.md` and
15991
+ * captures `billing`. Unless the pattern itself ends in `/`, an input path ending in one `/`
15992
+ * matches as if the slash were absent, so `threads/t1/` is `threads/t1` (captures and official
15993
+ * spelling included) and a lone `/` after a host is the empty path; a doubled `//` is never
15994
+ * dropped, nor the root path of an address with no host (`bfs:///`).
15989
15995
  */
15990
15996
  readonly pathname?: string;
15991
15997
  /** `&`-delimited query pattern; `""` matches only an address with no query. */
@@ -823,12 +823,13 @@ declare interface UriPatternInit {
823
823
  */
824
824
  readonly hostname?: string;
825
825
  /**
826
- * Slash-delimited path pattern. A final capture may use `:name*` to consume
827
- * the remaining path segments, preserving `/` in the captured value. Unless the pattern itself
828
- * ends in `/`, an input path ending in one `/` matches as if the slash were absent, so
829
- * `threads/t1/` is `threads/t1` (captures and official spelling included) and a lone `/` after a
830
- * host is the empty path; a doubled `//` is never dropped, nor the root path of an address with
831
- * no host (`bfs:///`).
826
+ * Slash-delimited path pattern, starting with `/`. `""` matches only an address with no path. A
827
+ * final capture may use `:name*` to consume the remaining path segments, preserving `/` in the
828
+ * captured value. A capture may end in a literal extension: `:name.md` matches `billing.md` and
829
+ * captures `billing`. Unless the pattern itself ends in `/`, an input path ending in one `/`
830
+ * matches as if the slash were absent, so `threads/t1/` is `threads/t1` (captures and official
831
+ * spelling included) and a lone `/` after a host is the empty path; a doubled `//` is never
832
+ * dropped, nor the root path of an address with no host (`bfs:///`).
832
833
  */
833
834
  readonly pathname?: string;
834
835
  /** `&`-delimited query pattern; `""` matches only an address with no query. */
@@ -73,7 +73,7 @@ function copyClaim(claim) {
73
73
  var SCHEME_RE = /^([a-z][a-z0-9+.-]*):\/\//i;
74
74
  var CAPTURE_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
75
75
  var REST_CAPTURE_RE = /^:([A-Za-z_][A-Za-z0-9_]*)\*$/;
76
- var CONSTRAINED_CAPTURE_RE = /^([A-Za-z_][A-Za-z0-9_]*)(?:\((.*)\))?$/;
76
+ var CONSTRAINED_CAPTURE_RE = /^([A-Za-z_][A-Za-z0-9_]*)(?:\((.*)\))?(\.[A-Za-z0-9]+)?$/;
77
77
  var MAX_CAPTURE_CONSTRAINT_LENGTH = 64;
78
78
  function compileUriClaim(claim) {
79
79
  if (claim.kind === "scheme") {
@@ -215,8 +215,10 @@ function compileParts(value, separator, options = {}) {
215
215
  const constraint = match[2];
216
216
  if (constraint !== void 0)
217
217
  assertSupportedConstraint(constraint);
218
+ const suffix = match[3];
218
219
  return {
219
220
  capture,
221
+ ...suffix !== void 0 ? { suffix } : {},
220
222
  ...constraint !== void 0 ? { constraint: new RegExp(`^(?:${constraint})$`) } : {}
221
223
  };
222
224
  }
@@ -236,8 +238,11 @@ function matchRoute(pattern, input) {
236
238
  if (pattern.hostname !== void 0 && !matchParts(pattern.hostname, input.hostname, isLoneCapture(pattern.hostname) ? void 0 : ".", captures, true)) {
237
239
  return void 0;
238
240
  }
239
- if (pattern.pathname !== void 0 && !matchParts(pattern.pathname, pattern.pathnameEndsInSlash === true ? input.pathname : withoutTrailingSlash(input), "/", captures)) {
240
- return void 0;
241
+ if (pattern.pathname !== void 0) {
242
+ const pathname = pattern.pathnameEndsInSlash === true ? input.pathname : withoutTrailingSlash(input);
243
+ if (pattern.pathname.length === 0 ? pathname !== "" : !matchParts(pattern.pathname, pathname, "/", captures)) {
244
+ return void 0;
245
+ }
241
246
  }
242
247
  if (pattern.search !== void 0 && (pattern.search.length === 0 ? input.search !== "" : !matchParts(pattern.search, input.search, "&", captures))) {
243
248
  return void 0;
@@ -271,7 +276,11 @@ function matchParts(pattern, value, separator, captures, foldLiterals = false) {
271
276
  return false;
272
277
  const actual = parts[partIndex];
273
278
  if (expected.capture !== void 0) {
274
- const decoded = safeDecode(actual);
279
+ const { suffix } = expected;
280
+ if (suffix !== void 0 && (!actual.endsWith(suffix) || actual.length === suffix.length)) {
281
+ return false;
282
+ }
283
+ const decoded = safeDecode(suffix === void 0 ? actual : actual.slice(0, -suffix.length));
275
284
  if (expected.constraint !== void 0 && !expected.constraint.test(decoded)) {
276
285
  return false;
277
286
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaklabs-ai/plugin-sdk",
3
- "version": "0.35.0",
3
+ "version": "0.36.0",
4
4
  "description": "The Kay plugin SDK — types and helpers for authoring a Kay directory plugin.",
5
5
  "author": "YakLabs",
6
6
  "type": "module",