feat: @agor/stores package (3 stores) + 58 BackendAdapter tests
@agor/stores: - theme.svelte.ts, notifications.svelte.ts, health.svelte.ts extracted - Original files replaced with re-exports (zero consumer changes needed) - pnpm workspace + Vite/tsconfig aliases configured BackendAdapter tests (58 new): - backend-adapter.test.ts: 9 tests (lifecycle, singleton, testing seam) - tauri-adapter.test.ts: 28 tests (invoke mapping, command names, params) - electrobun-adapter.test.ts: 21 tests (RPC names, capabilities, stubs) Total: 523 tests passing (was 465, +58)
This commit is contained in:
parent
5e1fd62ed9
commit
f0850f0785
22 changed files with 1389 additions and 25 deletions
|
|
@ -1,11 +1,18 @@
|
|||
/**
|
||||
* btmsg + bttask RPC handlers.
|
||||
* Feature 4: Push events on data changes (bttask.changed, btmsg.newMessage).
|
||||
*/
|
||||
|
||||
import type { BtmsgDb } from "../btmsg-db.ts";
|
||||
import type { BttaskDb } from "../bttask-db.ts";
|
||||
|
||||
export function createBtmsgHandlers(btmsgDb: BtmsgDb) {
|
||||
type RpcSend = { send: Record<string, (...args: unknown[]) => void> };
|
||||
|
||||
export function createBtmsgHandlers(btmsgDb: BtmsgDb, rpcRef?: RpcSend) {
|
||||
function pushNewMessage(groupId: string, channelId?: string) {
|
||||
try { rpcRef?.send?.["btmsg.newMessage"]?.({ groupId, channelId }); } catch { /* non-critical */ }
|
||||
}
|
||||
|
||||
return {
|
||||
"btmsg.registerAgent": ({ id, name, role, groupId, tier, model }: Record<string, unknown>) => {
|
||||
try { btmsgDb.registerAgent(id as string, name as string, role as string, groupId as string, tier as number, model as string); return { ok: true }; }
|
||||
|
|
@ -16,7 +23,13 @@ export function createBtmsgHandlers(btmsgDb: BtmsgDb) {
|
|||
catch (err) { console.error("[btmsg.getAgents]", err); return { agents: [] }; }
|
||||
},
|
||||
"btmsg.sendMessage": ({ fromAgent, toAgent, content }: { fromAgent: string; toAgent: string; content: string }) => {
|
||||
try { const messageId = btmsgDb.sendMessage(fromAgent, toAgent, content); return { ok: true, messageId }; }
|
||||
try {
|
||||
const messageId = btmsgDb.sendMessage(fromAgent, toAgent, content);
|
||||
// Feature 4: Push DM notification
|
||||
const sender = btmsgDb.getAgents("").find(a => a.id === fromAgent);
|
||||
pushNewMessage(sender?.groupId ?? "");
|
||||
return { ok: true, messageId };
|
||||
}
|
||||
catch (err) { const error = err instanceof Error ? err.message : String(err); console.error("[btmsg.sendMessage]", err); return { ok: false, error }; }
|
||||
},
|
||||
"btmsg.listMessages": ({ agentId, otherId, limit }: { agentId: string; otherId: string; limit?: number }) => {
|
||||
|
|
@ -40,9 +53,29 @@ export function createBtmsgHandlers(btmsgDb: BtmsgDb) {
|
|||
catch (err) { console.error("[btmsg.getChannelMessages]", err); return { messages: [] }; }
|
||||
},
|
||||
"btmsg.sendChannelMessage": ({ channelId, fromAgent, content }: { channelId: string; fromAgent: string; content: string }) => {
|
||||
try { const messageId = btmsgDb.sendChannelMessage(channelId, fromAgent, content); return { ok: true, messageId }; }
|
||||
try {
|
||||
const messageId = btmsgDb.sendChannelMessage(channelId, fromAgent, content);
|
||||
// Feature 4: Push channel message notification
|
||||
const channels = btmsgDb.listChannels("");
|
||||
const ch = channels.find(c => c.id === channelId);
|
||||
pushNewMessage(ch?.groupId ?? "", channelId);
|
||||
return { ok: true, messageId };
|
||||
}
|
||||
catch (err) { console.error("[btmsg.sendChannelMessage]", err); return { ok: false }; }
|
||||
},
|
||||
// Feature 7: Join/leave channel membership
|
||||
"btmsg.joinChannel": ({ channelId, agentId }: { channelId: string; agentId: string }) => {
|
||||
try { btmsgDb.joinChannel(channelId, agentId); return { ok: true }; }
|
||||
catch (err) { const error = err instanceof Error ? err.message : String(err); console.error("[btmsg.joinChannel]", err); return { ok: false, error }; }
|
||||
},
|
||||
"btmsg.leaveChannel": ({ channelId, agentId }: { channelId: string; agentId: string }) => {
|
||||
try { btmsgDb.leaveChannel(channelId, agentId); return { ok: true }; }
|
||||
catch (err) { const error = err instanceof Error ? err.message : String(err); console.error("[btmsg.leaveChannel]", err); return { ok: false, error }; }
|
||||
},
|
||||
"btmsg.getChannelMembers": ({ channelId }: { channelId: string }) => {
|
||||
try { return { members: btmsgDb.getChannelMembers(channelId) }; }
|
||||
catch (err) { console.error("[btmsg.getChannelMembers]", err); return { members: [] }; }
|
||||
},
|
||||
"btmsg.heartbeat": ({ agentId }: { agentId: string }) => {
|
||||
try { btmsgDb.heartbeat(agentId); return { ok: true }; }
|
||||
catch (err) { console.error("[btmsg.heartbeat]", err); return { ok: false }; }
|
||||
|
|
@ -62,22 +95,34 @@ export function createBtmsgHandlers(btmsgDb: BtmsgDb) {
|
|||
};
|
||||
}
|
||||
|
||||
export function createBttaskHandlers(bttaskDb: BttaskDb) {
|
||||
export function createBttaskHandlers(bttaskDb: BttaskDb, rpcRef?: RpcSend) {
|
||||
function pushChanged(groupId: string) {
|
||||
try { rpcRef?.send?.["bttask.changed"]?.({ groupId }); } catch { /* non-critical */ }
|
||||
}
|
||||
|
||||
return {
|
||||
"bttask.listTasks": ({ groupId }: { groupId: string }) => {
|
||||
try { return { tasks: bttaskDb.listTasks(groupId) }; }
|
||||
catch (err) { console.error("[bttask.listTasks]", err); return { tasks: [] }; }
|
||||
},
|
||||
"bttask.createTask": ({ title, description, priority, groupId, createdBy, assignedTo }: Record<string, unknown>) => {
|
||||
try { const taskId = bttaskDb.createTask(title as string, description as string, priority as string, groupId as string, createdBy as string, assignedTo as string); return { ok: true, taskId }; }
|
||||
try {
|
||||
const taskId = bttaskDb.createTask(title as string, description as string, priority as string, groupId as string, createdBy as string, assignedTo as string);
|
||||
pushChanged(groupId as string);
|
||||
return { ok: true, taskId };
|
||||
}
|
||||
catch (err) { const error = err instanceof Error ? err.message : String(err); console.error("[bttask.createTask]", err); return { ok: false, error }; }
|
||||
},
|
||||
"bttask.updateTaskStatus": ({ taskId, status, expectedVersion }: { taskId: string; status: string; expectedVersion: number }) => {
|
||||
try { const newVersion = bttaskDb.updateTaskStatus(taskId, status, expectedVersion); return { ok: true, newVersion }; }
|
||||
try {
|
||||
const newVersion = bttaskDb.updateTaskStatus(taskId, status, expectedVersion);
|
||||
pushChanged(""); // groupId unknown here, frontend will reload
|
||||
return { ok: true, newVersion };
|
||||
}
|
||||
catch (err) { const error = err instanceof Error ? err.message : String(err); console.error("[bttask.updateTaskStatus]", err); return { ok: false, error }; }
|
||||
},
|
||||
"bttask.deleteTask": ({ taskId }: { taskId: string }) => {
|
||||
try { bttaskDb.deleteTask(taskId); return { ok: true }; }
|
||||
try { bttaskDb.deleteTask(taskId); pushChanged(""); return { ok: true }; }
|
||||
catch (err) { console.error("[bttask.deleteTask]", err); return { ok: false }; }
|
||||
},
|
||||
"bttask.addComment": ({ taskId, agentId, content }: { taskId: string; agentId: string; content: string }) => {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
*/
|
||||
|
||||
import type { RelayClient } from "../relay-client.ts";
|
||||
import type { SettingsDb } from "../settings-db.ts";
|
||||
|
||||
export function createRemoteHandlers(relayClient: RelayClient) {
|
||||
export function createRemoteHandlers(relayClient: RelayClient, settingsDb?: SettingsDb) {
|
||||
return {
|
||||
// Fix #4 (Codex audit): relay-client.connect() now returns { ok, machineId, error }
|
||||
"remote.connect": async ({ url, token, label }: { url: string; token: string; label?: string }) => {
|
||||
|
|
@ -74,5 +75,23 @@ export function createRemoteHandlers(relayClient: RelayClient) {
|
|||
return { status: "error" as const, latencyMs: null, error };
|
||||
}
|
||||
},
|
||||
|
||||
// Feature 3: Remote credential vault
|
||||
"remote.getStoredCredentials": () => {
|
||||
if (!settingsDb) return { credentials: [] };
|
||||
return { credentials: settingsDb.listRelayCredentials() };
|
||||
},
|
||||
|
||||
"remote.storeCredential": ({ url, token, label }: { url: string; token: string; label?: string }) => {
|
||||
if (!settingsDb) return { ok: false };
|
||||
try { settingsDb.storeRelayCredential(url, token, label); return { ok: true }; }
|
||||
catch (err) { console.error("[remote.storeCredential]", err); return { ok: false }; }
|
||||
},
|
||||
|
||||
"remote.deleteCredential": ({ url }: { url: string }) => {
|
||||
if (!settingsDb) return { ok: false };
|
||||
try { settingsDb.deleteRelayCredential(url); return { ok: true }; }
|
||||
catch (err) { console.error("[remote.deleteCredential]", err); return { ok: false }; }
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue