import type { IncomingMessage, ServerResponse } from "node:http";
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type { Command } from "commander";
import type { AuthProfileCredential, OAuthCredential } from "../agents/auth-profiles/types.js";
import type { AnyAgentTool } from "../agents/tools/common.js";
import type { ReplyPayload } from "../auto-reply/types.js";
import type { ChannelDock } from "../channels/dock.js";
import type { ChannelId, ChannelPlugin } from "../channels/plugins/types.js";
import type { createVpsAwareOAuthHandlers } from "../commands/oauth-flow.js";
import type { FasedAgentConfig } from "../config/config.js";
import type { ModelProviderConfig } from "../config/types.js";
import type { OperatorScope } from "../gateway/method-scopes.js";
import type { GatewayRequestHandler } from "../gateway/server-methods/types.js";
import type { InternalHookHandler } from "../hooks/internal-hooks.js";
import type { HookEntry } from "../hooks/types.js";
import type { ImageGenerationProvider } from "../image-generation/types.js";
import type { RealtimeTranscriptionProviderConfig, RealtimeTranscriptionProviderConfiguredContext, RealtimeTranscriptionProviderId, RealtimeTranscriptionProviderResolveConfigContext, RealtimeTranscriptionSession, RealtimeTranscriptionSessionCreateRequest } from "../realtime-transcription/provider-types.js";
import type { RealtimeVoiceBridge, RealtimeVoiceBridgeCreateRequest, RealtimeVoiceProviderConfig, RealtimeVoiceProviderConfiguredContext, RealtimeVoiceProviderId, RealtimeVoiceProviderResolveConfigContext } from "../realtime-voice/provider-types.js";
import type { RuntimeEnv } from "../runtime.js";
import type { RuntimeWebSearchMetadata } from "../secrets/runtime-web-tools.types.js";
import type { VideoGenerationProvider } from "../video-generation/types.js";
import type { WizardPrompter } from "../wizard/prompts.js";
import type { PluginRuntime } from "./runtime/types.js";
export type { PluginRuntime } from "./runtime/types.js";
export type { AnyAgentTool } from "../agents/tools/common.js";
export type PluginLogger = {
    debug?: (message: string) => void;
    info: (message: string) => void;
    warn: (message: string) => void;
    error: (message: string) => void;
};
export type PluginConfigUiHint = {
    label?: string;
    help?: string;
    tags?: string[];
    advanced?: boolean;
    sensitive?: boolean;
    placeholder?: string;
};
export type PluginKind = "memory";
export type PluginConfigValidation = {
    ok: true;
    value?: unknown;
} | {
    ok: false;
    errors: string[];
};
export type FasedAgentPluginConfigSchema = {
    safeParse?: (value: unknown) => {
        success: boolean;
        data?: unknown;
        error?: {
            issues?: Array<{
                path: Array<string | number>;
                message: string;
            }>;
        };
    };
    parse?: (value: unknown) => unknown;
    validate?: (value: unknown) => PluginConfigValidation;
    uiHints?: Record<string, PluginConfigUiHint>;
    jsonSchema?: Record<string, unknown>;
};
export type FasedAgentPluginToolContext = {
    config?: FasedAgentConfig;
    workspaceDir?: string;
    agentDir?: string;
    agentId?: string;
    sessionKey?: string;
    messageChannel?: string;
    agentAccountId?: string;
    sandboxed?: boolean;
};
export type FasedAgentPluginToolFactory = (ctx: FasedAgentPluginToolContext) => AnyAgentTool | AnyAgentTool[] | null | undefined;
export type FasedAgentPluginToolOptions = {
    name?: string;
    names?: string[];
    optional?: boolean;
};
export type FasedAgentPluginHookOptions = {
    entry?: HookEntry;
    name?: string;
    description?: string;
    register?: boolean;
};
export type ProviderAuthKind = "oauth" | "api_key" | "token" | "device_code" | "custom";
export type ProviderAuthResult = {
    profiles: Array<{
        profileId: string;
        credential: AuthProfileCredential;
    }>;
    configPatch?: Partial<FasedAgentConfig>;
    defaultModel?: string;
    notes?: string[];
};
export type ProviderAuthContext = {
    config: FasedAgentConfig;
    agentDir?: string;
    workspaceDir?: string;
    prompter: WizardPrompter;
    runtime: RuntimeEnv;
    isRemote: boolean;
    openUrl: (url: string) => Promise<void>;
    oauth: {
        createVpsAwareHandlers: typeof createVpsAwareOAuthHandlers;
    };
};
export type ProviderAuthMethod = {
    id: string;
    label: string;
    hint?: string;
    kind: ProviderAuthKind;
    wizard?: ProviderPluginWizardSetup;
    run: (ctx: ProviderAuthContext) => Promise<ProviderAuthResult>;
};
export type ProviderPluginWizardSetup = {
    choiceId?: string;
    choiceLabel?: string;
    choiceHint?: string;
    assistantPriority?: number;
    assistantVisibility?: "visible" | "manual-only";
    deprecatedChoiceIds?: string[];
    groupId?: string;
    groupLabel?: string;
    groupHint?: string;
    optionKey?: string;
    cliFlag?: string;
    cliOption?: string;
    cliDescription?: string;
    onboardingScopes?: Array<"text-inference" | "image-generation">;
};
export type ProviderPluginWizardModelPicker = {
    label?: string;
    hint?: string;
    methodId?: string;
};
export type ProviderPluginWizard = {
    setup?: ProviderPluginWizardSetup;
    modelPicker?: ProviderPluginWizardModelPicker;
};
export type ProviderCatalogOrder = "simple" | "profile" | "paired" | "late";
export type ProviderCatalogContext = {
    config: FasedAgentConfig;
    agentDir?: string;
    workspaceDir?: string;
    env: NodeJS.ProcessEnv;
    resolveProviderApiKey: (providerId?: string) => {
        apiKey: string | undefined;
        discoveryApiKey?: string;
    };
    resolveProviderAuth: (providerId?: string, options?: {
        oauthMarker?: string;
    }) => {
        apiKey: string | undefined;
        discoveryApiKey?: string;
        mode: "api_key" | "oauth" | "token" | "none";
        source: "env" | "profile" | "none";
        profileId?: string;
    };
};
export type ProviderCatalogResult = {
    provider: ModelProviderConfig;
} | {
    providers: Record<string, ModelProviderConfig>;
} | null | undefined;
export type ProviderPluginCatalog = {
    order?: ProviderCatalogOrder;
    run: (ctx: ProviderCatalogContext) => Promise<ProviderCatalogResult>;
};
/**
 * @deprecated Use ProviderCatalogOrder.
 */
export type ProviderDiscoveryOrder = ProviderCatalogOrder;
/**
 * @deprecated Use ProviderCatalogContext.
 */
export type ProviderDiscoveryContext = ProviderCatalogContext;
/**
 * @deprecated Use ProviderCatalogResult.
 */
export type ProviderDiscoveryResult = ProviderCatalogResult;
/**
 * @deprecated Use ProviderPluginCatalog.
 */
export type ProviderPluginDiscovery = ProviderPluginCatalog;
export type ProviderPlugin = {
    id: string;
    label: string;
    docsPath?: string;
    aliases?: string[];
    envVars?: string[];
    models?: ModelProviderConfig;
    auth: ProviderAuthMethod[];
    catalog?: ProviderPluginCatalog;
    staticCatalog?: ProviderPluginCatalog;
    discovery?: ProviderPluginDiscovery;
    wizard?: ProviderPluginWizard;
    formatApiKey?: (cred: AuthProfileCredential) => string;
    refreshOAuth?: (cred: OAuthCredential) => Promise<OAuthCredential>;
};
export type ImageGenerationProviderPlugin = ImageGenerationProvider;
export type VideoGenerationProviderPlugin = VideoGenerationProvider;
export type RealtimeTranscriptionProviderPlugin = {
    id: RealtimeTranscriptionProviderId;
    label: string;
    aliases?: string[];
    autoSelectOrder?: number;
    resolveConfig?: (ctx: RealtimeTranscriptionProviderResolveConfigContext) => RealtimeTranscriptionProviderConfig;
    isConfigured: (ctx: RealtimeTranscriptionProviderConfiguredContext) => boolean;
    createSession: (req: RealtimeTranscriptionSessionCreateRequest) => RealtimeTranscriptionSession;
};
export type RealtimeVoiceProviderPlugin = {
    id: RealtimeVoiceProviderId;
    label: string;
    aliases?: string[];
    autoSelectOrder?: number;
    resolveConfig?: (ctx: RealtimeVoiceProviderResolveConfigContext) => RealtimeVoiceProviderConfig;
    isConfigured: (ctx: RealtimeVoiceProviderConfiguredContext) => boolean;
    createBridge: (req: RealtimeVoiceBridgeCreateRequest) => RealtimeVoiceBridge;
};
export type FasedAgentPluginGatewayMethod = {
    method: string;
    handler: GatewayRequestHandler;
};
export type WebSearchProviderToolDefinition = {
    description: string;
    parameters: Record<string, unknown>;
    execute: (args: Record<string, unknown>) => Promise<Record<string, unknown>>;
};
export type PluginWebSearchProviderEntry = {
    pluginId: string;
    id: string;
    label: string;
    hint?: string;
    inactiveSecretPaths?: string[];
    envVars: string[];
    placeholder?: string;
    signupUrl?: string;
    credentialPath: string;
    autoDetectOrder?: number;
    requiresCredential?: boolean;
    getCredentialValue?: (searchConfig?: Record<string, unknown>) => unknown;
    setCredentialValue?: (value: string, searchConfig?: Record<string, unknown>) => void;
    getConfiguredCredentialValue?: (config?: FasedAgentConfig) => unknown;
    setConfiguredCredentialValue?: (configTarget: FasedAgentConfig, value: unknown) => void;
    applySelectionConfig?: (config: FasedAgentConfig) => FasedAgentConfig;
    createTool: (params: {
        config?: FasedAgentConfig;
        searchConfig?: Record<string, unknown>;
        runtimeMetadata?: RuntimeWebSearchMetadata;
    }) => WebSearchProviderToolDefinition | null;
};
export type WebSearchProviderPlugin = Omit<PluginWebSearchProviderEntry, "pluginId">;
/**
 * Context passed to plugin command handlers.
 */
export type PluginCommandContext = {
    /** The sender's identifier (e.g., Telegram user ID) */
    senderId?: string;
    /** The channel/surface (e.g., "telegram", "discord") */
    channel: string;
    /** Provider channel id (e.g., "telegram") */
    channelId?: ChannelId;
    /** Whether the sender is on the allowlist */
    isAuthorizedSender: boolean;
    /** Raw command arguments after the command name */
    args?: string;
    /** The full normalized command body */
    commandBody: string;
    /** Current FasedAgent configuration */
    config: FasedAgentConfig;
    /** Raw "From" value (channel-scoped id) */
    from?: string;
    /** Raw "To" value (channel-scoped id) */
    to?: string;
    /** Account id for multi-account channels */
    accountId?: string;
    /** Thread/topic id if available */
    messageThreadId?: number;
};
/**
 * Result returned by a plugin command handler.
 */
export type PluginCommandResult = ReplyPayload;
/**
 * Handler function for plugin commands.
 */
export type PluginCommandHandler = (ctx: PluginCommandContext) => PluginCommandResult | Promise<PluginCommandResult>;
/**
 * Definition for a plugin-registered command.
 */
export type FasedAgentPluginCommandDefinition = {
    /** Command name without leading slash (e.g., "tts") */
    name: string;
    /** Description shown in /help and command menus */
    description: string;
    /** Whether this command accepts arguments */
    acceptsArgs?: boolean;
    /** Whether only authorized senders can use this command (default: true) */
    requireAuth?: boolean;
    /** The handler function */
    handler: PluginCommandHandler;
};
export type FasedAgentPluginHttpHandler = (req: IncomingMessage, res: ServerResponse) => Promise<boolean> | boolean;
export type FasedAgentPluginHttpRouteHandler = (req: IncomingMessage, res: ServerResponse) => Promise<void> | void;
export type FasedAgentPluginCliContext = {
    program: Command;
    config: FasedAgentConfig;
    workspaceDir?: string;
    logger: PluginLogger;
};
export type FasedAgentPluginCliRegistrar = (ctx: FasedAgentPluginCliContext) => void | Promise<void>;
export type FasedAgentPluginServiceContext = {
    config: FasedAgentConfig;
    workspaceDir?: string;
    stateDir: string;
    logger: PluginLogger;
};
export type FasedAgentPluginService = {
    id: string;
    start: (ctx: FasedAgentPluginServiceContext) => void | Promise<void>;
    stop?: (ctx: FasedAgentPluginServiceContext) => void | Promise<void>;
};
export type FasedAgentPluginChannelRegistration = {
    plugin: ChannelPlugin;
    dock?: ChannelDock;
};
export type FasedAgentPluginDefinition = {
    id?: string;
    name?: string;
    description?: string;
    version?: string;
    kind?: PluginKind;
    configSchema?: FasedAgentPluginConfigSchema;
    register?: (api: FasedAgentPluginApi) => void | Promise<void>;
    activate?: (api: FasedAgentPluginApi) => void | Promise<void>;
};
export type FasedAgentPluginModule = FasedAgentPluginDefinition | ((api: FasedAgentPluginApi) => void | Promise<void>);
export type FasedAgentPluginApi = {
    id: string;
    name: string;
    version?: string;
    description?: string;
    source: string;
    config: FasedAgentConfig;
    pluginConfig?: Record<string, unknown>;
    runtime: PluginRuntime;
    logger: PluginLogger;
    registerTool: (tool: AnyAgentTool | FasedAgentPluginToolFactory, opts?: FasedAgentPluginToolOptions) => void;
    registerHook: (events: string | string[], handler: InternalHookHandler, opts?: FasedAgentPluginHookOptions) => void;
    registerHttpHandler: (handler: FasedAgentPluginHttpHandler) => void;
    registerHttpRoute: (params: {
        path: string;
        handler: FasedAgentPluginHttpRouteHandler;
    }) => void;
    registerChannel: (registration: FasedAgentPluginChannelRegistration | ChannelPlugin) => void;
    registerGatewayMethod: (method: string, handler: GatewayRequestHandler, opts?: {
        scope?: OperatorScope;
    }) => void;
    registerCli: (registrar: FasedAgentPluginCliRegistrar, opts?: {
        commands?: string[];
    }) => void;
    registerService: (service: FasedAgentPluginService) => void;
    registerProvider: (provider: ProviderPlugin) => void;
    registerWebSearchProvider: (provider: WebSearchProviderPlugin) => void;
    registerImageGenerationProvider: (provider: ImageGenerationProviderPlugin) => void;
    registerVideoGenerationProvider: (provider: VideoGenerationProviderPlugin) => void;
    registerRealtimeTranscriptionProvider: (provider: RealtimeTranscriptionProviderPlugin) => void;
    registerRealtimeVoiceProvider: (provider: RealtimeVoiceProviderPlugin) => void;
    /**
     * Register a custom command that bypasses the LLM agent.
     * Plugin commands are processed before built-in commands and before agent invocation.
     * Use this for simple state-toggling or status commands that don't need AI reasoning.
     */
    registerCommand: (command: FasedAgentPluginCommandDefinition) => void;
    resolvePath: (input: string) => string;
    /** Register a lifecycle hook handler */
    on: <K extends PluginHookName>(hookName: K, handler: PluginHookHandlerMap[K], opts?: {
        priority?: number;
    }) => void;
};
export type PluginOrigin = "bundled" | "global" | "workspace" | "config";
export type PluginDiagnostic = {
    level: "warn" | "error";
    message: string;
    pluginId?: string;
    source?: string;
};
export type PluginHookName = "before_model_resolve" | "before_prompt_build" | "before_agent_start" | "llm_input" | "llm_output" | "agent_end" | "before_compaction" | "after_compaction" | "before_reset" | "message_received" | "message_sending" | "message_sent" | "before_tool_call" | "after_tool_call" | "tool_result_persist" | "before_message_write" | "session_start" | "session_end" | "subagent_spawning" | "subagent_delivery_target" | "subagent_spawned" | "subagent_ended" | "gateway_start" | "gateway_stop";
export type PluginHookAgentContext = {
    agentId?: string;
    sessionKey?: string;
    sessionId?: string;
    workspaceDir?: string;
    messageProvider?: string;
};
export type PluginHookBeforeModelResolveEvent = {
    /** User prompt for this run. No session messages are available yet in this phase. */
    prompt: string;
};
export type PluginHookBeforeModelResolveResult = {
    /** Override the model for this agent run. E.g. "llama3.3:8b" */
    modelOverride?: string;
    /** Override the provider for this agent run. E.g. "openrouter" */
    providerOverride?: string;
};
export type PluginHookBeforePromptBuildEvent = {
    prompt: string;
    /** Session messages prepared for this run. */
    messages: unknown[];
};
export type PluginHookBeforePromptBuildResult = {
    systemPrompt?: string;
    prependContext?: string;
};
export type PluginHookBeforeAgentStartEvent = {
    prompt: string;
    /** Optional because legacy hook can run in pre-session phase. */
    messages?: unknown[];
};
export type PluginHookBeforeAgentStartResult = PluginHookBeforePromptBuildResult & PluginHookBeforeModelResolveResult;
export type PluginHookLlmInputEvent = {
    runId: string;
    sessionId: string;
    provider: string;
    model: string;
    systemPrompt?: string;
    prompt: string;
    historyMessages: unknown[];
    imagesCount: number;
};
export type PluginHookLlmOutputEvent = {
    runId: string;
    sessionId: string;
    provider: string;
    model: string;
    assistantTexts: string[];
    lastAssistant?: unknown;
    usage?: {
        input?: number;
        output?: number;
        cacheRead?: number;
        cacheWrite?: number;
        total?: number;
    };
};
export type PluginHookAgentEndEvent = {
    messages: unknown[];
    success: boolean;
    error?: string;
    durationMs?: number;
};
export type PluginHookBeforeCompactionEvent = {
    /** Total messages in the session before any truncation or compaction */
    messageCount: number;
    /** Messages being fed to the compaction LLM (after history-limit truncation) */
    compactingCount?: number;
    tokenCount?: number;
    messages?: unknown[];
    /** Path to the session JSONL transcript. All messages are already on disk
     *  before compaction starts, so plugins can read this file asynchronously
     *  and process in parallel with the compaction LLM call. */
    sessionFile?: string;
};
export type PluginHookBeforeResetEvent = {
    sessionFile?: string;
    messages?: unknown[];
    reason?: string;
};
export type PluginHookAfterCompactionEvent = {
    messageCount: number;
    tokenCount?: number;
    compactedCount: number;
    /** Path to the session JSONL transcript. All pre-compaction messages are
     *  preserved on disk, so plugins can read and process them asynchronously
     *  without blocking the compaction pipeline. */
    sessionFile?: string;
};
export type PluginHookMessageContext = {
    channelId: string;
    accountId?: string;
    conversationId?: string;
};
export type PluginHookMessageReceivedEvent = {
    from: string;
    content: string;
    timestamp?: number;
    metadata?: Record<string, unknown>;
};
export type PluginHookMessageSendingEvent = {
    to: string;
    content: string;
    metadata?: Record<string, unknown>;
};
export type PluginHookMessageSendingResult = {
    content?: string;
    cancel?: boolean;
};
export type PluginHookMessageSentEvent = {
    to: string;
    content: string;
    success: boolean;
    error?: string;
};
export type PluginHookToolContext = {
    agentId?: string;
    sessionKey?: string;
    toolName: string;
};
export type PluginHookBeforeToolCallEvent = {
    toolName: string;
    params: Record<string, unknown>;
};
export type PluginHookBeforeToolCallResult = {
    params?: Record<string, unknown>;
    block?: boolean;
    blockReason?: string;
};
export type PluginHookAfterToolCallEvent = {
    toolName: string;
    params: Record<string, unknown>;
    result?: unknown;
    error?: string;
    durationMs?: number;
};
export type PluginHookToolResultPersistContext = {
    agentId?: string;
    sessionKey?: string;
    toolName?: string;
    toolCallId?: string;
};
export type PluginHookToolResultPersistEvent = {
    toolName?: string;
    toolCallId?: string;
    /**
     * The toolResult message about to be written to the session transcript.
     * Handlers may return a modified message (e.g. drop non-essential fields).
     */
    message: AgentMessage;
    /** True when the tool result was synthesized by a guard/repair step. */
    isSynthetic?: boolean;
};
export type PluginHookToolResultPersistResult = {
    message?: AgentMessage;
};
export type PluginHookBeforeMessageWriteEvent = {
    message: AgentMessage;
    sessionKey?: string;
    agentId?: string;
};
export type PluginHookBeforeMessageWriteResult = {
    block?: boolean;
    message?: AgentMessage;
};
export type PluginHookSessionContext = {
    agentId?: string;
    sessionId: string;
};
export type PluginHookSessionStartEvent = {
    sessionId: string;
    resumedFrom?: string;
};
export type PluginHookSessionEndEvent = {
    sessionId: string;
    messageCount: number;
    durationMs?: number;
};
export type PluginHookSubagentContext = {
    runId?: string;
    childSessionKey?: string;
    requesterSessionKey?: string;
};
export type PluginHookSubagentTargetKind = "subagent" | "acp";
export type PluginHookSubagentSpawningEvent = {
    childSessionKey: string;
    agentId: string;
    label?: string;
    mode: "run" | "session";
    requester?: {
        channel?: string;
        accountId?: string;
        to?: string;
        threadId?: string | number;
    };
    threadRequested: boolean;
};
export type PluginHookSubagentSpawningResult = {
    status: "ok";
    threadBindingReady?: boolean;
} | {
    status: "error";
    error: string;
};
export type PluginHookSubagentDeliveryTargetEvent = {
    childSessionKey: string;
    requesterSessionKey: string;
    requesterOrigin?: {
        channel?: string;
        accountId?: string;
        to?: string;
        threadId?: string | number;
    };
    childRunId?: string;
    spawnMode?: "run" | "session";
    expectsCompletionMessage: boolean;
};
export type PluginHookSubagentDeliveryTargetResult = {
    origin?: {
        channel?: string;
        accountId?: string;
        to?: string;
        threadId?: string | number;
    };
};
export type PluginHookSubagentSpawnedEvent = {
    runId: string;
    childSessionKey: string;
    agentId: string;
    label?: string;
    mode: "run" | "session";
    requester?: {
        channel?: string;
        accountId?: string;
        to?: string;
        threadId?: string | number;
    };
    threadRequested: boolean;
};
export type PluginHookSubagentEndedEvent = {
    targetSessionKey: string;
    targetKind: PluginHookSubagentTargetKind;
    reason: string;
    sendFarewell?: boolean;
    accountId?: string;
    runId?: string;
    endedAt?: number;
    outcome?: "ok" | "error" | "timeout" | "killed" | "reset" | "deleted";
    error?: string;
};
export type PluginHookGatewayContext = {
    port?: number;
};
export type PluginHookGatewayStartEvent = {
    port: number;
};
export type PluginHookGatewayStopEvent = {
    reason?: string;
};
export type PluginHookHandlerMap = {
    before_model_resolve: (event: PluginHookBeforeModelResolveEvent, ctx: PluginHookAgentContext) => Promise<PluginHookBeforeModelResolveResult | void> | PluginHookBeforeModelResolveResult | void;
    before_prompt_build: (event: PluginHookBeforePromptBuildEvent, ctx: PluginHookAgentContext) => Promise<PluginHookBeforePromptBuildResult | void> | PluginHookBeforePromptBuildResult | void;
    before_agent_start: (event: PluginHookBeforeAgentStartEvent, ctx: PluginHookAgentContext) => Promise<PluginHookBeforeAgentStartResult | void> | PluginHookBeforeAgentStartResult | void;
    llm_input: (event: PluginHookLlmInputEvent, ctx: PluginHookAgentContext) => Promise<void> | void;
    llm_output: (event: PluginHookLlmOutputEvent, ctx: PluginHookAgentContext) => Promise<void> | void;
    agent_end: (event: PluginHookAgentEndEvent, ctx: PluginHookAgentContext) => Promise<void> | void;
    before_compaction: (event: PluginHookBeforeCompactionEvent, ctx: PluginHookAgentContext) => Promise<void> | void;
    after_compaction: (event: PluginHookAfterCompactionEvent, ctx: PluginHookAgentContext) => Promise<void> | void;
    before_reset: (event: PluginHookBeforeResetEvent, ctx: PluginHookAgentContext) => Promise<void> | void;
    message_received: (event: PluginHookMessageReceivedEvent, ctx: PluginHookMessageContext) => Promise<void> | void;
    message_sending: (event: PluginHookMessageSendingEvent, ctx: PluginHookMessageContext) => Promise<PluginHookMessageSendingResult | void> | PluginHookMessageSendingResult | void;
    message_sent: (event: PluginHookMessageSentEvent, ctx: PluginHookMessageContext) => Promise<void> | void;
    before_tool_call: (event: PluginHookBeforeToolCallEvent, ctx: PluginHookToolContext) => Promise<PluginHookBeforeToolCallResult | void> | PluginHookBeforeToolCallResult | void;
    after_tool_call: (event: PluginHookAfterToolCallEvent, ctx: PluginHookToolContext) => Promise<void> | void;
    tool_result_persist: (event: PluginHookToolResultPersistEvent, ctx: PluginHookToolResultPersistContext) => PluginHookToolResultPersistResult | void;
    before_message_write: (event: PluginHookBeforeMessageWriteEvent, ctx: {
        agentId?: string;
        sessionKey?: string;
    }) => PluginHookBeforeMessageWriteResult | void;
    session_start: (event: PluginHookSessionStartEvent, ctx: PluginHookSessionContext) => Promise<void> | void;
    session_end: (event: PluginHookSessionEndEvent, ctx: PluginHookSessionContext) => Promise<void> | void;
    subagent_spawning: (event: PluginHookSubagentSpawningEvent, ctx: PluginHookSubagentContext) => Promise<PluginHookSubagentSpawningResult | void> | PluginHookSubagentSpawningResult | void;
    subagent_delivery_target: (event: PluginHookSubagentDeliveryTargetEvent, ctx: PluginHookSubagentContext) => Promise<PluginHookSubagentDeliveryTargetResult | void> | PluginHookSubagentDeliveryTargetResult | void;
    subagent_spawned: (event: PluginHookSubagentSpawnedEvent, ctx: PluginHookSubagentContext) => Promise<void> | void;
    subagent_ended: (event: PluginHookSubagentEndedEvent, ctx: PluginHookSubagentContext) => Promise<void> | void;
    gateway_start: (event: PluginHookGatewayStartEvent, ctx: PluginHookGatewayContext) => Promise<void> | void;
    gateway_stop: (event: PluginHookGatewayStopEvent, ctx: PluginHookGatewayContext) => Promise<void> | void;
};
export type PluginHookRegistration<K extends PluginHookName = PluginHookName> = {
    pluginId: string;
    hookName: K;
    handler: PluginHookHandlerMap[K];
    priority?: number;
    source: string;
};
