@byok-sdk/protocol 0.30.0 → 0.30.2

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.
@@ -329,15 +329,19 @@ export declare const AgentHomeAccessSchema: z.ZodLiteral<"memory-reader">;
329
329
  export type AgentHomeAccess = z.infer<typeof AgentHomeAccessSchema>;
330
330
  /**
331
331
  * The `agentMemory` of an ordinary Agent offer: the prepared modes plus
332
- * `read-if-admitted`. That value runs as `read` when the daemon admits the
333
- * memory MCP and as `none` when it does not. A host sends it only to a device
334
- * that advertises `agent-memory-read-if-admitted`. Prepared offers refuse it.
332
+ * `read-if-admitted` and `read-write-if-admitted`. When the daemon admits the
333
+ * memory MCP they run as `read` and `read-write`; when it does not, both run as
334
+ * `none`. A host sends each only to a device that advertises
335
+ * `agent-memory-read-if-admitted` or `agent-memory-read-write-if-admitted`. A
336
+ * `memory-reader` Attempt cannot select `read-write-if-admitted`. Prepared
337
+ * offers refuse both.
335
338
  */
336
339
  export declare const AgentMemorySelectionSchema: z.ZodEnum<{
337
340
  none: "none";
338
341
  read: "read";
339
342
  "read-if-admitted": "read-if-admitted";
340
343
  "read-write": "read-write";
344
+ "read-write-if-admitted": "read-write-if-admitted";
341
345
  }>;
342
346
  export type AgentMemorySelection = z.infer<typeof AgentMemorySelectionSchema>;
343
347
  /**
@@ -372,6 +376,7 @@ export declare const TaskOfferForAgentPayloadSchema: z.ZodObject<{
372
376
  read: "read";
373
377
  "read-if-admitted": "read-if-admitted";
374
378
  "read-write": "read-write";
379
+ "read-write-if-admitted": "read-write-if-admitted";
375
380
  }>>;
376
381
  requiredToolsets: z.ZodOptional<z.ZodArray<z.ZodString>>;
377
382
  runtime: z.ZodOptional<z.ZodEnum<{
@@ -447,6 +452,7 @@ export declare const TaskOfferForAgentWithEgressPayloadSchema: z.ZodObject<{
447
452
  read: "read";
448
453
  "read-if-admitted": "read-if-admitted";
449
454
  "read-write": "read-write";
455
+ "read-write-if-admitted": "read-write-if-admitted";
450
456
  }>>;
451
457
  requiredToolsets: z.ZodOptional<z.ZodArray<z.ZodString>>;
452
458
  runtime: z.ZodOptional<z.ZodEnum<{
@@ -559,6 +565,7 @@ export declare const TaskOfferForAgentWithEgressFreshPayloadSchema: z.ZodObject<
559
565
  read: "read";
560
566
  "read-if-admitted": "read-if-admitted";
561
567
  "read-write": "read-write";
568
+ "read-write-if-admitted": "read-write-if-admitted";
562
569
  }>>;
563
570
  requiredToolsets: z.ZodOptional<z.ZodArray<z.ZodString>>;
564
571
  runtime: z.ZodOptional<z.ZodEnum<{
@@ -1718,6 +1725,48 @@ export declare const TaskCompletePayloadSchema: z.ZodObject<{
1718
1725
  }, z.core.$strict>], "outcome">>;
1719
1726
  }, z.core.$strip>;
1720
1727
  export type TaskCompletePayload = z.infer<typeof TaskCompletePayloadSchema>;
1728
+ /** A closed runtime failure class (#869). `unknown` means the runtime gave no structured evidence. */
1729
+ export declare const RuntimeFailureClassSchema: z.ZodEnum<{
1730
+ auth: "auth";
1731
+ billing: "billing";
1732
+ input_too_large: "input_too_large";
1733
+ invalid_request: "invalid_request";
1734
+ limit_reached: "limit_reached";
1735
+ model_unavailable: "model_unavailable";
1736
+ output_schema: "output_schema";
1737
+ overloaded: "overloaded";
1738
+ provider: "provider";
1739
+ quota: "quota";
1740
+ rate_limited: "rate_limited";
1741
+ runtime_exited: "runtime_exited";
1742
+ unknown: "unknown";
1743
+ }>;
1744
+ export type RuntimeFailureClass = z.infer<typeof RuntimeFailureClassSchema>;
1745
+ /**
1746
+ * The machine-readable failure of a `task.fail` (#869); `reason` stays display
1747
+ * text. `resetsAt` (ISO 8601 UTC) exists only on `quota`, and only when the
1748
+ * runtime reported when the limit resets.
1749
+ */
1750
+ export declare const TaskFailureSchema: z.ZodUnion<readonly [z.ZodObject<{
1751
+ class: z.ZodLiteral<"quota">;
1752
+ resetsAt: z.ZodOptional<z.ZodISODateTime>;
1753
+ }, z.core.$strict>, z.ZodObject<{
1754
+ class: z.ZodEnum<{
1755
+ auth: "auth";
1756
+ billing: "billing";
1757
+ input_too_large: "input_too_large";
1758
+ invalid_request: "invalid_request";
1759
+ limit_reached: "limit_reached";
1760
+ model_unavailable: "model_unavailable";
1761
+ output_schema: "output_schema";
1762
+ overloaded: "overloaded";
1763
+ provider: "provider";
1764
+ rate_limited: "rate_limited";
1765
+ runtime_exited: "runtime_exited";
1766
+ unknown: "unknown";
1767
+ }>;
1768
+ }, z.core.$strict>]>;
1769
+ export type TaskFailure = z.infer<typeof TaskFailureSchema>;
1721
1770
  /** daemon -> server: task failed. */
1722
1771
  export declare const TaskFailPayloadSchema: z.ZodObject<{
1723
1772
  sealed: z.ZodOptional<z.ZodNever>;
@@ -1729,6 +1778,25 @@ export declare const TaskFailPayloadSchema: z.ZodObject<{
1729
1778
  harnessId: z.ZodOptional<z.ZodString>;
1730
1779
  reason: z.ZodString;
1731
1780
  retryable: z.ZodOptional<z.ZodBoolean>;
1781
+ failure: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
1782
+ class: z.ZodLiteral<"quota">;
1783
+ resetsAt: z.ZodOptional<z.ZodISODateTime>;
1784
+ }, z.core.$strict>, z.ZodObject<{
1785
+ class: z.ZodEnum<{
1786
+ auth: "auth";
1787
+ billing: "billing";
1788
+ input_too_large: "input_too_large";
1789
+ invalid_request: "invalid_request";
1790
+ limit_reached: "limit_reached";
1791
+ model_unavailable: "model_unavailable";
1792
+ output_schema: "output_schema";
1793
+ overloaded: "overloaded";
1794
+ provider: "provider";
1795
+ rate_limited: "rate_limited";
1796
+ runtime_exited: "runtime_exited";
1797
+ unknown: "unknown";
1798
+ }>;
1799
+ }, z.core.$strict>]>>;
1732
1800
  usage: z.ZodOptional<z.ZodObject<{
1733
1801
  runtime: z.ZodEnum<{
1734
1802
  claude: "claude";
@@ -1839,8 +1907,8 @@ export type TaskCancelledPayload = z.infer<typeof TaskCancelledPayloadSchema>;
1839
1907
  * resolves, `docs/protocol.md`): today the server only learns of a local
1840
1908
  * resolution IMPLICITLY, after the fact, once the daemon's next
1841
1909
  * `task.progress`/`task.artifact`/`task.complete` proves the task already
1842
- * moved on (`ConnectionHub.resumeIfImplicitlyApproved`,
1843
- * `packages/server/src/hub.ts`) — a window in which a SaaS-side
1910
+ * moved on (the `relay.onTaskActivity` hook in
1911
+ * `packages/server/src/index.ts`) — a window in which a SaaS-side
1844
1912
  * `TaskHandle.approve()`/`.reject()` can independently decide (and win) the
1845
1913
  * server's own authoritative record before that evidence ever arrives. This
1846
1914
  * message lets the daemon report the local resolution explicitly and
@@ -2059,6 +2127,7 @@ export declare const TaskOfferForAgentSealedPayloadSchema: z.ZodObject<{
2059
2127
  read: "read";
2060
2128
  "read-if-admitted": "read-if-admitted";
2061
2129
  "read-write": "read-write";
2130
+ "read-write-if-admitted": "read-write-if-admitted";
2062
2131
  }>>;
2063
2132
  requiredToolsets: z.ZodOptional<z.ZodArray<z.ZodString>>;
2064
2133
  runtime: z.ZodOptional<z.ZodEnum<{
@@ -2162,6 +2231,7 @@ export declare const TaskOfferForAgentWithEgressSealedPayloadSchema: z.ZodObject
2162
2231
  read: "read";
2163
2232
  "read-if-admitted": "read-if-admitted";
2164
2233
  "read-write": "read-write";
2234
+ "read-write-if-admitted": "read-write-if-admitted";
2165
2235
  }>>;
2166
2236
  requiredToolsets: z.ZodOptional<z.ZodArray<z.ZodString>>;
2167
2237
  runtime: z.ZodOptional<z.ZodEnum<{
@@ -2304,6 +2374,7 @@ export declare const TaskOfferForAgentWithEgressFreshSealedPayloadSchema: z.ZodO
2304
2374
  read: "read";
2305
2375
  "read-if-admitted": "read-if-admitted";
2306
2376
  "read-write": "read-write";
2377
+ "read-write-if-admitted": "read-write-if-admitted";
2307
2378
  }>>;
2308
2379
  requiredToolsets: z.ZodOptional<z.ZodArray<z.ZodString>>;
2309
2380
  runtime: z.ZodOptional<z.ZodEnum<{
@@ -2549,6 +2620,25 @@ export declare const TaskFailSealedPayloadSchema: z.ZodObject<{
2549
2620
  }, z.core.$strict>>;
2550
2621
  harnessId: z.ZodOptional<z.ZodString>;
2551
2622
  retryable: z.ZodOptional<z.ZodBoolean>;
2623
+ failure: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
2624
+ class: z.ZodLiteral<"quota">;
2625
+ resetsAt: z.ZodOptional<z.ZodISODateTime>;
2626
+ }, z.core.$strict>, z.ZodObject<{
2627
+ class: z.ZodEnum<{
2628
+ auth: "auth";
2629
+ billing: "billing";
2630
+ input_too_large: "input_too_large";
2631
+ invalid_request: "invalid_request";
2632
+ limit_reached: "limit_reached";
2633
+ model_unavailable: "model_unavailable";
2634
+ output_schema: "output_schema";
2635
+ overloaded: "overloaded";
2636
+ provider: "provider";
2637
+ rate_limited: "rate_limited";
2638
+ runtime_exited: "runtime_exited";
2639
+ unknown: "unknown";
2640
+ }>;
2641
+ }, z.core.$strict>]>>;
2552
2642
  usage: z.ZodOptional<z.ZodObject<{
2553
2643
  runtime: z.ZodEnum<{
2554
2644
  claude: "claude";
@@ -2905,12 +2995,12 @@ export declare const MESSAGE_TYPES: MessageType[];
2905
2995
  export declare const SERVER_TO_DAEMON_TYPES: readonly ["conn.ack", "task.offer", "task.offer_with_toolsets", "task.offer_for_agent", "task.offer_for_agent_with_egress", "task.offer_for_agent_with_egress_fresh", "task.offer_prepared", "agent.egress.ack", "agent.message.disposition", "agent.content.read", "agent.home.projection", "agent.input.preparation", "provider.provisioning.available", "agent.memory.intent.available", "task.approve", "task.reject", "task.cancel", "task.steer", "task.offer_sealed", "task.offer_with_toolsets_sealed", "task.offer_for_agent_sealed", "task.offer_for_agent_with_egress_sealed", "task.offer_for_agent_with_egress_fresh_sealed", "task.steer_sealed", "e2ee.key_package.available"];
2906
2996
  /**
2907
2997
  * Message types the daemon sends to the server — the flip side of
2908
- * {@link SERVER_TO_DAEMON_TYPES}. `conn.hello` is deliberately excluded: it's
2909
- * only ever valid as the first frame of a WS handshake (`ws-server.ts`), not
2910
- * as ongoing inbound traffic through `ConnectionHub.handleInbound`.
2998
+ * {@link SERVER_TO_DAEMON_TYPES}. `conn.hello` is deliberately excluded: the
2999
+ * inbound gate handles a bearer-authenticated `conn.hello` as a capability
3000
+ * snapshot on its own, before the type-allow check.
2911
3001
  *
2912
- * Used by `handleInbound` (`@byok-sdk/server`'s `hub.ts`) as the type-allow gate
2913
- * for every inbound envelope, WS and `POST /byok/messages` alike (finding
3002
+ * Used by `handleInboundEnvelope` (`@byok-sdk/cloud`'s `inbound.ts`) as the
3003
+ * type-allow gate for every inbound `POST /byok/messages` envelope (finding
2914
3004
  * P2): a `type` outside this set — a server -> daemon type arriving inbound,
2915
3005
  * or anything unrecognized — is rejected before it's dispatched to any
2916
3006
  * handler or counted `accepted` on the `/byok/messages` wire.
@@ -58,6 +58,12 @@ export interface SealedSplitEntry {
58
58
  readonly limits?: {
59
59
  readonly [field: string]: number;
60
60
  };
61
+ /**
62
+ * The sealed form carries inline ciphertext only, never `ciphertextRef`
63
+ * (decision 12e). The Host keeps it in a tail row that expires, so it holds
64
+ * no blob for it. The schema does not check this; the Host and the device do.
65
+ */
66
+ readonly inlineOnly?: true;
61
67
  }
62
68
  /**
63
69
  * The split table (design §8.3): each sealed message type, the plaintext type
@@ -146,6 +152,7 @@ export declare const SEALED_SPLIT_TABLE: Readonly<{
146
152
  readonly digests: {
147
153
  readonly 'events[].spill.blob.contentHash': 'sealed';
148
154
  };
155
+ readonly inlineOnly: true;
149
156
  };
150
157
  readonly 'task.artifact_sealed': {
151
158
  readonly plainType: 'task.artifact';
@@ -167,6 +174,7 @@ export declare const SEALED_SPLIT_TABLE: Readonly<{
167
174
  readonly moved: readonly ["summary"];
168
175
  readonly forbidden: readonly [];
169
176
  readonly digests: {};
177
+ readonly inlineOnly: true;
170
178
  };
171
179
  }>;
172
180
  export type SealedMessageType = keyof typeof SEALED_SPLIT_TABLE;
package/dist/version.d.ts CHANGED
@@ -43,9 +43,10 @@ export declare const STRICT_AGENT_ONLY_CAPABILITY: 'strict-agent-only';
43
43
  */
44
44
  export declare const AGENT_HOME_READERS_CAPABILITY: 'agent-home-readers';
45
45
  /**
46
- * Capability flags exchanged during the connection handshake (`conn.hello` /
47
- * `conn.ack`). Additional flags may be introduced without a protocol version
48
- * bump; unrecognized flags must be ignored by both sides.
46
+ * Capability flags. The daemon sends its flags in `conn.hello`; the server
47
+ * sends its own on every long-poll response (`EventsPollResponse`). Additional
48
+ * flags may be introduced without a protocol version bump; unrecognized flags
49
+ * must be ignored by both sides.
49
50
  *
50
51
  * `interactive-approval` is RESERVED as of this addition: it gates the
51
52
  * (currently unexercised) approval seam — a server must not route an
@@ -56,11 +57,10 @@ export declare const AGENT_HOME_READERS_CAPABILITY: 'agent-home-readers';
56
57
  * `approval_resolved` (additive-minor): a SERVER-advertised flag meaning
57
58
  * "I understand the `task.approval_resolved` message" (`messages.ts`). This
58
59
  * is the N/N-1 answer for that new daemon -> server message: an old server's
59
- * `CAPABILITY_FLAGS`/`conn.ack.capabilities` never includes it, so a new
60
- * daemon talking to an old server never sends `task.approval_resolved` at
61
- * all (see `packages/client`'s `task-runner.ts`) and falls back to the
62
- * pre-existing implicit-resume inference
63
- * (`ConnectionHub.resumeIfImplicitlyApproved`, `packages/server/src/hub.ts`)
60
+ * advertised capabilities never include it, so a new daemon talking to an old
61
+ * server never sends `task.approval_resolved` at all (see `packages/client`'s
62
+ * `task-runner.ts`) and falls back to the pre-existing implicit-resume inference
63
+ * (the `relay.onTaskActivity` hook in `packages/server/src/index.ts`)
64
64
  * unconditionally, exactly as before this flag existed. Unlike
65
65
  * `interactive-approval`, this one IS exercised the moment both sides
66
66
  * support it — there is no reserved/dormant period for it.
@@ -77,13 +77,14 @@ export declare const AGENT_HOME_READERS_CAPABILITY: 'agent-home-readers';
77
77
  * by FIELD PRESENCE on the specific message at hand (does this particular
78
78
  * `task.approve`/`task.reject`/`onApprovalResolved` payload carry an
79
79
  * `approvalId`, and does a stored one exist to compare it against?), never
80
- * by checking this flag -- see `ConnectionHub.approveTask`/`rejectTask`/
81
- * `onApprovalResolved` and `TaskRunner.handleApprove`/`handleReject`
82
- * (`packages/client`'s `task-runner.ts`). This flag exists only so each side
83
- * can advertise, and an embedder/operator can observe (`ConnectionHub.
84
- * getDeviceCapabilities`), whether the OTHER side is new enough to
85
- * participate in targeting at all -- the same N/N-1-safe shape as every
86
- * other flag here, just consumed for observability instead of gating.
80
+ * by checking this flag -- see `approveTask`/`rejectTask` (`@byok-sdk/cloud`)
81
+ * and `TaskRunner.handleApprove`/`handleReject` (`packages/client`'s
82
+ * `task-runner.ts`). This flag exists only so each side can advertise
83
+ * whether the OTHER side is new enough to participate in targeting at all (an
84
+ * embedder could observe it through the old
85
+ * reference server's `ConnectionHub.getDeviceCapabilities`; `@byok-sdk/server`
86
+ * now reads it only internally) -- the same N/N-1-safe shape as every other
87
+ * flag here, just consumed for observability instead of gating.
87
88
  */
88
89
  /**
89
90
  * `dispatch-selection` (additive-minor) is a correctness gate for the
@@ -100,5 +101,5 @@ export declare const AGENT_HOME_READERS_CAPABILITY: 'agent-home-readers';
100
101
  * cannot accidentally execute the instruction without the required tools.
101
102
  */
102
103
  export declare const CUSTOM_HARNESS_CAPABILITY: 'custom-harness';
103
- export declare const CAPABILITY_FLAGS: readonly ['steer', 'blob-upload', 'interactive-approval', 'approval_resolved', 'approval-targeting', 'dispatch-selection', "provider-profile-binding", 'toolset-selection', 'agent-home-contract', "agent-home-readers", "strict-agent-only", "agent-egress-policy", "agent-egress-reliable-ack", "agent-message-egress", "agent-egress-fresh-session", "agent-content-workspace-read", "agent-content-transcript-read", "agent-content-artifact-read", "agent-home-projection", "agent-input-preparation-v9", "terminal-projection-selection", "host-mcp-task-context", "custom-harness", "mailbox-read-ahead", "provider-provisioning.v1", "agent-memory-intent.v1", "agent-memory-selection", "agent-memory-read-if-admitted", 'agent-message-draft', "sealed-payload-v1"];
104
+ export declare const CAPABILITY_FLAGS: readonly ['steer', 'blob-upload', 'interactive-approval', 'approval_resolved', 'approval-targeting', 'dispatch-selection', "provider-profile-binding", 'toolset-selection', 'agent-home-contract', "agent-home-readers", "strict-agent-only", "agent-egress-policy", "agent-egress-reliable-ack", "agent-message-egress", "agent-egress-fresh-session", "agent-content-workspace-read", "agent-content-transcript-read", "agent-content-artifact-read", "agent-home-projection", "agent-input-preparation-v9", "terminal-projection-selection", "host-mcp-task-context", "custom-harness", "mailbox-read-ahead", "provider-provisioning.v1", "agent-memory-intent.v1", "agent-memory-selection", "agent-memory-read-if-admitted", "agent-memory-read-write-if-admitted", 'agent-message-draft', "sealed-payload-v1", "sealed-output-ciphertext-ref", "runtime-failure-class"];
104
105
  export type CapabilityFlag = (typeof CAPABILITY_FLAGS)[number];
@@ -8,7 +8,8 @@
8
8
  *
9
9
  * - `gated`: the sender must not emit the surface unless the receiver
10
10
  * durably advertised `capability`. A field entry applies when the payload
11
- * carries the field (and, with `value`, when the field equals it); a type
11
+ * carries the field (and, with `value`, when the field equals it); a
12
+ * dotted field names a nested field, for example `sealed.ciphertextRef`. A type
12
13
  * entry applies to every message of that type. Server-to-daemon surfaces
13
14
  * are gated by a device flag, daemon-to-server surfaces by a server flag.
14
15
  * - `strip-safe`: an optional field an older receiver drops without changing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byok-sdk/protocol",
3
- "version": "0.30.0",
3
+ "version": "0.30.2",
4
4
  "description": "BYOK SDK wire protocol: envelope schema, message types, and codec helpers",
5
5
  "type": "module",
6
6
  "license": "MIT",