@yaklabs-ai/plugin-sdk 0.55.3 → 0.55.5

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.55.3"
16
+ "@bonsai/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.55.5"
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.55.3" },
65
+ "compatibility": { "sdk": "^0.55.5" },
66
66
  "targets": {
67
67
  "kay": {
68
68
  "agent": {
@@ -153,7 +153,7 @@ naming both versions, instead of loading it and finding no `activate`.
153
153
  | `@bonsai/plugin-sdk/system-one` | The types and error class for `api.systemOne` / `app.systemOne`, from 0.13.8 |
154
154
  | `@bonsai/plugin-sdk/zod` | `z` (the host's in the daemon), on an entry with no other import, from 0.13.9 |
155
155
 
156
- A plugin that imports these subpaths declares the current supported SDK range (`^0.55.3`).
156
+ A plugin that imports these subpaths declares the current supported SDK range (`^0.55.5`).
157
157
  The rows record when each subpath appeared, not retained runtime compatibility. `vendored-mcp` builds the plugin's URI module (its link cards and help); hosting the
158
158
  vendor's MCP server itself is a separate host decision: Bonsai hosts it once a person approves
159
159
  the plugin's `mcp.host-server` grant for that server's name and URL. A server that needs an OAuth
@@ -161,7 +161,7 @@ sign-in names one of the plugin's auth services in `authService`; that service m
161
161
  one `delegated` scheme, which Bonsai uses to sign the person in to the server. Bonsai declares that
162
162
  scheme at runtime; the plugin's code must not declare it again. From 0.16.2 a plugin's code can also
163
163
  call the server's tools through `api.vendoredMcp.port(<server>)`, typed by this subpath's
164
- `VendoredMcpPort` and `VendoredMcpOutcome` (declare `^0.55.3`).
164
+ `VendoredMcpPort` and `VendoredMcpOutcome` (declare `^0.55.5`).
165
165
 
166
166
  From 0.13.10 the manifest schema carries two facts Bonsai reads for its own plugins only; another
167
167
  plugin's are ignored, with a load diagnostic. An `external-cli` auth scheme's `cli` says how Bonsai
@@ -243,7 +243,7 @@ Provider schemas remain authoritative; declaring a dependency grants no authorit
243
243
  through `app.uri`, parse returned Markdown in the consuming plugin, and retain the read's
244
244
  revision (or `contentDigest` from `/uri`) for edits. The old `memory.read` and `memory.write`
245
245
  grants do not authorize the replacement scheme-and-verb calls. Contracts before 0.49.0 are
246
- refused; migrate and declare `^0.55.3`. The current host also serves the 0.49.0 resource contract.
246
+ refused; migrate and declare `^0.55.5`. The current host also serves the 0.49.0 resource contract.
247
247
 
248
248
  ## What this package is, and is not, at runtime
249
249
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@yaklabs-ai/plugin-sdk",
4
- "version": "0.55.3",
4
+ "version": "0.55.5",
5
5
  "target": "npm",
6
6
  "firstPartyLicense": "MIT",
7
7
  "bundled": [
@@ -805,6 +805,13 @@ declare interface CollaborationMessageDetails {
805
805
  readonly kind: "message" | "progress";
806
806
  }
807
807
 
808
+ /**
809
+ * Why a compaction committed the code-written fallback text instead of a model-written summary:
810
+ * the standalone executor's reasons, with every provider failure folded into `provider`. A closed
811
+ * set, so the reason can leave the device; `other` holds anything the executor adds later.
812
+ */
813
+ declare const COMPACTION_FALLBACK_REASONS: readonly ["deadline", "invalid-cut", "no-callable-model", "insufficient-context", "provider", "unusable-output", "unsupported-stop-directive", "preparation", "model-resolution", "prompt-preparation", "output-validation", "other"];
814
+
808
815
  declare interface CompactionEntry extends EntryBase {
809
816
  type: "compaction";
810
817
  summary: string;
@@ -826,6 +833,8 @@ declare interface CompactionFailedSessionEvent {
826
833
  readonly durationMs: number;
827
834
  }
828
835
 
836
+ declare type CompactionFallbackReason = (typeof COMPACTION_FALLBACK_REASONS)[number];
837
+
829
838
  /**
830
839
  * Why a session-initiated compaction ran. `threshold` is the pluggable-policy
831
840
  * usage check, now consulted at TWO points - every tool-batch boundary inside a
@@ -1841,6 +1850,12 @@ declare type HerdHarnessEvent = {
1841
1850
  readonly type: "session_compact";
1842
1851
  readonly compactionEntry: CompactionEntry;
1843
1852
  readonly fromHook: boolean;
1853
+ /** The measurements `herd.context.compacted` carries; see its payload. */
1854
+ readonly tokensBefore?: number;
1855
+ readonly durationMs?: number;
1856
+ readonly fallbackReason?: CompactionFallbackReason;
1857
+ readonly fallbackProviderReason?: RunFailureReason;
1858
+ readonly operationId?: string;
1844
1859
  } | {
1845
1860
  readonly type: "summary_operation_settled";
1846
1861
  } | {
@@ -227,7 +227,7 @@ export declare interface AuditPluginDisclosureInput {
227
227
 
228
228
  /**
229
229
  * The codegen-pair equivalence check every bundled-skill plugin hand-rolled (see
230
- * `plugins/ARCHITECTURE.md` -> "Bundled skills", step 4): every exported `PluginSkillDefinition`
230
+ * `plugins/gmail/test/gmail-plugin.test.ts`): every exported `PluginSkillDefinition`
231
231
  * must have a matching manifest declaration (same `localId`, same `description`), and the
232
232
  * declared `SKILL.md` file's decoded YAML name and description must match the export.
233
233
  * The body is compared byte-for-byte after trimming surrounding whitespace.
@@ -845,6 +845,12 @@ declare interface DerivedToolClassification {
845
845
  readonly kind?: ToolActionKind;
846
846
  readonly ruleKey?: string;
847
847
  readonly scheme?: string;
848
+ /**
849
+ * This call needs a person's one-time answer: no allow rule, no mode (allow mode included) and
850
+ * no automatic approver settles it, and the approval cannot be remembered. Deny rules still
851
+ * apply. Stricter only, so it grants nothing. The same flag a URI route classification carries.
852
+ */
853
+ readonly humanOnly?: true;
848
854
  }
849
855
 
850
856
  declare const Digit: TDigit;
@@ -1357,11 +1363,53 @@ declare interface InteractionActed {
1357
1363
  * afterwards when `submit` is set.
1358
1364
  */
1359
1365
  declare const InteractionAction: z.ZodDiscriminatedUnion<[z.ZodObject<{
1366
+ kind: z.ZodLiteral<"upload">;
1367
+ element: z.ZodObject<{
1368
+ id: z.ZodString;
1369
+ kind: z.ZodEnum<{
1370
+ fill: "fill";
1371
+ upload: "upload";
1372
+ activate: "activate";
1373
+ click: "click";
1374
+ select: "select";
1375
+ scroll: "scroll";
1376
+ wait: "wait";
1377
+ press: "press";
1378
+ }>;
1379
+ label: z.ZodString;
1380
+ node: z.ZodOptional<z.ZodNumber>;
1381
+ role: z.ZodOptional<z.ZodString>;
1382
+ value: z.ZodOptional<z.ZodString>;
1383
+ current_value: z.ZodOptional<z.ZodString>;
1384
+ checked: z.ZodOptional<z.ZodString>;
1385
+ selected: z.ZodOptional<z.ZodString>;
1386
+ expanded: z.ZodOptional<z.ZodString>;
1387
+ look: z.ZodOptional<z.ZodEnum<{
1388
+ link: "link";
1389
+ widget: "widget";
1390
+ }>>;
1391
+ delta: z.ZodOptional<z.ZodNumber>;
1392
+ position: z.ZodOptional<z.ZodEnum<{
1393
+ above: "above";
1394
+ below: "below";
1395
+ beside: "beside";
1396
+ }>>;
1397
+ region: z.ZodOptional<z.ZodObject<{
1398
+ role: z.ZodString;
1399
+ name: z.ZodString;
1400
+ front: z.ZodOptional<z.ZodBoolean>;
1401
+ }, z.core.$loose>>;
1402
+ scroller: z.ZodOptional<z.ZodNumber>;
1403
+ }, z.core.$loose>;
1404
+ path: z.ZodString;
1405
+ origin: z.ZodString;
1406
+ }, z.core.$strict>, z.ZodObject<{
1360
1407
  kind: z.ZodLiteral<"click">;
1361
1408
  element: z.ZodObject<{
1362
1409
  id: z.ZodString;
1363
1410
  kind: z.ZodEnum<{
1364
1411
  fill: "fill";
1412
+ upload: "upload";
1365
1413
  activate: "activate";
1366
1414
  click: "click";
1367
1415
  select: "select";
@@ -1400,6 +1448,7 @@ declare const InteractionAction: z.ZodDiscriminatedUnion<[z.ZodObject<{
1400
1448
  id: z.ZodString;
1401
1449
  kind: z.ZodEnum<{
1402
1450
  fill: "fill";
1451
+ upload: "upload";
1403
1452
  activate: "activate";
1404
1453
  click: "click";
1405
1454
  select: "select";
@@ -1441,6 +1490,7 @@ declare const InteractionAction: z.ZodDiscriminatedUnion<[z.ZodObject<{
1441
1490
  id: z.ZodString;
1442
1491
  kind: z.ZodEnum<{
1443
1492
  fill: "fill";
1493
+ upload: "upload";
1444
1494
  activate: "activate";
1445
1495
  click: "click";
1446
1496
  select: "select";
@@ -1479,6 +1529,7 @@ declare const InteractionAction: z.ZodDiscriminatedUnion<[z.ZodObject<{
1479
1529
  id: z.ZodString;
1480
1530
  kind: z.ZodEnum<{
1481
1531
  fill: "fill";
1532
+ upload: "upload";
1482
1533
  activate: "activate";
1483
1534
  click: "click";
1484
1535
  select: "select";
@@ -1517,6 +1568,7 @@ declare const InteractionAction: z.ZodDiscriminatedUnion<[z.ZodObject<{
1517
1568
  id: z.ZodString;
1518
1569
  kind: z.ZodEnum<{
1519
1570
  fill: "fill";
1571
+ upload: "upload";
1520
1572
  activate: "activate";
1521
1573
  click: "click";
1522
1574
  select: "select";
@@ -1556,6 +1608,7 @@ declare const InteractionAction: z.ZodDiscriminatedUnion<[z.ZodObject<{
1556
1608
  id: z.ZodString;
1557
1609
  kind: z.ZodEnum<{
1558
1610
  fill: "fill";
1611
+ upload: "upload";
1559
1612
  activate: "activate";
1560
1613
  click: "click";
1561
1614
  select: "select";
@@ -1652,6 +1705,7 @@ declare const InteractionObservation: z.ZodObject<{
1652
1705
  id: z.ZodString;
1653
1706
  kind: z.ZodEnum<{
1654
1707
  fill: "fill";
1708
+ upload: "upload";
1655
1709
  activate: "activate";
1656
1710
  click: "click";
1657
1711
  select: "select";
@@ -2687,8 +2741,19 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2687
2741
  * text, at most `PLUGIN_SIGNAL_BODY_MAX` (20,000) characters. Gmail puts a mail's text there, so
2688
2742
  * Flows can keep the messages a task came from. Additive: a plugin that publishes a body declares
2689
2743
  * ^0.55.3.
2744
+ *
2745
+ * 0.55.4 adds `app.plugins.listServices()` under the new `plugins.read` claim: every auth service
2746
+ * of the installed, enabled plugins, with the plugin's id and display name and whether the person
2747
+ * has connected it. No account, identity or scope. Built-ins hold the claim; any other plugin needs
2748
+ * a grant. Additive; plugins calling it declare ^0.55.4.
2749
+ *
2750
+ * 0.55.5 adds `app.sessions.readState()` and `writeState()` under the new `sessions.state` claim:
2751
+ * a plugin keeps its own state entries in a session's transcript, stored as `plugin-state:<pluginId>:<name>`,
2752
+ * and each write names the newest entry it was computed from, so a write from a stale base is
2753
+ * answered with the newest one instead of landing (compaction plan, phase 2). Additive; plugins
2754
+ * calling them declare ^0.55.5.
2690
2755
  */
2691
- declare const KAY_PLUGIN_SDK_VERSION: "0.55.3";
2756
+ declare const KAY_PLUGIN_SDK_VERSION: "0.55.5";
2692
2757
 
2693
2758
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2694
2759
 
@@ -810,6 +810,12 @@ declare interface DerivedToolClassification {
810
810
  readonly kind?: ToolActionKind;
811
811
  readonly ruleKey?: string;
812
812
  readonly scheme?: string;
813
+ /**
814
+ * This call needs a person's one-time answer: no allow rule, no mode (allow mode included) and
815
+ * no automatic approver settles it, and the approval cannot be remembered. Deny rules still
816
+ * apply. Stricter only, so it grants nothing. The same flag a URI route classification carries.
817
+ */
818
+ readonly humanOnly?: true;
813
819
  }
814
820
 
815
821
  /**
@@ -1393,11 +1399,53 @@ declare interface InteractionActed {
1393
1399
  * afterwards when `submit` is set.
1394
1400
  */
1395
1401
  declare const InteractionAction: z.ZodDiscriminatedUnion<[z.ZodObject<{
1402
+ kind: z.ZodLiteral<"upload">;
1403
+ element: z.ZodObject<{
1404
+ id: z.ZodString;
1405
+ kind: z.ZodEnum<{
1406
+ fill: "fill";
1407
+ upload: "upload";
1408
+ activate: "activate";
1409
+ click: "click";
1410
+ select: "select";
1411
+ scroll: "scroll";
1412
+ wait: "wait";
1413
+ press: "press";
1414
+ }>;
1415
+ label: z.ZodString;
1416
+ node: z.ZodOptional<z.ZodNumber>;
1417
+ role: z.ZodOptional<z.ZodString>;
1418
+ value: z.ZodOptional<z.ZodString>;
1419
+ current_value: z.ZodOptional<z.ZodString>;
1420
+ checked: z.ZodOptional<z.ZodString>;
1421
+ selected: z.ZodOptional<z.ZodString>;
1422
+ expanded: z.ZodOptional<z.ZodString>;
1423
+ look: z.ZodOptional<z.ZodEnum<{
1424
+ link: "link";
1425
+ widget: "widget";
1426
+ }>>;
1427
+ delta: z.ZodOptional<z.ZodNumber>;
1428
+ position: z.ZodOptional<z.ZodEnum<{
1429
+ above: "above";
1430
+ below: "below";
1431
+ beside: "beside";
1432
+ }>>;
1433
+ region: z.ZodOptional<z.ZodObject<{
1434
+ role: z.ZodString;
1435
+ name: z.ZodString;
1436
+ front: z.ZodOptional<z.ZodBoolean>;
1437
+ }, z.core.$loose>>;
1438
+ scroller: z.ZodOptional<z.ZodNumber>;
1439
+ }, z.core.$loose>;
1440
+ path: z.ZodString;
1441
+ origin: z.ZodString;
1442
+ }, z.core.$strict>, z.ZodObject<{
1396
1443
  kind: z.ZodLiteral<"click">;
1397
1444
  element: z.ZodObject<{
1398
1445
  id: z.ZodString;
1399
1446
  kind: z.ZodEnum<{
1400
1447
  fill: "fill";
1448
+ upload: "upload";
1401
1449
  activate: "activate";
1402
1450
  click: "click";
1403
1451
  select: "select";
@@ -1436,6 +1484,7 @@ declare const InteractionAction: z.ZodDiscriminatedUnion<[z.ZodObject<{
1436
1484
  id: z.ZodString;
1437
1485
  kind: z.ZodEnum<{
1438
1486
  fill: "fill";
1487
+ upload: "upload";
1439
1488
  activate: "activate";
1440
1489
  click: "click";
1441
1490
  select: "select";
@@ -1477,6 +1526,7 @@ declare const InteractionAction: z.ZodDiscriminatedUnion<[z.ZodObject<{
1477
1526
  id: z.ZodString;
1478
1527
  kind: z.ZodEnum<{
1479
1528
  fill: "fill";
1529
+ upload: "upload";
1480
1530
  activate: "activate";
1481
1531
  click: "click";
1482
1532
  select: "select";
@@ -1515,6 +1565,7 @@ declare const InteractionAction: z.ZodDiscriminatedUnion<[z.ZodObject<{
1515
1565
  id: z.ZodString;
1516
1566
  kind: z.ZodEnum<{
1517
1567
  fill: "fill";
1568
+ upload: "upload";
1518
1569
  activate: "activate";
1519
1570
  click: "click";
1520
1571
  select: "select";
@@ -1553,6 +1604,7 @@ declare const InteractionAction: z.ZodDiscriminatedUnion<[z.ZodObject<{
1553
1604
  id: z.ZodString;
1554
1605
  kind: z.ZodEnum<{
1555
1606
  fill: "fill";
1607
+ upload: "upload";
1556
1608
  activate: "activate";
1557
1609
  click: "click";
1558
1610
  select: "select";
@@ -1592,6 +1644,7 @@ declare const InteractionAction: z.ZodDiscriminatedUnion<[z.ZodObject<{
1592
1644
  id: z.ZodString;
1593
1645
  kind: z.ZodEnum<{
1594
1646
  fill: "fill";
1647
+ upload: "upload";
1595
1648
  activate: "activate";
1596
1649
  click: "click";
1597
1650
  select: "select";
@@ -1688,6 +1741,7 @@ declare const InteractionObservation: z.ZodObject<{
1688
1741
  id: z.ZodString;
1689
1742
  kind: z.ZodEnum<{
1690
1743
  fill: "fill";
1744
+ upload: "upload";
1691
1745
  activate: "activate";
1692
1746
  click: "click";
1693
1747
  select: "select";
@@ -2741,8 +2795,19 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2741
2795
  * text, at most `PLUGIN_SIGNAL_BODY_MAX` (20,000) characters. Gmail puts a mail's text there, so
2742
2796
  * Flows can keep the messages a task came from. Additive: a plugin that publishes a body declares
2743
2797
  * ^0.55.3.
2798
+ *
2799
+ * 0.55.4 adds `app.plugins.listServices()` under the new `plugins.read` claim: every auth service
2800
+ * of the installed, enabled plugins, with the plugin's id and display name and whether the person
2801
+ * has connected it. No account, identity or scope. Built-ins hold the claim; any other plugin needs
2802
+ * a grant. Additive; plugins calling it declare ^0.55.4.
2803
+ *
2804
+ * 0.55.5 adds `app.sessions.readState()` and `writeState()` under the new `sessions.state` claim:
2805
+ * a plugin keeps its own state entries in a session's transcript, stored as `plugin-state:<pluginId>:<name>`,
2806
+ * and each write names the newest entry it was computed from, so a write from a stale base is
2807
+ * answered with the newest one instead of landing (compaction plan, phase 2). Additive; plugins
2808
+ * calling them declare ^0.55.5.
2744
2809
  */
2745
- declare const KAY_PLUGIN_SDK_VERSION: "0.55.3";
2810
+ declare const KAY_PLUGIN_SDK_VERSION: "0.55.5";
2746
2811
 
2747
2812
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2748
2813
 
@@ -1055,6 +1055,12 @@ declare interface DerivedToolClassification {
1055
1055
  readonly kind?: ToolActionKind;
1056
1056
  readonly ruleKey?: string;
1057
1057
  readonly scheme?: string;
1058
+ /**
1059
+ * This call needs a person's one-time answer: no allow rule, no mode (allow mode included) and
1060
+ * no automatic approver settles it, and the approval cannot be remembered. Deny rules still
1061
+ * apply. Stricter only, so it grants nothing. The same flag a URI route classification carries.
1062
+ */
1063
+ readonly humanOnly?: true;
1058
1064
  }
1059
1065
 
1060
1066
  /**
@@ -1668,11 +1674,53 @@ export declare type InteractionAction = DriverAction<InteractionAction_2>;
1668
1674
  * afterwards when `submit` is set.
1669
1675
  */
1670
1676
  declare const InteractionAction_2: z.ZodDiscriminatedUnion<[z.ZodObject<{
1677
+ kind: z.ZodLiteral<"upload">;
1678
+ element: z.ZodObject<{
1679
+ id: z.ZodString;
1680
+ kind: z.ZodEnum<{
1681
+ fill: "fill";
1682
+ upload: "upload";
1683
+ activate: "activate";
1684
+ click: "click";
1685
+ select: "select";
1686
+ scroll: "scroll";
1687
+ wait: "wait";
1688
+ press: "press";
1689
+ }>;
1690
+ label: z.ZodString;
1691
+ node: z.ZodOptional<z.ZodNumber>;
1692
+ role: z.ZodOptional<z.ZodString>;
1693
+ value: z.ZodOptional<z.ZodString>;
1694
+ current_value: z.ZodOptional<z.ZodString>;
1695
+ checked: z.ZodOptional<z.ZodString>;
1696
+ selected: z.ZodOptional<z.ZodString>;
1697
+ expanded: z.ZodOptional<z.ZodString>;
1698
+ look: z.ZodOptional<z.ZodEnum<{
1699
+ link: "link";
1700
+ widget: "widget";
1701
+ }>>;
1702
+ delta: z.ZodOptional<z.ZodNumber>;
1703
+ position: z.ZodOptional<z.ZodEnum<{
1704
+ above: "above";
1705
+ below: "below";
1706
+ beside: "beside";
1707
+ }>>;
1708
+ region: z.ZodOptional<z.ZodObject<{
1709
+ role: z.ZodString;
1710
+ name: z.ZodString;
1711
+ front: z.ZodOptional<z.ZodBoolean>;
1712
+ }, z.core.$loose>>;
1713
+ scroller: z.ZodOptional<z.ZodNumber>;
1714
+ }, z.core.$loose>;
1715
+ path: z.ZodString;
1716
+ origin: z.ZodString;
1717
+ }, z.core.$strict>, z.ZodObject<{
1671
1718
  kind: z.ZodLiteral<"click">;
1672
1719
  element: z.ZodObject<{
1673
1720
  id: z.ZodString;
1674
1721
  kind: z.ZodEnum<{
1675
1722
  fill: "fill";
1723
+ upload: "upload";
1676
1724
  activate: "activate";
1677
1725
  click: "click";
1678
1726
  select: "select";
@@ -1711,6 +1759,7 @@ declare const InteractionAction_2: z.ZodDiscriminatedUnion<[z.ZodObject<{
1711
1759
  id: z.ZodString;
1712
1760
  kind: z.ZodEnum<{
1713
1761
  fill: "fill";
1762
+ upload: "upload";
1714
1763
  activate: "activate";
1715
1764
  click: "click";
1716
1765
  select: "select";
@@ -1752,6 +1801,7 @@ declare const InteractionAction_2: z.ZodDiscriminatedUnion<[z.ZodObject<{
1752
1801
  id: z.ZodString;
1753
1802
  kind: z.ZodEnum<{
1754
1803
  fill: "fill";
1804
+ upload: "upload";
1755
1805
  activate: "activate";
1756
1806
  click: "click";
1757
1807
  select: "select";
@@ -1790,6 +1840,7 @@ declare const InteractionAction_2: z.ZodDiscriminatedUnion<[z.ZodObject<{
1790
1840
  id: z.ZodString;
1791
1841
  kind: z.ZodEnum<{
1792
1842
  fill: "fill";
1843
+ upload: "upload";
1793
1844
  activate: "activate";
1794
1845
  click: "click";
1795
1846
  select: "select";
@@ -1828,6 +1879,7 @@ declare const InteractionAction_2: z.ZodDiscriminatedUnion<[z.ZodObject<{
1828
1879
  id: z.ZodString;
1829
1880
  kind: z.ZodEnum<{
1830
1881
  fill: "fill";
1882
+ upload: "upload";
1831
1883
  activate: "activate";
1832
1884
  click: "click";
1833
1885
  select: "select";
@@ -1867,6 +1919,7 @@ declare const InteractionAction_2: z.ZodDiscriminatedUnion<[z.ZodObject<{
1867
1919
  id: z.ZodString;
1868
1920
  kind: z.ZodEnum<{
1869
1921
  fill: "fill";
1922
+ upload: "upload";
1870
1923
  activate: "activate";
1871
1924
  click: "click";
1872
1925
  select: "select";
@@ -1919,6 +1972,7 @@ declare const InteractionCandidate_2: z.ZodObject<{
1919
1972
  id: z.ZodString;
1920
1973
  kind: z.ZodEnum<{
1921
1974
  fill: "fill";
1975
+ upload: "upload";
1922
1976
  activate: "activate";
1923
1977
  click: "click";
1924
1978
  select: "select";
@@ -1955,7 +2009,7 @@ declare const InteractionCandidate_2: z.ZodObject<{
1955
2009
  declare type InteractionCandidate_2 = z.infer<typeof InteractionCandidate_2>;
1956
2010
 
1957
2011
  /** The candidate kinds a driver may offer. */
1958
- export declare type InteractionCandidateKind = "click" | "fill" | "select" | "scroll" | "wait" | "activate" | "press";
2012
+ export declare type InteractionCandidateKind = "click" | "fill" | "upload" | "select" | "scroll" | "wait" | "activate" | "press";
1959
2013
 
1960
2014
  export declare interface InteractionDriver {
1961
2015
  /** Unique in the session. `builtin:` is reserved for Bonsai's own drivers. */
@@ -2017,6 +2071,7 @@ declare const InteractionObservation_2: z.ZodObject<{
2017
2071
  id: z.ZodString;
2018
2072
  kind: z.ZodEnum<{
2019
2073
  fill: "fill";
2074
+ upload: "upload";
2020
2075
  activate: "activate";
2021
2076
  click: "click";
2022
2077
  select: "select";
@@ -3095,8 +3150,19 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
3095
3150
  * text, at most `PLUGIN_SIGNAL_BODY_MAX` (20,000) characters. Gmail puts a mail's text there, so
3096
3151
  * Flows can keep the messages a task came from. Additive: a plugin that publishes a body declares
3097
3152
  * ^0.55.3.
3153
+ *
3154
+ * 0.55.4 adds `app.plugins.listServices()` under the new `plugins.read` claim: every auth service
3155
+ * of the installed, enabled plugins, with the plugin's id and display name and whether the person
3156
+ * has connected it. No account, identity or scope. Built-ins hold the claim; any other plugin needs
3157
+ * a grant. Additive; plugins calling it declare ^0.55.4.
3158
+ *
3159
+ * 0.55.5 adds `app.sessions.readState()` and `writeState()` under the new `sessions.state` claim:
3160
+ * a plugin keeps its own state entries in a session's transcript, stored as `plugin-state:<pluginId>:<name>`,
3161
+ * and each write names the newest entry it was computed from, so a write from a stale base is
3162
+ * answered with the newest one instead of landing (compaction plan, phase 2). Additive; plugins
3163
+ * calling them declare ^0.55.5.
3098
3164
  */
3099
- declare const KAY_PLUGIN_SDK_VERSION: "0.55.3";
3165
+ declare const KAY_PLUGIN_SDK_VERSION: "0.55.5";
3100
3166
 
3101
3167
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
3102
3168
 
@@ -5441,6 +5507,10 @@ declare const PluginCapabilityRefusalV1: z.ZodObject<{
5441
5507
  target: z.ZodLiteral<"kay.app">;
5442
5508
  slug: z.ZodLiteral<"plugins.set-enabled">;
5443
5509
  envelope: z.ZodObject<{}, z.core.$strict>;
5510
+ }, z.core.$strict>, z.ZodObject<{
5511
+ target: z.ZodLiteral<"kay.app">;
5512
+ slug: z.ZodLiteral<"plugins.read">;
5513
+ envelope: z.ZodObject<{}, z.core.$strict>;
5444
5514
  }, z.core.$strict>, z.ZodObject<{
5445
5515
  target: z.ZodLiteral<"kay.app">;
5446
5516
  slug: z.ZodLiteral<"sessions.assign-project">;
@@ -5461,6 +5531,10 @@ declare const PluginCapabilityRefusalV1: z.ZodObject<{
5461
5531
  target: z.ZodLiteral<"kay.app">;
5462
5532
  slug: z.ZodLiteral<"sessions.compact">;
5463
5533
  envelope: z.ZodObject<{}, z.core.$strict>;
5534
+ }, z.core.$strict>, z.ZodObject<{
5535
+ target: z.ZodLiteral<"kay.app">;
5536
+ slug: z.ZodLiteral<"sessions.state">;
5537
+ envelope: z.ZodObject<{}, z.core.$strict>;
5464
5538
  }, z.core.$strict>, z.ZodObject<{
5465
5539
  target: z.ZodLiteral<"kay.app">;
5466
5540
  slug: z.ZodLiteral<"soul.write">;
@@ -2265,6 +2265,21 @@ declare interface KayAppSessions {
2265
2265
  * an allowed compaction failed.
2266
2266
  */
2267
2267
  compact?(sessionId: string): Promise<boolean>;
2268
+ /**
2269
+ * The newest of this plugin's own state entries named `name` in a session (SDK 0.55.5). Checked
2270
+ * against `sessions.state`, for any session. Rejects for a name outside the grammar.
2271
+ */
2272
+ readState?(sessionId: string, name: string): Promise<KayAppSessionStateRead>;
2273
+ /**
2274
+ * Append this plugin's next state entry of `write.name` to a session's transcript, only if the
2275
+ * newest one is still `write.baseEntryId` (SDK 0.55.5). Checked against `sessions.state`, and
2276
+ * bound like {@link annotate}: only for a session whose event one of this plugin's
2277
+ * `sessionEvents` handlers is handling now. On `conflict`, apply the change again to `newest`
2278
+ * and write with its id as the base. Rejects for a name or data outside the bounds; nothing is
2279
+ * written then. The entries are not shown to the agent; a plugin or page that can read the
2280
+ * conversation can read them.
2281
+ */
2282
+ writeState?(sessionId: string, write: KayAppSessionStateWriteInput): Promise<KayAppSessionStateWrite>;
2268
2283
  create?(input: {
2269
2284
  /** Omit to inherit the opener's cwd, unless an explicit project supplies its default. */
2270
2285
  readonly cwd?: string;
@@ -2374,6 +2389,68 @@ declare interface KayAppSessionState {
2374
2389
  };
2375
2390
  }
2376
2391
 
2392
+ /** One of a plugin's own state entries in a session. */
2393
+ declare interface KayAppSessionStateEntry {
2394
+ readonly entryId: string;
2395
+ readonly data: JsonValue_3;
2396
+ }
2397
+
2398
+ /** What {@link KayAppSessions.readState} answers: the newest entry of the name. */
2399
+ declare type KayAppSessionStateRead = ({
2400
+ readonly status: "found";
2401
+ } & KayAppSessionStateEntry) | {
2402
+ readonly status: "none";
2403
+ } | {
2404
+ readonly status: "unavailable";
2405
+ readonly reason: KayAppSessionStateUnavailableReason;
2406
+ };
2407
+
2408
+ /** Why a plugin state entry could not be read or written. Not a refusal of the plugin. */
2409
+ declare type KayAppSessionStateUnavailableReason =
2410
+ /** The session does not exist, or is deleted (in the trash or being purged). */
2411
+ "not_found"
2412
+ /** The session's log could not be read. */
2413
+ | "unreadable"
2414
+ /**
2415
+ * The newest entry of the name lies further back in the log than one bounded read scans (about
2416
+ * 1 GiB of other records). The name cannot be read or written in that session.
2417
+ */
2418
+ | "too_far_back";
2419
+
2420
+ /**
2421
+ * What {@link KayAppSessions.writeState} answers. `conflict`: the newest entry is not the
2422
+ * `baseEntryId`, so nothing was written, and `newest` is what to build on (`null` when there is
2423
+ * none). A write that rejected or timed out may still have landed: reading again then shows it as
2424
+ * the newest entry, and a retry from the old base answers `conflict` with the plugin's own data.
2425
+ */
2426
+ declare type KayAppSessionStateWrite = {
2427
+ readonly status: "written";
2428
+ readonly entryId: string;
2429
+ } | {
2430
+ readonly status: "conflict";
2431
+ readonly newest: KayAppSessionStateEntry | null;
2432
+ } | {
2433
+ readonly status: "unavailable";
2434
+ readonly reason: KayAppSessionStateUnavailableReason;
2435
+ };
2436
+
2437
+ /** One write for {@link KayAppSessions.writeState}. */
2438
+ declare interface KayAppSessionStateWriteInput {
2439
+ /**
2440
+ * The plugin's own name for the entry: lowercase letters, digits and dashes, starting with a
2441
+ * letter, at most 64 characters (`PLUGIN_STATE_ENTRY_NAME_PATTERN`). Stored as
2442
+ * `plugin-state:<pluginId>:<name>`.
2443
+ */
2444
+ readonly name: string;
2445
+ /** The entry id of the newest entry of this name the plugin read, or `null` when it read none. */
2446
+ readonly baseEntryId: string | null;
2447
+ /**
2448
+ * Plain JSON: finite numbers, at most 64 levels deep and 256 KiB serialized
2449
+ * (`PLUGIN_STATE_ENTRY_MAX_BYTES`), no credential-shaped field names.
2450
+ */
2451
+ readonly data: JsonValue_3;
2452
+ }
2453
+
2377
2454
  export declare interface KayAppSessionSummaryChunk {
2378
2455
  readonly goal: string;
2379
2456
  readonly work: readonly string[];
package/dist/kay-app.d.ts CHANGED
@@ -1045,7 +1045,7 @@ declare type AgentRuntimeSessionOutcomeConfidence = z.infer<typeof AgentRuntimeS
1045
1045
 
1046
1046
  /**
1047
1047
  * How a session's work is judged to have served the user (telemetry lane
1048
- * PR 5, `docs/telemetry-lane-pr5-contracts.md` §2.1).
1048
+ * PR 5, `docs/records/telemetry-lane-pr5-contracts.md` §2.1).
1049
1049
  *
1050
1050
  * `"unclear"` is a FIRST-CLASS verdict, not an error code: a judge that cannot
1051
1051
  * tell must say so rather than guess, and the share of `unclear` is itself a
@@ -2645,6 +2645,12 @@ declare interface DerivedToolClassification {
2645
2645
  readonly kind?: ToolActionKind;
2646
2646
  readonly ruleKey?: string;
2647
2647
  readonly scheme?: string;
2648
+ /**
2649
+ * This call needs a person's one-time answer: no allow rule, no mode (allow mode included) and
2650
+ * no automatic approver settles it, and the approval cannot be remembered. Deny rules still
2651
+ * apply. Stricter only, so it grants nothing. The same flag a URI route classification carries.
2652
+ */
2653
+ readonly humanOnly?: true;
2648
2654
  }
2649
2655
 
2650
2656
  declare interface DiagnosticErrorInfo {
@@ -4397,8 +4403,19 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
4397
4403
  * text, at most `PLUGIN_SIGNAL_BODY_MAX` (20,000) characters. Gmail puts a mail's text there, so
4398
4404
  * Flows can keep the messages a task came from. Additive: a plugin that publishes a body declares
4399
4405
  * ^0.55.3.
4406
+ *
4407
+ * 0.55.4 adds `app.plugins.listServices()` under the new `plugins.read` claim: every auth service
4408
+ * of the installed, enabled plugins, with the plugin's id and display name and whether the person
4409
+ * has connected it. No account, identity or scope. Built-ins hold the claim; any other plugin needs
4410
+ * a grant. Additive; plugins calling it declare ^0.55.4.
4411
+ *
4412
+ * 0.55.5 adds `app.sessions.readState()` and `writeState()` under the new `sessions.state` claim:
4413
+ * a plugin keeps its own state entries in a session's transcript, stored as `plugin-state:<pluginId>:<name>`,
4414
+ * and each write names the newest entry it was computed from, so a write from a stale base is
4415
+ * answered with the newest one instead of landing (compaction plan, phase 2). Additive; plugins
4416
+ * calling them declare ^0.55.5.
4400
4417
  */
4401
- declare const KAY_PLUGIN_SDK_VERSION: "0.55.3";
4418
+ declare const KAY_PLUGIN_SDK_VERSION: "0.55.5";
4402
4419
 
4403
4420
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
4404
4421
 
@@ -6736,7 +6753,7 @@ export declare interface KayAppPluginApi {
6736
6753
  * in the daemon process and could walk the disk to find these directories anyway, so withholding
6737
6754
  * the path would buy friction rather than safety. It is not a containment boundary. Expect this
6738
6755
  * posture to tighten if plugin execution is ever isolated (deferred: D1 in
6739
- * `docs/plugins/trust-model-decisions.md`).
6756
+ * `docs/decisions/2026-08-24-plugins-trust-model-decisions.md`).
6740
6757
  */
6741
6758
  readonly paths: KayAppPaths;
6742
6759
  /**
@@ -6912,9 +6929,11 @@ export declare interface KayAppPluginApi {
6912
6929
  */
6913
6930
  readonly soul?: KayAppSoul;
6914
6931
  /**
6915
- * Private API: only plugins Bonsai ships; refused for any other. Turns installed plugins on and
6916
- * off, each call checked against `plugins.set-enabled`. Absent when the host cannot change
6917
- * which plugins run.
6932
+ * The installed plugins. `listServices()` answers each enabled plugin's auth services and whether
6933
+ * each is connected, checked against `plugins.read`. `setEnabled()` is private API (only plugins
6934
+ * Bonsai ships; refused for any other): it turns installed plugins on and off, checked against
6935
+ * `plugins.set-enabled`. Absent when the host composed neither; a method the host did not
6936
+ * compose rejects.
6918
6937
  */
6919
6938
  readonly plugins?: KayAppPlugins;
6920
6939
  /**
@@ -7002,16 +7021,14 @@ export declare interface KayAppPluginEvents {
7002
7021
  }
7003
7022
 
7004
7023
  /**
7005
- * The `kay.app` plugins contract (`app.plugins`): the user's installed plugins.
7006
- */
7007
- /**
7008
- * Private API: only plugins Bonsai ships; refused for any other. Each call is checked against
7009
- * `plugins.set-enabled`. A refused call rejects with an `Error`.
7024
+ * Each method is checked against its own claim at the call. A refused call rejects with an
7025
+ * `Error`.
7010
7026
  */
7011
7027
  export declare interface KayAppPlugins {
7012
7028
  /**
7013
- * Turn an installed plugin on, which starts its code under the grants the user gave it, or off,
7014
- * which stops it. `changed` is false when it was already in that state.
7029
+ * Private API: only plugins Bonsai ships; refused for any other. Checked against
7030
+ * `plugins.set-enabled`. Turn an installed plugin on, which starts its code under the grants the
7031
+ * user gave it, or off, which stops it. `changed` is false when it was already in that state.
7015
7032
  */
7016
7033
  setEnabled(request: {
7017
7034
  readonly pluginId: string;
@@ -7019,6 +7036,34 @@ export declare interface KayAppPlugins {
7019
7036
  }): Promise<{
7020
7037
  readonly changed: boolean;
7021
7038
  }>;
7039
+ /**
7040
+ * Checked against `plugins.read`. Every auth service of the installed, enabled plugins, one row
7041
+ * per service, sorted by plugin name then service id. A plugin with no auth service is not
7042
+ * listed. Never resolves, decrypts, refreshes or calls a provider.
7043
+ */
7044
+ listServices(): Promise<readonly KayAppPluginService[]>;
7045
+ }
7046
+
7047
+ /**
7048
+ * The `kay.app` plugins contract (`app.plugins`): the user's installed plugins.
7049
+ */
7050
+ /**
7051
+ * One auth service an installed, enabled plugin declares, and whether the person has connected
7052
+ * it. Metadata only: no account, identity, scope or credential.
7053
+ */
7054
+ export declare interface KayAppPluginService {
7055
+ /** The plugin that declares the service: `com.kay.integration.ramp`. */
7056
+ readonly pluginId: string;
7057
+ /** The plugin's display name, as the person reads it: `Ramp`. */
7058
+ readonly pluginName: string;
7059
+ /** The service's global id, the one a connect card names: `ramp.account`. */
7060
+ readonly serviceId: string;
7061
+ /**
7062
+ * True when any scheme of the service has a usable account. An account that needs reconnecting
7063
+ * does not count, so a service with only such accounts reads as not connected. Not proof that a
7064
+ * provider call will authenticate.
7065
+ */
7066
+ readonly connected: boolean;
7022
7067
  }
7023
7068
 
7024
7069
  export declare interface KayAppPollerEvent {
@@ -7978,6 +8023,21 @@ export declare interface KayAppSessions {
7978
8023
  * an allowed compaction failed.
7979
8024
  */
7980
8025
  compact?(sessionId: string): Promise<boolean>;
8026
+ /**
8027
+ * The newest of this plugin's own state entries named `name` in a session (SDK 0.55.5). Checked
8028
+ * against `sessions.state`, for any session. Rejects for a name outside the grammar.
8029
+ */
8030
+ readState?(sessionId: string, name: string): Promise<KayAppSessionStateRead>;
8031
+ /**
8032
+ * Append this plugin's next state entry of `write.name` to a session's transcript, only if the
8033
+ * newest one is still `write.baseEntryId` (SDK 0.55.5). Checked against `sessions.state`, and
8034
+ * bound like {@link annotate}: only for a session whose event one of this plugin's
8035
+ * `sessionEvents` handlers is handling now. On `conflict`, apply the change again to `newest`
8036
+ * and write with its id as the base. Rejects for a name or data outside the bounds; nothing is
8037
+ * written then. The entries are not shown to the agent; a plugin or page that can read the
8038
+ * conversation can read them.
8039
+ */
8040
+ writeState?(sessionId: string, write: KayAppSessionStateWriteInput): Promise<KayAppSessionStateWrite>;
7981
8041
  create?(input: {
7982
8042
  /** Omit to inherit the opener's cwd, unless an explicit project supplies its default. */
7983
8043
  readonly cwd?: string;
@@ -8087,6 +8147,68 @@ export declare interface KayAppSessionState {
8087
8147
  };
8088
8148
  }
8089
8149
 
8150
+ /** One of a plugin's own state entries in a session. */
8151
+ export declare interface KayAppSessionStateEntry {
8152
+ readonly entryId: string;
8153
+ readonly data: JsonValue;
8154
+ }
8155
+
8156
+ /** What {@link KayAppSessions.readState} answers: the newest entry of the name. */
8157
+ export declare type KayAppSessionStateRead = ({
8158
+ readonly status: "found";
8159
+ } & KayAppSessionStateEntry) | {
8160
+ readonly status: "none";
8161
+ } | {
8162
+ readonly status: "unavailable";
8163
+ readonly reason: KayAppSessionStateUnavailableReason;
8164
+ };
8165
+
8166
+ /** Why a plugin state entry could not be read or written. Not a refusal of the plugin. */
8167
+ export declare type KayAppSessionStateUnavailableReason =
8168
+ /** The session does not exist, or is deleted (in the trash or being purged). */
8169
+ "not_found"
8170
+ /** The session's log could not be read. */
8171
+ | "unreadable"
8172
+ /**
8173
+ * The newest entry of the name lies further back in the log than one bounded read scans (about
8174
+ * 1 GiB of other records). The name cannot be read or written in that session.
8175
+ */
8176
+ | "too_far_back";
8177
+
8178
+ /**
8179
+ * What {@link KayAppSessions.writeState} answers. `conflict`: the newest entry is not the
8180
+ * `baseEntryId`, so nothing was written, and `newest` is what to build on (`null` when there is
8181
+ * none). A write that rejected or timed out may still have landed: reading again then shows it as
8182
+ * the newest entry, and a retry from the old base answers `conflict` with the plugin's own data.
8183
+ */
8184
+ export declare type KayAppSessionStateWrite = {
8185
+ readonly status: "written";
8186
+ readonly entryId: string;
8187
+ } | {
8188
+ readonly status: "conflict";
8189
+ readonly newest: KayAppSessionStateEntry | null;
8190
+ } | {
8191
+ readonly status: "unavailable";
8192
+ readonly reason: KayAppSessionStateUnavailableReason;
8193
+ };
8194
+
8195
+ /** One write for {@link KayAppSessions.writeState}. */
8196
+ export declare interface KayAppSessionStateWriteInput {
8197
+ /**
8198
+ * The plugin's own name for the entry: lowercase letters, digits and dashes, starting with a
8199
+ * letter, at most 64 characters (`PLUGIN_STATE_ENTRY_NAME_PATTERN`). Stored as
8200
+ * `plugin-state:<pluginId>:<name>`.
8201
+ */
8202
+ readonly name: string;
8203
+ /** The entry id of the newest entry of this name the plugin read, or `null` when it read none. */
8204
+ readonly baseEntryId: string | null;
8205
+ /**
8206
+ * Plain JSON: finite numbers, at most 64 levels deep and 256 KiB serialized
8207
+ * (`PLUGIN_STATE_ENTRY_MAX_BYTES`), no credential-shaped field names.
8208
+ */
8209
+ readonly data: JsonValue;
8210
+ }
8211
+
8090
8212
  /**
8091
8213
  * The durable summary of one session, as a run-detail activity item embeds it
8092
8214
  * (mirror of `AgentRuntimeSessionSummary` in its transformed shape).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaklabs-ai/plugin-sdk",
3
- "version": "0.55.3",
3
+ "version": "0.55.5",
4
4
  "description": "The Kay plugin SDK — types and helpers for authoring a Kay directory plugin.",
5
5
  "author": "YakLabs",
6
6
  "type": "module",
@@ -145,7 +145,7 @@ the plugin (`"./assets/rail.svg"`). Only its shape is used, painted in the rail'
145
145
  in the file are ignored, and it must be transparent where nothing should draw. A missing file is a
146
146
  load diagnostic and the entry falls back to the plugin icon. The page the entry opens wears the same
147
147
  icon. Full
148
- precedence: `packages/kay-frontend-sdk/ARCHITECTURE.md`, "Plugin icon".
148
+ precedence: `packages/kay-renderer/src/renderer/src/shell/contribution-icons.ts`.
149
149
 
150
150
  `ui.tsx` has no `node_modules` of its own. Bonsai compiles it and rewrites its `react` and
151
151
  `@bonsai/plugin-ui-sdk` imports to the host's `__KAY_UI_RUNTIME__` singletons, so the agent `tsconfig.json`