@zuoyehaoduoa/wire 0.1.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 +668 -0
- package/dist/index.cjs +880 -0
- package/dist/index.d.cts +2500 -0
- package/dist/index.d.mts +2500 -0
- package/dist/index.mjs +796 -0
- package/package.json +62 -0
- package/src/index.ts +5 -0
- package/src/messageMeta.ts +24 -0
- package/src/messages.test.ts +165 -0
- package/src/messages.ts +97 -0
- package/src/remote-auth-errors.ts +87 -0
- package/src/remote-crypto.test.ts +244 -0
- package/src/remote-crypto.ts +778 -0
- package/src/remote-protocol.test.ts +61 -0
- package/src/remote-protocol.ts +53 -0
- package/src/sessionProtocol.test.ts +170 -0
- package/src/sessionProtocol.ts +141 -0
package/README.md
ADDED
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
# @zuoyehaoduoa/wire
|
|
2
|
+
|
|
3
|
+
Canonical wire specification package for codex-deck clients and services.
|
|
4
|
+
|
|
5
|
+
This package defines shared wire contracts as TypeScript types + Zod schemas. It is intentionally small and focused on protocol-level data only.
|
|
6
|
+
|
|
7
|
+
## Quick Example
|
|
8
|
+
|
|
9
|
+
Session protocol format example (decrypted payload):
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"role": "session",
|
|
14
|
+
"content": {
|
|
15
|
+
"id": "msg_01",
|
|
16
|
+
"time": 1739347230000,
|
|
17
|
+
"role": "agent",
|
|
18
|
+
"turn": "turn_01",
|
|
19
|
+
"ev": {
|
|
20
|
+
"t": "text",
|
|
21
|
+
"text": "I found the issue in api/session.ts"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"meta": {
|
|
25
|
+
"sentFrom": "cli"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Session protocol user envelope (decrypted payload):
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"role": "session",
|
|
35
|
+
"content": {
|
|
36
|
+
"id": "msg_user_01",
|
|
37
|
+
"time": 1739347231000,
|
|
38
|
+
"role": "user",
|
|
39
|
+
"ev": {
|
|
40
|
+
"t": "text",
|
|
41
|
+
"text": "fix the failing test"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"meta": {
|
|
45
|
+
"sentFrom": "cli"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Protocol invariants:
|
|
51
|
+
|
|
52
|
+
- outer `role = "session"` marks modern session-protocol payloads.
|
|
53
|
+
- inside `content`, envelope `role` is only `"user"` or `"agent"`.
|
|
54
|
+
|
|
55
|
+
Wire-level encrypted container:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"id": "msg-db-row-id",
|
|
60
|
+
"seq": 101,
|
|
61
|
+
"localId": null,
|
|
62
|
+
"content": {
|
|
63
|
+
"t": "encrypted",
|
|
64
|
+
"c": "BASE64_ENCRYPTED_PAYLOAD"
|
|
65
|
+
},
|
|
66
|
+
"createdAt": 1739347230000,
|
|
67
|
+
"updatedAt": 1739347230000
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Purpose
|
|
72
|
+
|
|
73
|
+
`@zuoyehaoduoa/wire` centralizes definitions for:
|
|
74
|
+
|
|
75
|
+
- encrypted message/update payloads
|
|
76
|
+
- session protocol envelope and event stream
|
|
77
|
+
- helper for creating valid session envelopes
|
|
78
|
+
|
|
79
|
+
The goal is to keep CLI/app/server/agent on the same wire contract and avoid schema drift.
|
|
80
|
+
|
|
81
|
+
## Package Identity
|
|
82
|
+
|
|
83
|
+
- Name: `@zuoyehaoduoa/wire`
|
|
84
|
+
- Workspace path: `wire`
|
|
85
|
+
- Entry: `src/index.ts`
|
|
86
|
+
- Runtime deps: `zod`, `@paralleldrive/cuid2`
|
|
87
|
+
|
|
88
|
+
## Public Exports
|
|
89
|
+
|
|
90
|
+
`src/index.ts` exports everything from:
|
|
91
|
+
|
|
92
|
+
- `src/messages.ts`
|
|
93
|
+
- `src/sessionProtocol.ts`
|
|
94
|
+
|
|
95
|
+
### `messages.ts` exports
|
|
96
|
+
|
|
97
|
+
Schemas + inferred types:
|
|
98
|
+
|
|
99
|
+
- `SessionMessageContentSchema`
|
|
100
|
+
- `SessionMessage`
|
|
101
|
+
- `SessionMessageSchema`
|
|
102
|
+
- `MessageMetaSchema`
|
|
103
|
+
- `MessageMeta`
|
|
104
|
+
- `SessionProtocolMessageSchema`
|
|
105
|
+
- `SessionProtocolMessage`
|
|
106
|
+
- `MessageContentSchema`
|
|
107
|
+
- `MessageContent`
|
|
108
|
+
- `VersionedEncryptedValueSchema`
|
|
109
|
+
- `VersionedEncryptedValue`
|
|
110
|
+
- `VersionedNullableEncryptedValueSchema`
|
|
111
|
+
- `VersionedNullableEncryptedValue`
|
|
112
|
+
- `UpdateNewMessageBodySchema`
|
|
113
|
+
- `UpdateNewMessageBody`
|
|
114
|
+
- `UpdateSessionBodySchema`
|
|
115
|
+
- `UpdateSessionBody`
|
|
116
|
+
- `VersionedMachineEncryptedValueSchema`
|
|
117
|
+
- `VersionedMachineEncryptedValue`
|
|
118
|
+
- `UpdateMachineBodySchema`
|
|
119
|
+
- `UpdateMachineBody`
|
|
120
|
+
- `CoreUpdateBodySchema`
|
|
121
|
+
- `CoreUpdateBody`
|
|
122
|
+
- `CoreUpdateContainerSchema`
|
|
123
|
+
- `CoreUpdateContainer`
|
|
124
|
+
|
|
125
|
+
### `sessionProtocol.ts` exports
|
|
126
|
+
|
|
127
|
+
Schemas + inferred types:
|
|
128
|
+
|
|
129
|
+
- `sessionRoleSchema`
|
|
130
|
+
- `SessionRole`
|
|
131
|
+
- `sessionTextEventSchema`
|
|
132
|
+
- `sessionServiceMessageEventSchema`
|
|
133
|
+
- `sessionToolCallStartEventSchema`
|
|
134
|
+
- `sessionToolCallEndEventSchema`
|
|
135
|
+
- `sessionFileEventSchema`
|
|
136
|
+
- `sessionTurnStartEventSchema`
|
|
137
|
+
- `sessionStartEventSchema`
|
|
138
|
+
- `sessionTurnEndStatusSchema`
|
|
139
|
+
- `SessionTurnEndStatus`
|
|
140
|
+
- `sessionTurnEndEventSchema`
|
|
141
|
+
- `sessionStopEventSchema`
|
|
142
|
+
- `sessionEventSchema`
|
|
143
|
+
- `SessionEvent`
|
|
144
|
+
- `sessionEnvelopeSchema`
|
|
145
|
+
- `SessionEnvelope`
|
|
146
|
+
- `CreateEnvelopeOptions`
|
|
147
|
+
- `createEnvelope(...)`
|
|
148
|
+
|
|
149
|
+
## Wire Type Specifications
|
|
150
|
+
|
|
151
|
+
## Common Primitive Rules
|
|
152
|
+
|
|
153
|
+
These are schema-level requirements, not just recommendations.
|
|
154
|
+
|
|
155
|
+
- `id`, `sid`, `machineId`, `call`, `name`, `title`, `description`, `ref`: `string`
|
|
156
|
+
- `seq`, `createdAt`, `updatedAt`, `size`, `width`, `height`, `version`, `activeAt`: `number`
|
|
157
|
+
- All nullable fields are explicitly marked with `.nullable()`.
|
|
158
|
+
- All optional fields are explicitly marked with `.optional()`.
|
|
159
|
+
- `.nullish()` means `undefined | null | <type>`.
|
|
160
|
+
|
|
161
|
+
## Message/Update Specs (`messages.ts`)
|
|
162
|
+
|
|
163
|
+
### `SessionMessageContentSchema`
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
{
|
|
167
|
+
t: "encrypted";
|
|
168
|
+
c: string;
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Meaning:
|
|
173
|
+
|
|
174
|
+
- `t` is a strict discriminator with value `'encrypted'`.
|
|
175
|
+
- `c` is encrypted payload bytes encoded as a string (typically base64 in current usage).
|
|
176
|
+
|
|
177
|
+
### `SessionMessageSchema`
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
{
|
|
181
|
+
id: string;
|
|
182
|
+
seq: number;
|
|
183
|
+
localId?: string | null;
|
|
184
|
+
content: SessionMessageContent;
|
|
185
|
+
createdAt: number;
|
|
186
|
+
updatedAt: number;
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Notes:
|
|
191
|
+
|
|
192
|
+
- `localId` is `.nullish()` for compatibility with different producers.
|
|
193
|
+
- `createdAt` and `updatedAt` are required in this shared schema.
|
|
194
|
+
|
|
195
|
+
### `MessageMetaSchema`
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
{
|
|
199
|
+
sentFrom?: string;
|
|
200
|
+
permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'read-only' | 'safe-yolo' | 'yolo';
|
|
201
|
+
model?: string | null;
|
|
202
|
+
fallbackModel?: string | null;
|
|
203
|
+
customSystemPrompt?: string | null;
|
|
204
|
+
appendSystemPrompt?: string | null;
|
|
205
|
+
allowedTools?: string[] | null;
|
|
206
|
+
disallowedTools?: string[] | null;
|
|
207
|
+
displayText?: string;
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Top-Level Decrypted Payload Specs (`messages.ts`)
|
|
212
|
+
|
|
213
|
+
### `SessionProtocolMessageSchema` (modern decrypted payload wrapper)
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
{
|
|
217
|
+
role: 'session';
|
|
218
|
+
content: SessionEnvelope;
|
|
219
|
+
meta?: MessageMeta;
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### `MessageContentSchema`
|
|
224
|
+
|
|
225
|
+
Equivalent to `SessionProtocolMessageSchema`.
|
|
226
|
+
|
|
227
|
+
## Message/Update Specs (`messages.ts`) Continued
|
|
228
|
+
|
|
229
|
+
### `VersionedEncryptedValueSchema`
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
{
|
|
233
|
+
version: number;
|
|
234
|
+
value: string;
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Used for encrypted, version-tracked blobs that cannot be null when present.
|
|
239
|
+
|
|
240
|
+
### `VersionedNullableEncryptedValueSchema`
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
{
|
|
244
|
+
version: number;
|
|
245
|
+
value: string | null;
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Used where payload presence can be intentionally reset to null while still versioning.
|
|
250
|
+
|
|
251
|
+
### `VersionedMachineEncryptedValueSchema`
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
{
|
|
255
|
+
version: number;
|
|
256
|
+
value: string;
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Machine update variant. Equivalent shape to `VersionedEncryptedValueSchema`.
|
|
261
|
+
|
|
262
|
+
### `UpdateNewMessageBodySchema`
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
{
|
|
266
|
+
t: "new-message";
|
|
267
|
+
sid: string;
|
|
268
|
+
message: SessionMessage;
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### `UpdateSessionBodySchema`
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
{
|
|
276
|
+
t: 'update-session';
|
|
277
|
+
id: string;
|
|
278
|
+
metadata?: VersionedEncryptedValue | null;
|
|
279
|
+
agentState?: VersionedNullableEncryptedValue | null;
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Important distinction:
|
|
284
|
+
|
|
285
|
+
- `metadata.value` is `string` when metadata block exists.
|
|
286
|
+
- `agentState.value` may be `string` or `null` when block exists.
|
|
287
|
+
|
|
288
|
+
### `UpdateMachineBodySchema`
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
{
|
|
292
|
+
t: 'update-machine';
|
|
293
|
+
machineId: string;
|
|
294
|
+
metadata?: VersionedMachineEncryptedValue | null;
|
|
295
|
+
daemonState?: VersionedMachineEncryptedValue | null;
|
|
296
|
+
active?: boolean;
|
|
297
|
+
activeAt?: number;
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### `CoreUpdateBodySchema`
|
|
302
|
+
|
|
303
|
+
Discriminated union on `t` with exactly 3 variants:
|
|
304
|
+
|
|
305
|
+
- `'new-message'`
|
|
306
|
+
- `'update-session'`
|
|
307
|
+
- `'update-machine'`
|
|
308
|
+
|
|
309
|
+
### `CoreUpdateContainerSchema`
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
{
|
|
313
|
+
id: string;
|
|
314
|
+
seq: number;
|
|
315
|
+
body: CoreUpdateBody;
|
|
316
|
+
createdAt: number;
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Session Protocol Specs (`sessionProtocol.ts`)
|
|
321
|
+
|
|
322
|
+
## Role
|
|
323
|
+
|
|
324
|
+
### `sessionRoleSchema`
|
|
325
|
+
|
|
326
|
+
```ts
|
|
327
|
+
"user" | "agent";
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Role meaning:
|
|
331
|
+
|
|
332
|
+
- `'user'`: user-originated envelope.
|
|
333
|
+
- `'agent'`: agent-originated envelope.
|
|
334
|
+
|
|
335
|
+
## Event Variants
|
|
336
|
+
|
|
337
|
+
`sessionEventSchema` is a discriminated union on `t` with 9 variants.
|
|
338
|
+
|
|
339
|
+
### 1) Text event
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
{
|
|
343
|
+
t: 'text';
|
|
344
|
+
text: string;
|
|
345
|
+
thinking?: boolean;
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### 2) Service event
|
|
350
|
+
|
|
351
|
+
```ts
|
|
352
|
+
{
|
|
353
|
+
t: "service";
|
|
354
|
+
text: string;
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### 3) Tool-call-start event
|
|
359
|
+
|
|
360
|
+
```ts
|
|
361
|
+
{
|
|
362
|
+
t: "tool-call-start";
|
|
363
|
+
call: string;
|
|
364
|
+
name: string;
|
|
365
|
+
title: string;
|
|
366
|
+
description: string;
|
|
367
|
+
args: Record<string, unknown>;
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### 4) Tool-call-end event
|
|
372
|
+
|
|
373
|
+
```ts
|
|
374
|
+
{
|
|
375
|
+
t: "tool-call-end";
|
|
376
|
+
call: string;
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### 5) File event
|
|
381
|
+
|
|
382
|
+
```ts
|
|
383
|
+
{
|
|
384
|
+
t: 'file';
|
|
385
|
+
ref: string;
|
|
386
|
+
name: string;
|
|
387
|
+
size: number;
|
|
388
|
+
image?: {
|
|
389
|
+
width: number;
|
|
390
|
+
height: number;
|
|
391
|
+
thumbhash: string;
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### 6) Turn-start event
|
|
397
|
+
|
|
398
|
+
```ts
|
|
399
|
+
{
|
|
400
|
+
t: "turn-start";
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### 7) Start event
|
|
405
|
+
|
|
406
|
+
```ts
|
|
407
|
+
{
|
|
408
|
+
t: 'start';
|
|
409
|
+
title?: string;
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### 8) Turn-end event
|
|
414
|
+
|
|
415
|
+
```ts
|
|
416
|
+
{
|
|
417
|
+
t: "turn-end";
|
|
418
|
+
status: "completed" | "failed" | "cancelled";
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### 9) Stop event
|
|
423
|
+
|
|
424
|
+
```ts
|
|
425
|
+
{
|
|
426
|
+
t: "stop";
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
## Envelope
|
|
431
|
+
|
|
432
|
+
### `sessionEnvelopeSchema`
|
|
433
|
+
|
|
434
|
+
```ts
|
|
435
|
+
{
|
|
436
|
+
id: string;
|
|
437
|
+
time: number;
|
|
438
|
+
role: 'user' | 'agent';
|
|
439
|
+
turn?: string;
|
|
440
|
+
subagent?: string; // must pass cuid2 validation when present
|
|
441
|
+
ev: SessionEvent;
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
Additional validation (`superRefine`):
|
|
446
|
+
|
|
447
|
+
- If `ev.t === 'service'`, then `role` MUST be `'agent'`.
|
|
448
|
+
- If `ev.t === 'start'` or `ev.t === 'stop'`, then `role` MUST be `'agent'`.
|
|
449
|
+
- If `subagent` is present, it MUST satisfy `isCuid(...)`.
|
|
450
|
+
|
|
451
|
+
## Helper Function Contract
|
|
452
|
+
|
|
453
|
+
### `createEnvelope(role, ev, opts?)`
|
|
454
|
+
|
|
455
|
+
Input:
|
|
456
|
+
|
|
457
|
+
- `role: SessionRole`
|
|
458
|
+
- `ev: SessionEvent`
|
|
459
|
+
- `opts?: { id?: string; time?: number; turn?: string; subagent?: string }`
|
|
460
|
+
|
|
461
|
+
Behavior:
|
|
462
|
+
|
|
463
|
+
- If `opts.id` is absent, generates id using `createId()`.
|
|
464
|
+
- If `opts.time` is absent, sets `time` to `Date.now()`.
|
|
465
|
+
- Includes `turn` only when provided.
|
|
466
|
+
- Includes `subagent` only when provided.
|
|
467
|
+
|
|
468
|
+
Output:
|
|
469
|
+
|
|
470
|
+
- Returns a `SessionEnvelope` parsed by `sessionEnvelopeSchema`.
|
|
471
|
+
- Throws on invalid combinations (for example `role = 'user'` with `ev.t = 'service'`).
|
|
472
|
+
|
|
473
|
+
## Normative JSON Examples
|
|
474
|
+
|
|
475
|
+
## Update container with `new-message`
|
|
476
|
+
|
|
477
|
+
```json
|
|
478
|
+
{
|
|
479
|
+
"id": "upd-1",
|
|
480
|
+
"seq": 100,
|
|
481
|
+
"createdAt": 1739347200000,
|
|
482
|
+
"body": {
|
|
483
|
+
"t": "new-message",
|
|
484
|
+
"sid": "session-1",
|
|
485
|
+
"message": {
|
|
486
|
+
"id": "msg-1",
|
|
487
|
+
"seq": 55,
|
|
488
|
+
"localId": null,
|
|
489
|
+
"content": {
|
|
490
|
+
"t": "encrypted",
|
|
491
|
+
"c": "Zm9v"
|
|
492
|
+
},
|
|
493
|
+
"createdAt": 1739347199000,
|
|
494
|
+
"updatedAt": 1739347199000
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### Decrypted `new-message` content example
|
|
501
|
+
|
|
502
|
+
`message.content.c` (ciphertext) decrypts into the payload below for a session-protocol message:
|
|
503
|
+
|
|
504
|
+
```json
|
|
505
|
+
{
|
|
506
|
+
"role": "session",
|
|
507
|
+
"content": {
|
|
508
|
+
"id": "env_01",
|
|
509
|
+
"time": 1739347232000,
|
|
510
|
+
"role": "agent",
|
|
511
|
+
"turn": "turn_01",
|
|
512
|
+
"ev": {
|
|
513
|
+
"t": "text",
|
|
514
|
+
"text": "I found 3 TODOs."
|
|
515
|
+
}
|
|
516
|
+
},
|
|
517
|
+
"meta": {
|
|
518
|
+
"sentFrom": "cli"
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
Clients emit only the modern payload (`role = "session"` with `content.role = "user"`).
|
|
524
|
+
|
|
525
|
+
## Update container with `update-session`
|
|
526
|
+
|
|
527
|
+
```json
|
|
528
|
+
{
|
|
529
|
+
"id": "upd-2",
|
|
530
|
+
"seq": 101,
|
|
531
|
+
"createdAt": 1739347210000,
|
|
532
|
+
"body": {
|
|
533
|
+
"t": "update-session",
|
|
534
|
+
"id": "session-1",
|
|
535
|
+
"metadata": {
|
|
536
|
+
"version": 8,
|
|
537
|
+
"value": "BASE64..."
|
|
538
|
+
},
|
|
539
|
+
"agentState": {
|
|
540
|
+
"version": 13,
|
|
541
|
+
"value": null
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
## Update container with `update-machine`
|
|
548
|
+
|
|
549
|
+
```json
|
|
550
|
+
{
|
|
551
|
+
"id": "upd-3",
|
|
552
|
+
"seq": 102,
|
|
553
|
+
"createdAt": 1739347220000,
|
|
554
|
+
"body": {
|
|
555
|
+
"t": "update-machine",
|
|
556
|
+
"machineId": "machine-1",
|
|
557
|
+
"metadata": {
|
|
558
|
+
"version": 2,
|
|
559
|
+
"value": "BASE64..."
|
|
560
|
+
},
|
|
561
|
+
"daemonState": {
|
|
562
|
+
"version": 3,
|
|
563
|
+
"value": "BASE64..."
|
|
564
|
+
},
|
|
565
|
+
"active": true,
|
|
566
|
+
"activeAt": 1739347220000
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
## Session protocol envelope
|
|
572
|
+
|
|
573
|
+
```json
|
|
574
|
+
{
|
|
575
|
+
"id": "x8s1k2...",
|
|
576
|
+
"role": "agent",
|
|
577
|
+
"turn": "turn-42",
|
|
578
|
+
"ev": {
|
|
579
|
+
"t": "turn-start"
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
## Parsing/Validation Usage
|
|
585
|
+
|
|
586
|
+
```ts
|
|
587
|
+
import {
|
|
588
|
+
CoreUpdateContainerSchema,
|
|
589
|
+
sessionEnvelopeSchema,
|
|
590
|
+
} from "@zuoyehaoduoa/wire";
|
|
591
|
+
|
|
592
|
+
const maybeUpdate = CoreUpdateContainerSchema.safeParse(input);
|
|
593
|
+
if (!maybeUpdate.success) {
|
|
594
|
+
// invalid update payload
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
const maybeEnvelope = sessionEnvelopeSchema.safeParse(envelopeInput);
|
|
598
|
+
if (!maybeEnvelope.success) {
|
|
599
|
+
// invalid envelope/event payload
|
|
600
|
+
}
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
## Build and Distribution Specification
|
|
604
|
+
|
|
605
|
+
`package.json` contract:
|
|
606
|
+
|
|
607
|
+
- `main`: `./dist/index.cjs`
|
|
608
|
+
- `module`: `./dist/index.mjs`
|
|
609
|
+
- `types`: `./dist/index.d.cts`
|
|
610
|
+
- `exports["."]` provides both CJS and ESM entrypoints with type paths.
|
|
611
|
+
|
|
612
|
+
Build script:
|
|
613
|
+
|
|
614
|
+
- `shx rm -rf dist && npx tsc --noEmit && pkgroll`
|
|
615
|
+
|
|
616
|
+
Tests:
|
|
617
|
+
|
|
618
|
+
- `vitest` against `src/*.test.ts`
|
|
619
|
+
|
|
620
|
+
Publish gate:
|
|
621
|
+
|
|
622
|
+
- `prepublishOnly` runs build + test
|
|
623
|
+
|
|
624
|
+
Published files:
|
|
625
|
+
|
|
626
|
+
- `dist`
|
|
627
|
+
- `package.json`
|
|
628
|
+
- `README.md`
|
|
629
|
+
|
|
630
|
+
## Monorepo Build Dependency Behavior
|
|
631
|
+
|
|
632
|
+
In this repository, consumer workspaces import `@zuoyehaoduoa/wire` through the local workspace package.
|
|
633
|
+
|
|
634
|
+
That means on a clean checkout:
|
|
635
|
+
|
|
636
|
+
1. Build wire first: `pnpm --dir wire build`
|
|
637
|
+
2. Then build/typecheck dependents.
|
|
638
|
+
|
|
639
|
+
After publishing to npm, dependents consume prebuilt artifacts from the published tarball.
|
|
640
|
+
|
|
641
|
+
## Change Policy
|
|
642
|
+
|
|
643
|
+
When modifying wire schemas:
|
|
644
|
+
|
|
645
|
+
- Prefer additive changes to keep older consumers compatible.
|
|
646
|
+
- Treat discriminator values (`t`) as protocol-level API and avoid breaking renames.
|
|
647
|
+
- Document semantic changes in this README.
|
|
648
|
+
- Bump package version before downstream releases that depend on new schema behavior.
|
|
649
|
+
|
|
650
|
+
## Development Commands
|
|
651
|
+
|
|
652
|
+
```bash
|
|
653
|
+
# from repository root
|
|
654
|
+
pnpm --dir wire build
|
|
655
|
+
pnpm --dir wire test
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
## Release Commands (maintainers)
|
|
659
|
+
|
|
660
|
+
```bash
|
|
661
|
+
# interactive release target selection from repo root
|
|
662
|
+
pnpm release
|
|
663
|
+
|
|
664
|
+
# direct release invocation
|
|
665
|
+
pnpm --dir wire release
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
This prepares release artifacts using the same `release-it` flow as other publishable libraries in the monorepo.
|