feat: Agent Orchestrator — multi-project agent dashboard
Tauri + Svelte 5 + Rust application for orchestrating multiple AI coding agents. Includes Claude, Aider, Codex, and Ollama provider support, multi-agent communication (btmsg/bttask), session anchors, plugin sandbox, FTS5 search, Landlock sandboxing, and 507 vitest + 110 cargo tests.
This commit is contained in:
commit
3672e92b7e
272 changed files with 68600 additions and 0 deletions
180
src/lib/adapters/remote-bridge.ts
Normal file
180
src/lib/adapters/remote-bridge.ts
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
// Remote Machine Bridge — Tauri IPC adapter for multi-machine management
|
||||
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { listen, type UnlistenFn } from '@tauri-apps/api/event';
|
||||
|
||||
export interface RemoteMachineConfig {
|
||||
label: string;
|
||||
url: string;
|
||||
token: string;
|
||||
auto_connect: boolean;
|
||||
/** SPKI SHA-256 pin(s) for certificate verification. Empty = TOFU on first connect. */
|
||||
spki_pins?: string[];
|
||||
}
|
||||
|
||||
export interface RemoteMachineInfo {
|
||||
id: string;
|
||||
label: string;
|
||||
url: string;
|
||||
status: string;
|
||||
auto_connect: boolean;
|
||||
/** Currently stored SPKI pin hashes (hex-encoded SHA-256) */
|
||||
spki_pins: string[];
|
||||
}
|
||||
|
||||
// --- Machine management ---
|
||||
|
||||
export async function listRemoteMachines(): Promise<RemoteMachineInfo[]> {
|
||||
return invoke('remote_list');
|
||||
}
|
||||
|
||||
export async function addRemoteMachine(config: RemoteMachineConfig): Promise<string> {
|
||||
return invoke('remote_add', { config });
|
||||
}
|
||||
|
||||
export async function removeRemoteMachine(machineId: string): Promise<void> {
|
||||
return invoke('remote_remove', { machineId });
|
||||
}
|
||||
|
||||
export async function connectRemoteMachine(machineId: string): Promise<void> {
|
||||
return invoke('remote_connect', { machineId });
|
||||
}
|
||||
|
||||
export async function disconnectRemoteMachine(machineId: string): Promise<void> {
|
||||
return invoke('remote_disconnect', { machineId });
|
||||
}
|
||||
|
||||
// --- SPKI certificate pinning ---
|
||||
|
||||
/** Probe a relay server's TLS certificate and return its SHA-256 hash (hex-encoded). */
|
||||
export async function probeSpki(url: string): Promise<string> {
|
||||
return invoke('remote_probe_spki', { url });
|
||||
}
|
||||
|
||||
/** Add an SPKI pin hash to a machine's trusted pins. */
|
||||
export async function addSpkiPin(machineId: string, pin: string): Promise<void> {
|
||||
return invoke('remote_add_pin', { machineId, pin });
|
||||
}
|
||||
|
||||
/** Remove an SPKI pin hash from a machine's trusted pins. */
|
||||
export async function removeSpkiPin(machineId: string, pin: string): Promise<void> {
|
||||
return invoke('remote_remove_pin', { machineId, pin });
|
||||
}
|
||||
|
||||
// --- Remote event listeners ---
|
||||
|
||||
export interface RemoteSidecarMessage {
|
||||
machineId: string;
|
||||
sessionId?: string;
|
||||
event?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface RemotePtyData {
|
||||
machineId: string;
|
||||
sessionId?: string;
|
||||
data?: string;
|
||||
}
|
||||
|
||||
export interface RemotePtyExit {
|
||||
machineId: string;
|
||||
sessionId?: string;
|
||||
}
|
||||
|
||||
export interface RemoteMachineEvent {
|
||||
machineId: string;
|
||||
payload?: unknown;
|
||||
error?: unknown;
|
||||
}
|
||||
|
||||
export async function onRemoteSidecarMessage(
|
||||
callback: (msg: RemoteSidecarMessage) => void,
|
||||
): Promise<UnlistenFn> {
|
||||
return listen<RemoteSidecarMessage>('remote-sidecar-message', (event) => {
|
||||
callback(event.payload);
|
||||
});
|
||||
}
|
||||
|
||||
export async function onRemotePtyData(
|
||||
callback: (msg: RemotePtyData) => void,
|
||||
): Promise<UnlistenFn> {
|
||||
return listen<RemotePtyData>('remote-pty-data', (event) => {
|
||||
callback(event.payload);
|
||||
});
|
||||
}
|
||||
|
||||
export async function onRemotePtyExit(
|
||||
callback: (msg: RemotePtyExit) => void,
|
||||
): Promise<UnlistenFn> {
|
||||
return listen<RemotePtyExit>('remote-pty-exit', (event) => {
|
||||
callback(event.payload);
|
||||
});
|
||||
}
|
||||
|
||||
export async function onRemoteMachineReady(
|
||||
callback: (msg: RemoteMachineEvent) => void,
|
||||
): Promise<UnlistenFn> {
|
||||
return listen<RemoteMachineEvent>('remote-machine-ready', (event) => {
|
||||
callback(event.payload);
|
||||
});
|
||||
}
|
||||
|
||||
export async function onRemoteMachineDisconnected(
|
||||
callback: (msg: RemoteMachineEvent) => void,
|
||||
): Promise<UnlistenFn> {
|
||||
return listen<RemoteMachineEvent>('remote-machine-disconnected', (event) => {
|
||||
callback(event.payload);
|
||||
});
|
||||
}
|
||||
|
||||
export async function onRemoteStateSync(
|
||||
callback: (msg: RemoteMachineEvent) => void,
|
||||
): Promise<UnlistenFn> {
|
||||
return listen<RemoteMachineEvent>('remote-state-sync', (event) => {
|
||||
callback(event.payload);
|
||||
});
|
||||
}
|
||||
|
||||
export async function onRemoteError(
|
||||
callback: (msg: RemoteMachineEvent) => void,
|
||||
): Promise<UnlistenFn> {
|
||||
return listen<RemoteMachineEvent>('remote-error', (event) => {
|
||||
callback(event.payload);
|
||||
});
|
||||
}
|
||||
|
||||
export interface RemoteReconnectingEvent {
|
||||
machineId: string;
|
||||
backoffSecs: number;
|
||||
}
|
||||
|
||||
export async function onRemoteMachineReconnecting(
|
||||
callback: (msg: RemoteReconnectingEvent) => void,
|
||||
): Promise<UnlistenFn> {
|
||||
return listen<RemoteReconnectingEvent>('remote-machine-reconnecting', (event) => {
|
||||
callback(event.payload);
|
||||
});
|
||||
}
|
||||
|
||||
export async function onRemoteMachineReconnectReady(
|
||||
callback: (msg: RemoteMachineEvent) => void,
|
||||
): Promise<UnlistenFn> {
|
||||
return listen<RemoteMachineEvent>('remote-machine-reconnect-ready', (event) => {
|
||||
callback(event.payload);
|
||||
});
|
||||
}
|
||||
|
||||
// --- SPKI TOFU event ---
|
||||
|
||||
export interface RemoteSpkiTofuEvent {
|
||||
machineId: string;
|
||||
hash: string;
|
||||
}
|
||||
|
||||
/** Listen for TOFU (Trust On First Use) events when a new SPKI pin is auto-stored. */
|
||||
export async function onRemoteSpkiTofu(
|
||||
callback: (msg: RemoteSpkiTofuEvent) => void,
|
||||
): Promise<UnlistenFn> {
|
||||
return listen<RemoteSpkiTofuEvent>('remote-spki-tofu', (event) => {
|
||||
callback(event.payload);
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue