Files
Codewalkers/src/events/types.ts
Lukas May 3a3d3f4c08 feat(08.1-01): update AgentWaitingEvent with structured question data
- Add options array for predefined question choices
- Add multiSelect boolean for multi-selection questions
- Update dispatch manager test mock with getPendingQuestion
2026-01-31 15:25:11 +01:00

351 lines
7.0 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;
options?: Array<{ label: string; description?: string }>;
multiSelect?: boolean;
};
}
/**
* Task Dispatch Events
*/
export interface TaskQueuedEvent extends DomainEvent {
type: 'task:queued';
payload: {
taskId: string;
priority: string;
dependsOn: string[];
};
}
export interface TaskDispatchedEvent extends DomainEvent {
type: 'task:dispatched';
payload: {
taskId: string;
agentId: string;
agentName: string;
};
}
export interface TaskCompletedEvent extends DomainEvent {
type: 'task:completed';
payload: {
taskId: string;
agentId: string;
success: boolean;
message: string;
};
}
export interface TaskBlockedEvent extends DomainEvent {
type: 'task:blocked';
payload: {
taskId: string;
reason: string;
blockedBy?: string[];
};
}
/**
* Merge Coordination Events
*/
export interface MergeQueuedEvent extends DomainEvent {
type: 'merge:queued';
payload: {
taskId: string;
agentId: string;
worktreeId: string;
priority: 'low' | 'medium' | 'high';
};
}
export interface MergeStartedEvent extends DomainEvent {
type: 'merge:started';
payload: {
taskId: string;
agentId: string;
worktreeId: string;
targetBranch: string;
};
}
export interface MergeCompletedEvent extends DomainEvent {
type: 'merge:completed';
payload: {
taskId: string;
agentId: string;
worktreeId: string;
targetBranch: string;
};
}
export interface MergeConflictedEvent extends DomainEvent {
type: 'merge:conflicted';
payload: {
taskId: string;
agentId: string;
worktreeId: string;
targetBranch: string;
conflictingFiles: string[];
};
}
/**
* 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
| TaskQueuedEvent
| TaskDispatchedEvent
| TaskCompletedEvent
| TaskBlockedEvent
| MergeQueuedEvent
| MergeStartedEvent
| MergeCompletedEvent
| MergeConflictedEvent;
/**
* 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;
}