Major restructuring: - Split monolithic gatewayStore into 5 focused stores: - connectionStore: WebSocket connection and gateway lifecycle - configStore: quickConfig, workspaceInfo, MCP services - agentStore: clones, usage stats, agent management - handStore: hands, approvals, triggers, hand runs - workflowStore: workflows, workflow runs, execution - Update all components to use new stores with selector pattern - Remove
145 lines
3.2 KiB
TypeScript
145 lines
3.2 KiB
TypeScript
/**
|
|
* Viking Local Adapter - Tauri Sidecar Integration
|
|
*
|
|
* Provides local memory operations through the OpenViking CLI sidecar.
|
|
* This eliminates the need for a Python server dependency.
|
|
*/
|
|
|
|
import { invoke } from '@tauri-apps/api/core';
|
|
|
|
// === Types ===
|
|
|
|
export interface LocalVikingStatus {
|
|
available: boolean;
|
|
version?: string;
|
|
dataDir?: string;
|
|
error?: string;
|
|
}
|
|
|
|
export interface LocalVikingResource {
|
|
uri: string;
|
|
name: string;
|
|
type: string;
|
|
size?: number;
|
|
modifiedAt?: string;
|
|
}
|
|
|
|
export interface LocalVikingFindResult {
|
|
uri: string;
|
|
score: number;
|
|
content: string;
|
|
level: string;
|
|
overview?: string;
|
|
}
|
|
|
|
export interface LocalVikingGrepResult {
|
|
uri: string;
|
|
line: number;
|
|
content: string;
|
|
matchStart: number;
|
|
matchEnd: number;
|
|
}
|
|
|
|
export interface LocalVikingAddResult {
|
|
uri: string;
|
|
status: string;
|
|
}
|
|
|
|
// === Local Viking Client ===
|
|
|
|
export class VikingLocalClient {
|
|
private available: boolean | null = null;
|
|
|
|
async isAvailable(): Promise<boolean> {
|
|
if (this.available !== null) {
|
|
return this.available;
|
|
}
|
|
|
|
try {
|
|
const status = await this.status();
|
|
this.available = status.available;
|
|
return status.available;
|
|
} catch {
|
|
this.available = false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async status(): Promise<LocalVikingStatus> {
|
|
return await invoke<LocalVikingStatus>('viking_status');
|
|
}
|
|
|
|
async addResource(
|
|
uri: string,
|
|
content: string
|
|
): Promise<LocalVikingAddResult> {
|
|
// For small content, use inline; for large content. use file-based
|
|
if (content.length < 10000) {
|
|
return await invoke<LocalVikingAddResult>('viking_add_inline', { uri, content });
|
|
} else {
|
|
return await invoke<LocalVikingAddResult>('viking_add', { uri, content });
|
|
}
|
|
}
|
|
|
|
async find(
|
|
query: string,
|
|
options?: {
|
|
scope?: string;
|
|
limit?: number;
|
|
}
|
|
): Promise<LocalVikingFindResult[]> {
|
|
return await invoke<LocalVikingFindResult[]>('viking_find', {
|
|
query,
|
|
scope: options?.scope,
|
|
limit: options?.limit,
|
|
});
|
|
}
|
|
|
|
async grep(
|
|
pattern: string,
|
|
options?: {
|
|
uri?: string;
|
|
caseSensitive?: boolean;
|
|
limit?: number;
|
|
}
|
|
): Promise<LocalVikingGrepResult[]> {
|
|
return await invoke<LocalVikingGrepResult[]>('viking_grep', {
|
|
pattern,
|
|
uri: options?.uri,
|
|
caseSensitive: options?.caseSensitive,
|
|
limit: options?.limit,
|
|
});
|
|
}
|
|
|
|
async ls(path: string): Promise<LocalVikingResource[]> {
|
|
return await invoke<LocalVikingResource[]>('viking_ls', { path });
|
|
}
|
|
|
|
async readContent(uri: string, level?: string): Promise<string> {
|
|
return await invoke<string>('viking_read', { uri, level });
|
|
}
|
|
|
|
async removeResource(uri: string): Promise<void> {
|
|
await invoke('viking_remove', { uri });
|
|
}
|
|
|
|
async tree(path: string, depth?: number): Promise<unknown> {
|
|
return await invoke('viking_tree', { path, depth });
|
|
}
|
|
}
|
|
|
|
// === Singleton ===
|
|
|
|
let _localClient: VikingLocalClient | null;
|
|
|
|
export function getVikingLocalClient(): VikingLocalClient {
|
|
if (!_localClient) {
|
|
_localClient = new VikingLocalClient();
|
|
}
|
|
return _localClient;
|
|
}
|
|
|
|
export function resetVikingLocalClient(): void {
|
|
_localClient = null;
|
|
}
|