Replaces the in-memory filter (agentManager.list() + filter) with a direct repository query that LEFT JOINs tasks, phases, and initiatives to return taskName, phaseName, initiativeName, and taskDescription alongside agent fields. - Adds AgentWithContext interface and findWaitingWithContext() to AgentRepository port - Implements findWaitingWithContext() in DrizzleAgentRepository using getTableColumns - Wires agentRepository into TRPCContext, CreateContextOptions, and TrpcAdapterOptions - Adds requireAgentRepository() helper following existing pattern - Updates listWaitingAgents to use repository query instead of agentManager - Adds 5 unit tests for findWaitingWithContext() covering all FK join edge cases - Updates existing AgentRepository mocks to satisfy updated interface Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
135 lines
3.4 KiB
TypeScript
135 lines
3.4 KiB
TypeScript
/**
|
|
* Agent Repository Port Interface
|
|
*
|
|
* Port for Agent aggregate operations.
|
|
* Implementations (Drizzle, etc.) are adapters.
|
|
*/
|
|
|
|
import type { Agent } from '../schema.js';
|
|
import type { AgentMode } from '../../agent/types.js';
|
|
|
|
/** Agent row enriched with joined task/phase/initiative context fields. */
|
|
export interface AgentWithContext extends Agent {
|
|
taskName: string | null;
|
|
phaseName: string | null;
|
|
initiativeName: string | null;
|
|
taskDescription: string | null;
|
|
}
|
|
|
|
/**
|
|
* Agent status values.
|
|
*/
|
|
export type AgentStatus = 'idle' | 'running' | 'waiting_for_input' | 'stopped' | 'crashed';
|
|
|
|
/**
|
|
* Data for creating a new agent.
|
|
* Omits system-managed fields and makes optional fields explicit.
|
|
*/
|
|
export interface CreateAgentData {
|
|
name: string;
|
|
worktreeId: string;
|
|
taskId?: string | null;
|
|
initiativeId?: string | null;
|
|
sessionId?: string | null;
|
|
status?: AgentStatus;
|
|
mode?: AgentMode; // Defaults to 'execute' if not provided
|
|
provider?: string; // Defaults to 'claude' if not provided
|
|
accountId?: string | null;
|
|
}
|
|
|
|
/**
|
|
* Data for updating an existing agent.
|
|
* All fields optional. System-managed fields (id, createdAt, updatedAt) are excluded.
|
|
*/
|
|
export interface UpdateAgentData {
|
|
name?: string;
|
|
worktreeId?: string;
|
|
taskId?: string | null;
|
|
initiativeId?: string | null;
|
|
sessionId?: string | null;
|
|
status?: AgentStatus;
|
|
mode?: AgentMode;
|
|
provider?: string;
|
|
accountId?: string | null;
|
|
pid?: number | null;
|
|
exitCode?: number | null;
|
|
prompt?: string | null;
|
|
outputFilePath?: string | null;
|
|
result?: string | null;
|
|
pendingQuestions?: string | null;
|
|
userDismissedAt?: Date | null;
|
|
updatedAt?: Date;
|
|
}
|
|
|
|
/**
|
|
* Agent Repository Port
|
|
*
|
|
* Defines operations for the Agent aggregate.
|
|
* Enables agent state persistence for session resumption and listing.
|
|
*/
|
|
export interface AgentRepository {
|
|
/**
|
|
* Create a new agent.
|
|
* Generates id and sets timestamps automatically.
|
|
* Name must be unique.
|
|
*/
|
|
create(agent: CreateAgentData): Promise<Agent>;
|
|
|
|
/**
|
|
* Find an agent by its ID.
|
|
* Returns null if not found.
|
|
*/
|
|
findById(id: string): Promise<Agent | null>;
|
|
|
|
/**
|
|
* Find an agent by its human-readable name.
|
|
* Returns null if not found.
|
|
*/
|
|
findByName(name: string): Promise<Agent | null>;
|
|
|
|
/**
|
|
* Find an agent by its associated task.
|
|
* Returns null if no agent is assigned to that task.
|
|
*/
|
|
findByTaskId(taskId: string): Promise<Agent | null>;
|
|
|
|
/**
|
|
* Find an agent by its Claude CLI session ID.
|
|
* Used for session resumption.
|
|
* Returns null if not found.
|
|
*/
|
|
findBySessionId(sessionId: string): Promise<Agent | null>;
|
|
|
|
/**
|
|
* Find all agents.
|
|
* Returns empty array if none exist.
|
|
*/
|
|
findAll(): Promise<Agent[]>;
|
|
|
|
/**
|
|
* Find agents by status.
|
|
* Returns empty array if no agents have that status.
|
|
*/
|
|
findByStatus(status: AgentStatus): Promise<Agent[]>;
|
|
|
|
/**
|
|
* Update an agent with partial data.
|
|
* Only provided fields are updated, others remain unchanged.
|
|
* Throws if agent not found.
|
|
* Updates updatedAt timestamp automatically.
|
|
*/
|
|
update(id: string, data: UpdateAgentData): Promise<Agent>;
|
|
|
|
/**
|
|
* Delete an agent.
|
|
* Throws if agent not found.
|
|
*/
|
|
delete(id: string): Promise<void>;
|
|
|
|
/**
|
|
* Find all agents with status 'waiting_for_input', enriched with
|
|
* task, phase, and initiative names via LEFT JOINs.
|
|
*/
|
|
findWaitingWithContext(): Promise<AgentWithContext[]>;
|
|
}
|