Files
Codewalkers/src/events/types.ts
Lukas May ddc6f3b4e7 feat(04-02): add agent lifecycle events to events module
- AgentSpawnedEvent for new agent creation
- AgentStoppedEvent with reason (user_requested, task_complete, error, waiting_for_input)
- AgentCrashedEvent for unexpected failures
- AgentResumedEvent for session resumption
- AgentWaitingEvent when agent pauses on AskUserQuestion
- Updated DomainEventMap union with all agent events
2026-01-30 19:59:37 +01:00

255 lines
5.2 KiB
TypeScript

/**
* Event Bus Types
*
* Port interface for the event bus - the backbone of the hexagonal architecture.
* EventBus is the PORT. Implementations (EventEmitterBus, RabbitMQ, etc.) are ADAPTERS.
*/
/**
* Base interface for all domain events.
* Every event in the system extends this.
*/
export interface DomainEvent {
/** Event type identifier (e.g., 'process:spawned', 'server:started') */
type: string;
/** When the event occurred */
timestamp: Date;
/** Event-specific data */
payload: unknown;
}
/**
* Event Bus Port Interface
*
* All modules communicate through this interface.
* Can be swapped for external systems (RabbitMQ, WebSocket forwarding) later.
*/
// =============================================================================
// Domain Event Types - Typed payloads for each event
// =============================================================================
/**
* Process Events
*/
export interface ProcessSpawnedEvent extends DomainEvent {
type: 'process:spawned';
payload: {
processId: string;
pid: number;
command: string;
};
}
export interface ProcessStoppedEvent extends DomainEvent {
type: 'process:stopped';
payload: {
processId: string;
pid: number;
exitCode: number | null;
};
}
export interface ProcessCrashedEvent extends DomainEvent {
type: 'process:crashed';
payload: {
processId: string;
pid: number;
signal: string | null;
};
}
/**
* Server Events
*/
export interface ServerStartedEvent extends DomainEvent {
type: 'server:started';
payload: {
port: number;
host: string;
pid: number;
};
}
export interface ServerStoppedEvent extends DomainEvent {
type: 'server:stopped';
payload: {
uptime: number;
};
}
/**
* Log Events
*/
export interface LogEntryEvent extends DomainEvent {
type: 'log:entry';
payload: {
processId: string;
stream: 'stdout' | 'stderr';
data: string;
};
}
/**
* Git Worktree Events
*/
export interface WorktreeCreatedEvent extends DomainEvent {
type: 'worktree:created';
payload: {
worktreeId: string;
branch: string;
path: string;
};
}
export interface WorktreeRemovedEvent extends DomainEvent {
type: 'worktree:removed';
payload: {
worktreeId: string;
branch: string;
};
}
export interface WorktreeMergedEvent extends DomainEvent {
type: 'worktree:merged';
payload: {
worktreeId: string;
sourceBranch: string;
targetBranch: string;
};
}
export interface WorktreeConflictEvent extends DomainEvent {
type: 'worktree:conflict';
payload: {
worktreeId: string;
sourceBranch: string;
targetBranch: string;
conflictingFiles: string[];
};
}
/**
* Agent Events
*/
export interface AgentSpawnedEvent extends DomainEvent {
type: 'agent:spawned';
payload: {
agentId: string;
name: string;
taskId: string;
worktreeId: string;
};
}
export interface AgentStoppedEvent extends DomainEvent {
type: 'agent:stopped';
payload: {
agentId: string;
name: string;
taskId: string;
reason: 'user_requested' | 'task_complete' | 'error' | 'waiting_for_input';
};
}
export interface AgentCrashedEvent extends DomainEvent {
type: 'agent:crashed';
payload: {
agentId: string;
name: string;
taskId: string;
error: string;
};
}
export interface AgentResumedEvent extends DomainEvent {
type: 'agent:resumed';
payload: {
agentId: string;
name: string;
taskId: string;
sessionId: string;
};
}
export interface AgentWaitingEvent extends DomainEvent {
type: 'agent:waiting';
payload: {
agentId: string;
name: string;
taskId: string;
sessionId: string;
question: string; // The question being asked
};
}
/**
* Union of all domain events - enables type-safe event handling
*/
export type DomainEventMap =
| ProcessSpawnedEvent
| ProcessStoppedEvent
| ProcessCrashedEvent
| ServerStartedEvent
| ServerStoppedEvent
| LogEntryEvent
| WorktreeCreatedEvent
| WorktreeRemovedEvent
| WorktreeMergedEvent
| WorktreeConflictEvent
| AgentSpawnedEvent
| AgentStoppedEvent
| AgentCrashedEvent
| AgentResumedEvent
| AgentWaitingEvent;
/**
* Event type literal union for type checking
*/
export type DomainEventType = DomainEventMap['type'];
// =============================================================================
// Event Bus Port Interface
// =============================================================================
/**
* Event Bus Port Interface
*
* All modules communicate through this interface.
* Can be swapped for external systems (RabbitMQ, WebSocket forwarding) later.
*/
export interface EventBus {
/**
* Emit an event to all subscribed handlers
*/
emit<T extends DomainEvent>(event: T): void;
/**
* Subscribe to events of a specific type
*/
on<T extends DomainEvent>(
eventType: T['type'],
handler: (event: T) => void
): void;
/**
* Unsubscribe from events of a specific type
*/
off<T extends DomainEvent>(
eventType: T['type'],
handler: (event: T) => void
): void;
/**
* Subscribe to a single occurrence of an event type
*/
once<T extends DomainEvent>(
eventType: T['type'],
handler: (event: T) => void
): void;
}