@ccmsg/protocol 1.8.0 → 1.10.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.
@@ -0,0 +1,557 @@
1
+ import type { Static } from "@sinclair/typebox";
2
+ import type {
3
+ DirListRequest,
4
+ DirListResponse,
5
+ DirTreeRequest,
6
+ DirTreeResponse,
7
+ FileCreateRequest,
8
+ FileCreateResponse,
9
+ FileDeleteRequest,
10
+ FileDeleteResponse,
11
+ FileEditRequest,
12
+ FileEditResponse,
13
+ FileFindRequest,
14
+ FileFindResponse,
15
+ FileReadRequest,
16
+ FileReadResponse,
17
+ FileStatBatchRequest,
18
+ FileStatBatchResponse,
19
+ FileWriteRequest,
20
+ FileWriteResponse,
21
+ } from "../control/files.ts";
22
+ import type {
23
+ KvDeleteRequest,
24
+ KvDeleteResponse,
25
+ KvReadRequest,
26
+ KvReadResponse,
27
+ KvWriteRequest,
28
+ KvWriteResponse,
29
+ } from "../control/kv.ts";
30
+ import type {
31
+ LauncherConfigReadRequest,
32
+ LauncherConfigReadResponse,
33
+ LauncherRunRequest,
34
+ LauncherRunResponse,
35
+ } from "../control/launcher.ts";
36
+ import type {
37
+ LlmStatsReadRequest,
38
+ LlmStatsReadResponse,
39
+ LlmUsageReadRequest,
40
+ LlmUsageReadResponse,
41
+ } from "../control/llm.ts";
42
+ import type {
43
+ SandboxGrantRequest,
44
+ SandboxGrantResponse,
45
+ SandboxRevokeRequest,
46
+ SandboxRevokeResponse,
47
+ } from "../control/sandbox.ts";
48
+ import type {
49
+ SessionDumpWriteRequest,
50
+ SessionDumpWriteResponse,
51
+ SessionEnvReadRequest,
52
+ SessionEnvReadResponse,
53
+ SessionForkOriginRequest,
54
+ SessionForkOriginResponse,
55
+ SessionKillRequest,
56
+ SessionKillResponse,
57
+ SessionLastLiveRemoveRequest,
58
+ SessionLastLiveRemoveResponse,
59
+ SessionRenameRequest,
60
+ SessionRenameResponse,
61
+ SessionSearchRequest,
62
+ SessionSearchResponse,
63
+ } from "../control/session.ts";
64
+ import type { TranscriptReadRequest, TranscriptReadResponse } from "../control/transcript.ts";
65
+ import type { TranslateRunRequest, TranslateRunResponse } from "../control/translate.ts";
66
+ import { FIXTURE_IDS, FIXTURE_NOW } from "./ids.ts";
67
+
68
+ const { sid, other_sid, instance, request_id } = FIXTURE_IDS;
69
+
70
+ const WORKSPACE = "/repos/kawaz/ccmsg-protocol/main";
71
+ const FILE_PATH = "src/fixtures/index.ts";
72
+
73
+ export const SESSION_KILL_REQUEST: Static<typeof SessionKillRequest> = {
74
+ request_id,
75
+ op: "session_kill",
76
+ to_instance: instance,
77
+ sid,
78
+ force: false,
79
+ };
80
+
81
+ export const SESSION_KILL_RESPONSE: Static<typeof SessionKillResponse> = {
82
+ ok: true,
83
+ request_id,
84
+ terminated: true,
85
+ };
86
+
87
+ export const SESSION_RENAME_REQUEST: Static<typeof SessionRenameRequest> = {
88
+ request_id,
89
+ op: "session_rename",
90
+ sid,
91
+ title: "contract fixtures",
92
+ };
93
+
94
+ export const SESSION_RENAME_RESPONSE: Static<typeof SessionRenameResponse> = {
95
+ ok: true,
96
+ request_id,
97
+ terminal_id: "%17",
98
+ instance,
99
+ title: "contract fixtures",
100
+ };
101
+
102
+ export const SESSION_ENV_READ_REQUEST: Static<typeof SessionEnvReadRequest> = {
103
+ request_id,
104
+ op: "session_env_read",
105
+ sid,
106
+ };
107
+
108
+ export const SESSION_ENV_READ_RESPONSE: Static<typeof SessionEnvReadResponse> = {
109
+ ok: true,
110
+ request_id,
111
+ pid: 4821,
112
+ instance,
113
+ env: { CLAUDE_CONFIG_DIR: "/config/claude-personal", PWD: WORKSPACE },
114
+ };
115
+
116
+ export const SESSION_SEARCH_REQUEST: Static<typeof SessionSearchRequest> = {
117
+ request_id,
118
+ op: "session_search",
119
+ query: "fixture",
120
+ target_agent: true,
121
+ modified_within_ms: 86_400_000,
122
+ };
123
+
124
+ export const SESSION_SEARCH_RESPONSE: Static<typeof SessionSearchResponse> = {
125
+ ok: true,
126
+ request_id,
127
+ hits: [
128
+ {
129
+ sid,
130
+ instance,
131
+ config_dir: "/config/claude-personal",
132
+ file: "/transcripts/6f1a2b3c.jsonl",
133
+ cwd: WORKSPACE,
134
+ repo: "ccmsg-protocol",
135
+ ws: "main",
136
+ title: "contract fixtures",
137
+ created_at: FIXTURE_NOW - 3_600_000,
138
+ updated_at: FIXTURE_NOW,
139
+ size: 182_400,
140
+ matches: [{ role: "agent", text: "fixture を export する", said_at: FIXTURE_NOW }],
141
+ model: "claude-opus-5",
142
+ effort: "high",
143
+ },
144
+ ],
145
+ truncated: false,
146
+ };
147
+
148
+ export const SESSION_DUMP_WRITE_REQUEST: Static<typeof SessionDumpWriteRequest> = {
149
+ request_id,
150
+ op: "session_dump_write",
151
+ sid,
152
+ since_at: FIXTURE_NOW - 3_600_000,
153
+ no_thinking: true,
154
+ };
155
+
156
+ export const SESSION_DUMP_WRITE_RESPONSE: Static<typeof SessionDumpWriteResponse> = {
157
+ ok: true,
158
+ request_id,
159
+ path: "/transcripts/6f1a2b3c.dump.md",
160
+ instance,
161
+ entries: 128,
162
+ bytes: 65_536,
163
+ };
164
+
165
+ export const TRANSCRIPT_READ_REQUEST: Static<typeof TranscriptReadRequest> = {
166
+ request_id,
167
+ op: "transcript_read",
168
+ sid,
169
+ before: 182_400,
170
+ max_bytes: 65_536,
171
+ };
172
+
173
+ export const TRANSCRIPT_READ_RESPONSE: Static<typeof TranscriptReadResponse> = {
174
+ ok: true,
175
+ request_id,
176
+ sid,
177
+ lines: ['{"type":"assistant","text":"fixture を export した"}'],
178
+ start: 182_300,
179
+ end: 182_400,
180
+ size: 182_400,
181
+ };
182
+
183
+ export const SESSION_FORK_ORIGIN_REQUEST: Static<typeof SessionForkOriginRequest> = {
184
+ request_id,
185
+ op: "session_fork_origin",
186
+ sid,
187
+ };
188
+
189
+ export const SESSION_FORK_ORIGIN_RESPONSE: Static<typeof SessionForkOriginResponse> = {
190
+ ok: true,
191
+ request_id,
192
+ origin: { sid: other_sid, boundary_uuid: "6d1f0c2e-8a44-4b1e-9f30-5c7a2d9e4b81", copied: 128 },
193
+ };
194
+
195
+ export const SESSION_LAST_LIVE_REMOVE_REQUEST: Static<typeof SessionLastLiveRemoveRequest> = {
196
+ request_id,
197
+ op: "session_last_live_remove",
198
+ sid: other_sid,
199
+ };
200
+
201
+ export const SESSION_LAST_LIVE_REMOVE_RESPONSE: Static<typeof SessionLastLiveRemoveResponse> = {
202
+ ok: true,
203
+ request_id,
204
+ removed: true,
205
+ };
206
+
207
+ export const DIR_LIST_REQUEST: Static<typeof DirListRequest> = {
208
+ request_id,
209
+ op: "dir_list",
210
+ sid,
211
+ kind: "workspace",
212
+ path: "src/fixtures",
213
+ };
214
+
215
+ export const DIR_LIST_RESPONSE: Static<typeof DirListResponse> = {
216
+ ok: true,
217
+ request_id,
218
+ sid,
219
+ path: "src/fixtures",
220
+ entries: [
221
+ { name: "index.ts", type: "file", size: 2_048, mtime_at: FIXTURE_NOW },
222
+ { name: "topics.ts", type: "file", size: 4_096, mtime_at: FIXTURE_NOW },
223
+ ],
224
+ };
225
+
226
+ export const FILE_READ_REQUEST: Static<typeof FileReadRequest> = {
227
+ request_id,
228
+ op: "file_read",
229
+ sid,
230
+ kind: "workspace",
231
+ path: FILE_PATH,
232
+ };
233
+
234
+ export const FILE_READ_RESPONSE: Static<typeof FileReadResponse> = {
235
+ ok: true,
236
+ request_id,
237
+ sid,
238
+ path: FILE_PATH,
239
+ size: 2_048,
240
+ truncated: false,
241
+ binary: false,
242
+ content: "export const OP_FIXTURES = {} as const;\n",
243
+ mtime_at: FIXTURE_NOW,
244
+ };
245
+
246
+ export const FILE_WRITE_REQUEST: Static<typeof FileWriteRequest> = {
247
+ request_id,
248
+ op: "file_write",
249
+ sid,
250
+ path: FILE_PATH,
251
+ content: "export const OP_FIXTURES = {} as const;\n",
252
+ };
253
+
254
+ export const FILE_WRITE_RESPONSE: Static<typeof FileWriteResponse> = {
255
+ ok: true,
256
+ request_id,
257
+ sid,
258
+ path: FILE_PATH,
259
+ };
260
+
261
+ export const FILE_CREATE_REQUEST: Static<typeof FileCreateRequest> = {
262
+ request_id,
263
+ op: "file_create",
264
+ sid,
265
+ kind: "workspace",
266
+ path: "src/fixtures/ids.ts",
267
+ content: "export const FIXTURE_IDS = {} as const;\n",
268
+ };
269
+
270
+ export const FILE_CREATE_RESPONSE: Static<typeof FileCreateResponse> = {
271
+ ok: true,
272
+ request_id,
273
+ sid,
274
+ path: "src/fixtures/ids.ts",
275
+ };
276
+
277
+ export const FILE_EDIT_REQUEST: Static<typeof FileEditRequest> = {
278
+ request_id,
279
+ op: "file_edit",
280
+ sid,
281
+ kind: "workspace",
282
+ path: FILE_PATH,
283
+ content: "export const OP_FIXTURES = {} as const;\n",
284
+ expected_mtime_at: FIXTURE_NOW,
285
+ expected_size: 2_048,
286
+ };
287
+
288
+ export const FILE_EDIT_RESPONSE: Static<typeof FileEditResponse> = {
289
+ ok: true,
290
+ request_id,
291
+ sid,
292
+ path: FILE_PATH,
293
+ size: 2_112,
294
+ mtime_at: FIXTURE_NOW + 1_000,
295
+ };
296
+
297
+ export const FILE_DELETE_REQUEST: Static<typeof FileDeleteRequest> = {
298
+ request_id,
299
+ op: "file_delete",
300
+ sid,
301
+ kind: "workspace",
302
+ path: "src/fixtures/scratch.ts",
303
+ };
304
+
305
+ export const FILE_DELETE_RESPONSE: Static<typeof FileDeleteResponse> = {
306
+ ok: true,
307
+ request_id,
308
+ sid,
309
+ path: "src/fixtures/scratch.ts",
310
+ };
311
+
312
+ export const FILE_FIND_REQUEST: Static<typeof FileFindRequest> = {
313
+ request_id,
314
+ op: "file_find",
315
+ sid,
316
+ kind: "workspace",
317
+ root: "src",
318
+ query: "fixtures",
319
+ respect_gitignore: true,
320
+ };
321
+
322
+ export const FILE_FIND_RESPONSE: Static<typeof FileFindResponse> = {
323
+ ok: true,
324
+ request_id,
325
+ sid,
326
+ hits: [
327
+ { path: "src/fixtures", type: "dir" },
328
+ { path: FILE_PATH, type: "file" },
329
+ ],
330
+ truncated: false,
331
+ };
332
+
333
+ export const FILE_STAT_BATCH_REQUEST: Static<typeof FileStatBatchRequest> = {
334
+ request_id,
335
+ op: "file_stat_batch",
336
+ sid,
337
+ paths: [FILE_PATH, "/etc/hosts"],
338
+ };
339
+
340
+ /** A path the session may not reach answers `null` in its place rather than
341
+ * dropping out of the list, so the results line up with the paths asked for. */
342
+ export const FILE_STAT_BATCH_RESPONSE: Static<typeof FileStatBatchResponse> = {
343
+ ok: true,
344
+ request_id,
345
+ results: [{ kind: "workspace", path: FILE_PATH }, null],
346
+ };
347
+
348
+ export const DIR_TREE_REQUEST: Static<typeof DirTreeRequest> = {
349
+ request_id,
350
+ op: "dir_tree",
351
+ roots: ["/repos/kawaz"],
352
+ depth: 2,
353
+ filter: "ccmsg",
354
+ };
355
+
356
+ export const DIR_TREE_RESPONSE: Static<typeof DirTreeResponse> = {
357
+ ok: true,
358
+ request_id,
359
+ entries: [
360
+ {
361
+ path: "/repos/kawaz/ccmsg-protocol",
362
+ children: [{ path: WORKSPACE }],
363
+ },
364
+ ],
365
+ };
366
+
367
+ export const LAUNCHER_CONFIG_READ_REQUEST: Static<typeof LauncherConfigReadRequest> = {
368
+ request_id,
369
+ op: "launcher_config_read",
370
+ };
371
+
372
+ export const LAUNCHER_CONFIG_READ_RESPONSE: Static<typeof LauncherConfigReadResponse> = {
373
+ ok: true,
374
+ request_id,
375
+ root_dirs: ["/repos/kawaz"],
376
+ templates: [
377
+ {
378
+ name: "claude",
379
+ command: "claude --effort {effort}",
380
+ params: [{ name: "effort", default: "high" }],
381
+ },
382
+ ],
383
+ };
384
+
385
+ export const LAUNCHER_RUN_REQUEST: Static<typeof LauncherRunRequest> = {
386
+ request_id,
387
+ op: "launcher_run",
388
+ cwd: WORKSPACE,
389
+ params: { effort: "high" },
390
+ template: "claude",
391
+ };
392
+
393
+ export const LAUNCHER_RUN_RESPONSE: Static<typeof LauncherRunResponse> = {
394
+ ok: true,
395
+ request_id,
396
+ stdout: "started\n",
397
+ stderr: "",
398
+ exit_code: 0,
399
+ timed_out: false,
400
+ };
401
+
402
+ export const SANDBOX_GRANT_REQUEST: Static<typeof SandboxGrantRequest> = {
403
+ request_id,
404
+ op: "sandbox_grant",
405
+ sid,
406
+ kind: "workspace",
407
+ path: FILE_PATH,
408
+ };
409
+
410
+ export const SANDBOX_GRANT_RESPONSE: Static<typeof SandboxGrantResponse> = {
411
+ ok: true,
412
+ request_id,
413
+ gid: "g-01J9Z3W2Q",
414
+ token: "c2FuZGJveC10b2tlbg",
415
+ url: "https://mba.example.ts.net/ccmsg/personal/sandbox/g-01J9Z3W2Q/",
416
+ expires_at: FIXTURE_NOW + 600_000,
417
+ };
418
+
419
+ export const SANDBOX_REVOKE_REQUEST: Static<typeof SandboxRevokeRequest> = {
420
+ request_id,
421
+ op: "sandbox_revoke",
422
+ gid: "g-01J9Z3W2Q",
423
+ };
424
+
425
+ export const SANDBOX_REVOKE_RESPONSE: Static<typeof SandboxRevokeResponse> = {
426
+ ok: true,
427
+ request_id,
428
+ };
429
+
430
+ export const TRANSLATE_RUN_REQUEST: Static<typeof TranslateRunRequest> = {
431
+ request_id,
432
+ op: "translate_run",
433
+ texts: ["the contract's own fixtures", "one that the helper could not take"],
434
+ };
435
+
436
+ /** One text per result, each of them either the translation or why there is
437
+ * none. */
438
+ export const TRANSLATE_RUN_RESPONSE: Static<typeof TranslateRunResponse> = {
439
+ ok: true,
440
+ request_id,
441
+ results: [
442
+ { ok: true, text: "契約自身の fixture" },
443
+ { ok: false, error: "helper exited 1" },
444
+ ],
445
+ };
446
+
447
+ export const LLM_USAGE_READ_REQUEST: Static<typeof LlmUsageReadRequest> = {
448
+ request_id,
449
+ op: "llm_usage_read",
450
+ refresh: true,
451
+ };
452
+
453
+ export const LLM_USAGE_READ_RESPONSE: Static<typeof LlmUsageReadResponse> = {
454
+ ok: true,
455
+ request_id,
456
+ generated_at: FIXTURE_NOW,
457
+ credentials: [
458
+ {
459
+ name: "personal",
460
+ type: "oauth",
461
+ support: "full",
462
+ auth: { status: "ok", observed_at: FIXTURE_NOW },
463
+ snapshot: {
464
+ observed_at: FIXTURE_NOW,
465
+ overage: { status: "off" },
466
+ windows: {
467
+ five_hour: {
468
+ utilization: 0.42,
469
+ status: "allowed",
470
+ reset_at: FIXTURE_NOW + 7_200_000,
471
+ window_secs: 18_000,
472
+ },
473
+ },
474
+ },
475
+ limits: [
476
+ {
477
+ kind: "five_hour",
478
+ percent: 42,
479
+ severity: "ok",
480
+ resets_at: FIXTURE_NOW + 7_200_000,
481
+ is_active: true,
482
+ window_secs: 18_000,
483
+ },
484
+ ],
485
+ },
486
+ ],
487
+ };
488
+
489
+ export const LLM_STATS_READ_REQUEST: Static<typeof LlmStatsReadRequest> = {
490
+ request_id,
491
+ op: "llm_stats_read",
492
+ days: 7,
493
+ };
494
+
495
+ export const LLM_STATS_READ_RESPONSE: Static<typeof LlmStatsReadResponse> = {
496
+ ok: true,
497
+ request_id,
498
+ generated_at: FIXTURE_NOW,
499
+ days: {
500
+ "2026-09-08": {
501
+ credentials: {
502
+ personal: {
503
+ "claude-opus-5": {
504
+ requests: 12,
505
+ input_tokens: 48_000,
506
+ output_tokens: 6_400,
507
+ cache_creation_input_tokens: 12_000,
508
+ cache_read_input_tokens: 320_000,
509
+ usd: 1.23,
510
+ },
511
+ },
512
+ },
513
+ total_usd: 1.23,
514
+ },
515
+ },
516
+ };
517
+
518
+ export const KV_READ_REQUEST: Static<typeof KvReadRequest> = {
519
+ request_id,
520
+ op: "kv_read",
521
+ ns: "webui",
522
+ key: "layout",
523
+ };
524
+
525
+ export const KV_READ_RESPONSE: Static<typeof KvReadResponse> = {
526
+ ok: true,
527
+ request_id,
528
+ value: { pane: "peers", collapsed: false },
529
+ updated_at: FIXTURE_NOW,
530
+ };
531
+
532
+ export const KV_WRITE_REQUEST: Static<typeof KvWriteRequest> = {
533
+ request_id,
534
+ op: "kv_write",
535
+ ns: "webui",
536
+ key: "layout",
537
+ value: { pane: "peers", collapsed: true },
538
+ updated_at: FIXTURE_NOW,
539
+ };
540
+
541
+ export const KV_WRITE_RESPONSE: Static<typeof KvWriteResponse> = {
542
+ ok: true,
543
+ request_id,
544
+ updated_at: FIXTURE_NOW,
545
+ };
546
+
547
+ export const KV_DELETE_REQUEST: Static<typeof KvDeleteRequest> = {
548
+ request_id,
549
+ op: "kv_delete",
550
+ ns: "webui",
551
+ key: "layout",
552
+ };
553
+
554
+ export const KV_DELETE_RESPONSE: Static<typeof KvDeleteResponse> = {
555
+ ok: true,
556
+ request_id,
557
+ };
@@ -0,0 +1,15 @@
1
+ import type { ErrorResponse } from "../envelope.ts";
2
+ import { FIXTURE_IDS } from "./ids.ts";
3
+
4
+ export const ERROR_RESPONSE: ErrorResponse = {
5
+ ok: false,
6
+ request_id: FIXTURE_IDS.request_id,
7
+ error: { code: "capability_unavailable", msg: "launcher is not configured" },
8
+ };
9
+
10
+ /** The one reply that names no request: the frame could not be read far enough
11
+ * to find its correlation id. */
12
+ export const ERROR_RESPONSE_UNIDENTIFIED: ErrorResponse = {
13
+ ok: false,
14
+ error: { code: "bad_request", msg: "no request_id" },
15
+ };
@@ -0,0 +1,19 @@
1
+ /** The identifiers every fixture is built from.
2
+ *
3
+ * One session, one peer session, the instance the frames come from and one
4
+ * other instance, so a fixture that names two of anything names these. */
5
+ export const FIXTURE_IDS = {
6
+ sid: "6f1a2b3c-4d5e-4f60-8a91-b2c3d4e5f607",
7
+ other_sid: "0e9d8c7b-6a5f-4e3d-9c2b-1a0f9e8d7c6b",
8
+ instance: "3f9c1a7b5e2d48069c1a7b5e2d480691",
9
+ other_instance: "a1b2c3d4e5f60718293a4b5c6d7e8f90",
10
+ endpoint: "https://mba.example.ts.net/ccmsg/personal/",
11
+ other_endpoint: "https://nuc.example.ts.net/ccmsg/personal/",
12
+ mid: "3f9c1a7b5e2d48069c1a7b5e2d480691/1841",
13
+ request_id: "1",
14
+ } as const;
15
+
16
+ /** The instant the fixtures are written as happening at, with the few they
17
+ * derive from it. A fixture states a time in milliseconds since the epoch, as
18
+ * every `Timestamp` in the contract does. */
19
+ export const FIXTURE_NOW = 1_757_300_000_000;