test(agent-manager): add session ID verification and improve agent state persistence
This commit is contained in:
+125
-5
@@ -1,14 +1,134 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": "fc818184-5676-4f24-a92a-77e9e15c515d",
|
"id": "299ab613-74d7-478b-a990-f95b044606b4",
|
||||||
"title": "Agent fc818184",
|
"title": "Agent 299ab613",
|
||||||
|
"sessionId": "019a1f5d-1184-772c-acb4-0b61ad47bb18",
|
||||||
|
"options": {
|
||||||
|
"type": "claude",
|
||||||
|
"sessionId": null
|
||||||
|
},
|
||||||
|
"createdAt": "2025-10-26T07:13:03.607Z",
|
||||||
|
"lastActivityAt": "2025-10-26T07:13:07.664Z",
|
||||||
|
"cwd": "/var/folders/xl/kkk9drfd3ms_t8x7rmy4z6900000gn/T/acp-test-c5m2nU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c6132199-a93b-428e-ac6b-6e8067855117",
|
||||||
|
"title": "Agent c6132199",
|
||||||
|
"sessionId": "019a1f5d-5a27-712a-a003-c33d85514452",
|
||||||
|
"options": {
|
||||||
|
"type": "claude",
|
||||||
|
"sessionId": null
|
||||||
|
},
|
||||||
|
"createdAt": "2025-10-26T07:13:22.279Z",
|
||||||
|
"lastActivityAt": "2025-10-26T07:13:34.996Z",
|
||||||
|
"cwd": "/var/folders/xl/kkk9drfd3ms_t8x7rmy4z6900000gn/T/acp-test-YqAd2n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "01cb507d-5c45-402a-9010-278077d72511",
|
||||||
|
"title": "Agent 01cb507d",
|
||||||
|
"sessionId": "019a1f5e-63ae-7318-a927-ace1f5177b40",
|
||||||
|
"options": {
|
||||||
|
"type": "claude",
|
||||||
|
"sessionId": null
|
||||||
|
},
|
||||||
|
"createdAt": "2025-10-26T07:14:29.299Z",
|
||||||
|
"lastActivityAt": "2025-10-26T07:14:34.243Z",
|
||||||
|
"cwd": "/var/folders/xl/kkk9drfd3ms_t8x7rmy4z6900000gn/T/acp-test-YqAd2n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3647cfd5-7691-469d-a5b4-dfddf4950327",
|
||||||
|
"title": "Agent 3647cfd5",
|
||||||
|
"sessionId": "019a1f5f-f3e1-72b9-bca0-6a58fc8bd52a",
|
||||||
|
"options": {
|
||||||
|
"type": "claude",
|
||||||
|
"sessionId": null
|
||||||
|
},
|
||||||
|
"createdAt": "2025-10-26T07:16:12.630Z",
|
||||||
|
"lastActivityAt": "2025-10-26T07:16:26.477Z",
|
||||||
|
"cwd": "/var/folders/xl/kkk9drfd3ms_t8x7rmy4z6900000gn/T/acp-test-SHg6iy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "52623113-d211-4ee0-bdfd-329e8dd8378b",
|
||||||
|
"title": "Agent 52623113",
|
||||||
|
"sessionId": "019a1f60-2ce3-756c-8850-b310052bb04e",
|
||||||
|
"options": {
|
||||||
|
"type": "claude",
|
||||||
|
"sessionId": null
|
||||||
|
},
|
||||||
|
"createdAt": "2025-10-26T07:16:27.236Z",
|
||||||
|
"lastActivityAt": "2025-10-26T07:16:30.640Z",
|
||||||
|
"cwd": "/var/folders/xl/kkk9drfd3ms_t8x7rmy4z6900000gn/T/acp-test-SHg6iy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9c675fcd-50c0-4228-a8d5-544286655713",
|
||||||
|
"title": "Agent 9c675fcd",
|
||||||
|
"sessionId": "019a1f60-b291-739b-8f8c-d4615aaf8e80",
|
||||||
|
"options": {
|
||||||
|
"type": "claude",
|
||||||
|
"sessionId": null
|
||||||
|
},
|
||||||
|
"createdAt": "2025-10-26T07:17:01.370Z",
|
||||||
|
"lastActivityAt": "2025-10-26T07:17:16.318Z",
|
||||||
|
"cwd": "/var/folders/xl/kkk9drfd3ms_t8x7rmy4z6900000gn/T/acp-test-0sCjpk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9b7dc1ab-2465-4772-a821-760dd505b8d7",
|
||||||
|
"title": "Agent 9b7dc1ab",
|
||||||
|
"sessionId": "019a1f60-ef6b-76ab-9bce-e25cd24556cf",
|
||||||
|
"options": {
|
||||||
|
"type": "claude",
|
||||||
|
"sessionId": null
|
||||||
|
},
|
||||||
|
"createdAt": "2025-10-26T07:17:17.000Z",
|
||||||
|
"lastActivityAt": "2025-10-26T07:17:22.332Z",
|
||||||
|
"cwd": "/var/folders/xl/kkk9drfd3ms_t8x7rmy4z6900000gn/T/acp-test-0sCjpk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c83eea1e-f5c8-435a-bc02-716542d60e0e",
|
||||||
|
"title": "Agent c83eea1e",
|
||||||
"sessionId": null,
|
"sessionId": null,
|
||||||
"options": {
|
"options": {
|
||||||
"type": "claude",
|
"type": "claude",
|
||||||
"sessionId": null
|
"sessionId": null
|
||||||
},
|
},
|
||||||
"createdAt": "2025-10-26T06:59:13.289Z",
|
"createdAt": "2025-10-26T07:28:27.901Z",
|
||||||
"lastActivityAt": "2025-10-26T06:59:22.379Z",
|
"lastActivityAt": "2025-10-26T07:28:41.570Z",
|
||||||
"cwd": "/var/folders/xl/kkk9drfd3ms_t8x7rmy4z6900000gn/T/acp-test-wm5mun"
|
"cwd": "/var/folders/xl/kkk9drfd3ms_t8x7rmy4z6900000gn/T/acp-test-QcKr0I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "354b099b-ffb9-4c42-9b82-2590550e7299",
|
||||||
|
"title": "Agent 354b099b",
|
||||||
|
"sessionId": null,
|
||||||
|
"options": {
|
||||||
|
"type": "claude",
|
||||||
|
"sessionId": null
|
||||||
|
},
|
||||||
|
"createdAt": "2025-10-26T07:28:42.609Z",
|
||||||
|
"lastActivityAt": "2025-10-26T07:28:52.065Z",
|
||||||
|
"cwd": "/var/folders/xl/kkk9drfd3ms_t8x7rmy4z6900000gn/T/acp-test-QcKr0I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "28b888fa-7cbc-48a7-973a-964e8a5f29f5",
|
||||||
|
"title": "Agent 28b888fa",
|
||||||
|
"sessionId": "03e4b827-033e-4212-b3ca-cfee515cf1f0",
|
||||||
|
"options": {
|
||||||
|
"type": "claude",
|
||||||
|
"sessionId": "03e4b827-033e-4212-b3ca-cfee515cf1f0"
|
||||||
|
},
|
||||||
|
"createdAt": "2025-10-26T07:29:17.693Z",
|
||||||
|
"lastActivityAt": "2025-10-26T07:29:31.675Z",
|
||||||
|
"cwd": "/var/folders/xl/kkk9drfd3ms_t8x7rmy4z6900000gn/T/acp-test-Gi719a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "b535f9b4-230f-40a9-8db8-30b791be1df4",
|
||||||
|
"title": "Agent b535f9b4",
|
||||||
|
"sessionId": "06c94e04-8cc6-4219-8bf5-d0ef7eb9e46a",
|
||||||
|
"options": {
|
||||||
|
"type": "claude",
|
||||||
|
"sessionId": "06c94e04-8cc6-4219-8bf5-d0ef7eb9e46a"
|
||||||
|
},
|
||||||
|
"createdAt": "2025-10-26T07:29:32.156Z",
|
||||||
|
"lastActivityAt": "2025-10-26T07:29:40.533Z",
|
||||||
|
"cwd": "/var/folders/xl/kkk9drfd3ms_t8x7rmy4z6900000gn/T/acp-test-Gi719a"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -106,6 +106,12 @@ describe("AgentManager", () => {
|
|||||||
|
|
||||||
expect(status).toBe("completed");
|
expect(status).toBe("completed");
|
||||||
|
|
||||||
|
const agentBeforeKill = manager.listAgents().find((a) => a.id === agentId);
|
||||||
|
const claudeSessionId = manager.getClaudeSessionId(agentId);
|
||||||
|
console.log("Before kill - ACP Session ID:", agentBeforeKill?.sessionId);
|
||||||
|
console.log("Before kill - Claude Session ID:", claudeSessionId);
|
||||||
|
console.log("Working directory:", tmpDir);
|
||||||
|
|
||||||
await manager.killAgent(agentId);
|
await manager.killAgent(agentId);
|
||||||
|
|
||||||
const newManager = new AgentManager();
|
const newManager = new AgentManager();
|
||||||
@@ -113,6 +119,10 @@ describe("AgentManager", () => {
|
|||||||
|
|
||||||
const agents = newManager.listAgents();
|
const agents = newManager.listAgents();
|
||||||
const loadedAgent = agents.find((a) => a.id === agentId);
|
const loadedAgent = agents.find((a) => a.id === agentId);
|
||||||
|
const loadedClaudeSessionId = newManager.getClaudeSessionId(agentId);
|
||||||
|
|
||||||
|
console.log("After reload - ACP Session ID:", loadedAgent?.sessionId);
|
||||||
|
console.log("After reload - Claude Session ID:", loadedClaudeSessionId);
|
||||||
|
|
||||||
expect(loadedAgent).toBeDefined();
|
expect(loadedAgent).toBeDefined();
|
||||||
expect(loadedAgent?.id).toBe(agentId);
|
expect(loadedAgent?.id).toBe(agentId);
|
||||||
|
|||||||
@@ -29,7 +29,11 @@ import type {
|
|||||||
AgentRuntime,
|
AgentRuntime,
|
||||||
ManagedAgentState,
|
ManagedAgentState,
|
||||||
} from "./types.js";
|
} from "./types.js";
|
||||||
import { AgentPersistence, type AgentOptions } from "./agent-persistence.js";
|
import {
|
||||||
|
AgentPersistence,
|
||||||
|
type AgentOptions,
|
||||||
|
type PersistedAgent,
|
||||||
|
} from "./agent-persistence.js";
|
||||||
|
|
||||||
interface PendingPermission {
|
interface PendingPermission {
|
||||||
requestId: string;
|
requestId: string;
|
||||||
@@ -56,6 +60,14 @@ interface ManagedAgent {
|
|||||||
state: ManagedAgentState;
|
state: ManagedAgentState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateAgentCallback = (
|
||||||
|
agentId: string,
|
||||||
|
updateFn: (
|
||||||
|
agent: ManagedAgent
|
||||||
|
) => boolean | void | Promise<boolean | void>,
|
||||||
|
options?: { sessionId: string | null }
|
||||||
|
) => Promise<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the status from an agent's state
|
* Get the status from an agent's state
|
||||||
*/
|
*/
|
||||||
@@ -87,7 +99,7 @@ class ACPClient implements Client {
|
|||||||
agentId: string,
|
agentId: string,
|
||||||
params: RequestPermissionRequest
|
params: RequestPermissionRequest
|
||||||
) => Promise<RequestPermissionResponse>,
|
) => Promise<RequestPermissionResponse>,
|
||||||
private persistence: AgentPersistence
|
private updateAgent: UpdateAgentCallback
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async requestPermission(
|
async requestPermission(
|
||||||
@@ -100,21 +112,28 @@ class ACPClient implements Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async sessionUpdate(params: SessionNotification): Promise<void> {
|
async sessionUpdate(params: SessionNotification): Promise<void> {
|
||||||
|
if (params.update.sessionUpdate === "agent_message_chunk") {
|
||||||
|
console.log(`[Agent ${this.agentId}] Message chunk update:`, JSON.stringify(params, null, 2));
|
||||||
|
}
|
||||||
|
|
||||||
// Check if this update contains a Claude session ID
|
// Check if this update contains a Claude session ID
|
||||||
const claudeSessionId = params._meta?.claudeSessionId as string | undefined;
|
const claudeSessionId = params._meta?.claudeSessionId as string | undefined;
|
||||||
if (claudeSessionId && this.persistence) {
|
if (claudeSessionId) {
|
||||||
const persisted = await this.persistence.load();
|
await this.updateAgent(this.agentId, (agent) => {
|
||||||
const persistedAgent = persisted.find((a) => a.id === this.agentId);
|
if (agent.options.type !== "claude") {
|
||||||
if (persistedAgent && persistedAgent.options.type === "claude") {
|
return false;
|
||||||
if (
|
|
||||||
persistedAgent.options.sessionId === null ||
|
|
||||||
persistedAgent.options.sessionId !== claudeSessionId
|
|
||||||
) {
|
|
||||||
// Update the Claude session ID
|
|
||||||
persistedAgent.options.sessionId = claudeSessionId;
|
|
||||||
await this.persistence.upsert(persistedAgent);
|
|
||||||
}
|
}
|
||||||
}
|
if (agent.options.sessionId === claudeSessionId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
agent.options = {
|
||||||
|
...agent.options,
|
||||||
|
sessionId: claudeSessionId,
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
this.onUpdate(this.agentId, params);
|
this.onUpdate(this.agentId, params);
|
||||||
}
|
}
|
||||||
@@ -252,15 +271,7 @@ export class AgentManager {
|
|||||||
|
|
||||||
this.agents.set(agentId, agent);
|
this.agents.set(agentId, agent);
|
||||||
|
|
||||||
await this.persistence.upsert({
|
await this.updateAgent(agentId, () => undefined);
|
||||||
id: agentId,
|
|
||||||
title: agent.title || `Agent ${agentId.slice(0, 8)}`,
|
|
||||||
sessionId: null,
|
|
||||||
options: agent.options,
|
|
||||||
createdAt: createdAt.toISOString(),
|
|
||||||
lastActivityAt: agent.lastActivityAt.toISOString(),
|
|
||||||
cwd: agent.cwd,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.notifySubscribers(agentId);
|
this.notifySubscribers(agentId);
|
||||||
|
|
||||||
@@ -510,17 +521,8 @@ export class AgentManager {
|
|||||||
const runtime = this.getRuntime(agent);
|
const runtime = this.getRuntime(agent);
|
||||||
|
|
||||||
// Persist current state before killing
|
// Persist current state before killing
|
||||||
// Clear sessionId so next start creates a new session
|
|
||||||
if (runtime) {
|
if (runtime) {
|
||||||
await this.persistence.upsert({
|
await this.updateAgent(agentId, () => true);
|
||||||
id: agent.id,
|
|
||||||
title: agent.title || `Agent ${agent.id.slice(0, 8)}`,
|
|
||||||
sessionId: null,
|
|
||||||
options: { ...agent.options, sessionId: null },
|
|
||||||
createdAt: agent.createdAt.toISOString(),
|
|
||||||
lastActivityAt: agent.lastActivityAt.toISOString(),
|
|
||||||
cwd: agent.cwd,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
agent.state = { type: "killed" };
|
agent.state = { type: "killed" };
|
||||||
@@ -862,6 +864,63 @@ export class AgentManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getPersistableSessionId(agent: ManagedAgent): string | null {
|
||||||
|
const { state } = agent;
|
||||||
|
|
||||||
|
switch (state.type) {
|
||||||
|
case "ready":
|
||||||
|
case "processing":
|
||||||
|
case "completed":
|
||||||
|
return state.runtime.sessionId;
|
||||||
|
case "initializing":
|
||||||
|
return state.runtime?.sessionId ?? state.persistedSessionId ?? null;
|
||||||
|
case "failed":
|
||||||
|
return state.runtime?.sessionId ?? null;
|
||||||
|
case "uninitialized":
|
||||||
|
return state.persistedSessionId;
|
||||||
|
case "killed":
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private serializeAgent(agent: ManagedAgent): PersistedAgent {
|
||||||
|
return {
|
||||||
|
id: agent.id,
|
||||||
|
title: agent.title || `Agent ${agent.id.slice(0, 8)}`,
|
||||||
|
sessionId: this.getPersistableSessionId(agent),
|
||||||
|
options: agent.options,
|
||||||
|
createdAt: agent.createdAt.toISOString(),
|
||||||
|
lastActivityAt: agent.lastActivityAt.toISOString(),
|
||||||
|
cwd: agent.cwd,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async updateAgent(
|
||||||
|
agentId: string,
|
||||||
|
updateFn: (
|
||||||
|
agent: ManagedAgent
|
||||||
|
) => boolean | void | Promise<boolean | void>,
|
||||||
|
options?: { sessionId: string | null }
|
||||||
|
): Promise<void> {
|
||||||
|
const agent = this.agents.get(agentId);
|
||||||
|
if (!agent) {
|
||||||
|
throw new Error(`Agent ${agentId} not found`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const shouldPersist = await updateFn(agent);
|
||||||
|
if (shouldPersist === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const persistedAgent = this.serializeAgent(agent);
|
||||||
|
if (options) {
|
||||||
|
persistedAgent.sessionId = options.sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.persistence.upsert(persistedAgent);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start runtime for an agent (spawn process, create connection, initialize session)
|
* Start runtime for an agent (spawn process, create connection, initialize session)
|
||||||
*/
|
*/
|
||||||
@@ -905,7 +964,7 @@ export class AgentManager {
|
|||||||
(id, params) => {
|
(id, params) => {
|
||||||
return this.handlePermissionRequest(id, params);
|
return this.handlePermissionRequest(id, params);
|
||||||
},
|
},
|
||||||
this.persistence
|
(id, updateFn, options) => this.updateAgent(id, updateFn, options)
|
||||||
);
|
);
|
||||||
const connection = new ClientSideConnection(() => client, stream);
|
const connection = new ClientSideConnection(() => client, stream);
|
||||||
|
|
||||||
@@ -1003,37 +1062,30 @@ export class AgentManager {
|
|||||||
const claudeSessionId = sessionResponse._meta?.claudeSessionId as
|
const claudeSessionId = sessionResponse._meta?.claudeSessionId as
|
||||||
| string
|
| string
|
||||||
| undefined;
|
| undefined;
|
||||||
if (
|
|
||||||
claudeSessionId &&
|
|
||||||
agent.options.type === "claude" &&
|
|
||||||
agent.options.sessionId !== claudeSessionId
|
|
||||||
) {
|
|
||||||
agent.options = {
|
|
||||||
...agent.options,
|
|
||||||
sessionId: claudeSessionId,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`[Agent ${agentId}] Session ${
|
`[Agent ${agentId}] Session ${
|
||||||
mode === "new" ? "created" : "loaded"
|
mode === "new" ? "created" : "loaded"
|
||||||
}: ACP=${effectiveSessionId}, Claude=${claudeSessionId || "N/A"}`
|
}: ACP=${effectiveSessionId}, Claude=${claudeSessionId || "N/A"}`
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.persistence.upsert({
|
await this.updateAgent(agentId, (managedAgent) => {
|
||||||
id: agentId,
|
if (
|
||||||
title: agent.title || `Agent ${agentId.slice(0, 8)}`,
|
claudeSessionId &&
|
||||||
sessionId: runtime.sessionId,
|
managedAgent.options.type === "claude" &&
|
||||||
options: agent.options,
|
managedAgent.options.sessionId !== claudeSessionId
|
||||||
createdAt: agent.createdAt.toISOString(),
|
) {
|
||||||
lastActivityAt: agent.lastActivityAt.toISOString(),
|
managedAgent.options = {
|
||||||
cwd: agent.cwd,
|
...managedAgent.options,
|
||||||
});
|
sessionId: claudeSessionId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
agent.state = {
|
managedAgent.state = {
|
||||||
type: "ready",
|
type: "ready",
|
||||||
runtime,
|
runtime,
|
||||||
};
|
};
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
this.notifySubscribers(agentId);
|
this.notifySubscribers(agentId);
|
||||||
|
|
||||||
@@ -1223,15 +1275,12 @@ export class AgentManager {
|
|||||||
* Set the title for an agent
|
* Set the title for an agent
|
||||||
*/
|
*/
|
||||||
async setAgentTitle(agentId: string, title: string): Promise<void> {
|
async setAgentTitle(agentId: string, title: string): Promise<void> {
|
||||||
const agent = this.agents.get(agentId);
|
await this.updateAgent(agentId, (managedAgent) => {
|
||||||
if (!agent) {
|
managedAgent.title = title;
|
||||||
throw new Error(`Agent ${agentId} not found`);
|
return true;
|
||||||
}
|
});
|
||||||
|
|
||||||
agent.title = title;
|
|
||||||
console.log(`[Agent ${agentId}] Title set to: "${title}"`);
|
console.log(`[Agent ${agentId}] Title set to: "${title}"`);
|
||||||
|
|
||||||
await this.persistence.updateTitle(agentId, title);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1245,6 +1294,20 @@ export class AgentManager {
|
|||||||
return agent.title ?? null;
|
return agent.title ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Claude session ID for an agent
|
||||||
|
*/
|
||||||
|
getClaudeSessionId(agentId: string): string | null {
|
||||||
|
const agent = this.agents.get(agentId);
|
||||||
|
if (!agent) {
|
||||||
|
throw new Error(`Agent ${agentId} not found`);
|
||||||
|
}
|
||||||
|
if (agent.options.type === "claude") {
|
||||||
|
return agent.options.sessionId;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark that title generation has been triggered for this agent
|
* Mark that title generation has been triggered for this agent
|
||||||
*/
|
*/
|
||||||
@@ -1470,15 +1533,7 @@ export class AgentManager {
|
|||||||
|
|
||||||
// Persist current state if agent has a session
|
// Persist current state if agent has a session
|
||||||
if (runtime) {
|
if (runtime) {
|
||||||
await this.persistence.upsert({
|
await this.updateAgent(agent.id, () => undefined);
|
||||||
id: agent.id,
|
|
||||||
title: agent.title || `Agent ${agent.id.slice(0, 8)}`,
|
|
||||||
sessionId: runtime.sessionId,
|
|
||||||
options: agent.options,
|
|
||||||
createdAt: agent.createdAt.toISOString(),
|
|
||||||
lastActivityAt: agent.lastActivityAt.toISOString(),
|
|
||||||
cwd: agent.cwd,
|
|
||||||
});
|
|
||||||
console.log(`[Agent ${agent.id}] State persisted`);
|
console.log(`[Agent ${agent.id}] State persisted`);
|
||||||
|
|
||||||
// Send graceful termination signal
|
// Send graceful termination signal
|
||||||
|
|||||||
@@ -132,20 +132,4 @@ export class AgentPersistence {
|
|||||||
console.log(`[AgentPersistence] Removed agent ${agentId}`);
|
console.log(`[AgentPersistence] Removed agent ${agentId}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update agent title
|
|
||||||
*/
|
|
||||||
async updateTitle(agentId: string, title: string): Promise<void> {
|
|
||||||
const agents = await this.load();
|
|
||||||
const agent = agents.find((a) => a.id === agentId);
|
|
||||||
|
|
||||||
if (agent) {
|
|
||||||
agent.title = title;
|
|
||||||
await this.save(agents);
|
|
||||||
console.log(
|
|
||||||
`[AgentPersistence] Updated title for agent ${agentId}: "${title}"`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user