feat(memora): add Memora adapter with read-only SQLite backend
This commit is contained in:
parent
ad7e24e40d
commit
f3f740a8fe
4 changed files with 500 additions and 0 deletions
|
|
@ -9,6 +9,8 @@
|
|||
import { CLAUDE_PROVIDER } from './lib/providers/claude';
|
||||
import { CODEX_PROVIDER } from './lib/providers/codex';
|
||||
import { OLLAMA_PROVIDER } from './lib/providers/ollama';
|
||||
import { registerMemoryAdapter } from './lib/adapters/memory-adapter';
|
||||
import { MemoraAdapter } from './lib/adapters/memora-bridge';
|
||||
import { loadWorkspace, getActiveTab, setActiveTab, setActiveProject, getEnabledProjects } from './lib/stores/workspace.svelte';
|
||||
|
||||
// Workspace components
|
||||
|
|
@ -72,6 +74,9 @@
|
|||
registerProvider(CLAUDE_PROVIDER);
|
||||
registerProvider(CODEX_PROVIDER);
|
||||
registerProvider(OLLAMA_PROVIDER);
|
||||
const memora = new MemoraAdapter();
|
||||
registerMemoryAdapter(memora);
|
||||
memora.checkAvailability();
|
||||
startAgentDispatcher();
|
||||
startHealthTick();
|
||||
|
||||
|
|
|
|||
122
v2/src/lib/adapters/memora-bridge.ts
Normal file
122
v2/src/lib/adapters/memora-bridge.ts
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/**
|
||||
* Memora IPC bridge — read-only access to the Memora memory database.
|
||||
* Wraps Tauri commands and provides a MemoryAdapter implementation.
|
||||
*/
|
||||
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import type { MemoryAdapter, MemoryNode, MemorySearchResult } from './memory-adapter';
|
||||
|
||||
// --- Raw IPC types (match Rust structs) ---
|
||||
|
||||
interface MemoraNode {
|
||||
id: number;
|
||||
content: string;
|
||||
tags: string[];
|
||||
metadata?: Record<string, unknown>;
|
||||
created_at?: string;
|
||||
updated_at?: string;
|
||||
}
|
||||
|
||||
interface MemoraSearchResult {
|
||||
nodes: MemoraNode[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
// --- IPC wrappers ---
|
||||
|
||||
export async function memoraAvailable(): Promise<boolean> {
|
||||
return invoke<boolean>('memora_available');
|
||||
}
|
||||
|
||||
export async function memoraList(options?: {
|
||||
tags?: string[];
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}): Promise<MemoraSearchResult> {
|
||||
return invoke<MemoraSearchResult>('memora_list', {
|
||||
tags: options?.tags ?? null,
|
||||
limit: options?.limit ?? 50,
|
||||
offset: options?.offset ?? 0,
|
||||
});
|
||||
}
|
||||
|
||||
export async function memoraSearch(
|
||||
query: string,
|
||||
options?: { tags?: string[]; limit?: number },
|
||||
): Promise<MemoraSearchResult> {
|
||||
return invoke<MemoraSearchResult>('memora_search', {
|
||||
query,
|
||||
tags: options?.tags ?? null,
|
||||
limit: options?.limit ?? 50,
|
||||
});
|
||||
}
|
||||
|
||||
export async function memoraGet(id: number): Promise<MemoraNode | null> {
|
||||
return invoke<MemoraNode | null>('memora_get', { id });
|
||||
}
|
||||
|
||||
// --- MemoryAdapter implementation ---
|
||||
|
||||
function toMemoryNode(n: MemoraNode): MemoryNode {
|
||||
return {
|
||||
id: n.id,
|
||||
content: n.content,
|
||||
tags: n.tags,
|
||||
metadata: n.metadata,
|
||||
created_at: n.created_at,
|
||||
updated_at: n.updated_at,
|
||||
};
|
||||
}
|
||||
|
||||
function toSearchResult(r: MemoraSearchResult): MemorySearchResult {
|
||||
return {
|
||||
nodes: r.nodes.map(toMemoryNode),
|
||||
total: r.total,
|
||||
};
|
||||
}
|
||||
|
||||
export class MemoraAdapter implements MemoryAdapter {
|
||||
readonly name = 'memora';
|
||||
private _available: boolean | null = null;
|
||||
|
||||
get available(): boolean {
|
||||
// Optimistic: assume available until first check proves otherwise.
|
||||
// Actual availability is checked lazily on first operation.
|
||||
return this._available ?? true;
|
||||
}
|
||||
|
||||
async checkAvailability(): Promise<boolean> {
|
||||
this._available = await memoraAvailable();
|
||||
return this._available;
|
||||
}
|
||||
|
||||
async list(options?: {
|
||||
tags?: string[];
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}): Promise<MemorySearchResult> {
|
||||
const result = await memoraList(options);
|
||||
this._available = true;
|
||||
return toSearchResult(result);
|
||||
}
|
||||
|
||||
async search(
|
||||
query: string,
|
||||
options?: { tags?: string[]; limit?: number },
|
||||
): Promise<MemorySearchResult> {
|
||||
const result = await memoraSearch(query, options);
|
||||
this._available = true;
|
||||
return toSearchResult(result);
|
||||
}
|
||||
|
||||
async get(id: string | number): Promise<MemoryNode | null> {
|
||||
const numId = typeof id === 'string' ? parseInt(id, 10) : id;
|
||||
if (isNaN(numId)) return null;
|
||||
const node = await memoraGet(numId);
|
||||
if (node) {
|
||||
this._available = true;
|
||||
return toMemoryNode(node);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue