generated from nhcarrigan/template
feat: add feature to monitor background agents (#125)
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>
This commit was merged in pull request #125.
This commit is contained in:
+59
-3
@@ -12,6 +12,8 @@ import type {
|
||||
UserQuestionEvent,
|
||||
} from "$lib/types/messages";
|
||||
import type { CharacterState } from "$lib/types/states";
|
||||
import type { AgentStartPayload, AgentEndPayload } from "$lib/types/agents";
|
||||
import { agentStore } from "$lib/stores/agents";
|
||||
import {
|
||||
initializeNotificationRules,
|
||||
cleanupNotificationRules,
|
||||
@@ -95,6 +97,7 @@ interface OutputPayload {
|
||||
output_tokens: number;
|
||||
cost_usd: number;
|
||||
};
|
||||
parent_tool_use_id?: string;
|
||||
}
|
||||
|
||||
interface ConnectionPayload {
|
||||
@@ -175,6 +178,12 @@ export async function initializeTauriListeners() {
|
||||
} else if (status === "disconnected") {
|
||||
const targetConversationId = conversation_id || get(claudeStore.activeConversationId);
|
||||
|
||||
// Mark all running agents as errored on disconnect, but not during reconnects
|
||||
// (permission prompts trigger reconnects and agents may complete before reconnect)
|
||||
if (!skipNextGreeting && targetConversationId) {
|
||||
agentStore.markAllErrored(targetConversationId);
|
||||
}
|
||||
|
||||
// Only remove from connected set if we're not about to reconnect
|
||||
if (!skipNextGreeting && targetConversationId) {
|
||||
connectedConversations.delete(targetConversationId);
|
||||
@@ -247,7 +256,8 @@ export async function initializeTauriListeners() {
|
||||
unlisteners.push(stateUnlisten);
|
||||
|
||||
const outputUnlisten = await listen<OutputPayload>("claude:output", (event) => {
|
||||
const { line_type, content, tool_name, conversation_id, cost } = event.payload;
|
||||
const { line_type, content, tool_name, conversation_id, cost, parent_tool_use_id } =
|
||||
event.payload;
|
||||
|
||||
// Convert snake_case cost to camelCase for TypeScript
|
||||
const costData = cost
|
||||
@@ -265,7 +275,8 @@ export async function initializeTauriListeners() {
|
||||
line_type as "user" | "assistant" | "system" | "tool" | "error",
|
||||
content,
|
||||
tool_name || undefined,
|
||||
costData
|
||||
costData,
|
||||
parent_tool_use_id
|
||||
);
|
||||
} else {
|
||||
// Fallback to active conversation if no conversation_id provided
|
||||
@@ -273,7 +284,8 @@ export async function initializeTauriListeners() {
|
||||
line_type as "user" | "assistant" | "system" | "tool" | "error",
|
||||
content,
|
||||
tool_name || undefined,
|
||||
costData
|
||||
costData,
|
||||
parent_tool_use_id
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -345,6 +357,50 @@ export async function initializeTauriListeners() {
|
||||
});
|
||||
unlisteners.push(permissionUnlisten);
|
||||
|
||||
const agentStartUnlisten = await listen<AgentStartPayload>("claude:agent-start", (event) => {
|
||||
const {
|
||||
tool_use_id,
|
||||
agent_id,
|
||||
description,
|
||||
subagent_type,
|
||||
started_at,
|
||||
conversation_id,
|
||||
parent_tool_use_id,
|
||||
} = event.payload;
|
||||
const targetConversationId = conversation_id || get(claudeStore.activeConversationId);
|
||||
if (targetConversationId) {
|
||||
agentStore.addAgent(targetConversationId, {
|
||||
toolUseId: tool_use_id,
|
||||
agentId: agent_id,
|
||||
description,
|
||||
subagentType: subagent_type,
|
||||
startedAt: started_at,
|
||||
status: "running",
|
||||
parentToolUseId: parent_tool_use_id,
|
||||
});
|
||||
}
|
||||
});
|
||||
unlisteners.push(agentStartUnlisten);
|
||||
|
||||
const agentUpdateUnlisten = await listen<{
|
||||
conversationId: string;
|
||||
toolUseId: string;
|
||||
agentId: string;
|
||||
}>("claude:agent-update", (event) => {
|
||||
const { conversationId, toolUseId, agentId } = event.payload;
|
||||
agentStore.updateAgentId(conversationId, toolUseId, agentId);
|
||||
});
|
||||
unlisteners.push(agentUpdateUnlisten);
|
||||
|
||||
const agentEndUnlisten = await listen<AgentEndPayload>("claude:agent-end", (event) => {
|
||||
const { tool_use_id, ended_at, is_error, conversation_id } = event.payload;
|
||||
const targetConversationId = conversation_id || get(claudeStore.activeConversationId);
|
||||
if (targetConversationId) {
|
||||
agentStore.endAgent(targetConversationId, tool_use_id, ended_at, is_error);
|
||||
}
|
||||
});
|
||||
unlisteners.push(agentEndUnlisten);
|
||||
|
||||
const questionUnlisten = await listen<UserQuestionEvent>("claude:question", (event) => {
|
||||
const questionEvent = event.payload;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user