@ccmsg/protocol 1.17.0 → 1.19.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ccmsg/protocol",
3
- "version": "1.17.0",
3
+ "version": "1.19.0",
4
4
  "description": "Wire contract (schema + types + op attribute table) shared by the ccmsg daemon and web UI",
5
5
  "license": "MIT",
6
6
  "author": "kawaz",
@@ -24,7 +24,17 @@ import { Sid, Timestamp } from "../identifiers.ts";
24
24
  * Segments after the first carry the spelling of whatever named them, which is
25
25
  * why they are not held to snake_case: `tool:Bash` and `hook:PreToolUse` are
26
26
  * the harness's words, and rewriting them would leave the reader unable to
27
- * match what it sees against what it ran. */
27
+ * match what it sees against what it ran.
28
+ *
29
+ * Under `message`, the second segment is **a relation read from the subject**:
30
+ * `parent` is whoever started this agent, `sub` a throwaway agent it started,
31
+ * `team` a named counterpart that goes on standing, `session` another session
32
+ * over ccmsg. The one exception is `user` — a person is not a relation to
33
+ * anyone, but the user, standing alone. A harness's own name for a party is
34
+ * never a type: `message:main` would read as the main session's traffic being
35
+ * overheard wherever it happens, when what is meant is the party this subject
36
+ * answers to — which is what `parent` says. The literal names (`main`, a
37
+ * lead's, a teammate's) are kept in `harness_name` on the item. */
28
38
  export const TranscriptItemType = Type.String({
29
39
  pattern: "^[a-z]+(?::[A-Za-z0-9_.-]+)*$",
30
40
  $id: "TranscriptItemType",
@@ -69,6 +79,27 @@ export const TranscriptItemSelector = Type.String({
69
79
  });
70
80
  export type TranscriptItemSelector = Static<typeof TranscriptItemSelector>;
71
81
 
82
+ /** Whose transcript an item was read from, said as a standing rather than a
83
+ * name: `main` is a session's own transcript, `sub` a throwaway agent's — one
84
+ * started to answer once — and `team` a teammate's, an agent that was named and
85
+ * goes on standing.
86
+ *
87
+ * It is what the relations are read from. `message:parent:in` under a `sub` is
88
+ * an errand's brief and under a `team` is what its lead wrote, and an item that
89
+ * does not say which of the two it stood in can only be placed by whoever
90
+ * remembers the request that fetched it. Carrying it on the item is what lets
91
+ * several transcripts be drawn as one, and what lets the table of relations be
92
+ * checked against items rather than against the request that asked for them.
93
+ *
94
+ * It is not `harness_name`: that is the other party's literal name, this is the
95
+ * subject's own standing, and a subject has one whether or not anything it
96
+ * talked to was named. */
97
+ export const TranscriptSubject = Type.Union(
98
+ [Type.Literal("main"), Type.Literal("team"), Type.Literal("sub")],
99
+ { $id: "TranscriptSubject" },
100
+ );
101
+ export type TranscriptSubject = Static<typeof TranscriptSubject>;
102
+
72
103
  /** Where in the transcript the record an item was read from begins, and how far
73
104
  * it runs.
74
105
  *
@@ -105,10 +136,16 @@ export type TranscriptItemId = Static<typeof TranscriptItemId>;
105
136
  * `id` is what the links below point with — never a position in the array,
106
137
  * since a selection or a range decides which items exist in a given read — and
107
138
  * `uuid` stays beside it as the record the item came out of, which is what a
108
- * reader groups by when it wants the whole of one line. */
139
+ * reader groups by when it wants the whole of one line.
140
+ *
141
+ * `subject` is on every item because an item is read out of one transcript and
142
+ * ends up among items from others: a client draws a session beside the agents
143
+ * below it, and the standing it was read from is then the item's own to state
144
+ * and not something to be inferred from the call that fetched it. */
109
145
  const BASE_FIELDS = {
110
146
  id: TranscriptItemId,
111
147
  uuid: Type.String({ minLength: 1 }),
148
+ subject: TranscriptSubject,
112
149
  source: TranscriptItemSource,
113
150
  /** The item's own instant. A call and its result each keep their own. */
114
151
  at: Timestamp,
@@ -190,10 +227,10 @@ const MessageUserOut = item(Type.Literal("message:user:out"), { text: Text });
190
227
  * unnameable. */
191
228
  const MessageParentIn = item(Type.Literal("message:parent:in"), {
192
229
  text: Text,
193
- /** The parent as the harness named it where this arrived — `main`, a lead's
194
- * name, the agent above. Left out when the record says only that it came from
195
- * above, which is the case for the brief an agent opens with. */
196
- from: Type.Optional(Type.String()),
230
+ /** The harness's own name for the parent — `main`, a lead's name, the agent
231
+ * above. Left out when the record says only that it came from above, which is
232
+ * the case for the brief an agent opens with. */
233
+ harness_name: Type.Optional(Type.String()),
197
234
  msg_id: Type.Optional(Type.String()),
198
235
  });
199
236
 
@@ -202,8 +239,8 @@ const MessageParentIn = item(Type.Literal("message:parent:in"), {
202
239
  const MessageParentOutSent = item(Type.Literal("message:parent:out"), {
203
240
  ...USE_FIELDS,
204
241
  text: Text,
205
- /** The parent as the subject addressed it, in the harness's spelling. */
206
- to: Type.Optional(Type.String()),
242
+ /** The harness's own name for the parent, as the subject addressed it. */
243
+ harness_name: Type.Optional(Type.String()),
207
244
  summary: Type.Optional(Type.String()),
208
245
  });
209
246
 
@@ -223,7 +260,7 @@ const MessageTeamOut = item(Type.Literal("message:team:out"), {
223
260
  ...USE_FIELDS,
224
261
  text: Text,
225
262
  /** The teammate addressed, by the name it stands under. */
226
- to: Type.Optional(Type.String()),
263
+ harness_name: Type.Optional(Type.String()),
227
264
  summary: Type.Optional(Type.String()),
228
265
  agent_id: Type.Optional(Type.String()),
229
266
  /** Present on the call that started the teammate, absent on the ones that
@@ -236,7 +273,8 @@ const MessageTeamOut = item(Type.Literal("message:team:out"), {
236
273
  * was written. */
237
274
  const MessageTeamInSaid = item(Type.Literal("message:team:in"), {
238
275
  text: Text,
239
- from: Type.Optional(Type.String()),
276
+ /** The name the teammate stands under. */
277
+ harness_name: Type.Optional(Type.String()),
240
278
  msg_id: Type.Optional(Type.String()),
241
279
  });
242
280
 
@@ -244,6 +282,7 @@ const MessageTeamInSaid = item(Type.Literal("message:team:in"), {
244
282
  const MessageTeamInDone = item(Type.Literal("message:team:in"), {
245
283
  ...RESULT_FIELDS,
246
284
  text: Text,
285
+ harness_name: Type.Optional(Type.String()),
247
286
  agent_id: Type.Optional(Type.String()),
248
287
  status: Type.Optional(Type.String()),
249
288
  duration_ms: Type.Optional(Type.Integer({ minimum: 0 })),
@@ -230,6 +230,7 @@ export const TRANSCRIPT_ITEMS: Static<typeof TranscriptItem>[] = [
230
230
  {
231
231
  id: "3f9a21c4:0",
232
232
  uuid: "3f9a21c4",
233
+ subject: "main",
233
234
  source: { offset: 180_000, bytes: 420 },
234
235
  type: "message:user:in",
235
236
  at: FIXTURE_NOW - 3_600_000,
@@ -239,6 +240,7 @@ export const TRANSCRIPT_ITEMS: Static<typeof TranscriptItem>[] = [
239
240
  {
240
241
  id: "f10b6d43:0",
241
242
  uuid: "f10b6d43",
243
+ subject: "main",
242
244
  source: { offset: 180_420, bytes: 980 },
243
245
  type: "thinking",
244
246
  at: FIXTURE_NOW - 3_500_000,
@@ -247,6 +249,7 @@ export const TRANSCRIPT_ITEMS: Static<typeof TranscriptItem>[] = [
247
249
  {
248
250
  id: "f10b6d43:1",
249
251
  uuid: "f10b6d43",
252
+ subject: "main",
250
253
  source: { offset: 180_420, bytes: 980 },
251
254
  type: "tool:Bash",
252
255
  at: FIXTURE_NOW - 3_400_000,
@@ -259,6 +262,7 @@ export const TRANSCRIPT_ITEMS: Static<typeof TranscriptItem>[] = [
259
262
  {
260
263
  id: "18d6f2c9:0",
261
264
  uuid: "18d6f2c9",
265
+ subject: "main",
262
266
  source: { offset: 181_400, bytes: 260 },
263
267
  type: "tool:Bash",
264
268
  at: FIXTURE_NOW - 3_399_000,
@@ -271,6 +275,7 @@ export const TRANSCRIPT_ITEMS: Static<typeof TranscriptItem>[] = [
271
275
  {
272
276
  id: "b7e41d09:0",
273
277
  uuid: "b7e41d09",
278
+ subject: "main",
274
279
  source: { offset: 181_660, bytes: 640 },
275
280
  type: "message:sub:out",
276
281
  at: FIXTURE_NOW - 3_300_000,
@@ -284,6 +289,7 @@ export const TRANSCRIPT_ITEMS: Static<typeof TranscriptItem>[] = [
284
289
  {
285
290
  id: "92e6d4f5:0",
286
291
  uuid: "92e6d4f5",
292
+ subject: "main",
287
293
  source: { offset: 182_300, bytes: 310 },
288
294
  type: "hook:PreToolUse",
289
295
  at: FIXTURE_NOW - 3_200_000,
@@ -295,6 +301,7 @@ export const TRANSCRIPT_ITEMS: Static<typeof TranscriptItem>[] = [
295
301
  {
296
302
  id: "81d5c3e4:0",
297
303
  uuid: "81d5c3e4",
304
+ subject: "main",
298
305
  source: { offset: 182_610, bytes: 190 },
299
306
  type: "system:attachment:queued_command",
300
307
  at: FIXTURE_NOW - 3_100_000,
@@ -303,6 +310,7 @@ export const TRANSCRIPT_ITEMS: Static<typeof TranscriptItem>[] = [
303
310
  {
304
311
  id: "c8a2f371:0",
305
312
  uuid: "c8a2f371",
313
+ subject: "main",
306
314
  source: { offset: 182_800, bytes: 520 },
307
315
  type: "message:team:out",
308
316
  at: FIXTURE_NOW - 3_000_000,
@@ -310,22 +318,24 @@ export const TRANSCRIPT_ITEMS: Static<typeof TranscriptItem>[] = [
310
318
  result_item: "d4c1a0b2:0",
311
319
  tool_use_id: "toolu_01Tm5XYp",
312
320
  text: "契約に message:parent と message:team を足して",
313
- to: "contract-dump-items",
321
+ harness_name: "contract-dump-items",
314
322
  agent_id: "b83e0f114",
315
323
  subagent_type: "opus5-worker-high",
316
324
  },
317
325
  {
318
326
  id: "e5b70c93:0",
319
327
  uuid: "e5b70c93",
328
+ subject: "main",
320
329
  source: { offset: 183_320, bytes: 300 },
321
330
  type: "message:team:in",
322
331
  at: FIXTURE_NOW - 2_900_000,
323
332
  text: "fixtures まで通ったので ci を回す",
324
- from: "contract-dump-items",
333
+ harness_name: "contract-dump-items",
325
334
  },
326
335
  {
327
336
  id: "d4c1a0b2:0",
328
337
  uuid: "d4c1a0b2",
338
+ subject: "main",
329
339
  source: { offset: 183_620, bytes: 410 },
330
340
  type: "message:team:in",
331
341
  at: FIXTURE_NOW - 2_800_000,
@@ -339,15 +349,18 @@ export const TRANSCRIPT_ITEMS: Static<typeof TranscriptItem>[] = [
339
349
  },
340
350
  ];
341
351
 
342
- /** The same vocabulary read with an agent as the subject.
352
+ /** The same vocabulary read with a throwaway agent as the subject.
343
353
  *
344
354
  * Nothing here is a new type: the brief an agent opens with and the answer it
345
355
  * closes with are what `message:parent` names from wherever it is read, and the
346
- * answer comes as prose with no call behind it. */
356
+ * answer comes as prose with no call behind it. What says these were read from
357
+ * an errand's transcript rather than a session's is `subject`, which every item
358
+ * carries. */
347
359
  export const TRANSCRIPT_ITEMS_AGENT_SUBJECT: Static<typeof TranscriptItem>[] = [
348
360
  {
349
361
  id: "a9f30d15:0",
350
362
  uuid: "a9f30d15",
363
+ subject: "sub",
351
364
  source: { offset: 0, bytes: 1_240 },
352
365
  type: "message:parent:in",
353
366
  at: FIXTURE_NOW - 3_290_000,
@@ -357,18 +370,20 @@ export const TRANSCRIPT_ITEMS_AGENT_SUBJECT: Static<typeof TranscriptItem>[] = [
357
370
  {
358
371
  id: "b0e41c26:0",
359
372
  uuid: "b0e41c26",
373
+ subject: "sub",
360
374
  source: { offset: 1_240, bytes: 380 },
361
375
  type: "message:parent:out",
362
376
  at: FIXTURE_NOW - 3_260_000,
363
377
  role: "use",
364
378
  tool_use_id: "toolu_01Qz8Vbn",
365
379
  text: "型一覧は 4 群に分けた。preset の例まで直してよいか",
366
- to: "main",
380
+ harness_name: "main",
367
381
  summary: "型一覧の分け方を確認",
368
382
  },
369
383
  {
370
384
  id: "c1f52d37:0",
371
385
  uuid: "c1f52d37",
386
+ subject: "sub",
372
387
  source: { offset: 1_620, bytes: 690 },
373
388
  type: "message:parent:out",
374
389
  at: FIXTURE_NOW - 3_200_000,
@@ -376,6 +391,57 @@ export const TRANSCRIPT_ITEMS_AGENT_SUBJECT: Static<typeof TranscriptItem>[] = [
376
391
  },
377
392
  ];
378
393
 
394
+ /** The same vocabulary again, read with a teammate as the subject.
395
+ *
396
+ * A teammate stands where neither of the other two does: it answers a lead, as
397
+ * an errand does, and a person can also type at it directly, as a session's own
398
+ * transcript has. The relations are the ones already spelled out — what tells
399
+ * these apart from the errand's above is `subject`, and it is what makes the
400
+ * three columns of the table checkable against items. */
401
+ export const TRANSCRIPT_ITEMS_TEAM_SUBJECT: Static<typeof TranscriptItem>[] = [
402
+ {
403
+ id: "d2a63e48:0",
404
+ uuid: "d2a63e48",
405
+ subject: "team",
406
+ source: { offset: 0, bytes: 1_480 },
407
+ type: "message:parent:in",
408
+ at: FIXTURE_NOW - 3_000_000,
409
+ turn: 1,
410
+ text: "契約に message:parent と message:team を足して",
411
+ harness_name: "main",
412
+ },
413
+ {
414
+ id: "e3b74f59:0",
415
+ uuid: "e3b74f59",
416
+ subject: "team",
417
+ source: { offset: 1_480, bytes: 260 },
418
+ type: "message:user:in",
419
+ at: FIXTURE_NOW - 2_950_000,
420
+ text: "fixtures も忘れずに",
421
+ },
422
+ {
423
+ id: "f4c8506a:0",
424
+ uuid: "f4c8506a",
425
+ subject: "team",
426
+ source: { offset: 1_740, bytes: 340 },
427
+ type: "message:team:out",
428
+ at: FIXTURE_NOW - 2_920_000,
429
+ role: "use",
430
+ tool_use_id: "toolu_01Wc7Zdq",
431
+ text: "daemon 側の分類はどこまで進んでいる",
432
+ harness_name: "daemon-dump-items",
433
+ },
434
+ {
435
+ id: "a5d9617b:0",
436
+ uuid: "a5d9617b",
437
+ subject: "team",
438
+ source: { offset: 2_080, bytes: 410 },
439
+ type: "message:parent:out",
440
+ at: FIXTURE_NOW - 2_800_000,
441
+ text: "4 型を足して 1.17.0 を切った",
442
+ },
443
+ ];
444
+
379
445
  export const TRANSCRIPT_READ_REQUEST: Static<typeof TranscriptReadRequest> = {
380
446
  request_id,
381
447
  op: "transcript_read",