clawmatrix 0.1.23 → 0.2.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/README.md +4 -1
- package/package.json +4 -2
- package/src/acp-proxy.ts +2073 -0
- package/src/audit.ts +42 -0
- package/src/auth.ts +2 -3
- package/src/cli.ts +76 -2
- package/src/cluster-service.ts +243 -3
- package/src/compat.ts +84 -3
- package/src/config.ts +117 -4
- package/src/connection.ts +288 -85
- package/src/crypto.ts +179 -0
- package/src/debug.ts +15 -2
- package/src/e2e/helpers.ts +318 -0
- package/src/handoff.ts +131 -86
- package/src/identity.ts +95 -0
- package/src/index.ts +467 -52
- package/src/knowledge-sync.ts +776 -207
- package/src/model-proxy.ts +144 -39
- package/src/peer-approval.ts +628 -0
- package/src/peer-manager.ts +261 -32
- package/src/rate-limiter.ts +88 -0
- package/src/router.ts +32 -10
- package/src/sentinel-manager.ts +142 -0
- package/src/sentinel.ts +618 -0
- package/src/task-activity.ts +74 -0
- package/src/terminal.ts +566 -0
- package/src/tool-proxy.ts +127 -3
- package/src/tools/cluster-acp.ts +237 -0
- package/src/tools/cluster-batch.ts +76 -0
- package/src/tools/cluster-diagnostic.ts +174 -0
- package/src/tools/cluster-edit.ts +70 -0
- package/src/tools/cluster-peers.ts +59 -14
- package/src/tools/cluster-terminal.ts +232 -0
- package/src/tools/cluster-tool.ts +26 -11
- package/src/types.ts +475 -3
- package/src/web.ts +2 -2
package/src/types.ts
CHANGED
|
@@ -12,11 +12,33 @@ export interface ClusterFrame {
|
|
|
12
12
|
// ── Auth messages ──────────────────────────────────────────────────
|
|
13
13
|
export interface AuthChallenge extends ClusterFrame {
|
|
14
14
|
type: "auth_challenge";
|
|
15
|
-
payload: { nonce: string };
|
|
15
|
+
payload: { nonce: string; publicKey?: string };
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/** Legacy plaintext auth (used when E2EE is disabled). */
|
|
18
19
|
export interface AuthRequest extends ClusterFrame {
|
|
19
20
|
type: "auth";
|
|
21
|
+
payload: {
|
|
22
|
+
nodeId: string;
|
|
23
|
+
sig: string;
|
|
24
|
+
publicKey?: string;
|
|
25
|
+
agents?: AgentInfo[];
|
|
26
|
+
models?: ModelInfo[];
|
|
27
|
+
tags?: string[];
|
|
28
|
+
deviceInfo?: DeviceInfo;
|
|
29
|
+
toolProxy?: ToolProxyInfo;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Phase 2 of E2EE handshake: client sends its public key (plaintext). */
|
|
34
|
+
export interface AuthKeyExchange extends ClusterFrame {
|
|
35
|
+
type: "auth_key_exchange";
|
|
36
|
+
payload: { publicKey: string };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Phase 3 of E2EE handshake: client sends encrypted HMAC + capabilities. */
|
|
40
|
+
export interface AuthVerify extends ClusterFrame {
|
|
41
|
+
type: "auth_verify";
|
|
20
42
|
payload: {
|
|
21
43
|
nodeId: string;
|
|
22
44
|
sig: string;
|
|
@@ -115,6 +137,8 @@ export interface ModelResponse extends ClusterFrame {
|
|
|
115
137
|
payload: {
|
|
116
138
|
success: boolean;
|
|
117
139
|
content?: string;
|
|
140
|
+
/** Reasoning/thinking content from models like DeepSeek. */
|
|
141
|
+
reasoning?: string;
|
|
118
142
|
/** Full message object from upstream (choices[0].message or responses output).
|
|
119
143
|
* Carries tool_calls, refusal, etc. that `content` alone cannot represent. */
|
|
120
144
|
message?: unknown;
|
|
@@ -128,6 +152,8 @@ export interface ModelStreamChunk extends ClusterFrame {
|
|
|
128
152
|
id: string;
|
|
129
153
|
payload: {
|
|
130
154
|
delta: string;
|
|
155
|
+
/** Reasoning/thinking delta from models like DeepSeek (reasoning_content). */
|
|
156
|
+
reasoningDelta?: string;
|
|
131
157
|
/** Full delta object from upstream (choices[0].delta).
|
|
132
158
|
* Carries tool_calls chunks that `delta` string cannot represent. */
|
|
133
159
|
deltaObj?: unknown;
|
|
@@ -136,6 +162,14 @@ export interface ModelStreamChunk extends ClusterFrame {
|
|
|
136
162
|
};
|
|
137
163
|
}
|
|
138
164
|
|
|
165
|
+
// ── Image content ─────────────────────────────────────────────────
|
|
166
|
+
export interface ImageContent {
|
|
167
|
+
/** Base64-encoded image data (without data URI prefix) */
|
|
168
|
+
data: string;
|
|
169
|
+
/** MIME type, e.g. "image/png", "image/jpeg" */
|
|
170
|
+
mediaType: string;
|
|
171
|
+
}
|
|
172
|
+
|
|
139
173
|
// ── Handoff ────────────────────────────────────────────────────────
|
|
140
174
|
export type HandoffStatus = "working" | "input_required" | "completed" | "failed" | "canceled";
|
|
141
175
|
|
|
@@ -152,6 +186,8 @@ export interface HandoffRequest extends ClusterFrame {
|
|
|
152
186
|
target: string;
|
|
153
187
|
task: string;
|
|
154
188
|
context?: string;
|
|
189
|
+
sessionId?: string; // Reuse session for multi-turn conversation
|
|
190
|
+
images?: ImageContent[];
|
|
155
191
|
};
|
|
156
192
|
}
|
|
157
193
|
|
|
@@ -177,6 +213,7 @@ export interface HandoffResponse extends ClusterFrame {
|
|
|
177
213
|
artifacts?: Artifact[];
|
|
178
214
|
inputRequired?: boolean;
|
|
179
215
|
handoffId?: string;
|
|
216
|
+
sessionId?: string; // For multi-turn conversation reuse
|
|
180
217
|
};
|
|
181
218
|
}
|
|
182
219
|
|
|
@@ -216,6 +253,7 @@ export interface HandoffInput extends ClusterFrame {
|
|
|
216
253
|
id: string;
|
|
217
254
|
payload: {
|
|
218
255
|
message: string;
|
|
256
|
+
images?: ImageContent[];
|
|
219
257
|
};
|
|
220
258
|
}
|
|
221
259
|
|
|
@@ -248,6 +286,36 @@ export interface ToolProxyResponse extends ClusterFrame {
|
|
|
248
286
|
};
|
|
249
287
|
}
|
|
250
288
|
|
|
289
|
+
// ── Tool batch proxy ──────────────────────────────────────────────
|
|
290
|
+
export interface ToolBatchItem {
|
|
291
|
+
tool: string;
|
|
292
|
+
params: Record<string, unknown>;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export interface ToolBatchResultItem {
|
|
296
|
+
tool: string;
|
|
297
|
+
success: boolean;
|
|
298
|
+
result?: Record<string, unknown>;
|
|
299
|
+
error?: string;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export interface ToolBatchRequest extends ClusterFrame {
|
|
303
|
+
type: "tool_batch_req";
|
|
304
|
+
id: string;
|
|
305
|
+
payload: {
|
|
306
|
+
items: ToolBatchItem[];
|
|
307
|
+
stopOnError?: boolean; // default true
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export interface ToolBatchResponse extends ClusterFrame {
|
|
312
|
+
type: "tool_batch_res";
|
|
313
|
+
id: string;
|
|
314
|
+
payload: {
|
|
315
|
+
results: ToolBatchResultItem[];
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
251
319
|
// ── Device info ───────────────────────────────────────────────────
|
|
252
320
|
export interface DeviceInfo {
|
|
253
321
|
os: string; // e.g. "Darwin 24.6.0", "Linux 6.1.0"
|
|
@@ -285,6 +353,7 @@ export interface ModelInfo {
|
|
|
285
353
|
id: string;
|
|
286
354
|
provider: string;
|
|
287
355
|
description?: string;
|
|
356
|
+
input?: ("text" | "image")[];
|
|
288
357
|
compat?: ModelCompatInfo;
|
|
289
358
|
}
|
|
290
359
|
|
|
@@ -294,6 +363,11 @@ export interface ToolProxyInfo {
|
|
|
294
363
|
deny: string[];
|
|
295
364
|
}
|
|
296
365
|
|
|
366
|
+
export interface AcpAgentInfo {
|
|
367
|
+
id: string;
|
|
368
|
+
description: string;
|
|
369
|
+
}
|
|
370
|
+
|
|
297
371
|
export interface PeerInfo {
|
|
298
372
|
nodeId: string;
|
|
299
373
|
agents: AgentInfo[];
|
|
@@ -303,6 +377,8 @@ export interface PeerInfo {
|
|
|
303
377
|
directPeers?: string[]; // nodeIds this node has direct connections to
|
|
304
378
|
deviceInfo?: DeviceInfo; // system/hardware info
|
|
305
379
|
toolProxy?: ToolProxyInfo;
|
|
380
|
+
acpAgents?: AcpAgentInfo[]; // ACP agents available on this node
|
|
381
|
+
latencyMs?: number; // heartbeat RTT (direct) or estimated round-trip (relay)
|
|
306
382
|
}
|
|
307
383
|
|
|
308
384
|
export interface NodeCapabilities {
|
|
@@ -312,6 +388,7 @@ export interface NodeCapabilities {
|
|
|
312
388
|
tags: string[];
|
|
313
389
|
deviceInfo?: DeviceInfo;
|
|
314
390
|
toolProxy?: ToolProxyInfo;
|
|
391
|
+
acpAgents?: AcpAgentInfo[];
|
|
315
392
|
}
|
|
316
393
|
|
|
317
394
|
// ── Ingested events (from Shortcuts automations, etc.) ────────────
|
|
@@ -328,7 +405,367 @@ export interface IngestedEvent {
|
|
|
328
405
|
export interface KnowledgeSyncFrame extends ClusterFrame {
|
|
329
406
|
type: "knowledge_sync";
|
|
330
407
|
payload: {
|
|
331
|
-
|
|
408
|
+
docId: string; // "" = registry, otherwise file relPath
|
|
409
|
+
data: string; // base64-encoded Automerge sync message
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// ── Diagnostic (sentinel) ────────────────────────────────────────
|
|
414
|
+
export interface DiagnosticExec extends ClusterFrame {
|
|
415
|
+
type: "diagnostic_exec";
|
|
416
|
+
id: string;
|
|
417
|
+
payload: {
|
|
418
|
+
command: string;
|
|
419
|
+
timeout?: number; // seconds, default 30
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export interface DiagnosticExecResponse extends ClusterFrame {
|
|
424
|
+
type: "diagnostic_exec_res";
|
|
425
|
+
id: string;
|
|
426
|
+
payload: {
|
|
427
|
+
success: boolean;
|
|
428
|
+
exitCode?: number;
|
|
429
|
+
stdout?: string;
|
|
430
|
+
stderr?: string;
|
|
431
|
+
error?: string;
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export interface DiagnosticStatus extends ClusterFrame {
|
|
436
|
+
type: "diagnostic_status";
|
|
437
|
+
id: string;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
export interface DiagnosticStatusResponse extends ClusterFrame {
|
|
441
|
+
type: "diagnostic_status_res";
|
|
442
|
+
id: string;
|
|
443
|
+
payload: {
|
|
444
|
+
gatewayAlive: boolean;
|
|
445
|
+
uptimeMs: number;
|
|
446
|
+
pid: number;
|
|
447
|
+
gatewayPid?: number;
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// ── ACP proxy ─────────────────────────────────────────────────────
|
|
452
|
+
export type AcpSessionMode = "oneshot" | "persistent";
|
|
453
|
+
|
|
454
|
+
export interface AcpTaskRequest extends ClusterFrame {
|
|
455
|
+
type: "acp_req";
|
|
456
|
+
id: string;
|
|
457
|
+
payload: {
|
|
458
|
+
agent: string; // ACP harness: "claude", "codex", "gemini", etc.
|
|
459
|
+
task?: string; // prompt to execute (omit to create session without prompting)
|
|
460
|
+
sessionId?: string; // existing session ID for follow-up (persistent mode)
|
|
461
|
+
acpSessionId?: string; // ACP-level session ID for resume when sessionId is stale
|
|
462
|
+
mode?: AcpSessionMode; // default: "oneshot"
|
|
463
|
+
cwd?: string; // working directory on remote node
|
|
464
|
+
images?: ImageContent[];
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export interface AcpStreamChunk extends ClusterFrame {
|
|
469
|
+
type: "acp_stream";
|
|
470
|
+
id: string;
|
|
471
|
+
payload: {
|
|
472
|
+
delta: string;
|
|
473
|
+
event?: string; // "agent_message_chunk" | "tool_call" | etc.
|
|
474
|
+
done: boolean;
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
export interface AcpTaskResponse extends ClusterFrame {
|
|
479
|
+
type: "acp_res";
|
|
480
|
+
id: string;
|
|
481
|
+
payload: {
|
|
482
|
+
success: boolean;
|
|
483
|
+
nodeId?: string;
|
|
484
|
+
agent?: string;
|
|
485
|
+
result?: string;
|
|
486
|
+
sessionId?: string; // returned for persistent sessions
|
|
487
|
+
acpSessionId?: string; // ACP-level session ID for future resume
|
|
488
|
+
stopReason?: string; // ACP stop reason
|
|
489
|
+
error?: string;
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
export interface AcpCloseRequest extends ClusterFrame {
|
|
494
|
+
type: "acp_close";
|
|
495
|
+
id: string;
|
|
496
|
+
payload: {
|
|
497
|
+
sessionId: string;
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
export interface AcpCloseResponse extends ClusterFrame {
|
|
502
|
+
type: "acp_close_res";
|
|
503
|
+
id: string;
|
|
504
|
+
payload: {
|
|
505
|
+
success: boolean;
|
|
506
|
+
error?: string;
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// ── ACP session management ──────────────────────────────────────
|
|
511
|
+
export interface AcpSessionInfo {
|
|
512
|
+
sessionId: string;
|
|
513
|
+
cwd: string;
|
|
514
|
+
title?: string;
|
|
515
|
+
description?: string; // first user message (for display in session list)
|
|
516
|
+
updatedAt?: string;
|
|
517
|
+
agent?: string; // which ACP agent (claude, codex, etc.)
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
export interface AcpListRequest extends ClusterFrame {
|
|
521
|
+
type: "acp_list_req";
|
|
522
|
+
id: string;
|
|
523
|
+
payload: {
|
|
524
|
+
agent?: string; // filter by agent type
|
|
525
|
+
cwd?: string; // filter by working directory
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
export interface AcpListResponse extends ClusterFrame {
|
|
530
|
+
type: "acp_list_res";
|
|
531
|
+
id: string;
|
|
532
|
+
payload: {
|
|
533
|
+
success: boolean;
|
|
534
|
+
sessions?: AcpSessionInfo[];
|
|
535
|
+
error?: string;
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
export interface AcpResumeRequest extends ClusterFrame {
|
|
540
|
+
type: "acp_resume_req";
|
|
541
|
+
id: string;
|
|
542
|
+
payload: {
|
|
543
|
+
agent: string;
|
|
544
|
+
acpSessionId: string; // the ACP protocol session ID to resume
|
|
545
|
+
cwd: string;
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
export interface AcpResumeResponse extends ClusterFrame {
|
|
550
|
+
type: "acp_resume_res";
|
|
551
|
+
id: string;
|
|
552
|
+
payload: {
|
|
553
|
+
success: boolean;
|
|
554
|
+
sessionId?: string; // ClawMatrix session ID for follow-up prompts
|
|
555
|
+
error?: string;
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
export interface AcpCancelRequest extends ClusterFrame {
|
|
560
|
+
type: "acp_cancel";
|
|
561
|
+
id: string;
|
|
562
|
+
payload: {
|
|
563
|
+
sessionId: string; // ClawMatrix session ID
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
export interface AcpCancelResponse extends ClusterFrame {
|
|
568
|
+
type: "acp_cancel_res";
|
|
569
|
+
id: string;
|
|
570
|
+
payload: {
|
|
571
|
+
success: boolean;
|
|
572
|
+
error?: string;
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
export interface AcpModeInfo {
|
|
577
|
+
id: string;
|
|
578
|
+
name: string;
|
|
579
|
+
description?: string;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
export interface AcpSetModeRequest extends ClusterFrame {
|
|
583
|
+
type: "acp_set_mode";
|
|
584
|
+
id: string;
|
|
585
|
+
payload: {
|
|
586
|
+
sessionId: string; // ClawMatrix session ID
|
|
587
|
+
modeId: string; // e.g. "code", "architect", "ask"
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
export interface AcpSetModeResponse extends ClusterFrame {
|
|
592
|
+
type: "acp_set_mode_res";
|
|
593
|
+
id: string;
|
|
594
|
+
payload: {
|
|
595
|
+
success: boolean;
|
|
596
|
+
error?: string;
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
export interface AcpGetModesRequest extends ClusterFrame {
|
|
601
|
+
type: "acp_get_modes";
|
|
602
|
+
id: string;
|
|
603
|
+
payload: {
|
|
604
|
+
sessionId: string;
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
export interface AcpGetModesResponse extends ClusterFrame {
|
|
609
|
+
type: "acp_get_modes_res";
|
|
610
|
+
id: string;
|
|
611
|
+
payload: {
|
|
612
|
+
success: boolean;
|
|
613
|
+
modes?: AcpModeInfo[];
|
|
614
|
+
currentModeId?: string;
|
|
615
|
+
error?: string;
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// ── Chat history ──────────────────────────────────────────────────
|
|
620
|
+
|
|
621
|
+
export interface ChatHistoryMessage {
|
|
622
|
+
role: "user" | "assistant" | "system" | "tool";
|
|
623
|
+
text: string;
|
|
624
|
+
thinking?: string;
|
|
625
|
+
toolName?: string;
|
|
626
|
+
toolArgs?: string;
|
|
627
|
+
toolResult?: string;
|
|
628
|
+
images?: Array<{ data: string; mediaType: string }>;
|
|
629
|
+
timestamp?: number;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
export interface ChatHistoryRequest extends ClusterFrame {
|
|
633
|
+
type: "chat_history_req";
|
|
634
|
+
id: string;
|
|
635
|
+
payload: {
|
|
636
|
+
sessionId: string;
|
|
637
|
+
limit?: number;
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
export interface ChatHistoryResponse extends ClusterFrame {
|
|
642
|
+
type: "chat_history_res";
|
|
643
|
+
id: string;
|
|
644
|
+
payload: {
|
|
645
|
+
success: boolean;
|
|
646
|
+
messages?: ChatHistoryMessage[];
|
|
647
|
+
error?: string;
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// ── Task activity (Live Activity push to mobile nodes) ───────────
|
|
652
|
+
|
|
653
|
+
export type TaskActivityStatus = "started" | "progress" | "completed" | "failed";
|
|
654
|
+
|
|
655
|
+
export interface TaskActivityFrame extends ClusterFrame {
|
|
656
|
+
type: "task_activity";
|
|
657
|
+
payload: {
|
|
658
|
+
taskId: string;
|
|
659
|
+
taskType: "acp" | "handoff";
|
|
660
|
+
status: TaskActivityStatus;
|
|
661
|
+
agent: string;
|
|
662
|
+
nodeId: string; // node where task is running
|
|
663
|
+
title: string;
|
|
664
|
+
detail?: string;
|
|
665
|
+
progress?: number; // 0.0 - 1.0
|
|
666
|
+
startedAt: number;
|
|
667
|
+
elapsedMs?: number;
|
|
668
|
+
tool?: string; // current tool being executed
|
|
669
|
+
toolDone?: boolean;
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// ── Peer approval ────────────────────────────────────────────────
|
|
674
|
+
export interface PeerApprovalNotify extends ClusterFrame {
|
|
675
|
+
type: "peer_approval_notify";
|
|
676
|
+
payload: {
|
|
677
|
+
approvalId: string;
|
|
678
|
+
nodeId: string;
|
|
679
|
+
deviceInfo?: DeviceInfo;
|
|
680
|
+
mode: "notify" | "required";
|
|
681
|
+
ip?: string;
|
|
682
|
+
/** Present when this is a resolution notification (approved/denied). */
|
|
683
|
+
resolution?: {
|
|
684
|
+
decision: "approve" | "deny";
|
|
685
|
+
resolvedBy: string;
|
|
686
|
+
};
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
export interface PeerApprovalRequest extends ClusterFrame {
|
|
691
|
+
type: "peer_approval_req";
|
|
692
|
+
id: string;
|
|
693
|
+
payload: {
|
|
694
|
+
approvalId: string;
|
|
695
|
+
nodeId: string;
|
|
696
|
+
deviceInfo?: DeviceInfo;
|
|
697
|
+
ip?: string;
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
export interface PeerApprovalResponse extends ClusterFrame {
|
|
702
|
+
type: "peer_approval_res";
|
|
703
|
+
id: string;
|
|
704
|
+
payload: {
|
|
705
|
+
approvalId: string;
|
|
706
|
+
decision: "approve" | "deny";
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// ── Terminal (interactive PTY over WebSocket) ─────────────────────
|
|
711
|
+
|
|
712
|
+
export interface TerminalOpenRequest extends ClusterFrame {
|
|
713
|
+
type: "terminal_open";
|
|
714
|
+
id: string;
|
|
715
|
+
payload: {
|
|
716
|
+
shell?: string;
|
|
717
|
+
cols?: number;
|
|
718
|
+
rows?: number;
|
|
719
|
+
cwd?: string;
|
|
720
|
+
env?: Record<string, string>;
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
export interface TerminalOpenResponse extends ClusterFrame {
|
|
725
|
+
type: "terminal_open_res";
|
|
726
|
+
id: string;
|
|
727
|
+
payload: {
|
|
728
|
+
success: boolean;
|
|
729
|
+
sessionId?: string;
|
|
730
|
+
error?: string;
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
export interface TerminalData extends ClusterFrame {
|
|
735
|
+
type: "terminal_data";
|
|
736
|
+
id: string;
|
|
737
|
+
payload: {
|
|
738
|
+
sessionId: string;
|
|
739
|
+
data: string; // base64-encoded
|
|
740
|
+
direction: "input" | "output";
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
export interface TerminalResize extends ClusterFrame {
|
|
745
|
+
type: "terminal_resize";
|
|
746
|
+
id: string;
|
|
747
|
+
payload: {
|
|
748
|
+
sessionId: string;
|
|
749
|
+
cols: number;
|
|
750
|
+
rows: number;
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
export interface TerminalCloseRequest extends ClusterFrame {
|
|
755
|
+
type: "terminal_close";
|
|
756
|
+
id: string;
|
|
757
|
+
payload: {
|
|
758
|
+
sessionId: string;
|
|
759
|
+
exitCode?: number;
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
export interface TerminalCloseResponse extends ClusterFrame {
|
|
764
|
+
type: "terminal_close_res";
|
|
765
|
+
id: string;
|
|
766
|
+
payload: {
|
|
767
|
+
success: boolean;
|
|
768
|
+
error?: string;
|
|
332
769
|
};
|
|
333
770
|
}
|
|
334
771
|
|
|
@@ -336,6 +773,8 @@ export interface KnowledgeSyncFrame extends ClusterFrame {
|
|
|
336
773
|
export type AnyClusterFrame =
|
|
337
774
|
| AuthChallenge
|
|
338
775
|
| AuthRequest
|
|
776
|
+
| AuthKeyExchange
|
|
777
|
+
| AuthVerify
|
|
339
778
|
| AuthOk
|
|
340
779
|
| AuthFail
|
|
341
780
|
| PeerSync
|
|
@@ -357,4 +796,37 @@ export type AnyClusterFrame =
|
|
|
357
796
|
| HandoffInput
|
|
358
797
|
| ToolProxyRequest
|
|
359
798
|
| ToolProxyResponse
|
|
360
|
-
|
|
|
799
|
+
| ToolBatchRequest
|
|
800
|
+
| ToolBatchResponse
|
|
801
|
+
| DiagnosticExec
|
|
802
|
+
| DiagnosticExecResponse
|
|
803
|
+
| DiagnosticStatus
|
|
804
|
+
| DiagnosticStatusResponse
|
|
805
|
+
| KnowledgeSyncFrame
|
|
806
|
+
| AcpTaskRequest
|
|
807
|
+
| AcpStreamChunk
|
|
808
|
+
| AcpTaskResponse
|
|
809
|
+
| AcpCloseRequest
|
|
810
|
+
| AcpCloseResponse
|
|
811
|
+
| AcpListRequest
|
|
812
|
+
| AcpListResponse
|
|
813
|
+
| AcpResumeRequest
|
|
814
|
+
| AcpResumeResponse
|
|
815
|
+
| AcpCancelRequest
|
|
816
|
+
| AcpCancelResponse
|
|
817
|
+
| AcpSetModeRequest
|
|
818
|
+
| AcpSetModeResponse
|
|
819
|
+
| AcpGetModesRequest
|
|
820
|
+
| AcpGetModesResponse
|
|
821
|
+
| ChatHistoryRequest
|
|
822
|
+
| ChatHistoryResponse
|
|
823
|
+
| PeerApprovalNotify
|
|
824
|
+
| PeerApprovalRequest
|
|
825
|
+
| PeerApprovalResponse
|
|
826
|
+
| TaskActivityFrame
|
|
827
|
+
| TerminalOpenRequest
|
|
828
|
+
| TerminalOpenResponse
|
|
829
|
+
| TerminalData
|
|
830
|
+
| TerminalResize
|
|
831
|
+
| TerminalCloseRequest
|
|
832
|
+
| TerminalCloseResponse;
|
package/src/web.ts
CHANGED
|
@@ -288,14 +288,14 @@ export class WebHandler {
|
|
|
288
288
|
} : undefined,
|
|
289
289
|
clusterTools: [
|
|
290
290
|
"cluster_handoff", "cluster_send", "cluster_peers",
|
|
291
|
-
"cluster_exec", "cluster_read", "cluster_write", "
|
|
291
|
+
"cluster_exec", "cluster_read", "cluster_write", "cluster_edit",
|
|
292
292
|
],
|
|
293
293
|
};
|
|
294
294
|
|
|
295
295
|
// All mesh peers share these cluster tools (they all run the ClawMatrix plugin)
|
|
296
296
|
const CLUSTER_TOOLS = [
|
|
297
297
|
"cluster_handoff", "cluster_send", "cluster_peers",
|
|
298
|
-
"cluster_exec", "cluster_read", "cluster_write", "
|
|
298
|
+
"cluster_exec", "cluster_read", "cluster_write", "cluster_edit",
|
|
299
299
|
];
|
|
300
300
|
|
|
301
301
|
const peerNodes: Record<string, unknown>[] = peers.map((p) => ({
|