fix(#338): Add session cleanup on terminal states

- Add removeSession and scheduleSessionCleanup methods to AgentSpawnerService
- Schedule session cleanup after completed/failed/killed transitions
- Default 30 second delay before cleanup to allow status queries
- Implement OnModuleDestroy to clean up pending timers
- Add forwardRef injection to avoid circular dependency
- Add comprehensive tests for cleanup functionality

Refs #338
This commit is contained in:
Jason Woltje
2026-02-05 18:47:14 -06:00
parent 8d57191a91
commit a42f88d64c
4 changed files with 347 additions and 7 deletions

View File

@@ -1,5 +1,6 @@
import { Injectable, Logger } from "@nestjs/common";
import { Injectable, Logger, Inject, forwardRef } from "@nestjs/common";
import { ValkeyService } from "../valkey/valkey.service";
import { AgentSpawnerService } from "./agent-spawner.service";
import type { AgentState, AgentStatus, AgentEvent } from "../valkey/types";
import { isValidAgentTransition } from "../valkey/types/state.types";
@@ -18,7 +19,11 @@ import { isValidAgentTransition } from "../valkey/types/state.types";
export class AgentLifecycleService {
private readonly logger = new Logger(AgentLifecycleService.name);
constructor(private readonly valkeyService: ValkeyService) {
constructor(
private readonly valkeyService: ValkeyService,
@Inject(forwardRef(() => AgentSpawnerService))
private readonly spawnerService: AgentSpawnerService
) {
this.logger.log("AgentLifecycleService initialized");
}
@@ -84,6 +89,9 @@ export class AgentLifecycleService {
// Emit event
await this.publishStateChangeEvent("agent.completed", updatedState);
// Schedule session cleanup
this.spawnerService.scheduleSessionCleanup(agentId);
this.logger.log(`Agent ${agentId} transitioned to completed`);
return updatedState;
}
@@ -116,6 +124,9 @@ export class AgentLifecycleService {
// Emit event
await this.publishStateChangeEvent("agent.failed", updatedState, error);
// Schedule session cleanup
this.spawnerService.scheduleSessionCleanup(agentId);
this.logger.error(`Agent ${agentId} transitioned to failed: ${error}`);
return updatedState;
}
@@ -147,6 +158,9 @@ export class AgentLifecycleService {
// Emit event
await this.publishStateChangeEvent("agent.killed", updatedState);
// Schedule session cleanup
this.spawnerService.scheduleSessionCleanup(agentId);
this.logger.warn(`Agent ${agentId} transitioned to killed`);
return updatedState;
}