@ccmsg/protocol 1.15.0 → 1.17.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 +1 -1
- package/src/control/dump.ts +96 -3
- package/src/control/peers.ts +6 -5
- package/src/fixtures/control.ts +77 -1
- package/src/fixtures/topics.ts +8 -0
package/package.json
CHANGED
package/src/control/dump.ts
CHANGED
|
@@ -38,8 +38,12 @@ export type TranscriptItemType = Static<typeof TranscriptItemType>;
|
|
|
38
38
|
export const TRANSCRIPT_ITEM_TYPES = [
|
|
39
39
|
"message:user:in",
|
|
40
40
|
"message:user:out",
|
|
41
|
+
"message:parent:in",
|
|
42
|
+
"message:parent:out",
|
|
41
43
|
"message:sub:in",
|
|
42
44
|
"message:sub:out",
|
|
45
|
+
"message:team:in",
|
|
46
|
+
"message:team:out",
|
|
43
47
|
"message:session:in",
|
|
44
48
|
"message:session:out",
|
|
45
49
|
"thinking",
|
|
@@ -156,12 +160,95 @@ const Text = Type.String();
|
|
|
156
160
|
|
|
157
161
|
/** The subject is a session by default, or one agent below it when the dump
|
|
158
162
|
* names an agent, and `in` / `out` are read from wherever the subject stands.
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* lets one
|
|
163
|
+
* What moves when the subject moves is who the counterpart is, not the names:
|
|
164
|
+
* the same preset reads a session's talk with a person and an agent's talk with
|
|
165
|
+
* whoever started it, which is what lets one be carried down a chain of agents.
|
|
166
|
+
*
|
|
167
|
+
* The counterpart is named by the kind of party it is — a person, the one above,
|
|
168
|
+
* the throwaway agents below, a teammate that stays, another session — because a
|
|
169
|
+
* dump is read to find out who was talking, and a subject's own position is the
|
|
170
|
+
* one thing it cannot ask about itself. Hence `parent` rather than `user` for
|
|
171
|
+
* the one above: an agent's parent is a session or another agent, and calling it
|
|
172
|
+
* `user` would have a reader take a machine for a person.
|
|
173
|
+
*
|
|
174
|
+
* `message:user` is a person and nobody else. Both directions occur under a
|
|
175
|
+
* session and under a teammate, which someone can type at directly; under a
|
|
176
|
+
* throwaway agent neither does. A combination a subject is not expected to show
|
|
177
|
+
* — `team` below an agent, say — is not refused: an unexpected line is still a
|
|
178
|
+
* line, and it is emitted under the name it fits. */
|
|
162
179
|
const MessageUserIn = item(Type.Literal("message:user:in"), { text: Text });
|
|
163
180
|
const MessageUserOut = item(Type.Literal("message:user:out"), { text: Text });
|
|
164
181
|
|
|
182
|
+
/** What the one above said, and what was said back to it.
|
|
183
|
+
*
|
|
184
|
+
* An agent's first line is the brief it was started with, and its last is the
|
|
185
|
+
* answer that brief is discharged by; in between it may hand its parent
|
|
186
|
+
* something mid-flight. The answer is plain prose the harness collects, with no
|
|
187
|
+
* call behind it, so `parent:out` is prose-or-call and not a call alone:
|
|
188
|
+
* addressed to the parent is what the two forms have in common, and requiring a
|
|
189
|
+
* `tool_use_id` would leave the one message an agent is certain to send
|
|
190
|
+
* unnameable. */
|
|
191
|
+
const MessageParentIn = item(Type.Literal("message:parent:in"), {
|
|
192
|
+
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()),
|
|
197
|
+
msg_id: Type.Optional(Type.String()),
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
/** Sent to the parent through a call, which the parent's own transcript has the
|
|
201
|
+
* other half of. */
|
|
202
|
+
const MessageParentOutSent = item(Type.Literal("message:parent:out"), {
|
|
203
|
+
...USE_FIELDS,
|
|
204
|
+
text: Text,
|
|
205
|
+
/** The parent as the subject addressed it, in the harness's spelling. */
|
|
206
|
+
to: Type.Optional(Type.String()),
|
|
207
|
+
summary: Type.Optional(Type.String()),
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
/** Answered to the parent as prose — the agent's reply, final or interim. */
|
|
211
|
+
const MessageParentOutSaid = item(Type.Literal("message:parent:out"), { text: Text });
|
|
212
|
+
|
|
213
|
+
/** A teammate is an agent that was given a name and goes on standing, so what
|
|
214
|
+
* passes between the subject and one is a correspondence rather than an errand:
|
|
215
|
+
* a reply comes back as its own message, addressed and arriving whenever it is
|
|
216
|
+
* written, and not as the answer to the call that sent it.
|
|
217
|
+
*
|
|
218
|
+
* That is the whole of what separates `team` from `sub`. A throwaway agent is
|
|
219
|
+
* started, answers once and is done, which is why `sub:in` is the result of the
|
|
220
|
+
* `sub:out` that started it. Here the two halves of a round trip are two
|
|
221
|
+
* messages, and only the start of a teammate has a result to pair with. */
|
|
222
|
+
const MessageTeamOut = item(Type.Literal("message:team:out"), {
|
|
223
|
+
...USE_FIELDS,
|
|
224
|
+
text: Text,
|
|
225
|
+
/** The teammate addressed, by the name it stands under. */
|
|
226
|
+
to: Type.Optional(Type.String()),
|
|
227
|
+
summary: Type.Optional(Type.String()),
|
|
228
|
+
agent_id: Type.Optional(Type.String()),
|
|
229
|
+
/** Present on the call that started the teammate, absent on the ones that
|
|
230
|
+
* write to it afterwards. */
|
|
231
|
+
subagent_type: Type.Optional(Type.String()),
|
|
232
|
+
description: Type.Optional(Type.String()),
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
/** A teammate writing to the subject, arriving under its own name whenever it
|
|
236
|
+
* was written. */
|
|
237
|
+
const MessageTeamInSaid = item(Type.Literal("message:team:in"), {
|
|
238
|
+
text: Text,
|
|
239
|
+
from: Type.Optional(Type.String()),
|
|
240
|
+
msg_id: Type.Optional(Type.String()),
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
/** A teammate's run ending, which answers the call that started it. */
|
|
244
|
+
const MessageTeamInDone = item(Type.Literal("message:team:in"), {
|
|
245
|
+
...RESULT_FIELDS,
|
|
246
|
+
text: Text,
|
|
247
|
+
agent_id: Type.Optional(Type.String()),
|
|
248
|
+
status: Type.Optional(Type.String()),
|
|
249
|
+
duration_ms: Type.Optional(Type.Integer({ minimum: 0 })),
|
|
250
|
+
});
|
|
251
|
+
|
|
165
252
|
const MessageSubOut = item(Type.Literal("message:sub:out"), {
|
|
166
253
|
...USE_FIELDS,
|
|
167
254
|
prompt: Text,
|
|
@@ -373,8 +460,14 @@ export const TranscriptItem = Type.Union(
|
|
|
373
460
|
[
|
|
374
461
|
MessageUserIn,
|
|
375
462
|
MessageUserOut,
|
|
463
|
+
MessageParentIn,
|
|
464
|
+
MessageParentOutSent,
|
|
465
|
+
MessageParentOutSaid,
|
|
376
466
|
MessageSubOut,
|
|
377
467
|
MessageSubIn,
|
|
468
|
+
MessageTeamOut,
|
|
469
|
+
MessageTeamInSaid,
|
|
470
|
+
MessageTeamInDone,
|
|
378
471
|
MessageSessionOut,
|
|
379
472
|
MessageSessionIn,
|
|
380
473
|
Thinking,
|
package/src/control/peers.ts
CHANGED
|
@@ -57,7 +57,7 @@ export const StaleClientInfo = Type.Object(
|
|
|
57
57
|
);
|
|
58
58
|
export type StaleClientInfo = Static<typeof StaleClientInfo>;
|
|
59
59
|
|
|
60
|
-
/** One connected
|
|
60
|
+
/** One session an instance can call live (connected or not).
|
|
61
61
|
*
|
|
62
62
|
* The paths are the host's, so the entry names the instance holding them:
|
|
63
63
|
* `peers` carries every instance's sessions in one list, and two hosts' paths
|
|
@@ -122,10 +122,11 @@ export const PeerInfo = Type.Object(
|
|
|
122
122
|
send_message: Type.Optional(Type.Boolean()),
|
|
123
123
|
/** The build of the client that last greeted for this session. */
|
|
124
124
|
client_version: Type.Optional(Type.String()),
|
|
125
|
-
/** The generation
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
|
|
125
|
+
/** The generation the connected client speaks. Absent from a row that has
|
|
126
|
+
* no connection to read one from — the instance's state file names such a
|
|
127
|
+
* session live without any client ever having greeted it, so there is no
|
|
128
|
+
* generation to state. */
|
|
129
|
+
protocol_version: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
129
130
|
/** Set while some client of this session is being refused. */
|
|
130
131
|
stale_client: Type.Optional(StaleClientInfo),
|
|
131
132
|
},
|
package/src/fixtures/control.ts
CHANGED
|
@@ -213,7 +213,9 @@ export const DUMP_PRESETS_READ_RESPONSE: Static<typeof DumpPresetsReadResponse>
|
|
|
213
213
|
{
|
|
214
214
|
name: "howto",
|
|
215
215
|
description: "how the work was done: what was thought, run, read and written",
|
|
216
|
-
opts: {
|
|
216
|
+
opts: {
|
|
217
|
+
types: ["thinking", "message:user", "message:parent", "message:sub", "tool:Bash", "@file"],
|
|
218
|
+
},
|
|
217
219
|
},
|
|
218
220
|
],
|
|
219
221
|
};
|
|
@@ -298,6 +300,80 @@ export const TRANSCRIPT_ITEMS: Static<typeof TranscriptItem>[] = [
|
|
|
298
300
|
at: FIXTURE_NOW - 3_100_000,
|
|
299
301
|
attachment: { type: "queued_command", command: "/pre-clear" },
|
|
300
302
|
},
|
|
303
|
+
{
|
|
304
|
+
id: "c8a2f371:0",
|
|
305
|
+
uuid: "c8a2f371",
|
|
306
|
+
source: { offset: 182_800, bytes: 520 },
|
|
307
|
+
type: "message:team:out",
|
|
308
|
+
at: FIXTURE_NOW - 3_000_000,
|
|
309
|
+
role: "use",
|
|
310
|
+
result_item: "d4c1a0b2:0",
|
|
311
|
+
tool_use_id: "toolu_01Tm5XYp",
|
|
312
|
+
text: "契約に message:parent と message:team を足して",
|
|
313
|
+
to: "contract-dump-items",
|
|
314
|
+
agent_id: "b83e0f114",
|
|
315
|
+
subagent_type: "opus5-worker-high",
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
id: "e5b70c93:0",
|
|
319
|
+
uuid: "e5b70c93",
|
|
320
|
+
source: { offset: 183_320, bytes: 300 },
|
|
321
|
+
type: "message:team:in",
|
|
322
|
+
at: FIXTURE_NOW - 2_900_000,
|
|
323
|
+
text: "fixtures まで通ったので ci を回す",
|
|
324
|
+
from: "contract-dump-items",
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
id: "d4c1a0b2:0",
|
|
328
|
+
uuid: "d4c1a0b2",
|
|
329
|
+
source: { offset: 183_620, bytes: 410 },
|
|
330
|
+
type: "message:team:in",
|
|
331
|
+
at: FIXTURE_NOW - 2_800_000,
|
|
332
|
+
role: "result",
|
|
333
|
+
parent_item: "c8a2f371:0",
|
|
334
|
+
parent_tool_use_id: "toolu_01Tm5XYp",
|
|
335
|
+
text: "4 型を足して 1.17.0 を切った",
|
|
336
|
+
agent_id: "b83e0f114",
|
|
337
|
+
status: "ok",
|
|
338
|
+
duration_ms: 240_000,
|
|
339
|
+
},
|
|
340
|
+
];
|
|
341
|
+
|
|
342
|
+
/** The same vocabulary read with an agent as the subject.
|
|
343
|
+
*
|
|
344
|
+
* Nothing here is a new type: the brief an agent opens with and the answer it
|
|
345
|
+
* closes with are what `message:parent` names from wherever it is read, and the
|
|
346
|
+
* answer comes as prose with no call behind it. */
|
|
347
|
+
export const TRANSCRIPT_ITEMS_AGENT_SUBJECT: Static<typeof TranscriptItem>[] = [
|
|
348
|
+
{
|
|
349
|
+
id: "a9f30d15:0",
|
|
350
|
+
uuid: "a9f30d15",
|
|
351
|
+
source: { offset: 0, bytes: 1_240 },
|
|
352
|
+
type: "message:parent:in",
|
|
353
|
+
at: FIXTURE_NOW - 3_290_000,
|
|
354
|
+
turn: 1,
|
|
355
|
+
text: "docs/design/dump-kinds.md を書き直す",
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
id: "b0e41c26:0",
|
|
359
|
+
uuid: "b0e41c26",
|
|
360
|
+
source: { offset: 1_240, bytes: 380 },
|
|
361
|
+
type: "message:parent:out",
|
|
362
|
+
at: FIXTURE_NOW - 3_260_000,
|
|
363
|
+
role: "use",
|
|
364
|
+
tool_use_id: "toolu_01Qz8Vbn",
|
|
365
|
+
text: "型一覧は 4 群に分けた。preset の例まで直してよいか",
|
|
366
|
+
to: "main",
|
|
367
|
+
summary: "型一覧の分け方を確認",
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
id: "c1f52d37:0",
|
|
371
|
+
uuid: "c1f52d37",
|
|
372
|
+
source: { offset: 1_620, bytes: 690 },
|
|
373
|
+
type: "message:parent:out",
|
|
374
|
+
at: FIXTURE_NOW - 3_200_000,
|
|
375
|
+
text: "型一覧を 4 群に整理し、preset の例も揃えた",
|
|
376
|
+
},
|
|
301
377
|
];
|
|
302
378
|
|
|
303
379
|
export const TRANSCRIPT_READ_REQUEST: Static<typeof TranscriptReadRequest> = {
|
package/src/fixtures/topics.ts
CHANGED
|
@@ -88,6 +88,14 @@ export const PEERS_FRAME: Static<typeof PeersFrame> = {
|
|
|
88
88
|
protocol_version: 2,
|
|
89
89
|
},
|
|
90
90
|
},
|
|
91
|
+
{
|
|
92
|
+
sid: "1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
|
|
93
|
+
instance,
|
|
94
|
+
repo: "ccmsg",
|
|
95
|
+
ws: "daemon-v2",
|
|
96
|
+
cwd: "/repos/kawaz/ccmsg/daemon-v2",
|
|
97
|
+
state: "live_unmanaged",
|
|
98
|
+
},
|
|
91
99
|
],
|
|
92
100
|
last_live: [
|
|
93
101
|
{
|