fix: interrupt running agents before archive

This commit is contained in:
Mohamed Boudra
2026-02-20 13:34:06 +07:00
parent e22647af62
commit 6dad3212da
4 changed files with 94 additions and 2 deletions
@@ -196,6 +196,64 @@ describe("daemon client E2E", () => {
await expect(ctx.client.archiveAgent(randomUUID())).rejects.toThrow();
}, 10000);
test("interrupts a running agent before archiving", async () => {
const cwd = tmpCwd();
try {
const created = await ctx.client.createAgent({
config: {
...getFullAccessConfig("codex"),
cwd,
},
});
await ctx.client.sendMessage(
created.id,
"Use your shell tool to run `sleep 30` and then confirm when done."
);
await ctx.client.waitForAgentUpsert(
created.id,
(snapshot) => snapshot.status === "running",
15000
);
const result = await ctx.client.archiveAgent(created.id);
expect(result.archivedAt).toBeTruthy();
const archived = await ctx.client.fetchAgent(created.id);
expect(archived).not.toBeNull();
expect(archived?.archivedAt).toBeTruthy();
expect(archived?.status).not.toBe("running");
const runningAgents = await ctx.client.fetchAgents({
filter: { includeArchived: true, statuses: ["running"] },
});
expect(
runningAgents.entries.some((entry) => entry.agent.id === created.id)
).toBe(false);
} finally {
rmSync(cwd, { recursive: true, force: true });
}
}, 60000);
test("rejects send_agent_message for archived agents", async () => {
const cwd = tmpCwd();
try {
const created = await ctx.client.createAgent({
config: {
...getFullAccessConfig("codex"),
cwd,
},
});
await ctx.client.archiveAgent(created.id);
await expect(
ctx.client.sendMessage(created.id, "Say hello and nothing else")
).rejects.toThrow("archived");
} finally {
rmSync(cwd, { recursive: true, force: true });
}
}, 30000);
test("returns home-scoped directory suggestions", async () => {
const insideHomeDir = mkdtempSync(path.join(homedir(), "paseo-dir-suggestion-"));
const outsideHomeDir = mkdtempSync(path.join(tmpdir(), "paseo-dir-suggestion-outside-"));
+33
View File
@@ -1674,6 +1674,10 @@ export class Session {
private async handleArchiveAgentRequest(agentId: string, requestId: string): Promise<void> {
this.sessionLogger.info({ agentId }, `Archiving agent ${agentId}`)
if (this.agentManager.getAgent(agentId)) {
await this.interruptAgentIfRunning(agentId)
}
const archivedAt = new Date().toISOString()
const existing = await this.agentStorage.get(agentId)
@@ -1717,6 +1721,11 @@ export class Session {
})
}
private async getArchivedAt(agentId: string): Promise<string | null> {
const record = await this.agentStorage.get(agentId)
return record?.archivedAt ?? null
}
private async handleUpdateAgentRequest(
agentId: string,
name: string | undefined,
@@ -2308,6 +2317,16 @@ export class Session {
return
}
const archivedAt = await this.getArchivedAt(agentId)
if (archivedAt) {
this.handleAgentRunError(
agentId,
new Error(`Agent ${agentId} is archived`),
'Refusing to send prompt to archived agent'
)
return
}
try {
await this.interruptAgentIfRunning(agentId)
} catch (error) {
@@ -5250,6 +5269,20 @@ export class Session {
try {
const agentId = resolved.agentId
const archivedAt = await this.getArchivedAt(agentId)
if (archivedAt) {
this.emit({
type: 'send_agent_message_response',
payload: {
requestId: msg.requestId,
agentId,
accepted: false,
error: `Agent ${agentId} is archived`,
},
})
return
}
await this.ensureAgentLoaded(agentId)
await this.interruptAgentIfRunning(agentId)