generated from nhcarrigan/template
97a93c31c2
Also includes a fix to persist configuration across reconnects. Reviewed-on: #125 Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com> Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
122 lines
3.4 KiB
TypeScript
122 lines
3.4 KiB
TypeScript
import { writable, derived } from "svelte/store";
|
|
import type { AgentInfo } from "$lib/types/agents";
|
|
|
|
// Map of conversation ID -> agents in that conversation
|
|
const agentsByConversation = writable<Record<string, AgentInfo[]>>({});
|
|
|
|
function createAgentStore() {
|
|
return {
|
|
subscribe: agentsByConversation.subscribe,
|
|
|
|
addAgent(conversationId: string, agent: AgentInfo) {
|
|
agentsByConversation.update((state) => {
|
|
const existing = state[conversationId] || [];
|
|
return {
|
|
...state,
|
|
[conversationId]: [...existing, agent],
|
|
};
|
|
});
|
|
},
|
|
|
|
updateAgentId(conversationId: string, toolUseId: string, agentId: string) {
|
|
agentsByConversation.update((state) => {
|
|
const agents = state[conversationId];
|
|
if (!agents) return state;
|
|
|
|
const agentIndex = agents.findIndex((a) => a.toolUseId === toolUseId);
|
|
if (agentIndex === -1) return state;
|
|
|
|
const updated = [...agents];
|
|
updated[agentIndex] = {
|
|
...updated[agentIndex],
|
|
agentId,
|
|
};
|
|
|
|
return {
|
|
...state,
|
|
[conversationId]: updated,
|
|
};
|
|
});
|
|
},
|
|
|
|
endAgent(conversationId: string, toolUseId: string, endedAt: number, isError: boolean) {
|
|
agentsByConversation.update((state) => {
|
|
const agents = state[conversationId];
|
|
if (!agents) return state;
|
|
|
|
const agentIndex = agents.findIndex((a) => a.toolUseId === toolUseId);
|
|
if (agentIndex === -1) return state;
|
|
|
|
const updated = [...agents];
|
|
const agent = updated[agentIndex];
|
|
const durationMs = endedAt - agent.startedAt;
|
|
|
|
updated[agentIndex] = {
|
|
...agent,
|
|
endedAt,
|
|
status: isError ? "errored" : "completed",
|
|
durationMs,
|
|
};
|
|
|
|
return {
|
|
...state,
|
|
[conversationId]: updated,
|
|
};
|
|
});
|
|
},
|
|
|
|
markAllErrored(conversationId: string) {
|
|
agentsByConversation.update((state) => {
|
|
const agents = state[conversationId];
|
|
if (!agents) return state;
|
|
|
|
const now = Date.now();
|
|
const updated = agents.map((agent) =>
|
|
agent.status === "running"
|
|
? { ...agent, endedAt: now, status: "errored" as const }
|
|
: agent
|
|
);
|
|
|
|
return {
|
|
...state,
|
|
[conversationId]: updated,
|
|
};
|
|
});
|
|
},
|
|
|
|
clearCompleted(conversationId: string) {
|
|
agentsByConversation.update((state) => {
|
|
const agents = state[conversationId];
|
|
if (!agents) return state;
|
|
|
|
return {
|
|
...state,
|
|
[conversationId]: agents.filter((a) => a.status === "running"),
|
|
};
|
|
});
|
|
},
|
|
|
|
clearConversation(conversationId: string) {
|
|
agentsByConversation.update((state) => {
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- Unused destructured value
|
|
const { [conversationId]: _, ...rest } = state;
|
|
return rest;
|
|
});
|
|
},
|
|
};
|
|
}
|
|
|
|
export const agentStore = createAgentStore();
|
|
|
|
export function getAgentsForConversation(conversationId: string) {
|
|
return derived(agentsByConversation, ($state) => $state[conversationId] || []);
|
|
}
|
|
|
|
export const runningAgentCount = derived(agentsByConversation, ($state) => {
|
|
let count = 0;
|
|
for (const agents of Object.values($state)) {
|
|
count += agents.filter((a) => a.status === "running").length;
|
|
}
|
|
return count;
|
|
});
|