diff --git a/extensions/cli/src/commands/serve.ts b/extensions/cli/src/commands/serve.ts index f0a41469b3f..cefe2e6dd9b 100644 --- a/extensions/cli/src/commands/serve.ts +++ b/extensions/cli/src/commands/serve.ts @@ -529,7 +529,19 @@ export async function serve(prompt?: string, options: ServeOptions = {}) { // Update metadata after successful agent turn try { const history = services.chatHistory?.getHistory(); - await updateAgentMetadata(history); + + // Check if the agent should be marked as complete + // The agent is complete if the last message is from the assistant and has no tool calls + let isComplete = false; + if (history && history.length > 0) { + const lastItem = history[history.length - 1]; + if (lastItem?.message?.role === "assistant") { + const toolCalls = (lastItem.message as any).tool_calls; + isComplete = !toolCalls || toolCalls.length === 0; + } + } + + await updateAgentMetadata({ history, isComplete }); } catch (metadataErr) { // Non-critical: log but don't fail the agent execution logger.debug( diff --git a/extensions/cli/src/tools/exit.ts b/extensions/cli/src/tools/exit.ts index a6d84bdc3ee..987b9522ecf 100644 --- a/extensions/cli/src/tools/exit.ts +++ b/extensions/cli/src/tools/exit.ts @@ -1,3 +1,5 @@ +import { logger } from "../util/logger.js"; + import { Tool } from "./types.js"; export const exitTool: Tool = { @@ -12,7 +14,21 @@ export const exitTool: Tool = { readonly: false, isBuiltIn: true, run: async (): Promise => { - const { gracefulExit } = await import("../util/exit.js"); + const { gracefulExit, updateAgentMetadata } = await import( + "../util/exit.js" + ); + + // Mark agent as complete before exiting + try { + await updateAgentMetadata({ isComplete: true }); + } catch (err) { + // Non-critical: log but don't block exit + logger.debug( + "Failed to update completion metadata (non-critical)", + err as any, + ); + } + await gracefulExit(1); return ""; }, diff --git a/extensions/cli/src/tools/reportFailure.ts b/extensions/cli/src/tools/reportFailure.ts index 1e0fede2e65..a2d56fe3304 100644 --- a/extensions/cli/src/tools/reportFailure.ts +++ b/extensions/cli/src/tools/reportFailure.ts @@ -6,6 +6,7 @@ import { AuthenticationRequiredError, post, } from "../util/apiClient.js"; +import { updateAgentMetadata } from "../util/exit.js"; import { logger } from "../util/logger.js"; import { Tool } from "./types.js"; @@ -74,6 +75,18 @@ export const reportFailureTool: Tool = { errorMessage: trimmedMessage, }); + // Mark agent as complete since it failed + try { + await updateAgentMetadata({ isComplete: true }); + logger.debug("Marked agent as complete due to failure"); + } catch (metadataErr) { + // Non-critical: log but don't fail the failure report + logger.debug( + "Failed to update completion metadata (non-critical)", + metadataErr as any, + ); + } + logger.info(`Failure reported: ${trimmedMessage}`); return "Failure reported to user."; } catch (error) { diff --git a/extensions/cli/src/tools/status.ts b/extensions/cli/src/tools/status.ts index c75eec837f6..c545a8d581d 100644 --- a/extensions/cli/src/tools/status.ts +++ b/extensions/cli/src/tools/status.ts @@ -5,6 +5,7 @@ import { AuthenticationRequiredError, post, } from "../util/apiClient.js"; +import { updateAgentMetadata } from "../util/exit.js"; import { logger } from "../util/logger.js"; import { Tool } from "./types.js"; @@ -62,6 +63,24 @@ You should use this tool to notify the user whenever the state of your work chan await post(`agents/${agentId}/status`, { status: args.status }); logger.info(`Status: ${args.status}`); + + // If status is DONE or FAILED, mark agent as complete + const normalizedStatus = args.status.toUpperCase(); + if (normalizedStatus === "DONE" || normalizedStatus === "FAILED") { + try { + await updateAgentMetadata({ isComplete: true }); + logger.debug( + `Marked agent as complete due to status: ${args.status}`, + ); + } catch (metadataErr) { + // Non-critical: log but don't fail the status update + logger.debug( + "Failed to update completion metadata (non-critical)", + metadataErr as any, + ); + } + } + return `Status set: ${args.status}`; } catch (error) { if (error instanceof ContinueError) {