clawmatrix 0.1.22 → 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 +290 -85
- package/src/crypto.ts +179 -0
- package/src/debug.ts +15 -2
- package/src/e2e/helpers.ts +318 -0
- package/src/handoff.ts +132 -87
- package/src/identity.ts +95 -0
- package/src/index.ts +539 -45
- package/src/knowledge-sync.ts +777 -205
- package/src/local-tools.ts +9 -2
- package/src/model-proxy.ts +358 -110
- package/src/peer-approval.ts +628 -0
- package/src/peer-manager.ts +270 -38
- 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 +477 -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;
|
|
@@ -101,6 +123,8 @@ export interface ModelRequest extends ClusterFrame {
|
|
|
101
123
|
/** Format of `messages`: "chat" = OpenAI chat completions, "responses" = OpenAI Responses API input items.
|
|
102
124
|
* Defaults to "chat" for backward compatibility. */
|
|
103
125
|
inputFormat?: "chat" | "responses";
|
|
126
|
+
tools?: unknown[];
|
|
127
|
+
toolChoice?: unknown;
|
|
104
128
|
temperature?: number;
|
|
105
129
|
maxTokens?: number;
|
|
106
130
|
stream: boolean;
|
|
@@ -113,6 +137,8 @@ export interface ModelResponse extends ClusterFrame {
|
|
|
113
137
|
payload: {
|
|
114
138
|
success: boolean;
|
|
115
139
|
content?: string;
|
|
140
|
+
/** Reasoning/thinking content from models like DeepSeek. */
|
|
141
|
+
reasoning?: string;
|
|
116
142
|
/** Full message object from upstream (choices[0].message or responses output).
|
|
117
143
|
* Carries tool_calls, refusal, etc. that `content` alone cannot represent. */
|
|
118
144
|
message?: unknown;
|
|
@@ -126,6 +152,8 @@ export interface ModelStreamChunk extends ClusterFrame {
|
|
|
126
152
|
id: string;
|
|
127
153
|
payload: {
|
|
128
154
|
delta: string;
|
|
155
|
+
/** Reasoning/thinking delta from models like DeepSeek (reasoning_content). */
|
|
156
|
+
reasoningDelta?: string;
|
|
129
157
|
/** Full delta object from upstream (choices[0].delta).
|
|
130
158
|
* Carries tool_calls chunks that `delta` string cannot represent. */
|
|
131
159
|
deltaObj?: unknown;
|
|
@@ -134,6 +162,14 @@ export interface ModelStreamChunk extends ClusterFrame {
|
|
|
134
162
|
};
|
|
135
163
|
}
|
|
136
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
|
+
|
|
137
173
|
// ── Handoff ────────────────────────────────────────────────────────
|
|
138
174
|
export type HandoffStatus = "working" | "input_required" | "completed" | "failed" | "canceled";
|
|
139
175
|
|
|
@@ -150,6 +186,8 @@ export interface HandoffRequest extends ClusterFrame {
|
|
|
150
186
|
target: string;
|
|
151
187
|
task: string;
|
|
152
188
|
context?: string;
|
|
189
|
+
sessionId?: string; // Reuse session for multi-turn conversation
|
|
190
|
+
images?: ImageContent[];
|
|
153
191
|
};
|
|
154
192
|
}
|
|
155
193
|
|
|
@@ -175,6 +213,7 @@ export interface HandoffResponse extends ClusterFrame {
|
|
|
175
213
|
artifacts?: Artifact[];
|
|
176
214
|
inputRequired?: boolean;
|
|
177
215
|
handoffId?: string;
|
|
216
|
+
sessionId?: string; // For multi-turn conversation reuse
|
|
178
217
|
};
|
|
179
218
|
}
|
|
180
219
|
|
|
@@ -214,6 +253,7 @@ export interface HandoffInput extends ClusterFrame {
|
|
|
214
253
|
id: string;
|
|
215
254
|
payload: {
|
|
216
255
|
message: string;
|
|
256
|
+
images?: ImageContent[];
|
|
217
257
|
};
|
|
218
258
|
}
|
|
219
259
|
|
|
@@ -246,6 +286,36 @@ export interface ToolProxyResponse extends ClusterFrame {
|
|
|
246
286
|
};
|
|
247
287
|
}
|
|
248
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
|
+
|
|
249
319
|
// ── Device info ───────────────────────────────────────────────────
|
|
250
320
|
export interface DeviceInfo {
|
|
251
321
|
os: string; // e.g. "Darwin 24.6.0", "Linux 6.1.0"
|
|
@@ -283,6 +353,7 @@ export interface ModelInfo {
|
|
|
283
353
|
id: string;
|
|
284
354
|
provider: string;
|
|
285
355
|
description?: string;
|
|
356
|
+
input?: ("text" | "image")[];
|
|
286
357
|
compat?: ModelCompatInfo;
|
|
287
358
|
}
|
|
288
359
|
|
|
@@ -292,6 +363,11 @@ export interface ToolProxyInfo {
|
|
|
292
363
|
deny: string[];
|
|
293
364
|
}
|
|
294
365
|
|
|
366
|
+
export interface AcpAgentInfo {
|
|
367
|
+
id: string;
|
|
368
|
+
description: string;
|
|
369
|
+
}
|
|
370
|
+
|
|
295
371
|
export interface PeerInfo {
|
|
296
372
|
nodeId: string;
|
|
297
373
|
agents: AgentInfo[];
|
|
@@ -301,6 +377,8 @@ export interface PeerInfo {
|
|
|
301
377
|
directPeers?: string[]; // nodeIds this node has direct connections to
|
|
302
378
|
deviceInfo?: DeviceInfo; // system/hardware info
|
|
303
379
|
toolProxy?: ToolProxyInfo;
|
|
380
|
+
acpAgents?: AcpAgentInfo[]; // ACP agents available on this node
|
|
381
|
+
latencyMs?: number; // heartbeat RTT (direct) or estimated round-trip (relay)
|
|
304
382
|
}
|
|
305
383
|
|
|
306
384
|
export interface NodeCapabilities {
|
|
@@ -310,6 +388,7 @@ export interface NodeCapabilities {
|
|
|
310
388
|
tags: string[];
|
|
311
389
|
deviceInfo?: DeviceInfo;
|
|
312
390
|
toolProxy?: ToolProxyInfo;
|
|
391
|
+
acpAgents?: AcpAgentInfo[];
|
|
313
392
|
}
|
|
314
393
|
|
|
315
394
|
// ── Ingested events (from Shortcuts automations, etc.) ────────────
|
|
@@ -326,7 +405,367 @@ export interface IngestedEvent {
|
|
|
326
405
|
export interface KnowledgeSyncFrame extends ClusterFrame {
|
|
327
406
|
type: "knowledge_sync";
|
|
328
407
|
payload: {
|
|
329
|
-
|
|
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;
|
|
330
769
|
};
|
|
331
770
|
}
|
|
332
771
|
|
|
@@ -334,6 +773,8 @@ export interface KnowledgeSyncFrame extends ClusterFrame {
|
|
|
334
773
|
export type AnyClusterFrame =
|
|
335
774
|
| AuthChallenge
|
|
336
775
|
| AuthRequest
|
|
776
|
+
| AuthKeyExchange
|
|
777
|
+
| AuthVerify
|
|
337
778
|
| AuthOk
|
|
338
779
|
| AuthFail
|
|
339
780
|
| PeerSync
|
|
@@ -355,4 +796,37 @@ export type AnyClusterFrame =
|
|
|
355
796
|
| HandoffInput
|
|
356
797
|
| ToolProxyRequest
|
|
357
798
|
| ToolProxyResponse
|
|
358
|
-
|
|
|
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) => ({
|