@byok-sdk/protocol 0.30.1 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/agent-event.d.ts +2 -6
- package/dist/codec.d.ts +10 -86
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +2 -114
- package/dist/constants.js.map +1 -1
- package/dist/e2ee-member.d.ts +31 -3
- package/dist/envelope.d.ts +1 -1
- package/dist/http-api.d.ts +2 -2
- package/dist/index.d.ts +6 -7
- package/dist/index.js +3 -3037
- package/dist/index.js.map +1 -1
- package/dist/input-preparation.d.ts +1 -1
- package/dist/messages.d.ts +992 -1275
- package/dist/sealed-payload.d.ts +16 -14
- package/dist/sealed-split-table.d.ts +61 -55
- package/dist/version.d.ts +26 -57
- package/dist/wire-additions.d.ts +10 -6
- package/package.json +2 -3
package/dist/sealed-payload.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sealed payload v1 on the hosted wire (#654 design §8.1, §8.3, §8.6).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* sealed
|
|
4
|
+
* Sealed is a property of the payload, not a message type: each sealable
|
|
5
|
+
* type's payload is a plaintext branch or a sealed branch. The sealed branch is
|
|
6
|
+
* the plaintext fields without the ones one data category moves into the
|
|
7
|
+
* ciphertext, plus a sealed member; its marker field is gated on
|
|
8
|
+
* `sealed-payload-v1`, and the payload is strict, so a decoder that does not
|
|
9
|
+
* know the branch refuses the whole message. The Host reads only the sealed
|
|
10
|
+
* member's outer fields. It checks the shape here:
|
|
9
11
|
* version, suite, encodings, a legal padded length, and exactly one of inline
|
|
10
12
|
* `ciphertext` and `ciphertextRef`. Inline is the only legal form up to
|
|
11
13
|
* {@link SEALED_INLINE_MAX_PADDED_LENGTH}; above it, the ciphertext is a blob.
|
|
@@ -17,8 +19,8 @@
|
|
|
17
19
|
* length function; a cross-package test keeps the two equal.
|
|
18
20
|
*/
|
|
19
21
|
import { z } from 'zod';
|
|
20
|
-
export { SEALED_SPLIT_TABLE,
|
|
21
|
-
export type {
|
|
22
|
+
export { SEALED_SPLIT_TABLE, isSealableMessageType, isSealedPayload } from './sealed-split-table';
|
|
23
|
+
export type { SealableMessageType, SealedDigestRule, SealedSplitEntry } from './sealed-split-table';
|
|
22
24
|
export declare const SEALED_PAYLOAD_VERSION = 1;
|
|
23
25
|
/** The only suite v1 admits. A new suite is a new constant and a new capability, never a parser branch. */
|
|
24
26
|
export declare const SEALED_PAYLOAD_SUITE = "byok-sealed-v1.hkdf-sha256.aes-256-gcm";
|
|
@@ -41,10 +43,10 @@ export declare const SEALED_DECLINE_CODES: readonly ['sealed_key_unavailable', '
|
|
|
41
43
|
export type SealedDeclineCode = (typeof SEALED_DECLINE_CODES)[number];
|
|
42
44
|
/**
|
|
43
45
|
* The closed plaintext codes of a task whose output is sealed (#654 12d).
|
|
44
|
-
* It lists each
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
46
|
+
* It lists each output type that has a plaintext form on such a task, with
|
|
47
|
+
* the codes that each field moved or dropped by its sealed branch may hold.
|
|
48
|
+
* Such a field that is not listed here must be absent. An output type with a
|
|
49
|
+
* sealed branch that is not listed has no plaintext form. An
|
|
48
50
|
* interrupted task reports `daemon_interrupted`; a device that cannot seal
|
|
49
51
|
* reports `sealed_key_unavailable`. The Host check, the daemon and the member
|
|
50
52
|
* display read this one list, and compare by exact match.
|
|
@@ -62,11 +64,11 @@ export declare const SEALED_TASK_PLAIN_CODES: Readonly<{
|
|
|
62
64
|
}>;
|
|
63
65
|
/**
|
|
64
66
|
* True when `payload` is a legal plaintext `type` message of a task whose
|
|
65
|
-
* output is sealed: each field that
|
|
67
|
+
* output is sealed: each field that the `task-output` sealed branch of `type`
|
|
66
68
|
* moves or drops is absent or holds one of {@link SEALED_TASK_PLAIN_CODES}.
|
|
67
|
-
* A type that has a sealed output
|
|
69
|
+
* A type that has a sealed output branch and is not listed there is never
|
|
68
70
|
* legal. A plaintext decline also names its code as `code`. A type with no
|
|
69
|
-
* sealed output
|
|
71
|
+
* sealed output branch is always legal.
|
|
70
72
|
*/
|
|
71
73
|
export declare function isSealedTaskPlainOutput(type: string, payload: object): boolean;
|
|
72
74
|
/** Padded frames above this length travel as a ciphertext blob (§8.6). */
|
|
@@ -1,49 +1,41 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The split table of sealed payload v1 (#654 design §8.1, §9.3): for each
|
|
3
|
-
* sealed message type, its plaintext type, its data category, its identity
|
|
4
|
-
* fields, the fields that move into the ciphertext, the fields it drops, and
|
|
5
|
-
* the rule of each digest field (D16).
|
|
6
|
-
*
|
|
7
|
-
* Plain data with no runtime imports, so `wire-additions.ts` can derive the
|
|
8
|
-
* sealed gates from it and stay free of zod.
|
|
9
|
-
*/
|
|
10
|
-
import type { MessageType } from './messages';
|
|
11
1
|
import type { SealedPayloadV1Category } from './sealed-payload';
|
|
12
2
|
/**
|
|
13
|
-
* How
|
|
14
|
-
* (D16, design §9.3).
|
|
3
|
+
* How the sealed branch of a type treats one digest field of its plaintext
|
|
4
|
+
* branch (D16, design §9.3).
|
|
15
5
|
*
|
|
16
6
|
* - `ciphertext-sha256`: the SHA-256 of the sealed bytes, for a Host that
|
|
17
7
|
* checks the bytes it stores (a ciphertext blob).
|
|
18
8
|
* - `keyed-mac`: a keyed MAC under the scope's MAC key; the Host forwards it.
|
|
19
9
|
* - `sealed`: the field moves into the ciphertext with its parent.
|
|
20
10
|
* - `plain`: a digest that no sealed content derives, kept in plaintext.
|
|
21
|
-
* - `forbidden`: the sealed
|
|
11
|
+
* - `forbidden`: the sealed branch does not carry it in v1.
|
|
22
12
|
*/
|
|
23
13
|
export type SealedDigestRule = 'ciphertext-sha256' | 'keyed-mac' | 'sealed' | 'plain' | 'forbidden';
|
|
24
|
-
/** One
|
|
14
|
+
/** One sealable message type in the split table. */
|
|
25
15
|
export interface SealedSplitEntry {
|
|
26
16
|
/**
|
|
27
|
-
* The
|
|
28
|
-
*
|
|
17
|
+
* The payload field whose presence marks the sealed branch: `sealing` (the
|
|
18
|
+
* task's sealing policy) on `task.offer`, whose task may seal only its
|
|
19
|
+
* output and so carry no `sealed` member; `sealed` everywhere else. The AAD
|
|
20
|
+
* and the content MAC bind the wire type as the family.
|
|
29
21
|
*/
|
|
30
|
-
readonly
|
|
22
|
+
readonly marker: 'sealing' | 'sealed';
|
|
31
23
|
readonly category: SealedPayloadV1Category;
|
|
32
24
|
/**
|
|
33
25
|
* Payload fields that, after the envelope `task_id`, name this write in the
|
|
34
|
-
* AAD and the content MAC (§8.2, §9.1). The sealed
|
|
26
|
+
* AAD and the content MAC (§8.2, §9.1). The sealed branch requires them.
|
|
35
27
|
*/
|
|
36
28
|
readonly identity: readonly string[];
|
|
37
29
|
/**
|
|
38
|
-
* Top-level fields of the plaintext
|
|
39
|
-
* The sealed
|
|
40
|
-
* object back and validates the plaintext
|
|
30
|
+
* Top-level fields of the plaintext branch that move into the ciphertext.
|
|
31
|
+
* The sealed branch does not have them; the receiver merges the opened
|
|
32
|
+
* object back and validates the plaintext branch.
|
|
41
33
|
*/
|
|
42
34
|
readonly moved: readonly string[];
|
|
43
|
-
/** Top-level fields of the plaintext
|
|
35
|
+
/** Top-level fields of the plaintext branch that the sealed branch drops in v1. */
|
|
44
36
|
readonly forbidden: readonly string[];
|
|
45
37
|
/**
|
|
46
|
-
* Every path of the plaintext
|
|
38
|
+
* Every path of the plaintext branch whose name contains `digest`, `hash` or
|
|
47
39
|
* `revision` (case-insensitive), with its rule. A schema test keeps this
|
|
48
40
|
* complete.
|
|
49
41
|
*/
|
|
@@ -51,7 +43,7 @@ export interface SealedSplitEntry {
|
|
|
51
43
|
readonly [path: string]: SealedDigestRule;
|
|
52
44
|
};
|
|
53
45
|
/**
|
|
54
|
-
* UTF-8 byte limits of moved fields that replace the plaintext
|
|
46
|
+
* UTF-8 byte limits of moved fields that replace the plaintext branch's limit
|
|
55
47
|
* of that field after the merge (decision 12b). The category limit still
|
|
56
48
|
* bounds the whole opened content.
|
|
57
49
|
*/
|
|
@@ -66,36 +58,47 @@ export interface SealedSplitEntry {
|
|
|
66
58
|
readonly inlineOnly?: true;
|
|
67
59
|
}
|
|
68
60
|
/**
|
|
69
|
-
* The split table (design §8.3): each
|
|
70
|
-
*
|
|
71
|
-
* of each digest field. It is the one authority; the schemas, the
|
|
72
|
-
* comparison projection and the receiver's merge read it.
|
|
61
|
+
* The split table (design §8.3): each sealable message type, the marker of its
|
|
62
|
+
* sealed branch, its category, identity, moved and forbidden fields, and the
|
|
63
|
+
* rule of each digest field. It is the one authority; the schemas, the gates,
|
|
64
|
+
* the Host's comparison projection and the receiver's merge read it.
|
|
73
65
|
*
|
|
74
|
-
* A sealed offer
|
|
75
|
-
*
|
|
76
|
-
*
|
|
66
|
+
* A sealed offer carries the task's `sealing`. When the categories include
|
|
67
|
+
* `task-input`, `instruction` is sealed; otherwise it stays plaintext and only
|
|
68
|
+
* the task output is sealed. A prepared Execution is never sealed.
|
|
77
69
|
*
|
|
78
|
-
* Blob bytes have no sealing rule yet, so a sealed
|
|
70
|
+
* Blob bytes have no sealing rule yet, so a sealed branch carries no plaintext
|
|
79
71
|
* blob reference: `artifactRefs` and the artifact `blobRef` are dropped until
|
|
80
72
|
* that rule exists. A sealed artifact is inline content, so its `inline`
|
|
81
73
|
* takes up to 2 MiB instead of the plaintext 64 KB (decision 12b).
|
|
82
74
|
*/
|
|
83
75
|
export declare const SEALED_SPLIT_TABLE: Readonly<{
|
|
84
|
-
readonly 'task.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
readonly
|
|
76
|
+
readonly 'task.offer': {
|
|
77
|
+
readonly marker: 'sealing';
|
|
78
|
+
readonly category: 'task-input';
|
|
79
|
+
readonly identity: readonly [];
|
|
80
|
+
readonly moved: readonly ["instruction"];
|
|
81
|
+
readonly forbidden: readonly ["preparation"];
|
|
82
|
+
readonly digests: {
|
|
83
|
+
readonly 'instruction.blobRef.contentHash': 'sealed';
|
|
84
|
+
readonly 'agentRef.profileRevision': 'plain';
|
|
85
|
+
readonly 'dispatchSelection.providerProfile.profileRevision': 'plain';
|
|
86
|
+
readonly 'dispatchSelection.providerProfile.profileHash': 'plain';
|
|
87
|
+
readonly 'egressPolicy.policyRevision': 'plain';
|
|
88
|
+
readonly 'preparation.requestDigest': 'forbidden';
|
|
89
|
+
readonly 'preparation.artifactDigest': 'forbidden';
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
readonly 'task.steer': {
|
|
93
|
+
readonly marker: 'sealed';
|
|
91
94
|
readonly category: 'task-input';
|
|
92
95
|
readonly identity: readonly ["steerId"];
|
|
93
96
|
readonly moved: readonly ["text"];
|
|
94
97
|
readonly forbidden: readonly [];
|
|
95
98
|
readonly digests: {};
|
|
96
99
|
};
|
|
97
|
-
readonly 'task.
|
|
98
|
-
readonly
|
|
100
|
+
readonly 'task.complete': {
|
|
101
|
+
readonly marker: 'sealed';
|
|
99
102
|
readonly category: 'task-output';
|
|
100
103
|
readonly identity: readonly [];
|
|
101
104
|
readonly moved: readonly ["summary", "finalMessage", "document"];
|
|
@@ -108,8 +111,8 @@ export declare const SEALED_SPLIT_TABLE: Readonly<{
|
|
|
108
111
|
readonly 'preparedObservation.requestDigest': 'forbidden';
|
|
109
112
|
};
|
|
110
113
|
};
|
|
111
|
-
readonly 'task.
|
|
112
|
-
readonly
|
|
114
|
+
readonly 'task.fail': {
|
|
115
|
+
readonly marker: 'sealed';
|
|
113
116
|
readonly category: 'task-output';
|
|
114
117
|
readonly identity: readonly [];
|
|
115
118
|
readonly moved: readonly ["reason"];
|
|
@@ -121,8 +124,8 @@ export declare const SEALED_SPLIT_TABLE: Readonly<{
|
|
|
121
124
|
readonly 'preparedObservation.requestDigest': 'forbidden';
|
|
122
125
|
};
|
|
123
126
|
};
|
|
124
|
-
readonly 'task.
|
|
125
|
-
readonly
|
|
127
|
+
readonly 'task.decline': {
|
|
128
|
+
readonly marker: 'sealed';
|
|
126
129
|
readonly category: 'task-output';
|
|
127
130
|
readonly identity: readonly [];
|
|
128
131
|
readonly moved: readonly ["reason"];
|
|
@@ -131,8 +134,8 @@ export declare const SEALED_SPLIT_TABLE: Readonly<{
|
|
|
131
134
|
readonly 'agentRef.profileRevision': 'plain';
|
|
132
135
|
};
|
|
133
136
|
};
|
|
134
|
-
readonly 'task.
|
|
135
|
-
readonly
|
|
137
|
+
readonly 'task.cancelled': {
|
|
138
|
+
readonly marker: 'sealed';
|
|
136
139
|
readonly category: 'task-output';
|
|
137
140
|
readonly identity: readonly [];
|
|
138
141
|
readonly moved: readonly ["reason"];
|
|
@@ -143,8 +146,8 @@ export declare const SEALED_SPLIT_TABLE: Readonly<{
|
|
|
143
146
|
readonly 'agentHomeProjection.projectionHash': 'plain';
|
|
144
147
|
};
|
|
145
148
|
};
|
|
146
|
-
readonly 'task.
|
|
147
|
-
readonly
|
|
149
|
+
readonly 'task.progress': {
|
|
150
|
+
readonly marker: 'sealed';
|
|
148
151
|
readonly category: 'task-output';
|
|
149
152
|
readonly identity: readonly ["seq"];
|
|
150
153
|
readonly moved: readonly ["events"];
|
|
@@ -154,8 +157,8 @@ export declare const SEALED_SPLIT_TABLE: Readonly<{
|
|
|
154
157
|
};
|
|
155
158
|
readonly inlineOnly: true;
|
|
156
159
|
};
|
|
157
|
-
readonly 'task.
|
|
158
|
-
readonly
|
|
160
|
+
readonly 'task.artifact': {
|
|
161
|
+
readonly marker: 'sealed';
|
|
159
162
|
readonly category: 'task-output';
|
|
160
163
|
readonly identity: readonly ["artifactId"];
|
|
161
164
|
readonly moved: readonly ["inline"];
|
|
@@ -167,8 +170,8 @@ export declare const SEALED_SPLIT_TABLE: Readonly<{
|
|
|
167
170
|
readonly inline: number;
|
|
168
171
|
};
|
|
169
172
|
};
|
|
170
|
-
readonly 'task.
|
|
171
|
-
readonly
|
|
173
|
+
readonly 'task.await_approval': {
|
|
174
|
+
readonly marker: 'sealed';
|
|
172
175
|
readonly category: 'task-output';
|
|
173
176
|
readonly identity: readonly ["approvalId"];
|
|
174
177
|
readonly moved: readonly ["summary"];
|
|
@@ -177,5 +180,8 @@ export declare const SEALED_SPLIT_TABLE: Readonly<{
|
|
|
177
180
|
readonly inlineOnly: true;
|
|
178
181
|
};
|
|
179
182
|
}>;
|
|
180
|
-
|
|
181
|
-
export
|
|
183
|
+
/** A message type with a sealed branch. */
|
|
184
|
+
export type SealableMessageType = keyof typeof SEALED_SPLIT_TABLE;
|
|
185
|
+
export declare function isSealableMessageType(type: string): type is SealableMessageType;
|
|
186
|
+
/** Whether a `type` payload takes its sealed branch: it carries the type's marker field. */
|
|
187
|
+
export declare function isSealedPayload(type: string, payload: unknown): boolean;
|
package/dist/version.d.ts
CHANGED
|
@@ -2,14 +2,25 @@
|
|
|
2
2
|
export declare const MAILBOX_READ_AHEAD_MAX_SEQS = 4096;
|
|
3
3
|
export declare const MAILBOX_READ_AHEAD_CAPABILITY = "mailbox-read-ahead";
|
|
4
4
|
/**
|
|
5
|
-
* Wire protocol version. Every
|
|
5
|
+
* Wire protocol version. Every v4 change is a version bump, a gated addition
|
|
6
6
|
* or a strip-safe addition: see docs/protocol.md "Freeze rule", which is the
|
|
7
7
|
* one statement of the rule, and `src/wire-additions.ts`, which declares the
|
|
8
|
-
* receiver-capability gates and additions. No
|
|
9
|
-
* yet, so `src/__tests__/compat.test.ts` has no published
|
|
8
|
+
* receiver-capability gates and additions. No v4 release has been published
|
|
9
|
+
* yet, so `src/__tests__/compat.test.ts` has no published v4 decoder to prove
|
|
10
10
|
* additions against; cross-release gates stay unproven until one exists.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* v4 completes the ADR-034 cutover and retires the approval paths kept for
|
|
13
|
+
* pre-M5 peers. It removes the v3 handshake answer, the runtime-only offers
|
|
14
|
+
* (with and without toolsets) with their sealed twins, and the
|
|
15
|
+
* `strict-agent-only` flag: every offer is Agent-bound. `approvalId` is
|
|
16
|
+
* required on `task.await_approval`, `task.approve` and `task.reject`, so a
|
|
17
|
+
* decision resolves only the approval it names. `task.approval_resolved` is
|
|
18
|
+
* baseline: the daemon reports every locally resolved approval, and the
|
|
19
|
+
* server no longer infers one from later task activity. The three approval
|
|
20
|
+
* capability flags of v3 are gone. A v3 envelope is rejected; there is no v3 reader. Drain, then
|
|
21
|
+
* upgrade server and client together.
|
|
22
|
+
*
|
|
23
|
+
* v3 made `schema` required on the `terminalProjection.mode:
|
|
13
24
|
* 'result-document'` arm (`terminal-projection.ts`, `result-schema.ts`): the
|
|
14
25
|
* offer freezes the outcome schema, and the outcome reaches the Host only as
|
|
15
26
|
* `task.complete.document`. That narrows a strict shape, so it is a wire
|
|
@@ -31,9 +42,7 @@ export declare const MAILBOX_READ_AHEAD_CAPABILITY = "mailbox-read-ahead";
|
|
|
31
42
|
* attest tool executables. The artifact names its counted tools in
|
|
32
43
|
* `toolNames`.
|
|
33
44
|
*/
|
|
34
|
-
export declare const PROTOCOL_VERSION =
|
|
35
|
-
/** Host declares that this device accepts only Agent-bound offer variants. */
|
|
36
|
-
export declare const STRICT_AGENT_ONLY_CAPABILITY: 'strict-agent-only';
|
|
45
|
+
export declare const PROTOCOL_VERSION = 4;
|
|
37
46
|
/**
|
|
38
47
|
* The device runs `homeAccess: 'memory-reader'` Agent offers: each reader
|
|
39
48
|
* Attempt gets its own run directory under the Agent home, and readers are
|
|
@@ -43,62 +52,22 @@ export declare const STRICT_AGENT_ONLY_CAPABILITY: 'strict-agent-only';
|
|
|
43
52
|
*/
|
|
44
53
|
export declare const AGENT_HOME_READERS_CAPABILITY: 'agent-home-readers';
|
|
45
54
|
/**
|
|
46
|
-
* Capability flags
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* `interactive-approval` is RESERVED as of this addition: it gates the
|
|
51
|
-
* (currently unexercised) approval seam — a server must not route an
|
|
52
|
-
* approval-requiring policy to a daemon that hasn't advertised this flag. No
|
|
53
|
-
* bundled runtime adapter emits it yet; that's expected until interactive
|
|
54
|
-
* approval is actually wired up in a later wave.
|
|
55
|
+
* Capability flags. The daemon sends its flags in `conn.hello`; the server
|
|
56
|
+
* sends its own on every long-poll response (`EventsPollResponse`). Additional
|
|
57
|
+
* flags may be introduced without a protocol version bump; unrecognized flags
|
|
58
|
+
* must be ignored by both sides.
|
|
55
59
|
*
|
|
56
|
-
* `approval_resolved` (additive-minor): a SERVER-advertised flag meaning
|
|
57
|
-
* "I understand the `task.approval_resolved` message" (`messages.ts`). This
|
|
58
|
-
* 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`)
|
|
64
|
-
* unconditionally, exactly as before this flag existed. Unlike
|
|
65
|
-
* `interactive-approval`, this one IS exercised the moment both sides
|
|
66
|
-
* support it — there is no reserved/dormant period for it.
|
|
67
|
-
*/
|
|
68
|
-
/**
|
|
69
|
-
* `approval-targeting` (M5, additive-minor): unlike `approval_resolved`
|
|
70
|
-
* above, this flag is purely INFORMATIONAL/semantic, not a functional gate.
|
|
71
|
-
* `task.await_approval`/`task.approve`/`task.reject` all carry their new
|
|
72
|
-
* `approvalId` field UNCONDITIONALLY on both sides once each peer is
|
|
73
|
-
* upgraded -- the wire is tolerant (a plain, non-`.strict()` `z.object()`
|
|
74
|
-
* field, `messages.ts`), so no version/capability negotiation is needed just
|
|
75
|
-
* to send it safely; an older peer that doesn't recognize the field simply
|
|
76
|
-
* never reads it. Receivers decide whether to apply exact-match targeting
|
|
77
|
-
* by FIELD PRESENCE on the specific message at hand (does this particular
|
|
78
|
-
* `task.approve`/`task.reject`/`onApprovalResolved` payload carry an
|
|
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.
|
|
87
|
-
*/
|
|
88
|
-
/**
|
|
89
60
|
* `dispatch-selection` (additive-minor) is a correctness gate for the
|
|
90
|
-
* optional `
|
|
61
|
+
* optional offer `dispatchSelection` control field. An older v1 daemon
|
|
91
62
|
* legally strips unknown optional fields, so a server must never send an
|
|
92
63
|
* authoritative provider/model selection unless the target connection
|
|
93
64
|
* advertises this flag. Absence means reject before task creation, not send
|
|
94
|
-
*
|
|
65
|
+
* an offer that could reach a different provider.
|
|
95
66
|
*
|
|
96
|
-
* `toolset-selection` (additive-minor) means the daemon understands
|
|
97
|
-
* `
|
|
98
|
-
* MCP configuration.
|
|
99
|
-
* boundary for long-poll: an older daemon skips it as unknown and therefore
|
|
100
|
-
* cannot accidentally execute the instruction without the required tools.
|
|
67
|
+
* `toolset-selection` (additive-minor) means the daemon understands an
|
|
68
|
+
* offer's `requiredToolsets` and can resolve its logical ids against local
|
|
69
|
+
* MCP configuration.
|
|
101
70
|
*/
|
|
102
71
|
export declare const CUSTOM_HARNESS_CAPABILITY: 'custom-harness';
|
|
103
|
-
export declare const CAPABILITY_FLAGS: readonly ['steer', 'blob-upload', '
|
|
72
|
+
export declare const CAPABILITY_FLAGS: readonly ['steer', 'blob-upload', 'dispatch-selection', "provider-profile-binding", 'toolset-selection', 'agent-home-contract', "agent-home-readers", "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
73
|
export type CapabilityFlag = (typeof CAPABILITY_FLAGS)[number];
|
package/dist/wire-additions.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The one table of receiver-capability gates and wire additions
|
|
3
3
|
* (docs/protocol.md "Freeze rule").
|
|
4
4
|
*
|
|
5
|
-
* A
|
|
5
|
+
* A v4 change takes exactly one of three paths: a version bump, a gated
|
|
6
6
|
* addition, or a strip-safe addition. Envelope and HTTP rows have explicit
|
|
7
7
|
* kinds. The last two are declared here.
|
|
8
8
|
*
|
|
@@ -19,11 +19,15 @@
|
|
|
19
19
|
* strip-safe rows and the v2 `result-document` gate are gone. The device
|
|
20
20
|
* gates kept below name capabilities a daemon advertises only when it is
|
|
21
21
|
* configured for them (Agent home, egress, input preparation, provisioning,
|
|
22
|
-
* memory intents and so on): they gate on the receiver's configuration.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
22
|
+
* memory intents and so on): they gate on the receiver's configuration.
|
|
23
|
+
*
|
|
24
|
+
* v4 baseline: every v4 server reads `task.approval_resolved`, so its
|
|
25
|
+
* `approval_resolved` gate is gone. One `task.offer` replaces the Agent offer
|
|
26
|
+
* types and sealed is a payload branch, so a gate that a v3 type carried is a
|
|
27
|
+
* field or value row here. The offer is strict, so a daemon that does not know
|
|
28
|
+
* one of its fields stops instead of stripping it. The daemon also refuses an offer whose rows name a flag it did not advertise. No
|
|
29
|
+
* v4 release has been published yet, so no published decoder proves these rows
|
|
30
|
+
* across releases.
|
|
27
31
|
*
|
|
28
32
|
* Senders derive their admission flags from {@link requiredReceiverCapabilities}
|
|
29
33
|
* and nowhere else, so a gate cannot exist in one place and be missing in
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byok-sdk/protocol",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"description": "BYOK SDK wire protocol: envelope schema, message types, and codec helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -52,7 +52,6 @@
|
|
|
52
52
|
"zod": "^4.4.3"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"byok-protocol-
|
|
56
|
-
"byok-protocol-previous": "https://registry.npmjs.org/@byok-sdk/protocol/-/protocol-0.26.1.tgz"
|
|
55
|
+
"byok-protocol-previous": "https://registry.npmjs.org/@byok-sdk/protocol/-/protocol-0.30.2.tgz"
|
|
57
56
|
}
|
|
58
57
|
}
|