Files
openclaw/src/plugins/types.ts
2026-03-07 21:59:44 +00:00

893 lines
26 KiB
TypeScript

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 { OpenClawConfig } from "../config/config.js";
import type { ModelProviderConfig } from "../config/types.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 { RuntimeEnv } from "../runtime.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" | "context-engine";
export type PluginConfigValidation =
| { ok: true; value?: unknown }
| { ok: false; errors: string[] };
export type OpenClawPluginConfigSchema = {
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 OpenClawPluginToolContext = {
config?: OpenClawConfig;
workspaceDir?: string;
agentDir?: string;
agentId?: string;
sessionKey?: string;
/** Ephemeral session UUID — regenerated on /new and /reset. Use for per-conversation isolation. */
sessionId?: string;
messageChannel?: string;
agentAccountId?: string;
/** Trusted sender id from inbound context (runtime-provided, not tool args). */
requesterSenderId?: string;
/** Whether the trusted sender is an owner. */
senderIsOwner?: boolean;
sandboxed?: boolean;
};
export type OpenClawPluginToolFactory = (
ctx: OpenClawPluginToolContext,
) => AnyAgentTool | AnyAgentTool[] | null | undefined;
export type OpenClawPluginToolOptions = {
name?: string;
names?: string[];
optional?: boolean;
};
export type OpenClawPluginHookOptions = {
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<OpenClawConfig>;
defaultModel?: string;
notes?: string[];
};
export type ProviderAuthContext = {
config: OpenClawConfig;
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;
run: (ctx: ProviderAuthContext) => Promise<ProviderAuthResult>;
};
export type ProviderPlugin = {
id: string;
label: string;
docsPath?: string;
aliases?: string[];
envVars?: string[];
models?: ModelProviderConfig;
auth: ProviderAuthMethod[];
formatApiKey?: (cred: AuthProfileCredential) => string;
refreshOAuth?: (cred: OAuthCredential) => Promise<OAuthCredential>;
};
export type OpenClawPluginGatewayMethod = {
method: string;
handler: GatewayRequestHandler;
};
// =============================================================================
// Plugin Commands
// =============================================================================
/**
* 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 OpenClaw configuration */
config: OpenClawConfig;
/** 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 OpenClawPluginCommandDefinition = {
/** Command name without leading slash (e.g., "tts") */
name: string;
/**
* Optional native-command aliases for slash/menu surfaces.
* `default` applies to all native providers unless a provider-specific
* override exists (for example `{ default: "talkvoice", discord: "voice2" }`).
*/
nativeNames?: Partial<Record<string, string>> & { default?: 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 OpenClawPluginHttpRouteAuth = "gateway" | "plugin";
export type OpenClawPluginHttpRouteMatch = "exact" | "prefix";
export type OpenClawPluginHttpRouteHandler = (
req: IncomingMessage,
res: ServerResponse,
) => Promise<boolean | void> | boolean | void;
export type OpenClawPluginHttpRouteParams = {
path: string;
handler: OpenClawPluginHttpRouteHandler;
auth: OpenClawPluginHttpRouteAuth;
match?: OpenClawPluginHttpRouteMatch;
replaceExisting?: boolean;
};
export type OpenClawPluginCliContext = {
program: Command;
config: OpenClawConfig;
workspaceDir?: string;
logger: PluginLogger;
};
export type OpenClawPluginCliRegistrar = (ctx: OpenClawPluginCliContext) => void | Promise<void>;
export type OpenClawPluginServiceContext = {
config: OpenClawConfig;
workspaceDir?: string;
stateDir: string;
logger: PluginLogger;
};
export type OpenClawPluginService = {
id: string;
start: (ctx: OpenClawPluginServiceContext) => void | Promise<void>;
stop?: (ctx: OpenClawPluginServiceContext) => void | Promise<void>;
};
export type OpenClawPluginChannelRegistration = {
plugin: ChannelPlugin;
dock?: ChannelDock;
};
export type OpenClawPluginDefinition = {
id?: string;
name?: string;
description?: string;
version?: string;
kind?: PluginKind;
configSchema?: OpenClawPluginConfigSchema;
register?: (api: OpenClawPluginApi) => void | Promise<void>;
activate?: (api: OpenClawPluginApi) => void | Promise<void>;
};
export type OpenClawPluginModule =
| OpenClawPluginDefinition
| ((api: OpenClawPluginApi) => void | Promise<void>);
export type OpenClawPluginApi = {
id: string;
name: string;
version?: string;
description?: string;
source: string;
config: OpenClawConfig;
pluginConfig?: Record<string, unknown>;
runtime: PluginRuntime;
logger: PluginLogger;
registerTool: (
tool: AnyAgentTool | OpenClawPluginToolFactory,
opts?: OpenClawPluginToolOptions,
) => void;
registerHook: (
events: string | string[],
handler: InternalHookHandler,
opts?: OpenClawPluginHookOptions,
) => void;
registerHttpRoute: (params: OpenClawPluginHttpRouteParams) => void;
registerChannel: (registration: OpenClawPluginChannelRegistration | ChannelPlugin) => void;
registerGatewayMethod: (method: string, handler: GatewayRequestHandler) => void;
registerCli: (registrar: OpenClawPluginCliRegistrar, opts?: { commands?: string[] }) => void;
registerService: (service: OpenClawPluginService) => void;
registerProvider: (provider: ProviderPlugin) => 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: OpenClawPluginCommandDefinition) => void;
/** Register a context engine implementation (exclusive slot — only one active at a time). */
registerContextEngine: (
id: string,
factory: import("../context-engine/registry.js").ContextEngineFactory,
) => 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;
};
// ============================================================================
// Plugin Hooks
// ============================================================================
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 const PLUGIN_HOOK_NAMES = [
"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",
] as const satisfies readonly PluginHookName[];
type MissingPluginHookNames = Exclude<PluginHookName, (typeof PLUGIN_HOOK_NAMES)[number]>;
type AssertAllPluginHookNamesListed = MissingPluginHookNames extends never ? true : never;
const assertAllPluginHookNamesListed: AssertAllPluginHookNamesListed = true;
void assertAllPluginHookNamesListed;
const pluginHookNameSet = new Set<PluginHookName>(PLUGIN_HOOK_NAMES);
export const isPluginHookName = (hookName: unknown): hookName is PluginHookName =>
typeof hookName === "string" && pluginHookNameSet.has(hookName as PluginHookName);
export const PROMPT_INJECTION_HOOK_NAMES = [
"before_prompt_build",
"before_agent_start",
] as const satisfies readonly PluginHookName[];
export type PromptInjectionHookName = (typeof PROMPT_INJECTION_HOOK_NAMES)[number];
const promptInjectionHookNameSet = new Set<PluginHookName>(PROMPT_INJECTION_HOOK_NAMES);
export const isPromptInjectionHookName = (hookName: PluginHookName): boolean =>
promptInjectionHookNameSet.has(hookName);
// Agent context shared across agent hooks
export type PluginHookAgentContext = {
agentId?: string;
sessionKey?: string;
sessionId?: string;
workspaceDir?: string;
messageProvider?: string;
/** What initiated this agent run: "user", "heartbeat", "cron", or "memory". */
trigger?: string;
/** Channel identifier (e.g. "telegram", "discord", "whatsapp"). */
channelId?: string;
};
// before_model_resolve hook
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. "ollama" */
providerOverride?: string;
};
// before_prompt_build hook
export type PluginHookBeforePromptBuildEvent = {
prompt: string;
/** Session messages prepared for this run. */
messages: unknown[];
};
export type PluginHookBeforePromptBuildResult = {
systemPrompt?: string;
prependContext?: string;
/**
* Prepended to the agent system prompt so providers can cache it (e.g. prompt caching).
* Use for static plugin guidance instead of prependContext to avoid per-turn token cost.
*/
prependSystemContext?: string;
/**
* Appended to the agent system prompt so providers can cache it (e.g. prompt caching).
* Use for static plugin guidance instead of prependContext to avoid per-turn token cost.
*/
appendSystemContext?: string;
};
export const PLUGIN_PROMPT_MUTATION_RESULT_FIELDS = [
"systemPrompt",
"prependContext",
"prependSystemContext",
"appendSystemContext",
] as const satisfies readonly (keyof PluginHookBeforePromptBuildResult)[];
type MissingPluginPromptMutationResultFields = Exclude<
keyof PluginHookBeforePromptBuildResult,
(typeof PLUGIN_PROMPT_MUTATION_RESULT_FIELDS)[number]
>;
type AssertAllPluginPromptMutationResultFieldsListed =
MissingPluginPromptMutationResultFields extends never ? true : never;
const assertAllPluginPromptMutationResultFieldsListed: AssertAllPluginPromptMutationResultFieldsListed = true;
void assertAllPluginPromptMutationResultFieldsListed;
// before_agent_start hook (legacy compatibility: combines both phases)
export type PluginHookBeforeAgentStartEvent = {
prompt: string;
/** Optional because legacy hook can run in pre-session phase. */
messages?: unknown[];
};
export type PluginHookBeforeAgentStartResult = PluginHookBeforePromptBuildResult &
PluginHookBeforeModelResolveResult;
export type PluginHookBeforeAgentStartOverrideResult = Omit<
PluginHookBeforeAgentStartResult,
keyof PluginHookBeforePromptBuildResult
>;
export const stripPromptMutationFieldsFromLegacyHookResult = (
result: PluginHookBeforeAgentStartResult | void,
): PluginHookBeforeAgentStartOverrideResult | void => {
if (!result || typeof result !== "object") {
return result;
}
const remaining: Partial<PluginHookBeforeAgentStartResult> = { ...result };
for (const field of PLUGIN_PROMPT_MUTATION_RESULT_FIELDS) {
delete remaining[field];
}
return Object.keys(remaining).length > 0
? (remaining as PluginHookBeforeAgentStartOverrideResult)
: undefined;
};
// llm_input hook
export type PluginHookLlmInputEvent = {
runId: string;
sessionId: string;
provider: string;
model: string;
systemPrompt?: string;
prompt: string;
historyMessages: unknown[];
imagesCount: number;
};
// llm_output hook
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;
};
};
// agent_end hook
export type PluginHookAgentEndEvent = {
messages: unknown[];
success: boolean;
error?: string;
durationMs?: number;
};
// Compaction hooks
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;
};
// before_reset hook — fired when /new or /reset clears a session
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;
};
// Message context
export type PluginHookMessageContext = {
channelId: string;
accountId?: string;
conversationId?: string;
};
// message_received hook
export type PluginHookMessageReceivedEvent = {
from: string;
content: string;
timestamp?: number;
metadata?: Record<string, unknown>;
};
// message_sending hook
export type PluginHookMessageSendingEvent = {
to: string;
content: string;
metadata?: Record<string, unknown>;
};
export type PluginHookMessageSendingResult = {
content?: string;
cancel?: boolean;
};
// message_sent hook
export type PluginHookMessageSentEvent = {
to: string;
content: string;
success: boolean;
error?: string;
};
// Tool context
export type PluginHookToolContext = {
agentId?: string;
sessionKey?: string;
/** Ephemeral session UUID — regenerated on /new and /reset. */
sessionId?: string;
/** Stable run identifier for this agent invocation. */
runId?: string;
toolName: string;
/** Provider-specific tool call ID when available. */
toolCallId?: string;
};
// before_tool_call hook
export type PluginHookBeforeToolCallEvent = {
toolName: string;
params: Record<string, unknown>;
/** Stable run identifier for this agent invocation. */
runId?: string;
/** Provider-specific tool call ID when available. */
toolCallId?: string;
};
export type PluginHookBeforeToolCallResult = {
params?: Record<string, unknown>;
block?: boolean;
blockReason?: string;
};
// after_tool_call hook
export type PluginHookAfterToolCallEvent = {
toolName: string;
params: Record<string, unknown>;
/** Stable run identifier for this agent invocation. */
runId?: string;
/** Provider-specific tool call ID when available. */
toolCallId?: string;
result?: unknown;
error?: string;
durationMs?: number;
};
// tool_result_persist hook
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;
};
// before_message_write hook
export type PluginHookBeforeMessageWriteEvent = {
message: AgentMessage;
sessionKey?: string;
agentId?: string;
};
export type PluginHookBeforeMessageWriteResult = {
block?: boolean; // If true, message is NOT written to JSONL
message?: AgentMessage; // Optional: modified message to write instead
};
// Session context
export type PluginHookSessionContext = {
agentId?: string;
sessionId: string;
sessionKey?: string;
};
// session_start hook
export type PluginHookSessionStartEvent = {
sessionId: string;
sessionKey?: string;
resumedFrom?: string;
};
// session_end hook
export type PluginHookSessionEndEvent = {
sessionId: string;
sessionKey?: string;
messageCount: number;
durationMs?: number;
};
// Subagent context
export type PluginHookSubagentContext = {
runId?: string;
childSessionKey?: string;
requesterSessionKey?: string;
};
export type PluginHookSubagentTargetKind = "subagent" | "acp";
type PluginHookSubagentSpawnBase = {
childSessionKey: string;
agentId: string;
label?: string;
mode: "run" | "session";
requester?: {
channel?: string;
accountId?: string;
to?: string;
threadId?: string | number;
};
threadRequested: boolean;
};
// subagent_spawning hook
export type PluginHookSubagentSpawningEvent = PluginHookSubagentSpawnBase;
export type PluginHookSubagentSpawningResult =
| {
status: "ok";
threadBindingReady?: boolean;
}
| {
status: "error";
error: string;
};
// subagent_delivery_target hook
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;
};
};
// subagent_spawned hook
export type PluginHookSubagentSpawnedEvent = PluginHookSubagentSpawnBase & {
runId: string;
};
// subagent_ended hook
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;
};
// Gateway context
export type PluginHookGatewayContext = {
port?: number;
};
// gateway_start hook
export type PluginHookGatewayStartEvent = {
port: number;
};
// gateway_stop hook
export type PluginHookGatewayStopEvent = {
reason?: string;
};
// Hook handler types mapped by hook name
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;
};