@wrongstack/webui 0.260.0 → 0.265.1

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,1597 @@
1
+ import { Usage } from '@wrongstack/core';
2
+
3
+ interface WSMessage {
4
+ type: string;
5
+ payload: unknown;
6
+ }
7
+ interface WSSessionStart {
8
+ type: 'session.start';
9
+ payload: {
10
+ sessionId: string;
11
+ model: string;
12
+ provider: string;
13
+ maxContext?: number | undefined;
14
+ projectName?: string | undefined;
15
+ cwd?: string | undefined;
16
+ mode?: string | undefined;
17
+ contextMode?: string | undefined;
18
+ inputCost?: number | undefined;
19
+ outputCost?: number | undefined;
20
+ cacheReadCost?: number | undefined;
21
+ reset?: boolean | undefined;
22
+ replayMessages?: Array<{
23
+ role: string | undefined;
24
+ content: unknown;
25
+ }>;
26
+ replayUsage?: Usage | undefined;
27
+ /** True when no provider+model is configured yet — show the setup screen. */
28
+ needsSetup?: boolean | undefined;
29
+ };
30
+ }
31
+ interface WSSessionEnd {
32
+ type: 'session.end';
33
+ payload: {
34
+ sessionId: string;
35
+ usage: Usage;
36
+ totalCost: number;
37
+ };
38
+ }
39
+ interface WSUserMessage {
40
+ type: 'user_message';
41
+ payload: {
42
+ id: string;
43
+ content: string;
44
+ timestamp: number;
45
+ /** Base64-encoded clipboard image, if the user pasted one. */
46
+ imageBase64?: string;
47
+ };
48
+ }
49
+ interface WSTextDelta {
50
+ type: 'provider.text_delta';
51
+ payload: {
52
+ text: string;
53
+ messageId: string;
54
+ };
55
+ }
56
+ interface WSThinkingDelta {
57
+ type: 'provider.thinking_delta';
58
+ payload: {
59
+ text: string;
60
+ };
61
+ }
62
+ interface WSToolUseStart {
63
+ type: 'tool.started';
64
+ payload: {
65
+ id: string;
66
+ name: string;
67
+ input?: unknown | undefined;
68
+ messageId: string;
69
+ };
70
+ }
71
+ interface WSToolProgress {
72
+ type: 'tool.progress';
73
+ payload: {
74
+ name: string;
75
+ id: string;
76
+ event: {
77
+ type: 'log' | 'warning' | 'metric' | 'file_changed' | 'partial_output';
78
+ text?: string | undefined;
79
+ data?: Record<string, unknown>;
80
+ };
81
+ };
82
+ }
83
+ interface WSToolExecuted {
84
+ type: 'tool.executed';
85
+ payload: {
86
+ id: string;
87
+ name: string;
88
+ durationMs: number;
89
+ ok: boolean;
90
+ input?: unknown | undefined;
91
+ output?: string | undefined;
92
+ };
93
+ }
94
+ interface WSIterationStarted {
95
+ type: 'iteration.started';
96
+ payload: {
97
+ index: number;
98
+ maxIterations?: number | undefined;
99
+ };
100
+ }
101
+ interface WSIterationCompleted {
102
+ type: 'iteration.completed';
103
+ payload: {
104
+ index: number;
105
+ totalIterations: number;
106
+ };
107
+ }
108
+ interface WSProviderResponse {
109
+ type: 'provider.response';
110
+ payload: {
111
+ usage: Usage;
112
+ stopReason: string;
113
+ messageId: string;
114
+ };
115
+ }
116
+ interface WSRunResult {
117
+ type: 'run.result';
118
+ payload: {
119
+ status: 'done' | 'failed' | 'max_iterations' | 'aborted';
120
+ iterations: number;
121
+ finalText?: string | undefined;
122
+ error?: {
123
+ code: string;
124
+ message: string;
125
+ recoverable: boolean;
126
+ };
127
+ };
128
+ }
129
+ interface WSSessionStats {
130
+ type: 'session.stats';
131
+ payload: {
132
+ messages: number;
133
+ inputTokens: number;
134
+ outputTokens: number;
135
+ cacheReadTokens: number;
136
+ cost: number;
137
+ duration: number;
138
+ };
139
+ }
140
+ interface WSError {
141
+ type: 'error';
142
+ payload: {
143
+ phase: string;
144
+ message: string;
145
+ };
146
+ }
147
+ interface WSToolConfirmNeeded {
148
+ type: 'tool.confirm_needed';
149
+ payload: {
150
+ id: string;
151
+ toolName: string;
152
+ input: unknown;
153
+ suggestedPattern: string;
154
+ resolve: (decision: 'yes' | 'no' | 'always' | 'deny') => void;
155
+ };
156
+ }
157
+ interface WSToolConfirmResult {
158
+ type: 'tool.confirm_result';
159
+ payload: {
160
+ id: string;
161
+ decision: 'yes' | 'no' | 'always' | 'deny';
162
+ };
163
+ }
164
+ interface WSModelSwitch {
165
+ type: 'model.switch';
166
+ payload: {
167
+ provider: string;
168
+ model: string;
169
+ };
170
+ }
171
+ type MemoryScope = 'project-agents' | 'project-memory' | 'user-memory';
172
+ interface WSContextDebug {
173
+ type: 'context.debug';
174
+ payload: {
175
+ total: number;
176
+ mode?: string | undefined;
177
+ policy?: unknown | undefined;
178
+ systemPrompt: number;
179
+ tools: {
180
+ total: number;
181
+ count: number;
182
+ breakdown: Array<{
183
+ name: string;
184
+ tokens: number;
185
+ }>;
186
+ };
187
+ messages: {
188
+ total: number;
189
+ count: number;
190
+ breakdown: Array<{
191
+ index: number;
192
+ role: string;
193
+ tokens: number;
194
+ preview: string;
195
+ }>;
196
+ };
197
+ };
198
+ }
199
+ interface WSContextCompacted {
200
+ type: 'context.compacted';
201
+ payload: {
202
+ before: number;
203
+ after: number;
204
+ saved: number;
205
+ reductions: Array<{
206
+ phase: string;
207
+ saved: number;
208
+ }>;
209
+ repaired?: {
210
+ removedToolUses: string[];
211
+ removedToolResults: string[];
212
+ removedMessages: number;
213
+ };
214
+ };
215
+ }
216
+ interface WSContextRepaired {
217
+ type: 'context.repaired';
218
+ payload: {
219
+ removedToolUses: string[];
220
+ removedToolResults: string[];
221
+ removedMessages: number;
222
+ beforeMessages?: number | undefined;
223
+ afterMessages?: number | undefined;
224
+ };
225
+ }
226
+ interface WSContextModesList {
227
+ type: 'context.modes.list';
228
+ payload: {
229
+ activeId: string;
230
+ modes: Array<{
231
+ id: string;
232
+ name: string;
233
+ description: string;
234
+ isActive: boolean;
235
+ thresholds: {
236
+ warn: number;
237
+ soft: number;
238
+ hard: number;
239
+ };
240
+ preserveK: number;
241
+ eliseThreshold: number;
242
+ }>;
243
+ };
244
+ }
245
+ interface WSContextModeChanged {
246
+ type: 'context.mode.changed';
247
+ payload: {
248
+ id: string;
249
+ name: string;
250
+ policy: unknown;
251
+ };
252
+ }
253
+ interface WSToolsList {
254
+ type: 'tools.list';
255
+ payload: {
256
+ tools: Array<{
257
+ name: string;
258
+ description: string;
259
+ params: string[];
260
+ }>;
261
+ };
262
+ }
263
+ interface WSMemoryList {
264
+ type: 'memory.list';
265
+ payload: {
266
+ text: string;
267
+ error?: string | undefined;
268
+ };
269
+ }
270
+ interface WSSkillsList {
271
+ type: 'skills.list';
272
+ payload: {
273
+ enabled: boolean;
274
+ error?: string | undefined;
275
+ skills: Array<{
276
+ name: string;
277
+ description: string;
278
+ version: string;
279
+ source: string;
280
+ sourceUrl: string;
281
+ ref: string;
282
+ path: string;
283
+ trigger: string;
284
+ scope: string[];
285
+ }>;
286
+ };
287
+ }
288
+ interface WSSkillContent {
289
+ type: 'skills.content';
290
+ payload: {
291
+ name: string;
292
+ body: string;
293
+ path: string;
294
+ source: string;
295
+ relatedFiles: string[];
296
+ references: string[];
297
+ error?: string | undefined;
298
+ sourceUrl?: string;
299
+ };
300
+ }
301
+ interface WSSkillsInstalled {
302
+ type: 'skills.installed';
303
+ payload: {
304
+ success: boolean;
305
+ error: string | null;
306
+ results?: Array<{
307
+ name: string;
308
+ path: string;
309
+ scope: 'project' | 'user';
310
+ source: string;
311
+ ref: string;
312
+ skillCount: number;
313
+ }>;
314
+ };
315
+ }
316
+ interface WSSkillsUninstalled {
317
+ type: 'skills.uninstalled';
318
+ payload: {
319
+ success: boolean;
320
+ error: string | null;
321
+ };
322
+ }
323
+ interface WSSkillsUpdated {
324
+ type: 'skills.updated';
325
+ payload: {
326
+ success: boolean;
327
+ error: string | null;
328
+ updated?: Array<{
329
+ name: string;
330
+ oldRef: string;
331
+ newRef: string;
332
+ }>;
333
+ unchanged?: string[];
334
+ errors?: Array<{
335
+ name: string;
336
+ error: string;
337
+ }>;
338
+ };
339
+ }
340
+ interface WSSkillsCreated {
341
+ type: 'skills.created';
342
+ payload: {
343
+ success: boolean;
344
+ error: string | null;
345
+ skill?: {
346
+ name: string;
347
+ path: string;
348
+ scope: 'project' | 'user';
349
+ };
350
+ };
351
+ }
352
+ interface WSSkillsEdited {
353
+ type: 'skills.edited';
354
+ payload: {
355
+ success: boolean;
356
+ error: string | null;
357
+ };
358
+ }
359
+ interface WSSkillsExported {
360
+ type: 'skills.exported';
361
+ payload: {
362
+ /** Base64-encoded ZIP buffer containing all skills as SKILL.md files */
363
+ zipBase64: string;
364
+ skillCount: number;
365
+ error?: string | undefined;
366
+ };
367
+ }
368
+ interface WSDiagGet {
369
+ type: 'diag.get';
370
+ payload: {
371
+ provider: string;
372
+ model: string;
373
+ cwd: string;
374
+ sessionId: string;
375
+ tools: {
376
+ count: number;
377
+ names: string[];
378
+ };
379
+ features: {
380
+ memory: boolean;
381
+ skills: boolean;
382
+ modelsRegistry: boolean;
383
+ };
384
+ mode: string;
385
+ usage: {
386
+ input: number;
387
+ output: number;
388
+ cacheRead?: number | undefined;
389
+ };
390
+ messages: number;
391
+ todos: number;
392
+ };
393
+ }
394
+ interface WSStatsGet {
395
+ type: 'stats.get';
396
+ payload: {
397
+ sessionId: string;
398
+ provider: string;
399
+ model: string;
400
+ usage: {
401
+ input: number;
402
+ output: number;
403
+ cacheRead?: number | undefined;
404
+ cacheWrite?: number | undefined;
405
+ };
406
+ cache: {
407
+ readTokens: number;
408
+ writeTokens: number;
409
+ hitRatio: number;
410
+ } | null;
411
+ cost: number;
412
+ messages: number;
413
+ readFiles: number;
414
+ tools: number;
415
+ elapsedMs: number;
416
+ };
417
+ }
418
+ interface WSSessionsList {
419
+ type: 'sessions.list';
420
+ payload: {
421
+ sessions: Array<{
422
+ id: string;
423
+ title: string;
424
+ startedAt: string;
425
+ model: string;
426
+ provider: string;
427
+ tokenTotal: number;
428
+ isCurrent: boolean;
429
+ }>;
430
+ error?: string | undefined;
431
+ };
432
+ }
433
+ interface WSProviderCatalog {
434
+ type: 'provider.catalog';
435
+ payload: {
436
+ providers: Array<{
437
+ id: string;
438
+ name: string;
439
+ family: string;
440
+ apiBase?: string | undefined;
441
+ envVars: string[];
442
+ modelCount: number;
443
+ hasApiKey: boolean;
444
+ }>;
445
+ };
446
+ }
447
+ interface WSProviderModels {
448
+ type: 'provider.models';
449
+ payload: {
450
+ provider: string;
451
+ models: Array<{
452
+ id: string;
453
+ name: string;
454
+ releaseDate?: string | undefined;
455
+ contextWindow?: number | undefined;
456
+ inputCost?: number | undefined;
457
+ outputCost?: number | undefined;
458
+ capabilities: string[];
459
+ }>;
460
+ };
461
+ }
462
+ interface WSSavedProviders {
463
+ type: 'providers.saved';
464
+ payload: {
465
+ providers: Array<{
466
+ id: string;
467
+ family?: string | undefined;
468
+ baseUrl?: string | undefined;
469
+ /** Saved model allowlist, in the order the user pinned them. */
470
+ models?: string[] | undefined;
471
+ /** First entry of `models`, surfaced for the panel's "Using" line. */
472
+ pickedModelId?: string | undefined;
473
+ apiKeys: Array<{
474
+ label: string;
475
+ maskedKey: string;
476
+ isActive: boolean;
477
+ createdAt: string;
478
+ }>;
479
+ }>;
480
+ };
481
+ }
482
+ /**
483
+ * Health-probe result for a single provider, broadcast in reply to a
484
+ * `provider.probe` client message. Mirrors the `ProbeResult` shape
485
+ * from `@wrongstack/runtime/probe`, plus the `providerId` so panels
486
+ * can route the reply to the right card.
487
+ */
488
+ interface WSProviderProbe {
489
+ type: 'provider.probe';
490
+ payload: {
491
+ providerId: string;
492
+ ok: boolean;
493
+ status: string;
494
+ httpStatus?: number | undefined;
495
+ elapsedMs?: number | undefined;
496
+ modelCount?: number | undefined;
497
+ modelIds?: string[] | undefined;
498
+ detail?: string | undefined;
499
+ };
500
+ }
501
+ interface WSKeyOperationResult {
502
+ type: 'key.operation_result';
503
+ payload: {
504
+ success: boolean;
505
+ message: string;
506
+ };
507
+ }
508
+ interface WSFilesList {
509
+ type: 'files.list';
510
+ payload: {
511
+ files: string[];
512
+ };
513
+ }
514
+ interface WSTodosUpdated {
515
+ type: 'todos.updated';
516
+ payload: {
517
+ todos: Array<{
518
+ id: string;
519
+ content: string;
520
+ status: 'pending' | 'in_progress' | 'completed';
521
+ activeForm?: string | undefined;
522
+ }>;
523
+ };
524
+ }
525
+ interface WSModesList {
526
+ type: 'modes.list';
527
+ payload: {
528
+ modes: Array<{
529
+ id: string;
530
+ name: string;
531
+ description: string;
532
+ isActive: boolean;
533
+ }>;
534
+ activeId: string;
535
+ };
536
+ }
537
+ /** AutoPhase live state broadcast (see server/autophase-ws-handler.ts). */
538
+ interface WSAutoPhaseState {
539
+ type: 'autophase.state';
540
+ payload: Record<string, unknown>;
541
+ }
542
+ /** One worktree lane in the swim-lane / DAG view. */
543
+ interface WorktreeHandleView {
544
+ handleId: string;
545
+ ownerId: string;
546
+ ownerLabel: string;
547
+ branch: string;
548
+ baseBranch: string;
549
+ status: 'allocating' | 'active' | 'committing' | 'merging' | 'merged' | 'needs-review' | 'failed';
550
+ insertions: number;
551
+ deletions: number;
552
+ files: number;
553
+ conflictFiles?: string[] | undefined;
554
+ allocatedAt: number;
555
+ lastEventAt: number;
556
+ recentActivity: Array<{
557
+ kind: string;
558
+ text: string;
559
+ at: number;
560
+ }>;
561
+ }
562
+ /** Full worktree snapshot (broadcast on a timer, see worktree-ws-handler.ts). */
563
+ interface WSWorktreeState {
564
+ type: 'worktree.state';
565
+ payload: {
566
+ worktrees: WorktreeHandleView[];
567
+ baseBranch: string;
568
+ };
569
+ }
570
+ /** Incremental worktree lifecycle event — drives the flowing activity strip. */
571
+ interface WSWorktreeEvent {
572
+ type: 'worktree.event';
573
+ payload: {
574
+ kind: string;
575
+ handleId: string;
576
+ text: string;
577
+ at: number;
578
+ };
579
+ }
580
+ type WSClientMessage = WSUserMessage | WSToolConfirmResult | {
581
+ type: 'autophase.start';
582
+ payload: {
583
+ title: string;
584
+ phases?: unknown[] | undefined;
585
+ autonomous?: boolean | undefined;
586
+ };
587
+ } | {
588
+ type: 'autophase.pause';
589
+ payload: Record<string, never>;
590
+ } | {
591
+ type: 'autophase.resume';
592
+ payload: Record<string, never>;
593
+ } | {
594
+ type: 'autophase.stop';
595
+ payload: Record<string, never>;
596
+ } | {
597
+ type: 'autophase.toggleAutonomous';
598
+ payload: {
599
+ autonomous?: boolean | undefined;
600
+ };
601
+ } | {
602
+ type: 'autophase.selectPhase';
603
+ payload: {
604
+ phaseId: string;
605
+ };
606
+ } | {
607
+ type: 'autophase.taskStatus';
608
+ payload: {
609
+ taskId: string;
610
+ status: string;
611
+ };
612
+ } | {
613
+ type: 'abort';
614
+ payload: Record<string, never>;
615
+ } | {
616
+ type: 'session.resume';
617
+ payload: {
618
+ id: string;
619
+ };
620
+ } | {
621
+ type: 'session.new';
622
+ } | {
623
+ type: 'session.checkpoints';
624
+ } | {
625
+ type: 'session.rewind';
626
+ payload: {
627
+ checkpointIndex: number;
628
+ };
629
+ } | {
630
+ type: 'context.clear';
631
+ } | {
632
+ type: 'context.compact';
633
+ payload: {
634
+ aggressive: boolean;
635
+ };
636
+ } | {
637
+ type: 'context.repair';
638
+ } | {
639
+ type: 'context.debug';
640
+ } | {
641
+ type: 'context.modes.list';
642
+ } | {
643
+ type: 'context.mode.switch';
644
+ payload: {
645
+ id: string;
646
+ };
647
+ } | {
648
+ type: 'context.mode.create';
649
+ payload: {
650
+ id: string;
651
+ name: string;
652
+ description: string;
653
+ thresholds: {
654
+ warn: number;
655
+ soft: number;
656
+ hard: number;
657
+ };
658
+ preserveK: number;
659
+ eliseThreshold: number;
660
+ };
661
+ } | {
662
+ type: 'context.mode.update';
663
+ payload: {
664
+ id: string;
665
+ name?: string | undefined;
666
+ description?: string | undefined;
667
+ thresholds?: {
668
+ warn?: number | undefined;
669
+ soft?: number | undefined;
670
+ hard?: number | undefined;
671
+ } | undefined;
672
+ preserveK?: number | undefined;
673
+ eliseThreshold?: number | undefined;
674
+ };
675
+ } | {
676
+ type: 'context.mode.delete';
677
+ payload: {
678
+ id: string;
679
+ };
680
+ } | WSModelSwitch | {
681
+ type: 'providers.list';
682
+ } | {
683
+ type: 'provider.models';
684
+ payload: {
685
+ providerId: string;
686
+ };
687
+ } | {
688
+ type: 'providers.saved';
689
+ } | {
690
+ type: 'key.add';
691
+ payload: {
692
+ providerId: string;
693
+ label: string;
694
+ apiKey: string;
695
+ };
696
+ } | {
697
+ type: 'key.update';
698
+ payload: {
699
+ providerId: string;
700
+ label: string;
701
+ apiKey: string;
702
+ };
703
+ } | {
704
+ type: 'key.delete';
705
+ payload: {
706
+ providerId: string;
707
+ label: string;
708
+ };
709
+ } | {
710
+ type: 'key.set_active';
711
+ payload: {
712
+ providerId: string;
713
+ label: string;
714
+ };
715
+ } | {
716
+ type: 'provider.add';
717
+ payload: {
718
+ id: string;
719
+ family: string;
720
+ baseUrl?: string | undefined;
721
+ apiKey?: string | undefined;
722
+ };
723
+ } | {
724
+ type: 'provider.remove';
725
+ payload: {
726
+ providerId: string;
727
+ };
728
+ } | {
729
+ type: 'provider.clear_models';
730
+ payload: {
731
+ providerId: string;
732
+ };
733
+ } | {
734
+ type: 'provider.undo_clear';
735
+ payload: {
736
+ providerId: string;
737
+ previousModels: string[];
738
+ };
739
+ } | {
740
+ type: 'provider.update';
741
+ payload: {
742
+ id: string;
743
+ family?: string | undefined;
744
+ baseUrl?: string | undefined;
745
+ envVars?: string[] | undefined;
746
+ models?: string[] | undefined;
747
+ };
748
+ } | {
749
+ type: 'provider.probe';
750
+ payload: {
751
+ providerId: string;
752
+ timeoutMs?: number | undefined;
753
+ };
754
+ } | {
755
+ type: 'tools.list';
756
+ } | {
757
+ type: 'memory.list';
758
+ } | {
759
+ type: 'memory.remember';
760
+ payload: {
761
+ text: string;
762
+ scope?: MemoryScope | undefined;
763
+ };
764
+ } | {
765
+ type: 'memory.forget';
766
+ payload: {
767
+ text: string;
768
+ scope?: MemoryScope | undefined;
769
+ };
770
+ } | {
771
+ type: 'skills.list';
772
+ } | {
773
+ type: 'skills.content';
774
+ payload: {
775
+ name: string;
776
+ source: string;
777
+ };
778
+ } | {
779
+ type: 'diag.get';
780
+ } | {
781
+ type: 'stats.get';
782
+ } | {
783
+ type: 'session.save';
784
+ } | {
785
+ type: 'sessions.list';
786
+ payload: {
787
+ limit: number;
788
+ };
789
+ } | {
790
+ type: 'session.delete';
791
+ payload: {
792
+ id: string;
793
+ };
794
+ } | {
795
+ type: 'modes.list';
796
+ } | {
797
+ type: 'mode.switch';
798
+ payload: {
799
+ id: string;
800
+ };
801
+ } | {
802
+ type: 'files.list';
803
+ payload: {
804
+ query?: string | undefined;
805
+ limit?: number | undefined;
806
+ path?: string | undefined;
807
+ };
808
+ } | {
809
+ type: 'files.tree';
810
+ payload: {
811
+ path?: string | undefined;
812
+ } | Record<string, never>;
813
+ } | {
814
+ type: 'files.read';
815
+ payload: {
816
+ filePath: string;
817
+ };
818
+ } | {
819
+ type: 'files.write';
820
+ payload: {
821
+ filePath: string;
822
+ content: string;
823
+ };
824
+ } | {
825
+ type: 'todos.get';
826
+ } | {
827
+ type: 'todos.clear';
828
+ } | {
829
+ type: 'todos.remove';
830
+ payload: {
831
+ id?: string | undefined;
832
+ index?: number | undefined;
833
+ };
834
+ } | {
835
+ type: 'todo.update';
836
+ payload: {
837
+ id: string;
838
+ status?: 'pending' | 'in_progress' | 'completed' | undefined;
839
+ activeForm?: string | undefined;
840
+ };
841
+ } | {
842
+ type: 'tasks.get';
843
+ } | {
844
+ type: 'task.update';
845
+ payload: {
846
+ id: string;
847
+ status: string;
848
+ };
849
+ } | {
850
+ type: 'plan.get';
851
+ } | {
852
+ type: 'plan.item.update';
853
+ payload: {
854
+ target: string;
855
+ status: 'open' | 'in_progress' | 'done';
856
+ };
857
+ } | {
858
+ type: 'ping';
859
+ } | {
860
+ type: 'process.list';
861
+ } | {
862
+ type: 'process.kill';
863
+ payload: {
864
+ pid: number;
865
+ };
866
+ } | {
867
+ type: 'process.killAll';
868
+ } | {
869
+ type: 'git.info';
870
+ } | {
871
+ type: 'goal.get';
872
+ } | {
873
+ type: 'autonomy.switch';
874
+ payload: {
875
+ mode: string;
876
+ };
877
+ } | {
878
+ type: 'prefs.update';
879
+ payload: Record<string, unknown>;
880
+ } | {
881
+ type: 'prefs.get';
882
+ } | {
883
+ type: 'projects.list';
884
+ } | {
885
+ type: 'projects.add';
886
+ payload: {
887
+ root: string;
888
+ name?: string | undefined;
889
+ };
890
+ } | {
891
+ type: 'projects.select';
892
+ payload: {
893
+ root: string;
894
+ name?: string | undefined;
895
+ };
896
+ } | {
897
+ type: 'working_dir.set';
898
+ payload: {
899
+ path: string;
900
+ };
901
+ } | {
902
+ type: 'shell.open';
903
+ payload: {
904
+ path: string;
905
+ target: 'terminal' | 'file-manager';
906
+ };
907
+ } | WSCollabJoin | WSCollabLeave | WSCollabAnnotate | WSCollabResolve | WSCollabRequestPause | WSCollabResume | WSCollabGrantControl | WSCollabInjectTool | {
908
+ type: 'mailbox.messages';
909
+ payload: {
910
+ limit?: number | undefined;
911
+ incompleteOnly?: boolean | undefined;
912
+ };
913
+ } | {
914
+ type: 'mailbox.agents';
915
+ payload: {
916
+ onlineOnly?: boolean | undefined;
917
+ } | Record<string, never>;
918
+ } | {
919
+ type: 'mailbox.clear';
920
+ } | {
921
+ type: 'mailbox.purge';
922
+ payload?: {
923
+ completedMaxAgeMs?: number;
924
+ incompleteMaxAgeMs?: number;
925
+ } | undefined;
926
+ } | {
927
+ type: 'brain.status';
928
+ } | {
929
+ type: 'brain.risk';
930
+ payload: {
931
+ level: string;
932
+ };
933
+ } | {
934
+ type: 'brain.ask';
935
+ payload: {
936
+ question: string;
937
+ };
938
+ } | {
939
+ type: 'model.refine';
940
+ payload: {
941
+ text: string;
942
+ };
943
+ } | {
944
+ type: 'skills.list';
945
+ } | {
946
+ type: 'skills.content';
947
+ payload: {
948
+ name: string;
949
+ source: string;
950
+ };
951
+ } | {
952
+ type: 'skills.install';
953
+ payload: {
954
+ ref: string;
955
+ global?: boolean;
956
+ };
957
+ } | {
958
+ type: 'skills.uninstall';
959
+ payload: {
960
+ name: string;
961
+ global?: boolean;
962
+ };
963
+ } | {
964
+ type: 'skills.update';
965
+ payload: {
966
+ name?: string;
967
+ global?: boolean;
968
+ };
969
+ } | {
970
+ type: 'skills.create';
971
+ payload: {
972
+ name: string;
973
+ description: string;
974
+ scope: 'project' | 'global';
975
+ };
976
+ } | {
977
+ type: 'skills.export';
978
+ payload?: Record<string, unknown>;
979
+ } | {
980
+ type: 'skills.edit';
981
+ payload: {
982
+ name: string;
983
+ body: string;
984
+ };
985
+ } | {
986
+ type: 'mcp.list';
987
+ } | {
988
+ type: 'mcp.add';
989
+ payload: {
990
+ name: string;
991
+ transport: string;
992
+ description?: string;
993
+ enabled?: boolean;
994
+ command?: string;
995
+ args?: string[];
996
+ env?: Record<string, string>;
997
+ allowedTools?: string[];
998
+ };
999
+ } | {
1000
+ type: 'mcp.remove';
1001
+ payload: {
1002
+ name: string;
1003
+ };
1004
+ } | {
1005
+ type: 'mcp.update';
1006
+ payload: {
1007
+ name: string;
1008
+ transport?: string;
1009
+ description?: string;
1010
+ enabled?: boolean;
1011
+ command?: string;
1012
+ args?: string[];
1013
+ env?: Record<string, string>;
1014
+ allowedTools?: string[];
1015
+ };
1016
+ } | {
1017
+ type: 'mcp.wake';
1018
+ payload: {
1019
+ name: string;
1020
+ };
1021
+ } | {
1022
+ type: 'mcp.sleep';
1023
+ payload: {
1024
+ name: string;
1025
+ };
1026
+ } | {
1027
+ type: 'mcp.discover';
1028
+ payload: {
1029
+ name: string;
1030
+ };
1031
+ } | {
1032
+ type: 'mcp.enable';
1033
+ payload: {
1034
+ name: string;
1035
+ };
1036
+ } | {
1037
+ type: 'mcp.disable';
1038
+ payload: {
1039
+ name: string;
1040
+ };
1041
+ } | {
1042
+ type: 'mcp.restart';
1043
+ payload: {
1044
+ name: string;
1045
+ };
1046
+ } | {
1047
+ type: 'plan.template_use';
1048
+ payload: {
1049
+ template: string;
1050
+ };
1051
+ } | {
1052
+ type: 'webui.shutdown';
1053
+ };
1054
+ type WSServerMessage = WSSessionStart | WSSessionEnd | WSTextDelta | WSThinkingDelta | WSToolUseStart | WSToolProgress | WSToolExecuted | WSIterationStarted | WSIterationCompleted | WSProviderResponse | WSRunResult | WSSessionStats | WSError | WSToolConfirmNeeded | WSContextDebug | WSContextCompacted | WSContextRepaired | WSContextModesList | WSContextModeChanged | WSToolsList | WSMemoryList | WSSkillsList | WSSkillContent | WSSkillsInstalled | WSSkillsUninstalled | WSSkillsUpdated | WSSkillsCreated | WSSkillsEdited | WSSkillsExported | WSDiagGet | WSStatsGet | WSSessionsList | WSProviderCatalog | WSProviderModels | WSSavedProviders | WSProviderProbe | WSKeyOperationResult | WSFilesList | {
1055
+ type: 'files.tree';
1056
+ payload: {
1057
+ root: string;
1058
+ tree: unknown[];
1059
+ error?: string | undefined;
1060
+ };
1061
+ } | {
1062
+ type: 'files.read';
1063
+ payload: {
1064
+ filePath: string;
1065
+ content: string;
1066
+ error?: string | undefined;
1067
+ };
1068
+ } | {
1069
+ type: 'files.written';
1070
+ payload: {
1071
+ filePath: string;
1072
+ success: boolean;
1073
+ error?: string | undefined;
1074
+ };
1075
+ } | WSTodosUpdated | {
1076
+ type: 'tasks.updated';
1077
+ payload: {
1078
+ tasks: unknown[];
1079
+ error?: string | undefined;
1080
+ };
1081
+ } | {
1082
+ type: 'plan.updated';
1083
+ payload: {
1084
+ plan: unknown | null;
1085
+ error?: string | undefined;
1086
+ };
1087
+ } | WSModesList | WSAutoPhaseState | WSWorktreeState | WSWorktreeEvent | WSCollabState | WSCollabParticipantJoined | WSCollabParticipantLeft | WSCollabEvent | WSCollabAnnotationAdded | WSCollabAnnotationResolved | WSCollabPauseGranted | WSCollabPauseReleased | WSCollabInjectionGranted | {
1088
+ type: 'session.checkpoints';
1089
+ payload: {
1090
+ checkpoints: Array<{
1091
+ index: number;
1092
+ iteration: number;
1093
+ timestamp: string;
1094
+ label: string;
1095
+ messageCount: number;
1096
+ tokens: number;
1097
+ }>;
1098
+ };
1099
+ } | {
1100
+ type: 'goal.updated';
1101
+ payload: Record<string, unknown> | null;
1102
+ } | {
1103
+ type: 'prefs.updated';
1104
+ payload: Record<string, unknown>;
1105
+ } | {
1106
+ type: 'process.list';
1107
+ payload: {
1108
+ processes: Array<{
1109
+ pid: number;
1110
+ command: string;
1111
+ tool: string;
1112
+ startedAt: number;
1113
+ status: 'running' | 'exited' | 'killed';
1114
+ protected?: boolean | undefined;
1115
+ }>;
1116
+ };
1117
+ } | {
1118
+ type: 'git.info';
1119
+ payload: {
1120
+ branch: string;
1121
+ added: number;
1122
+ deleted: number;
1123
+ untracked: number;
1124
+ behind: number;
1125
+ ahead: number;
1126
+ };
1127
+ } | {
1128
+ type: 'projects.list';
1129
+ payload: {
1130
+ projects: Array<{
1131
+ name: string;
1132
+ root: string;
1133
+ slug: string;
1134
+ lastSeen?: string | undefined;
1135
+ }>;
1136
+ };
1137
+ } | {
1138
+ type: 'projects.added';
1139
+ payload: {
1140
+ name: string;
1141
+ root: string;
1142
+ slug: string;
1143
+ message: string;
1144
+ };
1145
+ } | {
1146
+ type: 'projects.selected';
1147
+ payload: {
1148
+ root: string;
1149
+ name: string;
1150
+ message: string;
1151
+ };
1152
+ } | {
1153
+ type: 'working_dir.changed';
1154
+ payload: {
1155
+ cwd: string;
1156
+ projectRoot: string;
1157
+ };
1158
+ } | {
1159
+ type: 'brain.status';
1160
+ payload: {
1161
+ maxAutoRisk: string;
1162
+ log: Array<{
1163
+ at: number;
1164
+ kind: string;
1165
+ question: string;
1166
+ outcome: string;
1167
+ }>;
1168
+ };
1169
+ } | {
1170
+ type: 'brain.answer';
1171
+ payload: {
1172
+ question: string;
1173
+ decision: {
1174
+ type: string;
1175
+ optionId?: string | undefined;
1176
+ text?: string | undefined;
1177
+ rationale?: string | undefined;
1178
+ reason?: string | undefined;
1179
+ prompt?: string | undefined;
1180
+ };
1181
+ };
1182
+ } | {
1183
+ type: 'brain.event';
1184
+ payload: Record<string, unknown> & {
1185
+ event: string;
1186
+ };
1187
+ } | {
1188
+ type: 'model.refine_result';
1189
+ payload: {
1190
+ refined: string;
1191
+ english: string;
1192
+ error?: string | undefined;
1193
+ };
1194
+ } | {
1195
+ type: 'coordinator.status';
1196
+ payload: {
1197
+ status: 'idle' | 'running' | 'draining' | 'stopped';
1198
+ mode?: string;
1199
+ subagentCount?: number;
1200
+ taskQueue?: {
1201
+ pending: number;
1202
+ running: number;
1203
+ completed: number;
1204
+ failed: number;
1205
+ };
1206
+ };
1207
+ } | {
1208
+ type: 'coordinator.stats';
1209
+ payload: {
1210
+ total: number;
1211
+ running: number;
1212
+ idle: number;
1213
+ stopped: number;
1214
+ inFlight: number;
1215
+ pending: number;
1216
+ completed: number;
1217
+ subagentStatuses?: Array<{
1218
+ id: string;
1219
+ name: string;
1220
+ status: string;
1221
+ currentTask?: string;
1222
+ }>;
1223
+ };
1224
+ } | {
1225
+ type: 'budget.threshold_reached';
1226
+ payload: {
1227
+ subagentId: string;
1228
+ taskId?: string;
1229
+ ts: number;
1230
+ kind: string;
1231
+ used: number;
1232
+ limit: number;
1233
+ timeoutMs: number;
1234
+ };
1235
+ } | {
1236
+ type: 'budget.decision';
1237
+ payload: {
1238
+ subagentId: string;
1239
+ kind: string;
1240
+ decision: 'extend' | 'deny';
1241
+ extended?: {
1242
+ timeoutMs?: number;
1243
+ maxIterations?: number;
1244
+ maxToolCalls?: number;
1245
+ };
1246
+ };
1247
+ } | {
1248
+ type: 'subagent.budget_extended';
1249
+ payload: {
1250
+ subagentId: string;
1251
+ kind: string;
1252
+ extendedMs?: number;
1253
+ extendedTo?: number;
1254
+ };
1255
+ } | {
1256
+ type: 'consensus.vote_initiated';
1257
+ payload: {
1258
+ changeId: string;
1259
+ title: string;
1260
+ eligible: Array<{
1261
+ agentId: string;
1262
+ agentName: string;
1263
+ }>;
1264
+ };
1265
+ } | {
1266
+ type: 'consensus.vote_cast';
1267
+ payload: {
1268
+ changeId: string;
1269
+ voterId: string;
1270
+ value: 'approve' | 'reject' | 'abstain';
1271
+ };
1272
+ } | {
1273
+ type: 'consensus.vote_resolved';
1274
+ payload: {
1275
+ changeId: string;
1276
+ result: 'approved' | 'rejected' | 'vetoed' | 'quorum_not_met';
1277
+ approveCount: number;
1278
+ rejectCount: number;
1279
+ };
1280
+ } | {
1281
+ type: 'task.pending';
1282
+ payload: {
1283
+ taskId: string;
1284
+ description: string;
1285
+ priority?: number;
1286
+ };
1287
+ } | {
1288
+ type: 'task.started';
1289
+ payload: {
1290
+ taskId: string;
1291
+ subagentId: string;
1292
+ };
1293
+ } | {
1294
+ type: 'task.completed';
1295
+ payload: {
1296
+ taskId: string;
1297
+ subagentId: string;
1298
+ status: string;
1299
+ durationMs: number;
1300
+ };
1301
+ } | {
1302
+ type: 'task.failed';
1303
+ payload: {
1304
+ taskId: string;
1305
+ subagentId: string;
1306
+ error: string;
1307
+ };
1308
+ } | {
1309
+ type: 'mcp.list';
1310
+ payload: {
1311
+ servers: Array<{
1312
+ name: string;
1313
+ transport: string;
1314
+ status: string;
1315
+ enabled: boolean;
1316
+ description?: string;
1317
+ tools?: string[];
1318
+ error?: string;
1319
+ pid?: number;
1320
+ }>;
1321
+ };
1322
+ } | {
1323
+ type: 'mcp.server.added';
1324
+ payload: {
1325
+ server: {
1326
+ name: string;
1327
+ transport: string;
1328
+ status: string;
1329
+ enabled: boolean;
1330
+ description?: string;
1331
+ tools?: string[];
1332
+ };
1333
+ };
1334
+ } | {
1335
+ type: 'mcp.server.removed';
1336
+ payload: {
1337
+ name: string;
1338
+ };
1339
+ } | {
1340
+ type: 'mcp.server.updated';
1341
+ payload: {
1342
+ server: {
1343
+ name: string;
1344
+ transport: string;
1345
+ status: string;
1346
+ enabled: boolean;
1347
+ description?: string;
1348
+ tools?: string[];
1349
+ };
1350
+ };
1351
+ } | {
1352
+ type: 'mcp.server.discovered';
1353
+ payload: {
1354
+ name: string;
1355
+ tools: string[];
1356
+ };
1357
+ } | {
1358
+ type: 'mcp.server.sleeping';
1359
+ payload: {
1360
+ name: string;
1361
+ };
1362
+ } | {
1363
+ type: 'mcp.server.waking';
1364
+ payload: {
1365
+ name: string;
1366
+ };
1367
+ } | {
1368
+ type: 'mcp.server.connected';
1369
+ payload: {
1370
+ name: string;
1371
+ pid?: number;
1372
+ };
1373
+ } | {
1374
+ type: 'mcp.server.error';
1375
+ payload: {
1376
+ name: string;
1377
+ error: string;
1378
+ };
1379
+ } | {
1380
+ type: 'mcp.operation_result';
1381
+ payload: {
1382
+ success: boolean;
1383
+ message: string;
1384
+ };
1385
+ };
1386
+ type BroadcastFn = (msg: WSServerMessage) => void;
1387
+ /** Narrow type for CollabPanel event handlers — only collab-related messages + errors. */
1388
+ type CollabPanelMessage = WSCollabState | WSCollabParticipantJoined | WSCollabParticipantLeft | WSCollabAnnotationAdded | WSCollabAnnotationResolved | WSCollabPauseGranted | WSCollabPauseReleased | WSCollabInjectionGranted | WSError;
1389
+ /**
1390
+ * Roles a collaboration participant can hold. The string union is the
1391
+ * wire contract — adding new roles (e.g. `controller`) in later phases
1392
+ * is a backward-compatible widening of this type as long as the server
1393
+ * gracefully rejects roles it does not yet implement.
1394
+ */
1395
+ type CollabRole = 'observer' | 'annotator' | 'controller';
1396
+ interface WSCollabJoin {
1397
+ type: 'collab.join';
1398
+ payload: {
1399
+ sessionId: string;
1400
+ role: CollabRole;
1401
+ };
1402
+ }
1403
+ interface WSCollabLeave {
1404
+ type: 'collab.leave';
1405
+ payload: {
1406
+ sessionId: string;
1407
+ };
1408
+ }
1409
+ /**
1410
+ * Annotate a specific event in the session log. The `atEventIndex`
1411
+ * is a stable pointer the UI can scroll to / highlight. The server
1412
+ * persists the annotation and broadcasts it to every participant
1413
+ * in the same session, including the author.
1414
+ */
1415
+ interface WSCollabAnnotate {
1416
+ type: 'collab.annotate';
1417
+ payload: {
1418
+ sessionId: string;
1419
+ atEventIndex: number;
1420
+ text: string;
1421
+ };
1422
+ }
1423
+ /** Mark an existing annotation as resolved. */
1424
+ interface WSCollabResolve {
1425
+ type: 'collab.resolve';
1426
+ payload: {
1427
+ sessionId: string;
1428
+ annotationId: string;
1429
+ };
1430
+ }
1431
+ /** Sent on connect and every 2s while at least one participant is watching. */
1432
+ interface WSCollabState {
1433
+ type: 'collab.state';
1434
+ payload: {
1435
+ sessionId: string;
1436
+ participants: Array<{
1437
+ participantId: string;
1438
+ role: CollabRole;
1439
+ joinedAt: string;
1440
+ }>;
1441
+ };
1442
+ }
1443
+ /** Broadcast when a new participant joins the session. */
1444
+ interface WSCollabParticipantJoined {
1445
+ type: 'collab.participant.joined';
1446
+ payload: {
1447
+ participantId: string;
1448
+ sessionId: string;
1449
+ role: CollabRole;
1450
+ joinedAt: string;
1451
+ };
1452
+ }
1453
+ /** Broadcast when a participant leaves (explicit leave or WS close/error). */
1454
+ interface WSCollabParticipantLeft {
1455
+ type: 'collab.participant.left';
1456
+ payload: {
1457
+ participantId: string;
1458
+ sessionId: string;
1459
+ };
1460
+ }
1461
+ /** Broadcast when a new annotation is added. Sent to all participants. */
1462
+ interface WSCollabAnnotationAdded {
1463
+ type: 'collab.annotation.added';
1464
+ payload: {
1465
+ sessionId: string;
1466
+ annotation: {
1467
+ id: string;
1468
+ atEventIndex: number;
1469
+ authorId: string;
1470
+ authorRole: 'annotator';
1471
+ text: string;
1472
+ createdAt: string;
1473
+ resolved: boolean;
1474
+ };
1475
+ };
1476
+ }
1477
+ /** Broadcast when an annotation is resolved. Sent to all participants. */
1478
+ interface WSCollabAnnotationResolved {
1479
+ type: 'collab.annotation.resolved';
1480
+ payload: {
1481
+ sessionId: string;
1482
+ annotationId: string;
1483
+ resolvedBy: string;
1484
+ resolvedAt: string;
1485
+ };
1486
+ }
1487
+ /** Client → server: controller asks the agent loop to pause before the next tool call. */
1488
+ interface WSCollabRequestPause {
1489
+ type: 'collab.request_pause';
1490
+ payload: {
1491
+ sessionId: string;
1492
+ };
1493
+ }
1494
+ /** Client → server: controller (or owner) clears the pause. */
1495
+ interface WSCollabResume {
1496
+ type: 'collab.resume';
1497
+ payload: {
1498
+ sessionId: string;
1499
+ };
1500
+ }
1501
+ /**
1502
+ * Client → server: owner hands the controller role to a different
1503
+ * participant. The current implementation is metadata-only — the
1504
+ * existing controller's effective permissions don't change yet;
1505
+ * the wire is reserved for a future iteration where per-participant
1506
+ * RBAC becomes dynamic.
1507
+ */
1508
+ interface WSCollabGrantControl {
1509
+ type: 'collab.grant_control';
1510
+ payload: {
1511
+ sessionId: string;
1512
+ toParticipant: string;
1513
+ };
1514
+ }
1515
+ /** Server → client: the bus transitioned to paused (controller's pause took effect). */
1516
+ interface WSCollabPauseGranted {
1517
+ type: 'collab.pause.granted';
1518
+ payload: {
1519
+ sessionId: string;
1520
+ pausedBy: string;
1521
+ pausedAt: string;
1522
+ /**
1523
+ * How long until the middleware auto-resumes (in ms). Clients
1524
+ * can render a countdown. Defaults to 60_000 on the server.
1525
+ */
1526
+ autoResumeInMs: number;
1527
+ };
1528
+ }
1529
+ /** Server → client: the bus transitioned back to running. */
1530
+ interface WSCollabPauseReleased {
1531
+ type: 'collab.pause.released';
1532
+ payload: {
1533
+ sessionId: string;
1534
+ /** 'controller' when a participant asked; 'timeout' when the middleware fired auto-resume. */
1535
+ reason: 'controller' | 'timeout';
1536
+ at: string;
1537
+ };
1538
+ }
1539
+ /**
1540
+ * Generic envelope wrapping a kernel event mirrored to observers.
1541
+ * `kind` matches the original kernel event name (e.g. `tool.started`),
1542
+ * `payload` is the original event payload (best-effort serialized),
1543
+ * `at` is the broadcast timestamp.
1544
+ *
1545
+ * `replay` is true when the event was sent from the on-disk session
1546
+ * log to a late-joining observer (Phase 1.5). Live events leave it
1547
+ * undefined. Clients use the flag to render a "history" affordance
1548
+ * (e.g. dim the styling or annotate the timestamp as "[joined late]").
1549
+ */
1550
+ interface WSCollabEvent {
1551
+ type: 'collab.event';
1552
+ payload: {
1553
+ kind: string;
1554
+ payload: unknown;
1555
+ at: string;
1556
+ replay?: boolean | undefined;
1557
+ };
1558
+ }
1559
+ /**
1560
+ * Client → server: a controller injects a synthetic tool_result for
1561
+ * the given tool_use_id. The next time the agent's toolCall pipeline
1562
+ * sees that id, the real tool is skipped and the injected content
1563
+ * is used. The injection is one-shot — consumed on first match.
1564
+ */
1565
+ interface WSCollabInjectTool {
1566
+ type: 'collab.inject_tool';
1567
+ payload: {
1568
+ sessionId: string;
1569
+ toolUseId: string;
1570
+ /** String or JSON-serializable value. */
1571
+ content: unknown;
1572
+ isError: boolean;
1573
+ /** Free-form context surfaced in the broadcast and audit log. */
1574
+ reason: string;
1575
+ };
1576
+ }
1577
+ /**
1578
+ * Server → client: an injection was queued or consumed. Sent to
1579
+ * every participant so observers can show "the controller just
1580
+ * replaced the tool result for tool X".
1581
+ */
1582
+ interface WSCollabInjectionGranted {
1583
+ type: 'collab.injection.granted';
1584
+ payload: {
1585
+ sessionId: string;
1586
+ toolUseId: string;
1587
+ toolName: string;
1588
+ authorId: string;
1589
+ reason: string;
1590
+ isError: boolean;
1591
+ /** 'queued' or 'consumed' — the bus does both. */
1592
+ phase: 'queued' | 'consumed';
1593
+ at: string;
1594
+ };
1595
+ }
1596
+
1597
+ export type { BroadcastFn, CollabPanelMessage, CollabRole, MemoryScope, WSAutoPhaseState, WSClientMessage, WSCollabAnnotate, WSCollabAnnotationAdded, WSCollabAnnotationResolved, WSCollabEvent, WSCollabGrantControl, WSCollabInjectTool, WSCollabInjectionGranted, WSCollabJoin, WSCollabLeave, WSCollabParticipantJoined, WSCollabParticipantLeft, WSCollabPauseGranted, WSCollabPauseReleased, WSCollabRequestPause, WSCollabResolve, WSCollabResume, WSCollabState, WSContextCompacted, WSContextDebug, WSContextModeChanged, WSContextModesList, WSContextRepaired, WSDiagGet, WSError, WSFilesList, WSIterationCompleted, WSIterationStarted, WSKeyOperationResult, WSMemoryList, WSMessage, WSModelSwitch, WSModesList, WSProviderCatalog, WSProviderModels, WSProviderProbe, WSProviderResponse, WSRunResult, WSSavedProviders, WSServerMessage, WSSessionEnd, WSSessionStart, WSSessionStats, WSSessionsList, WSSkillContent, WSSkillsCreated, WSSkillsEdited, WSSkillsExported, WSSkillsInstalled, WSSkillsList, WSSkillsUninstalled, WSSkillsUpdated, WSStatsGet, WSTextDelta, WSThinkingDelta, WSTodosUpdated, WSToolConfirmNeeded, WSToolConfirmResult, WSToolExecuted, WSToolProgress, WSToolUseStart, WSToolsList, WSUserMessage, WSWorktreeEvent, WSWorktreeState, WorktreeHandleView };