@yaklabs-ai/plugin-sdk 0.45.0 → 0.46.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.
@@ -2485,9 +2485,19 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2485
2485
  * 0.44.0 adds `words.kinds` to a reference presentation (#15905): an ordered list of address patterns
2486
2486
  * and the kind each one names. Additive: a plugin that lists them declares ^0.44.0.
2487
2487
  *
2488
- * 0.45.0 adds declared plugin cards and app.implementCard for their read/submit endpoints.
2488
+ * 0.45.0 adds declared plugin cards and app.implementCard for their read/submit endpoints. It also
2489
+ * lets a plugin declare what the window hardcoded about it (#15906). A reference presentation gains
2490
+ * `accountLinks`, how a page opens under the account an address means, and a `local-app` open, for
2491
+ * an item an app on this machine shows; a plugin the person installed can't declare that open. A
2492
+ * `webSession` gains `signInFirst`. A URI module defines `lookupWebLink` and sets `looksUpWebLinks`
2493
+ * to find a page when someone opens the address, and a preview field marks which `part` of a message
2494
+ * it is. A claim's `brandIcon` is a file path and no longer inline markup, which only this repo's
2495
+ * Microsoft plugin used. Otherwise additive: a plugin using any of these declares ^0.45.0.
2496
+ *
2497
+ * 0.46.0 adds `@bonsai/plugin-sdk/artifact-provenance`, so a plugin shipped as files can finalize
2498
+ * and read the provenance the host captured. Additive: a plugin that imports it declares ^0.46.0.
2489
2499
  */
2490
- declare const KAY_PLUGIN_SDK_VERSION: "0.45.0";
2500
+ declare const KAY_PLUGIN_SDK_VERSION: "0.46.0";
2491
2501
 
2492
2502
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2493
2503
 
@@ -4751,6 +4761,7 @@ declare function refineWebSessionScopeConfined(webSession: {
4751
4761
  readonly probe: {
4752
4762
  readonly url: string;
4753
4763
  };
4764
+ readonly signInFirst?: string | undefined;
4754
4765
  }, ctx: z.RefinementCtx): void;
4755
4766
 
4756
4767
  declare const RegistrableDomain: z.ZodString;
@@ -5059,6 +5070,7 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
5059
5070
  external: "external";
5060
5071
  embedded: "embedded";
5061
5072
  }>;
5073
+ signInFirst: z.ZodOptional<z.ZodString>;
5062
5074
  }, z.core.$strict>>;
5063
5075
  }, z.core.$strict>>;
5064
5076
  grants: z.ZodOptional<z.ZodObject<{
@@ -5518,6 +5530,7 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
5518
5530
  authSchemeId: z.ZodOptional<z.ZodString>;
5519
5531
  knownResources: z.ZodOptional<z.ZodLiteral<true>>;
5520
5532
  describesOperations: z.ZodOptional<z.ZodLiteral<true>>;
5533
+ looksUpWebLinks: z.ZodOptional<z.ZodLiteral<true>>;
5521
5534
  }, z.core.$strict>>>;
5522
5535
  kayAgentArtifactUriModules: z.ZodOptional<z.ZodArray<z.ZodObject<{
5523
5536
  localId: z.ZodString;
@@ -5769,6 +5782,29 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
5769
5782
  uriModule: z.ZodOptional<z.ZodString>;
5770
5783
  schemes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5771
5784
  displayName: z.ZodOptional<z.ZodString>;
5785
+ authService: z.ZodOptional<z.ZodString>;
5786
+ accountLinks: z.ZodOptional<z.ZodObject<{
5787
+ label: z.ZodOptional<z.ZodEnum<{
5788
+ email: "email";
5789
+ name: "name";
5790
+ }>>;
5791
+ pages: z.ZodOptional<z.ZodArray<z.ZodObject<{
5792
+ hostname: z.ZodString;
5793
+ pathname: z.ZodOptional<z.ZodString>;
5794
+ unlessPathname: z.ZodOptional<z.ZodArray<z.ZodString>>;
5795
+ setPathname: z.ZodOptional<z.ZodString>;
5796
+ addQuery: z.ZodRecord<z.ZodString, z.ZodString>;
5797
+ }, z.core.$strict>>>;
5798
+ addresses: z.ZodOptional<z.ZodArray<z.ZodObject<{
5799
+ pattern: z.ZodObject<{
5800
+ protocol: z.ZodString;
5801
+ hostname: z.ZodString;
5802
+ pathname: z.ZodOptional<z.ZodString>;
5803
+ search: z.ZodOptional<z.ZodString>;
5804
+ }, z.core.$strict>;
5805
+ url: z.ZodString;
5806
+ }, z.core.$strict>>>;
5807
+ }, z.core.$strict>>;
5772
5808
  addresses: z.ZodOptional<z.ZodArray<z.ZodObject<{
5773
5809
  pattern: z.ZodObject<{
5774
5810
  protocol: z.ZodString;
@@ -5789,6 +5825,9 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
5789
5825
  }, z.core.$strict>, z.ZodObject<{
5790
5826
  kind: z.ZodLiteral<"page">;
5791
5827
  pageId: z.ZodString;
5828
+ }, z.core.$strict>, z.ZodObject<{
5829
+ kind: z.ZodLiteral<"local-app">;
5830
+ schemes: z.ZodArray<z.ZodString>;
5792
5831
  }, z.core.$strict>], "kind">>;
5793
5832
  variants: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
5794
5833
  resourceKind: z.ZodString;
@@ -10670,6 +10709,11 @@ declare type UriClaim = UriSchemeClaim | UriPatternClaim | UrlPatternClaim;
10670
10709
  * - `base64`: unpadded base64 of the UTF-8 text (`{base64(:id :calendar)}`).
10671
10710
  * - `slackTimestamp`: a Slack archive message token as the API's timestamp
10672
10711
  * (`p1783350000000100` becomes `1783350000.000100`).
10712
+ * - `beforeColon`: the part of a `<team>:<user>` id before the colon. It fills nothing for an id
10713
+ * with no colon or nothing before it.
10714
+ * - `beforeTilde`: the part of an id before its last `~`. It fills nothing with no `~`.
10715
+ * - `encoded`: every reserved character escaped, `:` and `@` too, for a whole URL carried as a
10716
+ * query value (`continue={encoded(:url)}`).
10673
10717
  *
10674
10718
  * A transform that cannot read its input fills nothing. A claim whose `normalizeTo` fills nothing
10675
10719
  * does not match; a `sourceUrl` that fills nothing paints no link.
@@ -10928,6 +10972,13 @@ declare interface UriModule {
10928
10972
  readonly uri: string;
10929
10973
  readonly payload: unknown;
10930
10974
  }, ctx: UriResolveContext): Promise<UriOperationDescription | undefined>;
10975
+ /**
10976
+ * Find the web address of `uri` by asking the provider, for a resource whose address alone can't
10977
+ * name its page. Called only when someone opens the address, under the account it means, and never
10978
+ * to draw a reference. `undefined` means there's no page to open. A plugin module that defines
10979
+ * this sets `looksUpWebLinks` in its manifest.
10980
+ */
10981
+ lookupWebLink?(uri: string, ctx: UriResolveContext): Promise<string | undefined>;
10931
10982
  readonly getCachePolicy?: UriCachePolicyResolver;
10932
10983
  /**
10933
10984
  * Code matching, for the host's own modules whose addresses no claim can describe (a bare file
@@ -11049,6 +11100,11 @@ declare interface UriOperationDescription {
11049
11100
  readonly editable?: true;
11050
11101
  /** Longest edited value, in UTF-16 code units. Meaningful only with `editable`. */
11051
11102
  readonly maxLength?: number;
11103
+ /**
11104
+ * Which part of a message this field is, when the call sends one. A preview with a `to` and
11105
+ * a `text` is drawn as a message; without them it stays labelled rows.
11106
+ */
11107
+ readonly part?: "to" | "cc" | "bcc" | "subject" | "text";
11052
11108
  }[];
11053
11109
  };
11054
11110
  /** True only when every displayed fact comes from the input, independent of the executing account. */
@@ -2760,9 +2760,19 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2760
2760
  * 0.44.0 adds `words.kinds` to a reference presentation (#15905): an ordered list of address patterns
2761
2761
  * and the kind each one names. Additive: a plugin that lists them declares ^0.44.0.
2762
2762
  *
2763
- * 0.45.0 adds declared plugin cards and app.implementCard for their read/submit endpoints.
2763
+ * 0.45.0 adds declared plugin cards and app.implementCard for their read/submit endpoints. It also
2764
+ * lets a plugin declare what the window hardcoded about it (#15906). A reference presentation gains
2765
+ * `accountLinks`, how a page opens under the account an address means, and a `local-app` open, for
2766
+ * an item an app on this machine shows; a plugin the person installed can't declare that open. A
2767
+ * `webSession` gains `signInFirst`. A URI module defines `lookupWebLink` and sets `looksUpWebLinks`
2768
+ * to find a page when someone opens the address, and a preview field marks which `part` of a message
2769
+ * it is. A claim's `brandIcon` is a file path and no longer inline markup, which only this repo's
2770
+ * Microsoft plugin used. Otherwise additive: a plugin using any of these declares ^0.45.0.
2771
+ *
2772
+ * 0.46.0 adds `@bonsai/plugin-sdk/artifact-provenance`, so a plugin shipped as files can finalize
2773
+ * and read the provenance the host captured. Additive: a plugin that imports it declares ^0.46.0.
2764
2774
  */
2765
- declare const KAY_PLUGIN_SDK_VERSION: "0.45.0";
2775
+ declare const KAY_PLUGIN_SDK_VERSION: "0.46.0";
2766
2776
 
2767
2777
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2768
2778
 
@@ -5800,6 +5810,7 @@ declare function refineWebSessionScopeConfined(webSession: {
5800
5810
  readonly probe: {
5801
5811
  readonly url: string;
5802
5812
  };
5813
+ readonly signInFirst?: string | undefined;
5803
5814
  }, ctx: z.RefinementCtx): void;
5804
5815
 
5805
5816
  declare const RegistrableDomain: z.ZodString;
@@ -10790,6 +10801,11 @@ export declare type UriClaim = UriSchemeClaim | UriPatternClaim | UrlPatternClai
10790
10801
  * - `base64`: unpadded base64 of the UTF-8 text (`{base64(:id :calendar)}`).
10791
10802
  * - `slackTimestamp`: a Slack archive message token as the API's timestamp
10792
10803
  * (`p1783350000000100` becomes `1783350000.000100`).
10804
+ * - `beforeColon`: the part of a `<team>:<user>` id before the colon. It fills nothing for an id
10805
+ * with no colon or nothing before it.
10806
+ * - `beforeTilde`: the part of an id before its last `~`. It fills nothing with no `~`.
10807
+ * - `encoded`: every reserved character escaped, `:` and `@` too, for a whole URL carried as a
10808
+ * query value (`continue={encoded(:url)}`).
10793
10809
  *
10794
10810
  * A transform that cannot read its input fills nothing. A claim whose `normalizeTo` fills nothing
10795
10811
  * does not match; a `sourceUrl` that fills nothing paints no link.
@@ -11096,6 +11112,13 @@ export declare interface UriModule {
11096
11112
  readonly uri: string;
11097
11113
  readonly payload: unknown;
11098
11114
  }, ctx: UriResolveContext): Promise<UriOperationDescription | undefined>;
11115
+ /**
11116
+ * Find the web address of `uri` by asking the provider, for a resource whose address alone can't
11117
+ * name its page. Called only when someone opens the address, under the account it means, and never
11118
+ * to draw a reference. `undefined` means there's no page to open. A plugin module that defines
11119
+ * this sets `looksUpWebLinks` in its manifest.
11120
+ */
11121
+ lookupWebLink?(uri: string, ctx: UriResolveContext): Promise<string | undefined>;
11099
11122
  readonly getCachePolicy?: UriCachePolicyResolver;
11100
11123
  /**
11101
11124
  * Code matching, for the host's own modules whose addresses no claim can describe (a bare file
@@ -11234,6 +11257,11 @@ export declare interface UriOperationDescription {
11234
11257
  readonly editable?: true;
11235
11258
  /** Longest edited value, in UTF-16 code units. Meaningful only with `editable`. */
11236
11259
  readonly maxLength?: number;
11260
+ /**
11261
+ * Which part of a message this field is, when the call sends one. A preview with a `to` and
11262
+ * a `text` is drawn as a message; without them it stays labelled rows.
11263
+ */
11264
+ readonly part?: "to" | "cc" | "bcc" | "subject" | "text";
11237
11265
  }[];
11238
11266
  };
11239
11267
  /** True only when every displayed fact comes from the input, independent of the executing account. */
package/dist/kay-agent.js CHANGED
@@ -5,12 +5,15 @@ var REST_CAPTURE_RE = /^:([A-Za-z_][A-Za-z0-9_]*)\*$/;
5
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
+ return compileClaim(claim);
9
+ }
10
+ function compileClaim(claim) {
8
11
  if (claim.kind === "scheme") {
9
12
  const scheme = normalizeProtocol(claim.scheme);
10
13
  return {
11
14
  claim,
12
15
  match(input) {
13
- const actual = SCHEME_RE.exec(input.trim())?.[1]?.toLowerCase();
16
+ const actual = typeof input === "string" ? SCHEME_RE.exec(input.trim())?.[1]?.toLowerCase() : input.scheme;
14
17
  if (actual !== scheme)
15
18
  return void 0;
16
19
  return { claimKind: claim.kind };
@@ -20,8 +23,7 @@ function compileUriClaim(claim) {
20
23
  const pattern = compileRoutePattern(claim.pattern);
21
24
  const normalizeTo = claim.normalizeTo === void 0 ? void 0 : compileTemplate(claim.normalizeTo);
22
25
  const sourceUrl = claim.kind === "uriPattern" && claim.sourceUrl !== void 0 ? compileTemplate(claim.sourceUrl) : void 0;
23
- const matchAt = (target, selector) => {
24
- const parsed = parsePatternInput(target);
26
+ const matchAt = (parsed, selector) => {
25
27
  if (parsed === void 0)
26
28
  return void 0;
27
29
  const captures = matchRoute(pattern, parsed);
@@ -47,14 +49,14 @@ function compileUriClaim(claim) {
47
49
  claim,
48
50
  match(input) {
49
51
  if (claim.kind === "uriPattern") {
50
- const { selector, rest } = parseUriConnectionSelector(input);
52
+ const { selector, rest } = typeof input === "string" ? parseUriConnectionSelector(input) : input.connection;
51
53
  if (selector !== void 0) {
52
- const match = matchAt(rest, selector);
54
+ const match = matchAt(typeof input === "string" ? parsePatternInput(rest) : input.selected, selector);
53
55
  if (match !== void 0)
54
56
  return match;
55
57
  }
56
58
  }
57
- return matchAt(input, void 0);
59
+ return matchAt(typeof input === "string" ? parsePatternInput(input) : input.raw, void 0);
58
60
  }
59
61
  };
60
62
  }
@@ -252,7 +254,16 @@ var TRANSFORMS = {
252
254
  slackTimestamp: (value) => {
253
255
  const match = /^p(\d+)(\d{6})$/.exec(value);
254
256
  return match === null ? void 0 : `${match[1]}.${match[2]}`;
255
- }
257
+ },
258
+ beforeColon: (value) => {
259
+ const end = value.indexOf(":");
260
+ return end > 0 ? value.slice(0, end) : void 0;
261
+ },
262
+ beforeTilde: (value) => {
263
+ const end = value.lastIndexOf("~");
264
+ return end > 0 ? value.slice(0, end) : void 0;
265
+ },
266
+ encoded: encodeURIComponent
256
267
  };
257
268
  function isTransform(name) {
258
269
  return Object.prototype.hasOwnProperty.call(TRANSFORMS, name);
@@ -323,7 +334,7 @@ function fillTemplate(parts, captures, restCaptures) {
323
334
  const transformed = TRANSFORMS[part.transform](raw);
324
335
  if (transformed === void 0)
325
336
  return void 0;
326
- out += escapeForPosition(transformed, part.position);
337
+ out += part.transform === "encoded" ? transformed : escapeForPosition(transformed, part.position);
327
338
  }
328
339
  return out;
329
340
  }
package/dist/kay-app.d.ts CHANGED
@@ -2745,9 +2745,19 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2745
2745
  * 0.44.0 adds `words.kinds` to a reference presentation (#15905): an ordered list of address patterns
2746
2746
  * and the kind each one names. Additive: a plugin that lists them declares ^0.44.0.
2747
2747
  *
2748
- * 0.45.0 adds declared plugin cards and app.implementCard for their read/submit endpoints.
2748
+ * 0.45.0 adds declared plugin cards and app.implementCard for their read/submit endpoints. It also
2749
+ * lets a plugin declare what the window hardcoded about it (#15906). A reference presentation gains
2750
+ * `accountLinks`, how a page opens under the account an address means, and a `local-app` open, for
2751
+ * an item an app on this machine shows; a plugin the person installed can't declare that open. A
2752
+ * `webSession` gains `signInFirst`. A URI module defines `lookupWebLink` and sets `looksUpWebLinks`
2753
+ * to find a page when someone opens the address, and a preview field marks which `part` of a message
2754
+ * it is. A claim's `brandIcon` is a file path and no longer inline markup, which only this repo's
2755
+ * Microsoft plugin used. Otherwise additive: a plugin using any of these declares ^0.45.0.
2756
+ *
2757
+ * 0.46.0 adds `@bonsai/plugin-sdk/artifact-provenance`, so a plugin shipped as files can finalize
2758
+ * and read the provenance the host captured. Additive: a plugin that imports it declares ^0.46.0.
2749
2759
  */
2750
- declare const KAY_PLUGIN_SDK_VERSION: "0.45.0";
2760
+ declare const KAY_PLUGIN_SDK_VERSION: "0.46.0";
2751
2761
 
2752
2762
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2753
2763
 
@@ -3653,14 +3663,15 @@ export declare type KayAppAutomationMatch = {
3653
3663
  readonly requestedBy?: "user" | "agent" | undefined;
3654
3664
  };
3655
3665
 
3656
- /** Match any listed type; filters use strict equality or scalar-list containment. */
3666
+ /**
3667
+ * Match any listed type. `where` is an expression over the event: `==` and `!=` compare a whole
3668
+ * value, and `contains` looks inside a list, as in
3669
+ * `payload.status == 'open' && payload.labels contains 'urgent'`.
3670
+ */
3657
3671
  export declare interface KayAppAutomationPluginEventCondition {
3658
3672
  readonly kind: "plugin-event";
3659
3673
  readonly events: readonly string[];
3660
- readonly where?: readonly {
3661
- readonly path: string;
3662
- readonly equals: string | number | boolean;
3663
- }[];
3674
+ readonly where?: string;
3664
3675
  }
3665
3676
 
3666
3677
  /**
@@ -10234,6 +10245,7 @@ declare function refineWebSessionScopeConfined(webSession: {
10234
10245
  readonly probe: {
10235
10246
  readonly url: string;
10236
10247
  };
10248
+ readonly signInFirst?: string | undefined;
10237
10249
  }, ctx: z.RefinementCtx): void;
10238
10250
 
10239
10251
  export declare interface RegisteredHostApprovalType {
@@ -15652,6 +15664,11 @@ declare type UriClaim = UriSchemeClaim | UriPatternClaim | UrlPatternClaim;
15652
15664
  * - `base64`: unpadded base64 of the UTF-8 text (`{base64(:id :calendar)}`).
15653
15665
  * - `slackTimestamp`: a Slack archive message token as the API's timestamp
15654
15666
  * (`p1783350000000100` becomes `1783350000.000100`).
15667
+ * - `beforeColon`: the part of a `<team>:<user>` id before the colon. It fills nothing for an id
15668
+ * with no colon or nothing before it.
15669
+ * - `beforeTilde`: the part of an id before its last `~`. It fills nothing with no `~`.
15670
+ * - `encoded`: every reserved character escaped, `:` and `@` too, for a whole URL carried as a
15671
+ * query value (`continue={encoded(:url)}`).
15655
15672
  *
15656
15673
  * A transform that cannot read its input fills nothing. A claim whose `normalizeTo` fills nothing
15657
15674
  * does not match; a `sourceUrl` that fills nothing paints no link.
@@ -15893,6 +15910,13 @@ declare interface UriModule_2 {
15893
15910
  readonly uri: string;
15894
15911
  readonly payload: unknown;
15895
15912
  }, ctx: UriResolveContext): Promise<UriOperationDescription | undefined>;
15913
+ /**
15914
+ * Find the web address of `uri` by asking the provider, for a resource whose address alone can't
15915
+ * name its page. Called only when someone opens the address, under the account it means, and never
15916
+ * to draw a reference. `undefined` means there's no page to open. A plugin module that defines
15917
+ * this sets `looksUpWebLinks` in its manifest.
15918
+ */
15919
+ lookupWebLink?(uri: string, ctx: UriResolveContext): Promise<string | undefined>;
15896
15920
  /**
15897
15921
  * Set false when the generic write tool must reject `source` copies before
15898
15922
  * fetching the source. Inline `content` writes remain available.
@@ -16090,6 +16114,11 @@ declare interface UriOperationDescription {
16090
16114
  readonly editable?: true;
16091
16115
  /** Longest edited value, in UTF-16 code units. Meaningful only with `editable`. */
16092
16116
  readonly maxLength?: number;
16117
+ /**
16118
+ * Which part of a message this field is, when the call sends one. A preview with a `to` and
16119
+ * a `text` is drawn as a message; without them it stays labelled rows.
16120
+ */
16121
+ readonly part?: "to" | "cc" | "bcc" | "subject" | "text";
16093
16122
  }[];
16094
16123
  };
16095
16124
  /** True only when every displayed fact comes from the input, independent of the executing account. */
@@ -377,6 +377,11 @@ declare type UriClaim = UriSchemeClaim | UriPatternClaim | UrlPatternClaim;
377
377
  * - `base64`: unpadded base64 of the UTF-8 text (`{base64(:id :calendar)}`).
378
378
  * - `slackTimestamp`: a Slack archive message token as the API's timestamp
379
379
  * (`p1783350000000100` becomes `1783350000.000100`).
380
+ * - `beforeColon`: the part of a `<team>:<user>` id before the colon. It fills nothing for an id
381
+ * with no colon or nothing before it.
382
+ * - `beforeTilde`: the part of an id before its last `~`. It fills nothing with no `~`.
383
+ * - `encoded`: every reserved character escaped, `:` and `@` too, for a whole URL carried as a
384
+ * query value (`continue={encoded(:url)}`).
380
385
  *
381
386
  * A transform that cannot read its input fills nothing. A claim whose `normalizeTo` fills nothing
382
387
  * does not match; a `sourceUrl` that fills nothing paints no link.
@@ -635,6 +640,13 @@ declare interface UriModule {
635
640
  readonly uri: string;
636
641
  readonly payload: unknown;
637
642
  }, ctx: UriResolveContext): Promise<UriOperationDescription | undefined>;
643
+ /**
644
+ * Find the web address of `uri` by asking the provider, for a resource whose address alone can't
645
+ * name its page. Called only when someone opens the address, under the account it means, and never
646
+ * to draw a reference. `undefined` means there's no page to open. A plugin module that defines
647
+ * this sets `looksUpWebLinks` in its manifest.
648
+ */
649
+ lookupWebLink?(uri: string, ctx: UriResolveContext): Promise<string | undefined>;
638
650
  readonly getCachePolicy?: UriCachePolicyResolver;
639
651
  /**
640
652
  * Code matching, for the host's own modules whose addresses no claim can describe (a bare file
@@ -756,6 +768,11 @@ declare interface UriOperationDescription {
756
768
  readonly editable?: true;
757
769
  /** Longest edited value, in UTF-16 code units. Meaningful only with `editable`. */
758
770
  readonly maxLength?: number;
771
+ /**
772
+ * Which part of a message this field is, when the call sends one. A preview with a `to` and
773
+ * a `text` is drawn as a message; without them it stays labelled rows.
774
+ */
775
+ readonly part?: "to" | "cc" | "bcc" | "subject" | "text";
759
776
  }[];
760
777
  };
761
778
  /** True only when every displayed fact comes from the input, independent of the executing account. */
@@ -76,12 +76,15 @@ var REST_CAPTURE_RE = /^:([A-Za-z_][A-Za-z0-9_]*)\*$/;
76
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
+ return compileClaim(claim);
80
+ }
81
+ function compileClaim(claim) {
79
82
  if (claim.kind === "scheme") {
80
83
  const scheme = normalizeProtocol(claim.scheme);
81
84
  return {
82
85
  claim,
83
86
  match(input) {
84
- const actual = SCHEME_RE.exec(input.trim())?.[1]?.toLowerCase();
87
+ const actual = typeof input === "string" ? SCHEME_RE.exec(input.trim())?.[1]?.toLowerCase() : input.scheme;
85
88
  if (actual !== scheme)
86
89
  return void 0;
87
90
  return { claimKind: claim.kind };
@@ -91,8 +94,7 @@ function compileUriClaim(claim) {
91
94
  const pattern = compileRoutePattern(claim.pattern);
92
95
  const normalizeTo = claim.normalizeTo === void 0 ? void 0 : compileTemplate(claim.normalizeTo);
93
96
  const sourceUrl = claim.kind === "uriPattern" && claim.sourceUrl !== void 0 ? compileTemplate(claim.sourceUrl) : void 0;
94
- const matchAt = (target, selector) => {
95
- const parsed = parsePatternInput(target);
97
+ const matchAt = (parsed, selector) => {
96
98
  if (parsed === void 0)
97
99
  return void 0;
98
100
  const captures = matchRoute(pattern, parsed);
@@ -118,14 +120,14 @@ function compileUriClaim(claim) {
118
120
  claim,
119
121
  match(input) {
120
122
  if (claim.kind === "uriPattern") {
121
- const { selector, rest } = parseUriConnectionSelector(input);
123
+ const { selector, rest } = typeof input === "string" ? parseUriConnectionSelector(input) : input.connection;
122
124
  if (selector !== void 0) {
123
- const match = matchAt(rest, selector);
125
+ const match = matchAt(typeof input === "string" ? parsePatternInput(rest) : input.selected, selector);
124
126
  if (match !== void 0)
125
127
  return match;
126
128
  }
127
129
  }
128
- return matchAt(input, void 0);
130
+ return matchAt(typeof input === "string" ? parsePatternInput(input) : input.raw, void 0);
129
131
  }
130
132
  };
131
133
  }
@@ -323,7 +325,16 @@ var TRANSFORMS = {
323
325
  slackTimestamp: (value) => {
324
326
  const match = /^p(\d+)(\d{6})$/.exec(value);
325
327
  return match === null ? void 0 : `${match[1]}.${match[2]}`;
326
- }
328
+ },
329
+ beforeColon: (value) => {
330
+ const end = value.indexOf(":");
331
+ return end > 0 ? value.slice(0, end) : void 0;
332
+ },
333
+ beforeTilde: (value) => {
334
+ const end = value.lastIndexOf("~");
335
+ return end > 0 ? value.slice(0, end) : void 0;
336
+ },
337
+ encoded: encodeURIComponent
327
338
  };
328
339
  function isTransform(name) {
329
340
  return Object.prototype.hasOwnProperty.call(TRANSFORMS, name);
@@ -394,7 +405,7 @@ function fillTemplate(parts, captures, restCaptures) {
394
405
  const transformed = TRANSFORMS[part.transform](raw);
395
406
  if (transformed === void 0)
396
407
  return void 0;
397
- out += escapeForPosition(transformed, part.position);
408
+ out += part.transform === "encoded" ? transformed : escapeForPosition(transformed, part.position);
398
409
  }
399
410
  return out;
400
411
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaklabs-ai/plugin-sdk",
3
- "version": "0.45.0",
3
+ "version": "0.46.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",
@@ -33,6 +33,10 @@
33
33
  "types": "./dist/disclosure.d.ts",
34
34
  "default": "./dist/disclosure.js"
35
35
  },
36
+ "./artifact-provenance": {
37
+ "types": "./dist/artifact-provenance.d.ts",
38
+ "default": "./dist/artifact-provenance.js"
39
+ },
36
40
  "./signals": {
37
41
  "types": "./dist/signals.d.ts",
38
42
  "default": "./dist/signals.js"
@@ -43,8 +43,8 @@ pnpm create-plugin --id com.example.widgets
43
43
  Run from the root of a Bonsai checkout. It writes a working plugin (manifest, entrypoint, tsconfig,
44
44
  README) that already typechecks and loads; `--tier starter` adds a URI module, a bundled skill,
45
45
  and a standalone `node --test` test to copy from. Add `--ui` (either tier) when the plugin needs a
46
- page: it writes `ui.tsx`, declares the `kay.ui` entrypoint, and generates the UI typecheck config
47
- described below. `--ui` also needs `pnpm --filter @bonsai/ui build` once per checkout; the scaffold
46
+ page: it writes `ui.tsx`, declares it under the manifest's `apps`, and generates the UI typecheck
47
+ config described below. `--ui` also needs `pnpm --filter @bonsai/ui build` once per checkout; the scaffold
48
48
  stops and says so when that build is missing.
49
49
 
50
50
  Never hand-build a plugin as a tsc-compiled package and copy the output into `~/.kay/plugins/`.
@@ -122,14 +122,15 @@ a plugin you install yourself.
122
122
 
123
123
  A plugin with a UI has three targets. Each declared daemon target is a bundle root, so its
124
124
  entrypoint may import other files in the plugin; `kay.agent` runs in the daemon per session and
125
- `kay.app` runs in the daemon once. `kay.ui` runs in the renderer through its own UI bundle, which is a single
126
- self-contained module: unlike the daemon targets, `ui.tsx` cannot import sibling files. A
127
- plugin UI contributes through `api.slots` (`registerPage`, `registerSidebarItem`,
128
- `registerPaneAction`, and the rest of `buildSlots` in
129
- `packages/kay-renderer/src/renderer/src/extension-loader/build-extension-api.ts`). A page gets its own
125
+ `kay.app` runs in the daemon once. A page runs in the renderer: declare it under `apps` in
126
+ `targets.kay.ui.contributes`, with `entrypoint.module` naming your source and `entrypoint.export`
127
+ the component. Bonsai compiles it when it loads the plugin, so there is no build step: relative
128
+ imports work within the plugin's folder, and Tailwind classes work with no setup against Bonsai's
129
+ theme. A page imports only `react` and `@bonsai/plugin-ui-sdk`; a `kay.ui` `entrypoint` with an
130
+ `activate` function is for what a declaration cannot do yet, not for pages. A page gets its own
130
131
  activity-rail button when the manifest declares it: `railEntries` under `targets.kay.ui.contributes`,
131
- with `id`, `title` and `page`, and optionally `icon`, `shortcut`, `order` and `section`. That
132
- declaration works with no `ui.tsx` at all. To give the entry a sidebar, add `panel: { body }` naming
132
+ with `id`, `title` and `page` (`<namespace>.<app localId>`), and optionally `icon`, `shortcut`,
133
+ `order` and `section`. To give the entry a sidebar, add `panel: { body }` naming
133
134
  an app in the same manifest with `contextOnly: true`. The sidebar is always there once declared, so
134
135
  the app shows its own empty state. To give a notification rule's toast a "Show changes" preview, add
135
136
  a `toastPreviews` entry under `targets.kay.ui.contributes` with `rule` (the rule's `localId`), `body`
@@ -143,11 +144,11 @@ on a small white tile). Set `icon` on a rail entry to show a single-colour glyph
143
144
  the plugin (`"./assets/rail.svg"`). Only its shape is used, painted in the rail's colour, so colours
144
145
  in the file are ignored, and it must be transparent where nothing should draw. A missing file is a
145
146
  load diagnostic and the entry falls back to the plugin icon. The page the entry opens wears the same
146
- icon unless `registerPage`'s `icon` says otherwise. Full
147
+ icon. Full
147
148
  precedence: `packages/kay-frontend-sdk/ARCHITECTURE.md`, "Plugin icon".
148
149
 
149
- `ui.tsx` has no `node_modules` of its own. The renderer bundles it and rewrites its `react` and
150
- `@bonsai/*` imports to the host's `__KAY_UI_RUNTIME__` singletons, so the agent `tsconfig.json`
150
+ `ui.tsx` has no `node_modules` of its own. Bonsai compiles it and rewrites its `react` and
151
+ `@bonsai/plugin-ui-sdk` imports to the host's `__KAY_UI_RUNTIME__` singletons, so the agent `tsconfig.json`
151
152
  cannot cover it, and a plugin whose UI nothing typechecks has shipped three wrong API shapes at
152
153
  once. `pnpm create-plugin --ui` generates `tsconfig.ui.json` for exactly this: its `paths` are
153
154
  derived from the bundler's own shim set (`uiRuntimeShimModules` in `@bonsai/ui-app-bundler`), each
@@ -155,15 +156,13 @@ specifier mapped to the type entry the renderer binds it to, and `npm run typech
155
156
  configs. Do not hand-write the map; when the bundler's set changes, the scaffold's test fails and
156
157
  the generated config follows.
157
158
 
158
- Two facts about that config worth knowing when you read errors from it:
159
+ That config typechecks `ui.tsx` as a browser module: `Bundler` resolution, automatic JSX, DOM libs,
160
+ no Node globals. The agent config keeps `**/*.ts`, so the two programs never overlap. Add a new page
161
+ file to its `include`.
159
162
 
160
- - The bare `@bonsai/frontend-sdk` is typed against the SDK's `ui-runtime` facade, because that is
161
- what the renderer binds it to. The facade carries the SDK's whole type surface, so
162
- `KayUiExtensionApi` and every descriptor type import fine; a **value** only the package's main
163
- entry exports fails to compile there (TS1362, "exported using export type"), which is the
164
- compiler telling you the running extension would receive `undefined`.
165
- - It typechecks `ui.tsx` alone, as a browser module: `Bundler` resolution, automatic JSX, DOM
166
- libs, no Node globals. The agent config keeps `**/*.ts`, so the two programs never overlap.
163
+ `pnpm plugin:check` also compiles a page declared as source, so a broken import or a refused
164
+ `@bonsai/*` package shows up there as `kay-ui-app-compile-failed`. If a class with a variant seems
165
+ to do nothing, see "How a plugin page gets Tailwind" in `docs/frontend-styling.md`.
167
166
 
168
167
  For a plugin scaffolded before `--ui` existed, scaffold a throwaway `--ui` plugin from the same
169
168
  checkout and copy its `tsconfig.ui.json` and the second `typecheck` command into yours; `--force`