fix(electrobun): 7 bug fixes + 3 partial features completed

Bugs fixed:
- Agent retry: clear dead session on failed start (was non-recoverable)
- seqId persist: save seq_id column in agent_messages, migrate existing DBs
- Window frame save: wire resize event listener to saveWindowFrame()
- Diagnostics counters: real RPC call counter via withRpcCounting() proxy

Partial features completed:
- Search auto-seed: rebuildIndex() on startup + indexMessage() on save
- Notifications: removed 3 hardcoded demo entries, start empty
- Agent cost streaming: emitCostIfChanged() on every message batch

New: src/bun/rpc-stats.ts (RPC call + dropped event counters)
This commit is contained in:
Hibryda 2026-03-25 20:26:49 +01:00
parent 0dd402e282
commit 66dce7ebae
8 changed files with 139 additions and 47 deletions

View file

@ -4,11 +4,13 @@
import type { SidecarManager } from "../sidecar-manager.ts";
import type { SessionDb } from "../session-db.ts";
import type { SearchDb } from "../search-db.ts";
export function createAgentHandlers(
sidecarManager: SidecarManager,
sessionDb: SessionDb,
sendToWebview: { send: Record<string, (...args: unknown[]) => void> },
searchDb?: SearchDb,
) {
return {
"agent.start": ({ sessionId, provider, prompt, cwd, model, systemPrompt, maxTurns, permissionMode, claudeConfigDir, extraEnv, additionalDirectories, worktreeName }: Record<string, unknown>) => {
@ -21,12 +23,38 @@ export function createAgentHandlers(
);
if (result.ok) {
// Partial 3: Track last-sent cost to emit live updates only on change
let lastCostUsd = 0;
let lastInputTokens = 0;
let lastOutputTokens = 0;
/** Emit agent.cost if cost data changed since last emit. */
function emitCostIfChanged(sid: string): void {
const sessions = sidecarManager.listSessions();
const session = sessions.find((s: Record<string, unknown>) => s.sessionId === sid);
if (!session) return;
const cost = (session.costUsd as number) ?? 0;
const inTok = (session.inputTokens as number) ?? 0;
const outTok = (session.outputTokens as number) ?? 0;
if (cost === lastCostUsd && inTok === lastInputTokens && outTok === lastOutputTokens) return;
lastCostUsd = cost;
lastInputTokens = inTok;
lastOutputTokens = outTok;
try {
(sendToWebview.send as Record<string, Function>)["agent.cost"]({
sessionId: sid, costUsd: cost, inputTokens: inTok, outputTokens: outTok,
});
} catch { /* ignore */ }
}
sidecarManager.onMessage(sessionId as string, (sid: string, messages: unknown) => {
try {
(sendToWebview.send as Record<string, Function>)["agent.message"]({ sessionId: sid, messages });
} catch (err) {
console.error("[agent.message] forward error:", err);
}
// Partial 3: Stream cost on every message batch
emitCostIfChanged(sid);
});
sidecarManager.onStatus(sessionId as string, (sid: string, status: string, error?: string) => {
@ -35,19 +63,7 @@ export function createAgentHandlers(
} catch (err) {
console.error("[agent.status] forward error:", err);
}
const sessions = sidecarManager.listSessions();
const session = sessions.find((s: Record<string, unknown>) => s.sessionId === sid);
if (session) {
try {
(sendToWebview.send as Record<string, Function>)["agent.cost"]({
sessionId: sid,
costUsd: session.costUsd,
inputTokens: session.inputTokens,
outputTokens: session.outputTokens,
});
} catch { /* ignore */ }
}
emitCostIfChanged(sid);
});
}
@ -122,9 +138,22 @@ export function createAgentHandlers(
sessionDb.saveMessages(messages.map((m) => ({
sessionId: m.sessionId, msgId: m.msgId, role: m.role,
content: m.content, toolName: m.toolName, toolInput: m.toolInput,
timestamp: m.timestamp, costUsd: (m.costUsd as number) ?? 0,
timestamp: m.timestamp, seqId: (m.seqId as number) ?? 0,
costUsd: (m.costUsd as number) ?? 0,
inputTokens: (m.inputTokens as number) ?? 0, outputTokens: (m.outputTokens as number) ?? 0,
})));
// Partial 1: Index each new message in FTS5 search
if (searchDb) {
for (const m of messages) {
try {
searchDb.indexMessage(
String(m.sessionId ?? ""),
String(m.role ?? ""),
String(m.content ?? ""),
);
} catch { /* non-critical — don't fail the save */ }
}
}
return { ok: true };
} catch (err) {
console.error("[session.messages.save]", err);