mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
* fix(plugins): expose ephemeral sessionId in tool contexts for per-conversation isolation The plugin tool context (`OpenClawPluginToolContext`) and tool hook context (`PluginHookToolContext`) only provided `sessionKey`, which is a durable channel identifier that survives /new and /reset. Plugins like mem0 that need per-conversation isolation (e.g. mapping Mem0 `run_id`) had no way to distinguish between conversations, causing session-scoped memories to persist unbounded across resets. Add `sessionId` (ephemeral UUID regenerated on /new and /reset) to: - `OpenClawPluginToolContext` (factory context for plugin tools) - `PluginHookToolContext` (before_tool_call / after_tool_call hooks) - Internal `HookContext` for tool call wrappers Thread the value from the run attempt through createOpenClawCodingTools → createOpenClawTools → resolvePluginTools and through the tool hook wrapper. Closes #31253 Made-with: Cursor * fix(agents): propagate embedded sessionId through tool hook context * test(hooks): cover sessionId in embedded tool hook contexts * docs(changelog): add sessionId hook context follow-up note * test(hooks): avoid toolCallId collision in after_tool_call e2e --------- Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
768 lines
21 KiB
TypeScript
768 lines
21 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";
|
|
|
|
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;
|
|
/** 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;
|
|
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";
|
|
|
|
// Agent context shared across agent hooks
|
|
export type PluginHookAgentContext = {
|
|
agentId?: string;
|
|
sessionKey?: string;
|
|
sessionId?: string;
|
|
workspaceDir?: string;
|
|
messageProvider?: 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;
|
|
};
|
|
|
|
// 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;
|
|
|
|
// 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;
|
|
toolName: string;
|
|
};
|
|
|
|
// before_tool_call hook
|
|
export type PluginHookBeforeToolCallEvent = {
|
|
toolName: string;
|
|
params: Record<string, unknown>;
|
|
};
|
|
|
|
export type PluginHookBeforeToolCallResult = {
|
|
params?: Record<string, unknown>;
|
|
block?: boolean;
|
|
blockReason?: string;
|
|
};
|
|
|
|
// after_tool_call hook
|
|
export type PluginHookAfterToolCallEvent = {
|
|
toolName: string;
|
|
params: Record<string, unknown>;
|
|
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;
|
|
};
|
|
|
|
// session_start hook
|
|
export type PluginHookSessionStartEvent = {
|
|
sessionId: string;
|
|
resumedFrom?: string;
|
|
};
|
|
|
|
// session_end hook
|
|
export type PluginHookSessionEndEvent = {
|
|
sessionId: 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;
|
|
};
|