@wrongstack/webui 0.257.2 → 0.264.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,1208 @@
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
+ path: string;
281
+ trigger: string;
282
+ scope: string[];
283
+ }>;
284
+ };
285
+ }
286
+ interface WSDiagGet {
287
+ type: 'diag.get';
288
+ payload: {
289
+ provider: string;
290
+ model: string;
291
+ cwd: string;
292
+ sessionId: string;
293
+ tools: {
294
+ count: number;
295
+ names: string[];
296
+ };
297
+ features: {
298
+ memory: boolean;
299
+ skills: boolean;
300
+ modelsRegistry: boolean;
301
+ };
302
+ mode: string;
303
+ usage: {
304
+ input: number;
305
+ output: number;
306
+ cacheRead?: number | undefined;
307
+ };
308
+ messages: number;
309
+ todos: number;
310
+ };
311
+ }
312
+ interface WSStatsGet {
313
+ type: 'stats.get';
314
+ payload: {
315
+ sessionId: string;
316
+ provider: string;
317
+ model: string;
318
+ usage: {
319
+ input: number;
320
+ output: number;
321
+ cacheRead?: number | undefined;
322
+ cacheWrite?: number | undefined;
323
+ };
324
+ cache: {
325
+ readTokens: number;
326
+ writeTokens: number;
327
+ hitRatio: number;
328
+ } | null;
329
+ cost: number;
330
+ messages: number;
331
+ readFiles: number;
332
+ tools: number;
333
+ elapsedMs: number;
334
+ };
335
+ }
336
+ interface WSSessionsList {
337
+ type: 'sessions.list';
338
+ payload: {
339
+ sessions: Array<{
340
+ id: string;
341
+ title: string;
342
+ startedAt: string;
343
+ model: string;
344
+ provider: string;
345
+ tokenTotal: number;
346
+ isCurrent: boolean;
347
+ }>;
348
+ error?: string | undefined;
349
+ };
350
+ }
351
+ interface WSProviderCatalog {
352
+ type: 'provider.catalog';
353
+ payload: {
354
+ providers: Array<{
355
+ id: string;
356
+ name: string;
357
+ family: string;
358
+ apiBase?: string | undefined;
359
+ envVars: string[];
360
+ modelCount: number;
361
+ hasApiKey: boolean;
362
+ }>;
363
+ };
364
+ }
365
+ interface WSProviderModels {
366
+ type: 'provider.models';
367
+ payload: {
368
+ provider: string;
369
+ models: Array<{
370
+ id: string;
371
+ name: string;
372
+ releaseDate?: string | undefined;
373
+ contextWindow?: number | undefined;
374
+ inputCost?: number | undefined;
375
+ outputCost?: number | undefined;
376
+ capabilities: string[];
377
+ }>;
378
+ };
379
+ }
380
+ interface WSSavedProviders {
381
+ type: 'providers.saved';
382
+ payload: {
383
+ providers: Array<{
384
+ id: string;
385
+ family?: string | undefined;
386
+ baseUrl?: string | undefined;
387
+ /** Saved model allowlist, in the order the user pinned them. */
388
+ models?: string[] | undefined;
389
+ /** First entry of `models`, surfaced for the panel's "Using" line. */
390
+ pickedModelId?: string | undefined;
391
+ apiKeys: Array<{
392
+ label: string;
393
+ maskedKey: string;
394
+ isActive: boolean;
395
+ createdAt: string;
396
+ }>;
397
+ }>;
398
+ };
399
+ }
400
+ /**
401
+ * Health-probe result for a single provider, broadcast in reply to a
402
+ * `provider.probe` client message. Mirrors the `ProbeResult` shape
403
+ * from `@wrongstack/runtime/probe`, plus the `providerId` so panels
404
+ * can route the reply to the right card.
405
+ */
406
+ interface WSProviderProbe {
407
+ type: 'provider.probe';
408
+ payload: {
409
+ providerId: string;
410
+ ok: boolean;
411
+ status: string;
412
+ httpStatus?: number | undefined;
413
+ elapsedMs?: number | undefined;
414
+ modelCount?: number | undefined;
415
+ modelIds?: string[] | undefined;
416
+ detail?: string | undefined;
417
+ };
418
+ }
419
+ interface WSKeyOperationResult {
420
+ type: 'key.operation_result';
421
+ payload: {
422
+ success: boolean;
423
+ message: string;
424
+ };
425
+ }
426
+ interface WSFilesList {
427
+ type: 'files.list';
428
+ payload: {
429
+ files: string[];
430
+ };
431
+ }
432
+ interface WSTodosUpdated {
433
+ type: 'todos.updated';
434
+ payload: {
435
+ todos: Array<{
436
+ id: string;
437
+ content: string;
438
+ status: 'pending' | 'in_progress' | 'completed';
439
+ activeForm?: string | undefined;
440
+ }>;
441
+ };
442
+ }
443
+ interface WSModesList {
444
+ type: 'modes.list';
445
+ payload: {
446
+ modes: Array<{
447
+ id: string;
448
+ name: string;
449
+ description: string;
450
+ isActive: boolean;
451
+ }>;
452
+ activeId: string;
453
+ };
454
+ }
455
+ /** AutoPhase live state broadcast (see server/autophase-ws-handler.ts). */
456
+ interface WSAutoPhaseState {
457
+ type: 'autophase.state';
458
+ payload: Record<string, unknown>;
459
+ }
460
+ /** One worktree lane in the swim-lane / DAG view. */
461
+ interface WorktreeHandleView {
462
+ handleId: string;
463
+ ownerId: string;
464
+ ownerLabel: string;
465
+ branch: string;
466
+ baseBranch: string;
467
+ status: 'allocating' | 'active' | 'committing' | 'merging' | 'merged' | 'needs-review' | 'failed';
468
+ insertions: number;
469
+ deletions: number;
470
+ files: number;
471
+ conflictFiles?: string[] | undefined;
472
+ allocatedAt: number;
473
+ lastEventAt: number;
474
+ recentActivity: Array<{
475
+ kind: string;
476
+ text: string;
477
+ at: number;
478
+ }>;
479
+ }
480
+ /** Full worktree snapshot (broadcast on a timer, see worktree-ws-handler.ts). */
481
+ interface WSWorktreeState {
482
+ type: 'worktree.state';
483
+ payload: {
484
+ worktrees: WorktreeHandleView[];
485
+ baseBranch: string;
486
+ };
487
+ }
488
+ /** Incremental worktree lifecycle event — drives the flowing activity strip. */
489
+ interface WSWorktreeEvent {
490
+ type: 'worktree.event';
491
+ payload: {
492
+ kind: string;
493
+ handleId: string;
494
+ text: string;
495
+ at: number;
496
+ };
497
+ }
498
+ type WSClientMessage = WSUserMessage | WSToolConfirmResult | {
499
+ type: 'autophase.start';
500
+ payload: {
501
+ title: string;
502
+ phases?: unknown[] | undefined;
503
+ autonomous?: boolean | undefined;
504
+ };
505
+ } | {
506
+ type: 'autophase.pause';
507
+ payload: Record<string, never>;
508
+ } | {
509
+ type: 'autophase.resume';
510
+ payload: Record<string, never>;
511
+ } | {
512
+ type: 'autophase.stop';
513
+ payload: Record<string, never>;
514
+ } | {
515
+ type: 'autophase.toggleAutonomous';
516
+ payload: {
517
+ autonomous?: boolean | undefined;
518
+ };
519
+ } | {
520
+ type: 'autophase.selectPhase';
521
+ payload: {
522
+ phaseId: string;
523
+ };
524
+ } | {
525
+ type: 'autophase.taskStatus';
526
+ payload: {
527
+ taskId: string;
528
+ status: string;
529
+ };
530
+ } | {
531
+ type: 'abort';
532
+ payload: Record<string, never>;
533
+ } | {
534
+ type: 'session.resume';
535
+ payload: {
536
+ id: string;
537
+ };
538
+ } | {
539
+ type: 'session.new';
540
+ } | {
541
+ type: 'session.checkpoints';
542
+ } | {
543
+ type: 'session.rewind';
544
+ payload: {
545
+ checkpointIndex: number;
546
+ };
547
+ } | {
548
+ type: 'context.clear';
549
+ } | {
550
+ type: 'context.compact';
551
+ payload: {
552
+ aggressive: boolean;
553
+ };
554
+ } | {
555
+ type: 'context.repair';
556
+ } | {
557
+ type: 'context.debug';
558
+ } | {
559
+ type: 'context.modes.list';
560
+ } | {
561
+ type: 'context.mode.switch';
562
+ payload: {
563
+ id: string;
564
+ };
565
+ } | {
566
+ type: 'context.mode.create';
567
+ payload: {
568
+ id: string;
569
+ name: string;
570
+ description: string;
571
+ thresholds: {
572
+ warn: number;
573
+ soft: number;
574
+ hard: number;
575
+ };
576
+ preserveK: number;
577
+ eliseThreshold: number;
578
+ };
579
+ } | {
580
+ type: 'context.mode.update';
581
+ payload: {
582
+ id: string;
583
+ name?: string | undefined;
584
+ description?: string | undefined;
585
+ thresholds?: {
586
+ warn?: number | undefined;
587
+ soft?: number | undefined;
588
+ hard?: number | undefined;
589
+ } | undefined;
590
+ preserveK?: number | undefined;
591
+ eliseThreshold?: number | undefined;
592
+ };
593
+ } | {
594
+ type: 'context.mode.delete';
595
+ payload: {
596
+ id: string;
597
+ };
598
+ } | WSModelSwitch | {
599
+ type: 'providers.list';
600
+ } | {
601
+ type: 'provider.models';
602
+ payload: {
603
+ providerId: string;
604
+ };
605
+ } | {
606
+ type: 'providers.saved';
607
+ } | {
608
+ type: 'key.add';
609
+ payload: {
610
+ providerId: string;
611
+ label: string;
612
+ apiKey: string;
613
+ };
614
+ } | {
615
+ type: 'key.update';
616
+ payload: {
617
+ providerId: string;
618
+ label: string;
619
+ apiKey: string;
620
+ };
621
+ } | {
622
+ type: 'key.delete';
623
+ payload: {
624
+ providerId: string;
625
+ label: string;
626
+ };
627
+ } | {
628
+ type: 'key.set_active';
629
+ payload: {
630
+ providerId: string;
631
+ label: string;
632
+ };
633
+ } | {
634
+ type: 'provider.add';
635
+ payload: {
636
+ id: string;
637
+ family: string;
638
+ baseUrl?: string | undefined;
639
+ apiKey?: string | undefined;
640
+ };
641
+ } | {
642
+ type: 'provider.remove';
643
+ payload: {
644
+ providerId: string;
645
+ };
646
+ } | {
647
+ type: 'provider.clear_models';
648
+ payload: {
649
+ providerId: string;
650
+ };
651
+ } | {
652
+ type: 'provider.undo_clear';
653
+ payload: {
654
+ providerId: string;
655
+ previousModels: string[];
656
+ };
657
+ } | {
658
+ type: 'provider.update';
659
+ payload: {
660
+ id: string;
661
+ family?: string | undefined;
662
+ baseUrl?: string | undefined;
663
+ envVars?: string[] | undefined;
664
+ models?: string[] | undefined;
665
+ };
666
+ } | {
667
+ type: 'provider.probe';
668
+ payload: {
669
+ providerId: string;
670
+ timeoutMs?: number | undefined;
671
+ };
672
+ } | {
673
+ type: 'tools.list';
674
+ } | {
675
+ type: 'memory.list';
676
+ } | {
677
+ type: 'memory.remember';
678
+ payload: {
679
+ text: string;
680
+ scope?: MemoryScope | undefined;
681
+ };
682
+ } | {
683
+ type: 'memory.forget';
684
+ payload: {
685
+ text: string;
686
+ scope?: MemoryScope | undefined;
687
+ };
688
+ } | {
689
+ type: 'skills.list';
690
+ } | {
691
+ type: 'diag.get';
692
+ } | {
693
+ type: 'stats.get';
694
+ } | {
695
+ type: 'session.save';
696
+ } | {
697
+ type: 'sessions.list';
698
+ payload: {
699
+ limit: number;
700
+ };
701
+ } | {
702
+ type: 'session.delete';
703
+ payload: {
704
+ id: string;
705
+ };
706
+ } | {
707
+ type: 'modes.list';
708
+ } | {
709
+ type: 'mode.switch';
710
+ payload: {
711
+ id: string;
712
+ };
713
+ } | {
714
+ type: 'files.list';
715
+ payload: {
716
+ query?: string | undefined;
717
+ limit?: number | undefined;
718
+ path?: string | undefined;
719
+ };
720
+ } | {
721
+ type: 'files.tree';
722
+ payload: {
723
+ path?: string | undefined;
724
+ } | Record<string, never>;
725
+ } | {
726
+ type: 'files.read';
727
+ payload: {
728
+ filePath: string;
729
+ };
730
+ } | {
731
+ type: 'files.write';
732
+ payload: {
733
+ filePath: string;
734
+ content: string;
735
+ };
736
+ } | {
737
+ type: 'todos.get';
738
+ } | {
739
+ type: 'todos.clear';
740
+ } | {
741
+ type: 'todos.remove';
742
+ payload: {
743
+ id?: string | undefined;
744
+ index?: number | undefined;
745
+ };
746
+ } | {
747
+ type: 'todo.update';
748
+ payload: {
749
+ id: string;
750
+ status?: 'pending' | 'in_progress' | 'completed' | undefined;
751
+ activeForm?: string | undefined;
752
+ };
753
+ } | {
754
+ type: 'tasks.get';
755
+ } | {
756
+ type: 'task.update';
757
+ payload: {
758
+ id: string;
759
+ status: string;
760
+ };
761
+ } | {
762
+ type: 'plan.get';
763
+ } | {
764
+ type: 'plan.item.update';
765
+ payload: {
766
+ target: string;
767
+ status: 'open' | 'in_progress' | 'done';
768
+ };
769
+ } | {
770
+ type: 'ping';
771
+ } | {
772
+ type: 'process.list';
773
+ } | {
774
+ type: 'process.kill';
775
+ payload: {
776
+ pid: number;
777
+ };
778
+ } | {
779
+ type: 'process.killAll';
780
+ } | {
781
+ type: 'git.info';
782
+ } | {
783
+ type: 'goal.get';
784
+ } | {
785
+ type: 'autonomy.switch';
786
+ payload: {
787
+ mode: string;
788
+ };
789
+ } | {
790
+ type: 'prefs.update';
791
+ payload: Record<string, unknown>;
792
+ } | {
793
+ type: 'prefs.get';
794
+ } | {
795
+ type: 'projects.list';
796
+ } | {
797
+ type: 'projects.add';
798
+ payload: {
799
+ root: string;
800
+ name?: string | undefined;
801
+ };
802
+ } | {
803
+ type: 'projects.select';
804
+ payload: {
805
+ root: string;
806
+ name?: string | undefined;
807
+ };
808
+ } | {
809
+ type: 'working_dir.set';
810
+ payload: {
811
+ path: string;
812
+ };
813
+ } | {
814
+ type: 'shell.open';
815
+ payload: {
816
+ path: string;
817
+ target: 'terminal' | 'file-manager';
818
+ };
819
+ } | WSCollabJoin | WSCollabLeave | WSCollabAnnotate | WSCollabResolve | WSCollabRequestPause | WSCollabResume | WSCollabGrantControl | WSCollabInjectTool | {
820
+ type: 'mailbox.messages';
821
+ payload: {
822
+ limit?: number | undefined;
823
+ incompleteOnly?: boolean | undefined;
824
+ };
825
+ } | {
826
+ type: 'mailbox.agents';
827
+ payload: {
828
+ onlineOnly?: boolean | undefined;
829
+ } | Record<string, never>;
830
+ } | {
831
+ type: 'mailbox.clear';
832
+ } | {
833
+ type: 'mailbox.purge';
834
+ payload?: {
835
+ completedMaxAgeMs?: number;
836
+ incompleteMaxAgeMs?: number;
837
+ } | undefined;
838
+ } | {
839
+ type: 'brain.status';
840
+ } | {
841
+ type: 'brain.risk';
842
+ payload: {
843
+ level: string;
844
+ };
845
+ } | {
846
+ type: 'brain.ask';
847
+ payload: {
848
+ question: string;
849
+ };
850
+ } | {
851
+ type: 'model.refine';
852
+ payload: {
853
+ text: string;
854
+ };
855
+ };
856
+ type WSServerMessage = WSSessionStart | WSSessionEnd | WSTextDelta | WSThinkingDelta | WSToolUseStart | WSToolProgress | WSToolExecuted | WSIterationStarted | WSIterationCompleted | WSProviderResponse | WSRunResult | WSSessionStats | WSError | WSToolConfirmNeeded | WSContextDebug | WSContextCompacted | WSContextRepaired | WSContextModesList | WSContextModeChanged | WSToolsList | WSMemoryList | WSSkillsList | WSDiagGet | WSStatsGet | WSSessionsList | WSProviderCatalog | WSProviderModels | WSSavedProviders | WSProviderProbe | WSKeyOperationResult | WSFilesList | {
857
+ type: 'files.tree';
858
+ payload: {
859
+ root: string;
860
+ tree: unknown[];
861
+ error?: string | undefined;
862
+ };
863
+ } | {
864
+ type: 'files.read';
865
+ payload: {
866
+ filePath: string;
867
+ content: string;
868
+ error?: string | undefined;
869
+ };
870
+ } | {
871
+ type: 'files.written';
872
+ payload: {
873
+ filePath: string;
874
+ success: boolean;
875
+ error?: string | undefined;
876
+ };
877
+ } | WSTodosUpdated | {
878
+ type: 'tasks.updated';
879
+ payload: {
880
+ tasks: unknown[];
881
+ error?: string | undefined;
882
+ };
883
+ } | {
884
+ type: 'plan.updated';
885
+ payload: {
886
+ plan: unknown | null;
887
+ error?: string | undefined;
888
+ };
889
+ } | WSModesList | WSAutoPhaseState | WSWorktreeState | WSWorktreeEvent | WSCollabState | WSCollabParticipantJoined | WSCollabParticipantLeft | WSCollabEvent | WSCollabAnnotationAdded | WSCollabAnnotationResolved | WSCollabPauseGranted | WSCollabPauseReleased | WSCollabInjectionGranted | {
890
+ type: 'session.checkpoints';
891
+ payload: {
892
+ checkpoints: Array<{
893
+ index: number;
894
+ iteration: number;
895
+ timestamp: string;
896
+ label: string;
897
+ messageCount: number;
898
+ tokens: number;
899
+ }>;
900
+ };
901
+ } | {
902
+ type: 'goal.updated';
903
+ payload: Record<string, unknown> | null;
904
+ } | {
905
+ type: 'prefs.updated';
906
+ payload: Record<string, unknown>;
907
+ } | {
908
+ type: 'process.list';
909
+ payload: {
910
+ processes: Array<{
911
+ pid: number;
912
+ command: string;
913
+ tool: string;
914
+ startedAt: number;
915
+ status: 'running' | 'exited' | 'killed';
916
+ protected?: boolean | undefined;
917
+ }>;
918
+ };
919
+ } | {
920
+ type: 'git.info';
921
+ payload: {
922
+ branch: string;
923
+ added: number;
924
+ deleted: number;
925
+ untracked: number;
926
+ behind: number;
927
+ ahead: number;
928
+ };
929
+ } | {
930
+ type: 'projects.list';
931
+ payload: {
932
+ projects: Array<{
933
+ name: string;
934
+ root: string;
935
+ slug: string;
936
+ lastSeen?: string | undefined;
937
+ }>;
938
+ };
939
+ } | {
940
+ type: 'projects.added';
941
+ payload: {
942
+ name: string;
943
+ root: string;
944
+ slug: string;
945
+ message: string;
946
+ };
947
+ } | {
948
+ type: 'projects.selected';
949
+ payload: {
950
+ root: string;
951
+ name: string;
952
+ message: string;
953
+ };
954
+ } | {
955
+ type: 'working_dir.changed';
956
+ payload: {
957
+ cwd: string;
958
+ projectRoot: string;
959
+ };
960
+ } | {
961
+ type: 'brain.status';
962
+ payload: {
963
+ maxAutoRisk: string;
964
+ log: Array<{
965
+ at: number;
966
+ kind: string;
967
+ question: string;
968
+ outcome: string;
969
+ }>;
970
+ };
971
+ } | {
972
+ type: 'brain.answer';
973
+ payload: {
974
+ question: string;
975
+ decision: {
976
+ type: string;
977
+ optionId?: string | undefined;
978
+ text?: string | undefined;
979
+ rationale?: string | undefined;
980
+ reason?: string | undefined;
981
+ prompt?: string | undefined;
982
+ };
983
+ };
984
+ } | {
985
+ type: 'brain.event';
986
+ payload: Record<string, unknown> & {
987
+ event: string;
988
+ };
989
+ } | {
990
+ type: 'model.refine_result';
991
+ payload: {
992
+ refined: string;
993
+ english: string;
994
+ error?: string | undefined;
995
+ };
996
+ };
997
+ type BroadcastFn = (msg: WSServerMessage) => void;
998
+ /** Narrow type for CollabPanel event handlers — only collab-related messages + errors. */
999
+ type CollabPanelMessage = WSCollabState | WSCollabParticipantJoined | WSCollabParticipantLeft | WSCollabAnnotationAdded | WSCollabAnnotationResolved | WSCollabPauseGranted | WSCollabPauseReleased | WSCollabInjectionGranted | WSError;
1000
+ /**
1001
+ * Roles a collaboration participant can hold. The string union is the
1002
+ * wire contract — adding new roles (e.g. `controller`) in later phases
1003
+ * is a backward-compatible widening of this type as long as the server
1004
+ * gracefully rejects roles it does not yet implement.
1005
+ */
1006
+ type CollabRole = 'observer' | 'annotator' | 'controller';
1007
+ interface WSCollabJoin {
1008
+ type: 'collab.join';
1009
+ payload: {
1010
+ sessionId: string;
1011
+ role: CollabRole;
1012
+ };
1013
+ }
1014
+ interface WSCollabLeave {
1015
+ type: 'collab.leave';
1016
+ payload: {
1017
+ sessionId: string;
1018
+ };
1019
+ }
1020
+ /**
1021
+ * Annotate a specific event in the session log. The `atEventIndex`
1022
+ * is a stable pointer the UI can scroll to / highlight. The server
1023
+ * persists the annotation and broadcasts it to every participant
1024
+ * in the same session, including the author.
1025
+ */
1026
+ interface WSCollabAnnotate {
1027
+ type: 'collab.annotate';
1028
+ payload: {
1029
+ sessionId: string;
1030
+ atEventIndex: number;
1031
+ text: string;
1032
+ };
1033
+ }
1034
+ /** Mark an existing annotation as resolved. */
1035
+ interface WSCollabResolve {
1036
+ type: 'collab.resolve';
1037
+ payload: {
1038
+ sessionId: string;
1039
+ annotationId: string;
1040
+ };
1041
+ }
1042
+ /** Sent on connect and every 2s while at least one participant is watching. */
1043
+ interface WSCollabState {
1044
+ type: 'collab.state';
1045
+ payload: {
1046
+ sessionId: string;
1047
+ participants: Array<{
1048
+ participantId: string;
1049
+ role: CollabRole;
1050
+ joinedAt: string;
1051
+ }>;
1052
+ };
1053
+ }
1054
+ /** Broadcast when a new participant joins the session. */
1055
+ interface WSCollabParticipantJoined {
1056
+ type: 'collab.participant.joined';
1057
+ payload: {
1058
+ participantId: string;
1059
+ sessionId: string;
1060
+ role: CollabRole;
1061
+ joinedAt: string;
1062
+ };
1063
+ }
1064
+ /** Broadcast when a participant leaves (explicit leave or WS close/error). */
1065
+ interface WSCollabParticipantLeft {
1066
+ type: 'collab.participant.left';
1067
+ payload: {
1068
+ participantId: string;
1069
+ sessionId: string;
1070
+ };
1071
+ }
1072
+ /** Broadcast when a new annotation is added. Sent to all participants. */
1073
+ interface WSCollabAnnotationAdded {
1074
+ type: 'collab.annotation.added';
1075
+ payload: {
1076
+ sessionId: string;
1077
+ annotation: {
1078
+ id: string;
1079
+ atEventIndex: number;
1080
+ authorId: string;
1081
+ authorRole: 'annotator';
1082
+ text: string;
1083
+ createdAt: string;
1084
+ resolved: boolean;
1085
+ };
1086
+ };
1087
+ }
1088
+ /** Broadcast when an annotation is resolved. Sent to all participants. */
1089
+ interface WSCollabAnnotationResolved {
1090
+ type: 'collab.annotation.resolved';
1091
+ payload: {
1092
+ sessionId: string;
1093
+ annotationId: string;
1094
+ resolvedBy: string;
1095
+ resolvedAt: string;
1096
+ };
1097
+ }
1098
+ /** Client → server: controller asks the agent loop to pause before the next tool call. */
1099
+ interface WSCollabRequestPause {
1100
+ type: 'collab.request_pause';
1101
+ payload: {
1102
+ sessionId: string;
1103
+ };
1104
+ }
1105
+ /** Client → server: controller (or owner) clears the pause. */
1106
+ interface WSCollabResume {
1107
+ type: 'collab.resume';
1108
+ payload: {
1109
+ sessionId: string;
1110
+ };
1111
+ }
1112
+ /**
1113
+ * Client → server: owner hands the controller role to a different
1114
+ * participant. The current implementation is metadata-only — the
1115
+ * existing controller's effective permissions don't change yet;
1116
+ * the wire is reserved for a future iteration where per-participant
1117
+ * RBAC becomes dynamic.
1118
+ */
1119
+ interface WSCollabGrantControl {
1120
+ type: 'collab.grant_control';
1121
+ payload: {
1122
+ sessionId: string;
1123
+ toParticipant: string;
1124
+ };
1125
+ }
1126
+ /** Server → client: the bus transitioned to paused (controller's pause took effect). */
1127
+ interface WSCollabPauseGranted {
1128
+ type: 'collab.pause.granted';
1129
+ payload: {
1130
+ sessionId: string;
1131
+ pausedBy: string;
1132
+ pausedAt: string;
1133
+ /**
1134
+ * How long until the middleware auto-resumes (in ms). Clients
1135
+ * can render a countdown. Defaults to 60_000 on the server.
1136
+ */
1137
+ autoResumeInMs: number;
1138
+ };
1139
+ }
1140
+ /** Server → client: the bus transitioned back to running. */
1141
+ interface WSCollabPauseReleased {
1142
+ type: 'collab.pause.released';
1143
+ payload: {
1144
+ sessionId: string;
1145
+ /** 'controller' when a participant asked; 'timeout' when the middleware fired auto-resume. */
1146
+ reason: 'controller' | 'timeout';
1147
+ at: string;
1148
+ };
1149
+ }
1150
+ /**
1151
+ * Generic envelope wrapping a kernel event mirrored to observers.
1152
+ * `kind` matches the original kernel event name (e.g. `tool.started`),
1153
+ * `payload` is the original event payload (best-effort serialized),
1154
+ * `at` is the broadcast timestamp.
1155
+ *
1156
+ * `replay` is true when the event was sent from the on-disk session
1157
+ * log to a late-joining observer (Phase 1.5). Live events leave it
1158
+ * undefined. Clients use the flag to render a "history" affordance
1159
+ * (e.g. dim the styling or annotate the timestamp as "[joined late]").
1160
+ */
1161
+ interface WSCollabEvent {
1162
+ type: 'collab.event';
1163
+ payload: {
1164
+ kind: string;
1165
+ payload: unknown;
1166
+ at: string;
1167
+ replay?: boolean | undefined;
1168
+ };
1169
+ }
1170
+ /**
1171
+ * Client → server: a controller injects a synthetic tool_result for
1172
+ * the given tool_use_id. The next time the agent's toolCall pipeline
1173
+ * sees that id, the real tool is skipped and the injected content
1174
+ * is used. The injection is one-shot — consumed on first match.
1175
+ */
1176
+ interface WSCollabInjectTool {
1177
+ type: 'collab.inject_tool';
1178
+ payload: {
1179
+ sessionId: string;
1180
+ toolUseId: string;
1181
+ /** String or JSON-serializable value. */
1182
+ content: unknown;
1183
+ isError: boolean;
1184
+ /** Free-form context surfaced in the broadcast and audit log. */
1185
+ reason: string;
1186
+ };
1187
+ }
1188
+ /**
1189
+ * Server → client: an injection was queued or consumed. Sent to
1190
+ * every participant so observers can show "the controller just
1191
+ * replaced the tool result for tool X".
1192
+ */
1193
+ interface WSCollabInjectionGranted {
1194
+ type: 'collab.injection.granted';
1195
+ payload: {
1196
+ sessionId: string;
1197
+ toolUseId: string;
1198
+ toolName: string;
1199
+ authorId: string;
1200
+ reason: string;
1201
+ isError: boolean;
1202
+ /** 'queued' or 'consumed' — the bus does both. */
1203
+ phase: 'queued' | 'consumed';
1204
+ at: string;
1205
+ };
1206
+ }
1207
+
1208
+ 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, WSSkillsList, WSStatsGet, WSTextDelta, WSThinkingDelta, WSTodosUpdated, WSToolConfirmNeeded, WSToolConfirmResult, WSToolExecuted, WSToolProgress, WSToolUseStart, WSToolsList, WSUserMessage, WSWorktreeEvent, WSWorktreeState, WorktreeHandleView };