import type { McpConfig } from '../mcp.ts'; import type { WsEvent, AttachmentMeta, PermissionHandler, QuestionHandler } from '../claude.ts'; import type { ConvMessage } from '../sessions.ts'; import type { Directives } from '../directives.ts'; import type { AgentSettings } from '../shraga-config.ts'; import type { TurnGuard } from '../security/enforce.ts'; export interface EngineStreamOpts { /** The user's effective prompt (after directive stripping, slash command expansion, skill/workspace mentions) */ prompt: string; /** Raw conversation history from JSONL (engine formats as needed) */ conversation: ConvMessage[]; /** Contextual blocks to prepend (user block, skills, workspace tree, etc.) */ contextBlock: string; /** The same context split into named sections (in contextBlock order), so an engine that keeps * state across turns can send only what changed. Joined with '\n' they equal contextBlock. */ contextSections?: Record; attachments?: AttachmentMeta[]; images?: string[]; sessionId: string; uid: string; userEmail?: string; userName?: string; mcpServers?: McpConfig; abortController?: AbortController; onPermissionRequest?: PermissionHandler; onDestructiveApproval?: PermissionHandler; onUserQuestion?: QuestionHandler; /** The single command this turn was spawned to run in the foreground (a `bash` schedule). * Exempted from the long-running-script background guard — see server/hooks.ts. */ foregroundBashCommand?: string; /** Opaque per-send hints bag, forwarded verbatim from the client. The core interprets no key of it; * an add-on engine reads its own keys (e.g. a duplex engine's `voice` marker). */ turnHints?: Record; /** True when the conversation was truncated (user replayed/edited a message) — engines with cached state should reset. */ conversationReset?: boolean; context?: Record; /** SECURITY_ENFORCE only: the turn's security context. The engine derives tools/MCP/env from its effective * profile and gates every tool call through it. Absent (flag off) ⇒ today's behavior, untouched. */ security?: TurnGuard; directives: Directives; config: AgentSettings; } export interface AgentEngine { readonly name: string; /** True if the engine applies `EngineStreamOpts.security` (profile tools/MCP/env + per-call gate). Under * SECURITY_ENFORCE an engine without it may only run turns whose effective profile is unrestricted. */ readonly enforcesProfile?: boolean; stream(opts: EngineStreamOpts): AsyncGenerator; /** Return model options for the UI picker (only called when engine is available) */ getModels(): EngineModel[]; init?(): Promise; shutdown?(): Promise; } export interface EngineModel { value: string; label: string; provider?: string; }