openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
42,687 lines • 1.72 MB
TypeScript
import { Static, TSchema, Type } from "typebox";
import { z } from "zod";
import "@openclaw/ai/validation";
import { DatabaseSync } from "node:sqlite";
import "kysely";
import "json5";
import "@openclaw/fs-safe/config";
import "@openclaw/fs-safe/advanced";
import "@openclaw/ai";
import "@openclaw/ai/internal/runtime";
import "@openclaw/ai/internal/shared";
import { IncomingMessage, ServerResponse } from "node:http";
import { LookupAddress } from "node:dns";
import { Dispatcher } from "undici";
import { Duplex } from "node:stream";
import { Command } from "commander";
import "execa";
import { WebSocket } from "ws";
import { AutocompleteProvider, Component, EditorComponent, EditorTheme, KeybindingsConfig, KeybindingsManager, OverlayHandle, OverlayOptions, TUI } from "@earendil-works/pi-tui";
import "@modelcontextprotocol/sdk/types.js";
import { ImageMetadata } from "rastermill";
import "@openclaw/fs-safe";
import "@openclaw/fs-safe/secret";
//#endregion
//#region packages/normalization-core/src/string-coerce.d.ts
type FastMode = boolean | "auto";
//#endregion
//#region src/shared/silent-reply-policy.d.ts
type SilentReplyPolicy = "allow" | "disallow";
type SilentReplyConversationType = "direct" | "group" | "internal";
type SilentReplyPolicyShape = Partial<Record<Exclude<SilentReplyConversationType, "direct">, SilentReplyPolicy>>;
//#endregion
//#region src/config/types.secrets.d.ts
/** Supported secret reference backends in config. */
type SecretRefSource = "env" | "file" | "exec" | "store";
/**
* Stable identifier for a secret in a configured source.
* Examples:
* - env source: provider "default", id "OPENAI_API_KEY"
* - file source: provider "mounted-json", id "/providers/openai/apiKey"
* - exec source: provider "vault", id "openai/api-key"
* - store source: provider "default", id "OPENAI_API_KEY"
*/
type SecretRef = {
source: SecretRefSource;
provider: string;
id: string;
};
/** Secret-bearing config input: either a literal string or a structured SecretRef. */
type SecretInput = string | SecretRef;
type EnvSecretProviderConfig = {
source: "env";
/** Optional env var allowlist (exact names). */
allowlist?: string[];
};
type FileSecretProviderMode = "singleValue" | "json";
type FileSecretProviderConfig = {
source: "file";
path: string;
mode?: FileSecretProviderMode;
timeoutMs?: number;
maxBytes?: number;
};
type ManualExecSecretProviderConfig = {
source: "exec";
command: string;
args?: string[];
timeoutMs?: number;
noOutputTimeoutMs?: number;
maxOutputBytes?: number;
jsonOnly?: boolean;
env?: Record<string, string>;
passEnv?: string[];
trustedDirs?: string[];
};
type PluginIntegrationSecretProviderConfig = {
source: "exec";
pluginIntegration: {
pluginId: string;
integrationId: string;
};
};
type ExecSecretProviderConfig = ManualExecSecretProviderConfig | PluginIntegrationSecretProviderConfig;
type StoreSecretProviderConfig = {
source: "store";
};
type SecretProviderConfig = EnvSecretProviderConfig | FileSecretProviderConfig | ExecSecretProviderConfig | StoreSecretProviderConfig;
type SecretsConfig = {
egressProxy?: {
enabled?: boolean;
allowedHosts?: string[];
bypassHosts?: string[];
};
providers?: Record<string, SecretProviderConfig>;
defaults?: {
env?: string;
file?: string;
exec?: string;
store?: string;
};
};
//#endregion
//#region src/config/types.sandbox.d.ts
type SandboxDockerSettings = {
/** Docker image to use for sandbox containers. */
image?: string;
/** Prefix for sandbox container names. */
containerPrefix?: string;
/** Container workdir mount path (default: /workspace). */
workdir?: string;
/** Run container rootfs read-only. */
readOnlyRoot?: boolean;
/** Extra tmpfs mounts for read-only containers. */
tmpfs?: string[];
/** Container network mode (bridge|none|custom). */
network?: string;
/** Container user (uid:gid). */
user?: string;
/** Drop Linux capabilities. */
capDrop?: string[];
/** Explicit environment variables for sandbox container creation and exec. */
env?: Record<string, string>;
/** Optional setup command run once after container creation (array entries are joined by newline). */
setupCommand?: string;
/** Limit container PIDs (0 = Docker default). */
pidsLimit?: number;
/** Limit container memory (e.g. 512m, 2g, or bytes as number). */
memory?: string | number;
/** Limit container memory swap (same format as memory). */
memorySwap?: string | number;
/** Limit container CPU shares (e.g. 0.5, 1, 2). */
cpus?: number;
/** GPU devices to expose via Docker --gpus (e.g. "all", "device=GPU-uuid"). */
gpus?: string;
/**
* Set ulimit values by name (e.g. nofile, nproc).
* Use "soft:hard" string, a number, or { soft, hard }.
*/
ulimits?: Record<string, string | number | {
soft?: number;
hard?: number;
}>;
/** Seccomp profile (path or profile name). */
seccompProfile?: string;
/** AppArmor profile name. */
apparmorProfile?: string;
/** DNS servers (e.g. ["1.1.1.1", "8.8.8.8"]). */
dns?: string[];
/** Extra host mappings (e.g. ["api.local:10.0.0.2"]). */
extraHosts?: string[];
/** Additional bind mounts (host:container:mode format, e.g. ["/host/path:/container/path:rw"]). */
binds?: string[];
/**
* Dangerous override: allow bind mounts that target reserved container paths
* like /workspace or /agent.
*/
dangerouslyAllowReservedContainerTargets?: boolean;
/**
* Dangerous override: allow bind mount sources outside runtime allowlisted roots
* (workspace + agent workspace roots).
*/
dangerouslyAllowExternalBindSources?: boolean;
/**
* Dangerous override: allow Docker `network: "container:<id>"` namespace joins.
* Default behavior blocks container namespace joins to preserve sandbox isolation.
*/
dangerouslyAllowContainerNamespaceJoin?: boolean;
};
type SandboxBrowserSettings = {
enabled?: boolean;
image?: string;
containerPrefix?: string;
/** Docker network for sandbox browser containers (default: openclaw-sandbox-browser). */
network?: string;
cdpPort?: number;
/** Optional CIDR allowlist for CDP ingress at the container edge (for example: 172.21.0.1/32). */
cdpSourceRange?: string;
vncPort?: number;
noVncPort?: number;
headless?: boolean;
noVncEnabled?: boolean;
/** @deprecated Doctor-only legacy input. */
enableNoVnc?: boolean;
/**
* Allow sandboxed sessions to target the host browser control server.
* Default: false.
*/
allowHostControl?: boolean;
/**
* When true (default), sandboxed browser control will try to start/reattach to
* the sandbox browser container when a tool call needs it.
*/
autoStart?: boolean;
/** Max time to wait for CDP to become reachable after auto-start (ms). */
autoStartTimeoutMs?: number;
/** Additional bind mounts for the browser container only. When set, replaces docker.binds for the browser container. */
binds?: string[];
};
type SandboxPruneSettings = {
/** Prune if idle for more than N hours (0 disables). */
idleHours?: number;
/** Prune if older than N days (0 disables). */
maxAgeDays?: number;
};
type SandboxSshSettings = {
/** SSH target in user@host[:port] form. */
target?: string;
/** SSH client command. Default: "ssh". */
command?: string;
/** Absolute remote root used for per-scope workspaces. */
workspaceRoot?: string;
/** Enforce host-key verification. Default: true. */
strictHostKeyChecking?: boolean;
/** Allow OpenSSH host-key updates. Default: true. */
updateHostKeys?: boolean;
/** Existing private key path on the host. */
identityFile?: string;
/** Existing SSH certificate path on the host. */
certificateFile?: string;
/** Existing known_hosts file path on the host. */
knownHostsFile?: string;
/** Inline or SecretRef-backed private key contents. */
identityData?: SecretInput;
/** Inline or SecretRef-backed SSH certificate contents. */
certificateData?: SecretInput;
/** Inline or SecretRef-backed known_hosts contents. */
knownHostsData?: SecretInput;
};
//#endregion
//#region src/config/types.agents-shared.d.ts
/** Agent model selector: a single provider/model ref or primary+fallback chain. */
type AgentModelConfig = string | {
/** Primary model (provider/model). */
primary?: string;
/** Per-agent model fallbacks (provider/model). */
fallbacks?: string[];
};
/** Tool-specific model selector with an optional capability timeout override. */
type AgentToolModelConfig = string | {
/** Primary model (provider/model). */
primary?: string;
/** Per-tool model fallbacks (provider/model). */
fallbacks?: string[];
/** Optional provider request timeout in milliseconds for capabilities that support it. */
timeoutMs?: number;
};
/** Runtime selection policy attached to providers, models, and agent defaults. */
type AgentRuntimePolicyConfig = {
/** Agent runtime id. Omitted uses "openclaw"; "auto" opts into plugin harness auto-selection. */
id?: string;
};
/** Per-agent sandbox policy shared by embedded agents and sandbox backends. */
type AgentSandboxConfig = {
/** Sandbox activation mode for this agent. */
mode?: "off" | "non-main" | "all";
/** Sandbox runtime backend id. Default: "docker". */
backend?: string;
/** Agent workspace access inside the sandbox. */
workspaceAccess?: "none" | "ro" | "rw";
/**
* Session tools visibility for sandboxed sessions.
* - "spawned": only allow session tools to target sessions spawned from this session (default)
* - "all": allow session tools to target any session
*/
sessionToolsVisibility?: "spawned" | "all";
/** Container/workspace scope for sandbox isolation. */
scope?: "session" | "agent" | "shared";
/** Host workspace root mounted or copied into the sandbox. */
workspaceRoot?: string;
/** Docker-specific sandbox settings. */
docker?: SandboxDockerSettings;
/** SSH-specific sandbox settings. */
ssh?: SandboxSshSettings;
/** Optional sandboxed browser settings. */
browser?: SandboxBrowserSettings;
/** Auto-prune sandbox settings. */
prune?: SandboxPruneSettings;
};
//#endregion
//#region src/channels/chat-type.d.ts
/**
* Normalized conversation kind shared by channel routing, sessions, and SDK helpers.
*/
type ChatType = "direct" | "group" | "channel";
//#endregion
//#region src/config/types.base.d.ts
/** Typing indicator timing policy shared by channel configs. */
type TypingMode = "never" | "instant" | "thinking" | "message";
/** Session-key ownership model for inbound messages. */
type SessionScope = "per-sender" | "global";
/** DM session-key granularity across peers, channels, and accounts. */
type DmScope = "main" | "per-peer" | "per-channel-peer" | "per-account-channel-peer";
type GroupScope = "main" | "per-group";
/** Which source messages outbound replies should thread or quote against. */
type ReplyToMode = "off" | "first" | "all" | "batched";
/** Group-chat admission policy for channels with allowlists. */
type GroupPolicy = "open" | "disabled" | "allowlist";
/** Direct-message admission policy for channels with pairing/allowlists. */
type DmPolicy = "pairing" | "allowlist" | "open" | "disabled";
/** How much non-allowlisted context is visible to an agent. */
type ContextVisibilityMode = "all" | "allowlist" | "allowlist_quote";
/** Text splitting strategy for outbound channel delivery. */
type TextChunkMode = "length" | "newline";
/** Preview/progress delivery mode while an agent response is still streaming. */
type StreamingMode = "off" | "partial" | "block" | "progress";
/** How command text is represented in streaming progress previews. */
type ChannelStreamingCommandTextMode = "raw" | "status";
type BlockStreamingCoalesceConfig = {
/** Minimum buffered characters before coalesced block delivery. */
minChars?: number;
/** Maximum buffered characters before a block must be flushed. */
maxChars?: number;
/** Idle time in ms before flushing a partial coalesced block. */
idleMs?: number;
};
type BlockStreamingChunkConfig = {
/** Minimum preview chunk size before sending another draft update. */
minChars?: number;
/** Maximum preview chunk size before forcing a draft update. */
maxChars?: number;
/** Preferred natural boundary when splitting preview chunks. */
breakPreference?: "paragraph" | "newline" | "sentence";
};
type ChannelStreamingProgressConfig = {
/** Initial progress title. "auto" picks from labels; false hides the title. Default: "auto". */
label?: string | false;
/** Candidate labels for label="auto". Defaults to OpenClaw's built-in progress labels. */
labels?: string[];
/** Maximum number of progress lines to keep below the label. Default: 8. */
maxLines?: number;
/** Maximum characters per compact progress line before truncation. Default: 120. */
maxLineChars?: number;
/** Include compact tool/task progress in the draft. Default: true. */
toolProgress?: boolean;
/** Command/exec progress detail in the draft. "raw" opts into command text; "status" shows only the tool label. Default: "status". */
commandText?: ChannelStreamingCommandTextMode;
/** Include assistant commentary/preamble text in the progress draft. Default: false. */
commentary?: boolean;
/**
* Replace tool lines with a short utility-model narration of what the agent
* is doing. Runs when a utility model resolves (explicit `utilityModel` or
* the primary provider's declared default). Default: true.
*/
narration?: boolean;
};
type ChannelStreamingPreviewConfig = {
/** Chunking thresholds for preview-draft updates while streaming. */
chunk?: BlockStreamingChunkConfig;
/**
* Render live tool/activity updates into the preview draft for channels that
* edit a single preview message in place.
* Default: true.
*/
toolProgress?: boolean;
/** Command/exec progress detail in the preview. "raw" opts into command text; "status" shows only the tool label. Default: "status". */
commandText?: ChannelStreamingCommandTextMode;
};
type ChannelStreamingBlockConfig = {
/** Enable chunked block-reply delivery for channels that support it. */
enabled?: boolean;
/** Merge streamed block replies before sending. */
coalesce?: BlockStreamingCoalesceConfig;
};
type ChannelStreamingConfig<TProgress extends ChannelStreamingProgressConfig = ChannelStreamingProgressConfig> = {
/**
* Preview streaming mode:
* - "off": disable preview updates
* - "partial": update one preview in place
* - "block": emit larger chunked preview updates
* - "progress": progress/status preview mode for channels that support it
*/
mode?: StreamingMode;
/** Chunking mode for outbound text delivery. */
chunkMode?: TextChunkMode;
/** Prefer a channel's native streaming transport over its portable draft path. */
nativeTransport?: boolean;
preview?: ChannelStreamingPreviewConfig;
progress?: TProgress;
block?: ChannelStreamingBlockConfig;
};
type ChannelDeliveryStreamingConfig = Pick<ChannelStreamingConfig, "chunkMode" | "block">;
/** Streaming subset used by channels that render visible preview/progress replies. */
type ChannelPreviewStreamingConfig = Pick<ChannelStreamingConfig, "mode" | "chunkMode" | "preview" | "progress" | "block">;
type MarkdownTableMode$1 = "off" | "bullets" | "code" | "block";
type MarkdownConfig = {
/** Table rendering mode (off|bullets|code|block). */
tables?: MarkdownTableMode$1;
};
type HumanDelayConfig = {
/** Delay style for block replies (off|natural|custom). */
mode?: "off" | "natural" | "custom";
/** Minimum delay in milliseconds (default: 800). */
minMs?: number;
/** Maximum delay in milliseconds (default: 2500). */
maxMs?: number;
};
type SessionSendPolicyAction = "allow" | "deny";
type SessionSendPolicyMatch = {
/** Channel/provider id match. */
channel?: string;
/** Direct/group/thread classification when the caller has channel metadata. */
chatType?: ChatType;
/**
* Session key prefix match.
* Note: some consumers match against a normalized key (for example, stripping `agent:<id>:`).
*/
keyPrefix?: string;
/** Optional raw session-key prefix match for consumers that normalize session keys. */
rawKeyPrefix?: string;
};
type SessionSendPolicyRule = {
/** Action applied when match criteria select this rule. */
action: SessionSendPolicyAction;
/** Optional match filter; omitted match behaves as a catch-all rule. */
match?: SessionSendPolicyMatch;
};
type SessionSendPolicyConfig = {
/** Fallback action when no send-policy rule matches. */
default?: SessionSendPolicyAction;
/** Ordered allow/deny rules; first matching rule wins. */
rules?: SessionSendPolicyRule[];
};
type SessionResetMode = "none" | "daily" | "idle";
type SessionResetConfig = {
mode?: SessionResetMode;
/** Local hour (0-23) for the daily reset boundary. */
atHour?: number;
/** Sliding idle window (minutes). When set with daily mode, whichever expires first wins. */
idleMinutes?: number;
};
type SessionResetByTypeConfig = {
direct?: SessionResetConfig;
group?: SessionResetConfig;
thread?: SessionResetConfig;
};
type SessionThreadBindingsConfig = {
/**
* Master switch for thread-bound session routing features.
* Channel/provider keys can override this default.
*/
enabled?: boolean;
/**
* Inactivity window for thread-bound sessions (hours).
* Binding expires after this amount of idle time. Set to 0 to disable. Default: 24.
*/
idleHours?: number;
/**
* Optional hard max age for thread-bound sessions (hours).
* Binding expires once this age is reached even if active. Set to 0 to disable. Default: 0.
*/
maxAgeHours?: number;
/**
* Allow channel integrations to create thread-bound work sessions from
* sessions_spawn or native ACP spawn flows. Channel/account keys can override.
* Default: true when thread bindings are enabled.
*/
spawnSessions?: boolean;
/**
* Default context mode for native subagents spawned into a bound thread.
* Default: "fork" so the child starts from the requester transcript.
*/
defaultSpawnContext?: "isolated" | "fork";
};
type SessionSharingConfig = {
/** Allow owners/admins to set sessions read-only. Default: true. */
readOnly?: boolean;
/** Allow owners/admins to select suggest mode. Default: true. */
suggest?: boolean;
/** Allow owners/admins to hide draft sessions from other operators. Default: true. */
drafts?: boolean;
};
type SessionConfig = {
scope?: SessionScope;
/** DM session scoping (default: "main"). */
dmScope?: DmScope;
/** Group/channel session scoping (default: "per-group"). */
groupScope?: GroupScope;
/** Map platform-prefixed identities (e.g. "telegram:123") to canonical DM peers. */
identityLinks?: Record<string, string[]>;
resetTriggers?: string[];
reset?: SessionResetConfig;
resetByType?: SessionResetByTypeConfig;
/** Channel-specific reset overrides (e.g. { discord: { mode: "idle", idleMinutes: 10080 } }). */
resetByChannel?: Record<string, SessionResetConfig>;
store?: string;
mainKey?: string;
sendPolicy?: SessionSendPolicyConfig;
/** Shared defaults for thread-bound session routing across channels/providers. */
threadBindings?: SessionThreadBindingsConfig;
/** Collaboration modes owners and administrators may select. */
sharing?: SessionSharingConfig;
/** Automatic session store maintenance (pruning, capping, archive retention, disk budget). */
maintenance?: SessionMaintenanceConfig;
};
type SessionMaintenanceMode = "enforce" | "warn";
/** Session-store cleanup policy for transcript count, age, archives, and disk budget. */
type SessionMaintenanceConfig = {
/** Whether to enforce maintenance or warn only. Default: "enforce". */
mode?: SessionMaintenanceMode;
/** Remove session entries older than this duration (e.g. "30d", "12h"). Default: "30d". */
pruneAfter?: string | number;
/** Archive inactive dashboard sessions after this duration. Default: "7d"; false or 0 disables. */
archiveDashboardAfter?: string | number | false;
/** Maximum total session entries to keep when protection permits. Default: 500. */
maxEntries?: number;
/** Protect interactive sessions active within this duration. Default and false: disabled. */
preserveRecent?: string | number | false;
/**
* Age-based retention for archived transcripts (`*.reset.<timestamp>` and
* `*.deleted.<timestamp>`). Default and `false`: keep archives until the
* disk budget evicts them oldest-first; a duration opts into deletion.
*/
resetArchiveRetention?: string | number | false;
/**
* Per-agent sessions-directory disk budget (e.g. "500mb"). Default: "10gb".
* When exceeded, warn (mode=warn) or enforce oldest-first cleanup
* (mode=enforce). Set `false`, `0`, or `"0"` to disable the budget entirely.
*/
maxDiskBytes?: number | string | false;
/**
* Target size after disk-budget cleanup (high-water mark), e.g. "400mb".
* Default: 80% of maxDiskBytes. A value that resolves to zero falls back to
* the default instead of clearing history; negative values are invalid.
*/
highWaterBytes?: number | string;
};
type LoggingConfig = {
level?: "silent" | "fatal" | "error" | "warn" | "info" | "debug" | "trace";
file?: string;
/** Maximum size of a single log file in bytes before rotation. Default: 100 MB. */
maxFileBytes?: number;
consoleLevel?: "silent" | "fatal" | "error" | "warn" | "info" | "debug" | "trace";
consoleStyle?: "pretty" | "json";
/** Redact sensitive tokens in log sinks and persisted transcript text. Default: "tools". Safety-boundary UI/tool/diagnostic payloads may still redact when this is "off". */
/** Regex patterns used to redact sensitive tokens from logs and transcripts. */
redactPatterns?: string[];
/** Metadata-only agent activity audit ledger settings. */
audit?: AuditConfig;
};
type DiagnosticsOtelConfig = {
enabled?: boolean;
endpoint?: string;
tracesEndpoint?: string;
metricsEndpoint?: string;
logsEndpoint?: string;
protocol?: "http/protobuf";
headers?: Record<string, string>;
serviceName?: string;
/** Replacement prefix for OpenClaw-owned metric names. Empty removes the prefix; defaults to "openclaw.". */
metricNamePrefix?: string;
traces?: boolean;
metrics?: boolean;
logs?: boolean;
/** Log export sink: OTLP by default, stdout JSONL, or both. */
logsExporter?: "otlp" | "stdout" | "both";
/** Trace sample rate (0.0 - 1.0). */
sampleRate?: number;
/** Metric export interval (ms). */
flushIntervalMs?: number;
/** Opt in to raw non-system message/tool content in OTEL span attributes. */
captureContent?: boolean;
};
type DiagnosticsCacheTraceConfig = {
/** Write prompt-cache trace artifacts for debugging deterministic cache input. */
enabled?: boolean;
};
type AuditConfig = {
/**
* Record metadata-only run, tool, and enabled message lifecycle events into
* the shared state database. Content is never stored. Default: true. This is
* startup-scoped; disabling stops new event inserts after restart while retained
* records stay readable until they expire.
*/
enabled?: boolean;
/**
* Retain bounded execution-identity attribution for exact-run inspection.
* Default: false. Requires the audit ledger and takes effect after Gateway restart.
*/
executionIdentity?: boolean;
/**
* Record content-free message lifecycle metadata. `direct` records only
* known direct conversations; `all` also records group, channel, and
* unknown conversation kinds. Default: `off`.
*/
messages?: "off" | "direct" | "all";
};
type DiagnosticsConfig = {
enabled?: boolean;
/** Optional ad-hoc diagnostics flags (e.g. "telegram.http"). */
flags?: string[];
otel?: DiagnosticsOtelConfig;
cacheTrace?: DiagnosticsCacheTraceConfig;
};
type AgentElevatedAllowFromConfig = Partial<Record<string, Array<string | number>>>;
type IdentityConfig = {
name?: string;
theme?: string;
emoji?: string;
/** Avatar image: workspace-relative path, http(s) URL, or data URI. */
avatar?: string;
};
//#endregion
//#region src/config/types.agent-defaults.d.ts
/** Workspace bootstrap-file injection policy for agent system prompts. */
type AgentContextInjection = "always" | "continuation-skip" | "never";
/**
* Optional bootstrap files that setup can skip while still creating required
* agent files. "HEARTBEAT.md" stays accepted as legacy config input even
* though workspace setup no longer writes it.
*/
type OptionalBootstrapFileName = "SOUL.md" | "USER.md" | "HEARTBEAT.md" | "IDENTITY.md";
/** Embedded runner behavior contract used by strict-agentic provider flows. */
type EmbeddedAgentExecutionContract = "default" | "strict-agentic";
/** Prompt-only default for how strongly agents should delegate to sub-agents. */
type SubagentDelegationMode = "suggest" | "prefer";
/** Image compression/detail preference used before sending image inputs to models. */
type AgentImageQualityPreference = "auto" | "efficient" | "balanced" | "high";
/** Scope of an interactive model selection when no explicit scope is supplied. */
type ModelSelectionScope = "session" | "agent" | "global";
/** Canonical thinking levels accepted by agent defaults and compaction overrides. */
type AgentThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive" | "max" | "ultra";
type AgentModelEntryConfig = {
/** Optional display/lookup alias for this provider/model entry. */
alias?: string;
/** Provider-specific API parameters (e.g., GLM-4.7 thinking mode). */
params?: Record<string, unknown>;
/** Optional agent execution runtime for this specific provider/model entry. */
agentRuntime?: AgentRuntimePolicyConfig;
/** OpenClaw Code Mode override; omitted inherits the enclosing activation policy. */
codeMode?: boolean;
/** Enable streaming for this model (default: true, false for Ollama to avoid SDK issue #1205). */
streaming?: boolean;
};
type AgentModelPolicyConfig = {
/** Model refs allowed for session/run overrides. Empty or omitted allows any model. */
allow?: string[];
};
type AgentContextPruningConfig = {
/** Pruning mode for old tool results in model context. */
mode?: "off" | "cache-ttl";
/** TTL to consider cache expired (duration string, default unit: minutes). */
ttl?: string;
tools?: {
/** Tool names eligible for context pruning. */
allow?: string[];
/** Tool names excluded from context pruning. */
deny?: string[];
};
hardClear?: {
/** Replace oversized old tool results with a placeholder at high pressure. */
enabled?: boolean;
/** Placeholder text inserted when a tool result is hard-cleared. */
placeholder?: string;
};
};
type AgentStartupContextConfig = {
/** Enable runtime-owned startup-context prelude on bare session resets (default: true). */
enabled?: boolean;
/** Which bare reset commands should receive startup context (default: ["new", "reset"]). */
applyOn?: Array<"new" | "reset">;
/** How many dated memory files to load counting backward from today (default: 2). */
dailyMemoryDays?: number;
/** Max bytes to read from each daily memory file before skipping (default: 16384). */
maxFileBytes?: number;
/** Max characters retained from each daily memory file (default: 1200). */
maxFileChars?: number;
/** Max total characters retained across the startup prelude (default: 2800). */
maxTotalChars?: number;
};
type AgentContextLimitsConfig = {
/** Default max chars returned by memory_get before truncation metadata/notice (default: 12000). */
memoryGetMaxChars?: number;
/** Max chars retained from post-compaction AGENTS.md context injection (default: 1800). */
postCompactionMaxChars?: number;
};
type AgentDefaultsConfig = {
/** @deprecated Doctor-only legacy input. */
imageGenerationModel?: AgentToolModelConfig;
/** @deprecated Doctor-only legacy input. */
videoGenerationModel?: AgentToolModelConfig;
/** @deprecated Doctor-only legacy input. */
musicGenerationModel?: AgentToolModelConfig;
/** @deprecated Doctor-only legacy input. */
envelopeTimezone?: string;
/** @deprecated Doctor-only legacy input. */
envelopeTimestamp?: "on" | "off";
/** @deprecated Doctor-only legacy input. */
envelopeElapsed?: "on" | "off";
/** @deprecated Doctor-only legacy input. */
timeFormat?: "auto" | "12" | "24";
/** @deprecated Doctor-only legacy input. */
promptOverlays?: {
gpt5?: {
personality?: "friendly" | "on" | "off";
};
};
/** Global default provider params applied to all models before per-model and per-agent overrides. */
params?: Record<string, unknown>;
/** Primary model and fallbacks (provider/model). Accepts string or {primary,fallbacks}. */
model?: AgentModelConfig;
/** Optional model-selection scope. Omitted preserves each surface's existing behavior. */
modelSelectionScope?: ModelSelectionScope;
/** Optional lower-cost model for short internal tasks such as generated session titles. */
utilityModel?: string;
/**
* @deprecated Legacy raw config accepted only by doctor/migration repair.
* Normal schema parsing rejects this key; use per-model agentRuntime instead.
*/
agentRuntime?: AgentRuntimePolicyConfig;
/** Optional image-capable model and fallbacks (provider/model). Accepts string or {primary,fallbacks}. */
imageModel?: AgentToolModelConfig;
/** Media-generation model preferences by output modality. */
mediaModels?: {
image?: AgentToolModelConfig;
video?: AgentToolModelConfig;
music?: AgentToolModelConfig;
};
/** Optional voice model and fallbacks (provider/model) for TTS/STT/realtime voice providers. */
voiceModel?: AgentToolModelConfig;
/** Optional PDF-capable model and fallbacks (provider/model). Accepts string or {primary,fallbacks}. */
pdfModel?: AgentToolModelConfig;
/** Maximum PDF file size in megabytes (default: 10). */
pdfMaxMb?: number;
/** Maximum number of PDF pages to process (default: 20). */
pdfMaxPages?: number;
/** Model catalog with optional aliases (full provider/model keys). */
models?: Record<string, AgentModelEntryConfig>;
/** Explicit model override policy. Empty or omitted allow permits any model. */
modelPolicy?: AgentModelPolicyConfig;
/** Agent bootstrap and memory directory; also the working directory when cwd is unset. */
workspace?: string;
/** Working directory for agent reply runs, separate from workspace bootstrap and memory files. */
cwd?: string;
/** Optional default allowlist of skills for agents that do not set agents.entries.*.skills. */
skills?: string[];
/** Silent-reply policy by conversation type. */
silentReply?: SilentReplyPolicyShape;
/** Optional repository root for system prompt runtime line (overrides auto-detect). */
repoRoot?: string;
/** Provider-independent prompt overlays applied by model family. */
/** Skip bootstrap (BOOTSTRAP.md creation, etc.) for pre-configured deployments. */
skipBootstrap?: boolean;
/**
* List of optional bootstrap filenames to skip writing to the workspace root.
* Applies to: SOUL.md, USER.md, IDENTITY.md ("HEARTBEAT.md" is accepted but a no-op).
* Required workspace setup such as AGENTS.md still runs.
* Example: ["SOUL.md", "USER.md", "IDENTITY.md"]
*/
skipOptionalBootstrapFiles?: OptionalBootstrapFileName[];
/**
* Controls when workspace bootstrap files (AGENTS.md, SOUL.md, etc.) are
* injected into the system prompt:
* - always: inject on every turn (default)
* - continuation-skip: skip injection on safe continuation turns once the
* transcript already contains a completed assistant turn
*/
contextInjection?: AgentContextInjection;
/** Max chars for injected bootstrap files before truncation (default: 20000). */
bootstrapMaxChars?: number;
/** Max total chars across all injected bootstrap files (default: 150000). */
bootstrapTotalMaxChars?: number;
/** Experimental agent-default flags. Keep off unless you are intentionally testing a preview surface. */
experimental?: {
/**
* Drop heavyweight non-essential default tools for weaker or smaller local
* model backends. Experimental preview only.
*/
localModelLean?: boolean;
};
/**
* Agent-visible bootstrap truncation warning mode:
* - off: do not inject warning text
* - once: inject once per unique truncation signature
* - always: inject on every run with truncation (default)
*/
/**
* Optional IANA timezone for model-visible timestamps, prompt context, system events,
* and heartbeat active hours. Defaults to the host timezone.
*/
userTimezone?: string;
/** Runtime-owned first-turn startup context for bare /new and /reset. */
startupContext?: AgentStartupContextConfig;
/** Focused context-budget overrides for high-volume injected/read surfaces. */
contextLimits?: AgentContextLimitsConfig;
/** Opt-in: prune old tool results from the LLM context to reduce token usage. */
contextPruning?: AgentContextPruningConfig;
/** Compaction tuning and pre-compaction memory flush behavior. */
compaction?: AgentCompactionConfig;
/** Embedded OpenClaw runner hardening and compatibility controls. */
embeddedAgent?: {
/**
* How embedded OpenClaw should trust workspace-local `.openclaw/settings.json`.
* - sanitize (default): apply project settings except shellPath/shellCommandPrefix
* - ignore: ignore project settings entirely
* - trusted: trust project settings as-is
*/
projectSettingsPolicy?: "trusted" | "sanitize" | "ignore";
/**
* Embedded OpenClaw execution contract:
* - default: keep the standard runner behavior
* - strict-agentic: enable structured plan tracking and non-visible turn recovery on supported GPT-5 runs
*/
executionContract?: EmbeddedAgentExecutionContract;
};
/** Default thinking level when no /think directive is present. */
thinkingDefault?: AgentThinkingLevel;
/** Default fast-mode policy inherited by agent entries that omit it. */
fastModeDefault?: FastMode;
/** Default verbose level when no /verbose directive is present. */
verboseDefault?: "off" | "on" | "full";
/**
* Detail mode for user-visible tool progress in /verbose and editable progress drafts.
* - explain: compact human summary (default)
* - raw: include raw command/detail when available
*/
toolProgressDetail?: "explain" | "raw";
/** Default reasoning level when no /reasoning directive is present. */
reasoningDefault?: "off" | "on" | "stream";
/** Default elevated level when no /elevated directive is present. */
elevatedDefault?: "off" | "on" | "ask" | "full";
/** Default block streaming level when no override is present. */
blockStreamingDefault?: "off" | "on";
/**
* Block streaming boundary:
* - "text_end": end of each assistant text content block (before tool calls)
* - "message_end": end of the whole assistant message (may include tool blocks)
*/
blockStreamingBreak?: "text_end" | "message_end";
/** Soft block chunking for streamed replies (min/max chars, prefer paragraph/newline). */
blockStreamingChunk?: BlockStreamingChunkConfig;
/**
* Block reply coalescing (merge streamed chunks before send).
* idleMs: wait time before flushing when idle.
*/
blockStreamingCoalesce?: BlockStreamingCoalesceConfig;
/** Human-like delay between block replies. */
humanDelay?: HumanDelayConfig;
timeoutSeconds?: number;
/** Max inbound media size in MB for agent-visible attachments (text note or future image attach). */
mediaMaxMb?: number;
/**
* Max image side length (pixels) when sanitizing base64 image payloads in transcripts/tool results.
* Default: 1200.
*/
imageMaxDimensionPx?: number;
/**
* Image compression/detail preference for image-tool media loading.
* Default: auto, which adapts to provider/model limits and image count.
*/
imageQuality?: AgentImageQualityPreference;
typingIntervalSeconds?: number;
/** Typing indicator start mode (never|instant|thinking|message). */
typingMode?: TypingMode;
/** Periodic background heartbeat runs. */
heartbeat?: {
/** Agent that owns ambient heartbeat runs when no per-agent heartbeat is configured. */
agentId?: string;
/** Heartbeat interval (duration string, default unit: minutes; default: 30m). */
every?: string;
/** Optional active-hours window (local time); heartbeats run only inside this window. */
activeHours?: {
/** Start time (24h, HH:MM). Inclusive. */
start?: string;
/** End time (24h, HH:MM). Exclusive. Use "24:00" for end-of-day. */
end?: string;
/** Timezone for the window ("user", "local", or IANA TZ id). Default: "user". */
timezone?: string;
};
/** Heartbeat model override (provider/model). */
model?: string;
/** Session key for heartbeat runs ("main" or explicit session key). */
session?: string;
/** Delivery target. Default "owner" uses explicit ownerAllowFrom/allowFrom; "last" may follow groups. */
target?: string;
/** Direct/DM delivery policy. Default: "allow". */
directPolicy?: "allow" | "block";
/** Explicit channel destination; ignored for target "owner" or an unset target. */
to?: string;
/** Optional account id for multi-account channels. */
accountId?: string;
/** Override the heartbeat prompt body. The default treats scratch as monitor prose and directs recurring work to cron jobs. */
prompt?: string;
/** Run timeout in seconds for heartbeat agent turns. Unset uses global timeout or heartbeat cadence capped at 600 seconds. */
timeoutSeconds?: number;
/**
* If true, run heartbeat turns with lightweight bootstrap context.
* Lightweight mode skips workspace bootstrap files; monitor scratch is
* injected by the heartbeat runner either way.
*/
lightContext?: boolean;
/**
* If true, run heartbeat turns in an isolated session with no prior
* conversation history. Dramatically reduces per-heartbeat token cost by
* avoiding the full session transcript.
*/
isolatedSession?: boolean;
};
/** Owner for ambient system-agent/Custodian inference and unscoped operator-read fallbacks. */
systemAgent?: {
agentId?: string;
};
/** Upgrade-only owner for the inherited credential store until H2-2 relocates credentials. */
authInheritance?: {
agentId?: string;
};
/** Upgrade-only owner for retired main-agent rows and legacy fixed session stores. */
sessionStore?: {
agentId?: string;
};
/** Max concurrent agent runs across all conversations. Default: min(16, max(8, available CPU parallelism)). */
maxConcurrent?: number;
/** Sub-agent defaults (spawned via sessions_spawn). */
subagents?: {
/** Prompt-only guidance for how strongly the main agent should delegate work. Default: "suggest". */
delegationMode?: SubagentDelegationMode;
/** Default allowlist of target agent ids for sessions_spawn. Use "*" to allow any configured target. */
allowAgents?: string[];
/** Max concurrent sub-agent runs (global lane: "subagent"). Default: 8. */
maxConcurrent?: number;
/** Maximum depth allowed for sessions_spawn chains. Default behavior: 1 (no nested spawns). */
maxSpawnDepth?: number;
/** Maximum active children a single requester session may spawn. Default behavior: 5. */
maxChildrenPerAgent?: number;
/** Auto-archive sub-agent sessions after N minutes (default: 60, set 0 to disable). */
archiveAfterMinutes?: number;
/** Default model selection for spawned sub-agents (string or {primary,fallbacks}). */
model?: AgentModelConfig;
/** Default thinking level for spawned sub-agents (e.g. "off", "low", "medium", "high"). */
thinking?: string;
/** Default run timeout in seconds for spawned sub-agents (0 = no timeout). */
runTimeoutSeconds?: number;
/** Gateway timeout in ms for sub-agent announce delivery calls (default: 120000). */
announceTimeoutMs?: number;
/** Require explicit agentId in sessions_spawn (no default same-as-caller). Default: false. */
requireAgentId?: boolean;
};
/** Optional sandbox settings for non-main sessions. */
sandbox?: AgentSandboxConfig;
};
type AgentCompactionMode = "default" | "safeguard";
type AgentCompactionPostIndexSyncMode = "off" | "async" | "await";
type AgentCompactionIdentifierPolicy = "strict" | "off";
type AgentCompactionQualityGuardConfig = {
/** Enable compaction summary quality audits and regeneration retries. Default: false. */
enabled?: boolean;
/** Maximum regeneration retries after a failed quality audit. Default: 1 when enabled. */
maxRetries?: number;
};
type AgentCompactionMidTurnPrecheckConfig = {
/**
* Enable structured context pressure checks after tool results are appended
* and before the next agent model call. Default: false.
*/
enabled?: boolean;
};
type AgentCompactionConfig = {
/** Enable embedded proactive auto-compaction. Default: true. */
enabled?: boolean;
/** Compaction summarization mode. */
mode?: AgentCompactionMode;
/** Thinking level for embedded OpenClaw compaction summaries. Default: low. */
thinkingLevel?: AgentThinkingLevel | "inherit";
/** Embedded OpenClaw keepRecentTokens budget used for cut-point selection. */
keepRecentTokens?: number;
/** Preserve this many most-recent user/assistant turns verbatim in compaction summary context. */
recentTurnsPreserve?: number;
/** Identifier-preservation instruction policy for compaction summaries. */
identifierPolicy?: AgentCompactionIdentifierPolicy;
/** Optional quality-audit retries for safeguard compaction summaries. */
qualityGuard?: AgentCompactionQualityGuardConfig;
/** Mid-turn precheck for tool-loop context pressure. Default: disabled. */
midTurnPrecheck?: AgentCompactionMidTurnPrecheckConfig;
/** Post-compaction session memory index sync mode. */
postIndexSync?: AgentCompactionPostIndexSyncMode;
/** Pre-compaction memory flush (agentic turn). Default: enabled. */
memoryFlush?: AgentCompactionMemoryFlushConfig;
/** H2/H3 section names from AGENTS.md to inject after compaction. */
postCompactionSections?: string[];
/** Optional provider/model or configured bare alias for compaction summarization.
* When set, compaction uses this model instead of the agent's primary model.
* Falls back to the primary model when unset. */
model?: string;
/** Safety window in seconds for each built-in compaction model request (default: 180). */
timeoutSeconds?: number;
/**
* Id of a registered compaction provider plugin.
* When set, the provider's summarize() is called instead of
* the built-in summarizeInStages(). Falls back to built-in on failure.
*/
provider?: string;
/**
* Byte threshold for normal preflight local compaction (bytes, or a byte-size
* string like "20mb"). Set to 0 or leave unset to disable. Also caps Codex
* app-server native rollouts; oversized native threads restart fresh.
*/
maxActiveTranscriptBytes?: number | string;
/**
* Send brief context-maintenance notices to the user: when compaction starts
* and completes, and when a pre-compaction memory flush is exhausted so the
* reply continues in a degraded state.
* Default: false (silent by default).
*/
notifyUser?: boolean;
};
type AgentCompactionMemoryFlushConfig = {
/** Enable the pre-compaction memory flush (default: true). */
enabled?: boolean;
/** Optional provider/model override used only for pre-compaction memory flush turns. */
model?: string;
/** Run the memory flush when context is within this many tokens of the compaction threshold. */
softThresholdTokens?: number;
/**
* Force a memory flush when transcript size reaches this threshold
* (bytes, or byte-size string like "2mb"). Set to 0 to disable.
*/
forceFlushTranscriptBytes?: number | string;
};
//#endregion
//#region packages/memory-host-sdk/src/host/types.d.ts
type MemorySource = "memory" | "sessions";
type MemoryOriginClass = "owner" | "agent" | "untrusted" | "system";
type MemorySessionKind = "interactive" | "cron" | "heartbeat" | "subagent" | "unknown";
/** Additional memory root, optionally narrowed by a root-relative glob. */
type MemoryExtraPath = string | {
path: string;
pattern?: string;
};
type MemoryEntryProvenance = {
originClass: MemoryOriginClass;
sessionKind: MemorySessionKind;
observedAt: number;
supersedesKey?: string;
};
/** One ranked memory search hit with optional vector/text scoring details. */
type MemorySearchResult = {
path: string;
startLine: number;
endLine: number;
score: number;
vectorScore?: number;
textScore?: number;
snippet: string;
source: MemorySource;
importance?: number;
triggers?: string;
/** Semicolon-separated stable repository identities lifted from inline annotations. */
projectKey?: string;
/** @deprecated Use provenance.originClass. This field is not authoritative for automatic injection. */
originClass?: string;
citation?: string;
provenance?: MemoryEntryProvenance;
};
/** Cached/probed embedding availability status. */
type MemoryEmbeddingProbeResult = {
ok: boolean;
error?: string;
checked?: boolean;
cached?: boolean;
checkedAtMs?: number;
cacheExpiresAtMs?: number;
};
/** Progress event emitted during memory sync. */
type MemorySyncProgressUpdate = {
completed: number;
total: number;
label?: string;
};
type MemorySessionSyncTarget = {
/** Owning OpenClaw agent. Omit only when the active manager scope already supplies it. */
agentId?: string;
/** Storage-neutral transcript/session identity. */
sessionId: string;
/** Optional visible session-store key for callers that already carry it. */
sessionKey?: string;
};
type MemorySyncParams = {
reason?: string;
force?: boolean;
/** Storage-neutral session transcript targets to refresh. */
sessions?: MemorySessionSyncTarget[];
/** Archive/support transcript files to refresh without treating paths as active session identity. */
archiveFiles?: string[];
progress?: (update: MemorySyncProgressUpdate) => void;
};
type MemorySearchRuntimeDebug = {
backend: "builtin";
configuredMode?: string;
effectiveMode?: string;
fallback?: string;
embeddingBootstrap?: {
ok: false;
provider: string;
reason: string;
degradedTo: "keyword-only";
};
};
/** Successful memory-file excerpt, optionally paginated/truncated. */
type MemoryReadSuccessResult = {
status: "ok";
text: string;
path: string;
truncated?: boolean;
from?: number;
lines?: number;
nextFrom?: number;
};
/** An allowed memory path that does not exist. */
type MemoryReadNotFoundResult = {
status: "not_found";
text: "";
path: string;
truncated?: never;
from?: never;
lines?: never;
nextFrom?: never;
};
type MemoryReadResult = MemoryReadSuccessResult | MemoryReadNotFoundResult;
/** Pre-status result accepted only from registered memory managers during migration. */
type LegacyMemoryReadResult = {
status?: never;
text: string;
path: string;
truncated?: boolean;
from?: number;
lines?: number;
nextFrom?: number;
};
/** Aggregated memory backend status for CLI/UI diagnostics. */
type MemoryVectorIndexState = {
state: "empty";
} | {
state: "complete";
} | {
state: "incomplete";
} | {
state: "unverified";
};
type MemoryProviderStatus = {
backend: "builtin";
provider: string;
model?: string;
requestedProvider?: string;
files?: number;
chunks?: number;
dirty?: boolean;
/** Process-local failure from the newest admitted sync without a newer successful sync. */
lastSyncError?: string;
workspaceDir?: string;
dbPath?: string;
/** Explicit diagnostics for the whole shared agent database; payload sizes are not additive. */
storage?: {
databaseBytes: number;
walBytes: number;
reusableBytes: number;
embeddingCacheBytes: number;
embeddingCacheEntries: number;
};
extraPaths?: MemoryExtraPath[];
sources?: MemorySource[];
sourceCounts?: Array<{
source: MemorySource;
files: number;
chunks: number;
/** Stored chunk text and JSON embedding bytes, excluding cache and index overhead. */
chunkBytes?: number;
eligible?: number | null;
issues?: string[];
}>;
cache?: {
enabled: boolean;
entries?: number;
maxEntries?: number;
};
fts?: {
enabled: boolean;
available: boolean;
error?: string;
};
fallback?: {
from: string;
reason?: string;
};
vector?: {
enabled: boolean;
index?: MemoryVectorIndexState;
storeAvailable?: boolean;
semanticAvailable?: boolean;
available?: boolean;
extensionPath?: string;
loadError?: string;
dims?: number;
};
batch?: {
enabled: boolean;
failures: number;
limit: number;
wait: boolean;
concurrency: number;
pollIntervalMs: number;
timeoutMs: number;
lastError?: string;
lastProvider?: string;
};
custom?: Record<string, unknown>;
};
/** Search/read/sync/status contract implemented by memory managers. */
interface MemorySearchManager {
search(query: string, opts?: {
maxResults?: number;
minScore?: number;
sessionKey?: string;
/**
* Keyword/FTS scoring only: skip query embedding and vector search.
* For reply-path recall (trigger injection) that must not add a
* network round-trip per inbound message.
*/
lexicalOnly?: boolean;
/** Active repository identities used only for project-aware ranking. */
activeProjectKeys?: string[];
onDebug?: (debug: MemorySearchRuntimeDebug) => void;
sources?: MemorySource[];
/** Optional caller cancellation; managers consume it where their runtime supports cancellation. */
signal?: AbortSignal;
}): Promise<MemorySearchResult[]>;
listTriggerCandidates?(opts?: {
limit?: number;
activeProjectKeys?: string[];
}): Promise<MemorySearchResult[]>;
listCuratedProjectCandidates?(opts: {
activeProjectKeys: string[];
limit?: number;
}): Promise<MemorySearchResult[]>;
readFile(params: {
relPath: string;
from?: number;
lines?: number;
}): Promise<MemoryReadResult>;
status(): MemoryProviderStatus;
sync?(params?: MemorySyncParams): Promise<void>;
getCachedEmbeddingAvailability?(): MemoryEmbeddingProbeResult | null;
probeEmbeddingAvailability(): Promise<MemoryEmbeddingProbeResult>;
probeVectorStoreAvailability?(): Promise<boolean>;
probeVectorAvailability(): Promise<boolean>;
close?(): Promise<void>;
}
//#endregion
//#region src/config/types.memory.d.ts
/** Citation rendering mode for memory-injected context. */
type MemoryCitationsMode = "auto" | "on" | "off";
/** Top-level memory config block. */
type MemoryConfig = {
citations?: MemoryCitationsMode;
/** Shared embedding/search defaults. Per-agent overrides live under agents.entries.*.memory.search. */
search?: MemorySearchConfig;
};
type MemorySearchConfig = {
/** Enable vector memory search (default: true). */
enabled?: boolean;
/** Use relevant context from this agent's other private conversations. */
rememberAcrossConversations?: boolean;
/** Sources to index and search (default: ["memory"]). */
sources?: Array<"memory" | "sessions">;
/** Extra paths to include in memory search, optionally filtered by a glob. */
extraPaths?: MemoryExtraPath[];
/** Optional multimodal file indexing for selected extra paths. */
multimodal?: {
/** Enable image/audio embeddings from extraPaths. */
enabled?: boolean;
/** Which non-text file types to index. */
modalities?: Array<"image" | "audio" | "all">;
/** Max bytes allowed per multimodal file before it is skipped. */
maxFileBytes?: number;
};
/** Experimental session transcript indexing. */
experimental?: {
sessionMemory?: boolean;
};
/** Memory embedding provider adapter id. */
provider?: string;
remote?: {
baseUrl?: string;
apiKey?: SecretInput;
headers?: Record<string, string>;
batch?: {
/** Enable batch API for embedding indexing (OpenAI/Gemini; default: true). */
enabled?: boolean;
};
};
/** Fallback memory embedding provider adapter id when embeddings fail. */
fallback?: string;
/** Embedding model id (remote) or alias (local). */
model?: string;
/** Optional provider-specific embedding input_type for query and document requests. */
inputType?: string;
/** Optional provider-specific embedding input_type for query-time memory search. */
queryInputType?: string;
/** Optional provider-specific embedding input_type for document/index embeddings. */
documentInputType?: string;
/**
* Provider-specific output vector dimensions. Gemini supports 128 to 3072.
* Google recommends 768, 1536, or 3072 dimensions.
*/
outputDimensionality?: number;
/** Local embedding settings for the managed llama.cpp server. */
local?: {
/** GGUF model path or hf: URI. */
modelPath?: string;
};
/** Index storage configuration. */
store?: {
fts?: {
/** FTS5 tokenizer (default: "unicode61"). Use "trigram" for CJK text support. */
tokenizer?: "unicode61" | "trigram";
};
vector?: {
/** Enable the sqlite-vec semantic index (default: true). */
enabled?: boolean;
/** Optional override path to sqlite-vec extension (.dylib/.so/.dll). */
extensionPath?: string;
};
cache?: {
/** Enable embedding cache (default: true). */
enabled?: boolean;
/** Optional max cache entries per provider/model. */
maxEntries?: number;
};
};
/** Query behavior. */
query?: {
maxResults?: number;
minScore?: number;
};
/** Index cache behavior. */
cache?: {
/** Cache chunk embeddings in SQLite (default: true). */
enabled?: boolean;
};
};
//#endregion
//#region packages/gateway-protocol/src/schema/logs-chat.d.ts
declare const QUEUE_MODES: readonly ["steer", "followup", "collect", "interrupt"];
type QueueMode = (typeof QUEUE_MODES)[number];
//#endregion
//#region src/config/types.queue.d.ts
/** Queue overflow policy for inbound channel messages. */
type QueueDropPolicy = "old" | "new" | "summarize";
type QueueModeByProvider = {
whatsapp?: QueueMode;
telegram?: QueueMode;
discord?: QueueMode;
irc?: QueueMode;
googlechat?: QueueMode;
slack?: QueueMode;
mattermost?: QueueMode;
signal?: QueueMode;
imessage?: QueueMode;
msteams?: QueueMode;
webchat?: QueueMode;
matrix?: QueueMode;
};
//#endregion
//#region src/config/types.messages.d.ts
type MentionPatternsMode = "allow" | "deny";
type MentionPatternsPolicyConfig = {
mode?: MentionPatternsMode;
allowIn?: string[];
denyIn?: string[];
};
type GroupChatConfig = {
mentionPatterns?: string[];
historyLimit?: number;
/**
* Controls how unmentioned always-on group chatter is submitted.
* Default: "user_request".
*/
unmentionedInbound?: "user_request" | "room_event";
/**
* Controls how group/channel inbound events produce model-authored room replies.
* The message-tool mode requires explicit message sends for normal assistant
* output; explicitly host-owned runtime output remains deliverable except for
* ambient room events.
* Default: "automatic".
*/
visibleReplies?: "automatic" | "message_tool";
};
type DmConfig = {
historyLimit?: number;
};
type QueueConfig = {
mode?: QueueMode;
byChannel?: QueueModeByProvider;
/** Per-channel debounce overrides (ms). */
debounceMsByChannel?: InboundDebounceByProvider;
cap?: number;
drop?: QueueDropPolicy;
};
type InboundDebounceByProvider = Record<string, number>;
type InboundDebounceConfig = {
debounceMs?: number;
byChannel?: InboundDebounceByProvider;
};
type BroadcastStrategy = "parallel" | "sequential";
type BroadcastConfig = {
/** Default processing strategy for broadcast peers. */
strategy?: BroadcastStrategy;
/**
* Map peer IDs to arrays of agent IDs that should ALL process messages.
*
* Note: the index signature includes `undefined` so `strategy?: ...` remains type-safe.
*/
[peerId: string]: string[] | BroadcastStrategy | undefined;
};
type StatusReactionsConfig = {
/** Enable lifecycle status reactions (default: false). */
enabled?: boolean;
};
type MessagesConfig = {
/** @deprecated Doctor-only legacy input. */
removeAckAfterReply?: boolean;
/**
* Controls how source inbound events produce visible replies across direct,
* group, and channel conversations. Group/channel events still default to
* `groupChat.visibleReplies` when it is set.
*
* Default: "automatic". In group/channel rooms, "message_tool" keeps normal
* assistant output private unless the model sends visibly through the message
* tool; explicitly host-owned runtime output remains deliverable.
*/
visibleReplies?: "automatic" | "message_tool";
/**
* Prefix auto-added to all outbound replies.
*
* - string: explicit prefix (may include template variables)
* - special value: `"auto"` derives `[{agents.entries.*.identity.name}]` for the routed agent (when set)
*
* Supported template variables (case-insensitive):
* - `{model}` - short model name (e.g., `claude-opus-4-6`, `gpt-4o`)
* - `{modelFull}` - full model identifier (e.g., `anthropic/claude-opus-4-6`)
* - `{provider}` - provider name (e.g., `anthropic`, `openai`)
* - `{thinkingLevel}` or `{think}` - current thinking level (`high`, `low`, `off`)
* - `{identity.name}` or `{identityName}` - agent identity name
*
* Example: `"[{model} | think:{thinkingLevel}]"` → `"[claude-opus-4-6 | think:high]"`
*
* Unresolved variables remain as literal text (e.g., `{model}` if context unavailable).
*
* Default: none
*/
responsePrefix?: string;
/** Custom `/usage full` footer template, inline or JSON file path. */
usageTemplate?: string | Record<string, unknown>;
/**
* Default per-reply usage footer mode (`responseUsage`) seeded into any session
* that has not set its own via `/usage`. Precedence: session value → channel entry
* → `default` → `off`. Absent ⇒ `off` (unchanged behavior).
*
* - string: one default for every channel, e.g. `"full"`.
* - object: per-channel with a fallback, e.g. `{ "default": "off", "discord": "full" }`.
*/
responseUsage?: "on" | "off" | "tokens" | "full" | {
default?: "on" | "off" | "tokens" | "full";
[channel: string]: "on" | "off" | "tokens" | "full" | undefined;
};
groupChat?: GroupChatConfig;
queue?: QueueConfig;
/** Debounce rapid inbound messages per sender (global + per-channel overrides). */
inbound?: InboundDebounceConfig;
/** Emoji reaction used to acknowledge inbound messages (empty disables). */
ackReaction?: string;
/** When to send ack reactions. Default: "group-mentions". */
ackReactionScope?: "group-mentions" | "group-all" | "direct" | "all" | "off" | "none";
/** Lifecycle status reactions configuration. */
statusReactions?: StatusReactionsConfig;
};
type NativeCommandsSetting = boolean | "auto";
/**
* Per-provider allowlist for command authorization.
* Keys are channel IDs (e.g., "discord", "whatsapp") or "*" for global default.
* Values are arrays of sender IDs allowed to use commands on that channel.
*/
type CommandAllowFrom = Record<string, Array<string | number>>;
type CommandsConfig = {
/** @deprecated Doctor-only legacy input. */
ownerDisplay?: "raw" | "hash";
/** @deprecated Doctor-only legacy input. */
ownerDisplaySecret?: string;
/** Enable native command registration when supported (default: "auto"). */
native?: NativeCommandsSetting;
/** Enable native skill command registration when supported (default: "auto"). */
nativeSkills?: NativeCommandsSetting;
/** Enable text command parsing (default: true). */
text?: boolean;
/** Allow bash chat command (`!`; `/bash` alias) (default: false). */
bash?: boolean;
/** How long bash waits before backgrounding (default: 2000; 0 backgrounds immediately). */
bashForegroundMs?: number;
/** Allow /config command (default: false). */
config?: boolean;
/** Allow /mcp command for OpenClaw-managed MCP settings (default: false). */
mcp?: boolean;
/** Allow /plugins command for plugin listing and enablement toggles (default: false). */
plugins?: boolean;
/** Allow /debug command (default: false). */
debug?: boolean;
/** Allow restart commands/tools and /update (default: true). */
restart?: boolean;
/** Explicit owner allowlist for owner-scoped commands (channel-native IDs). */
ownerAllowFrom?: Array<string | number>;
/** How owner IDs are rendered in system prompts. */
/**
* Per-provider allowlist restricting who can use slash commands.
* If set, overrides the channel's allowFrom for command authorization.
* Use "*" key for global default, provider-specific keys override the global.
* Example: { "*": ["user1"], discord: ["user:123"] }
*/
allowFrom?: CommandAllowFrom;
};
type ProviderCommandsConfig = {
/** Override native command registration for this provider (bool or "auto"). */
native?: NativeCommandsSetting;
/** Override native skill command registration for this provider (bool or "auto"). */
nativeSkills?: NativeCommandsSetting;
};
//#endregion
//#region src/config/types.skills.d.ts
/** Per-skill runtime override keyed by skill name or source-specific skill key. */
type SkillConfig = {
/** Disable a discovered skill without removing it from disk. */
enabled?: boolean;
/** Optional secret made available to the skill runtime through skill env handling. */
apiKey?: SecretInput;
/** Plain environment overrides applied when the skill runs. */
env?: Record<string, string>;
/** Skill-specific structured config consumed by the skill runtime. */
config?: Record<string, unknown>;
};
/** Discovery and watcher settings for skill sources. */
type SkillsLoadConfig = {
/**
* Additional skill folders to scan (lowest precedence).
* Each directory should contain skill subfolders with `SKILL.md`.
*/
extraDirs?: string[];
/**
* Real target directories that skill symlinks may resolve into even when they
* sit outside the configured source root.
*/
allowSymlinkTargets?: string[];
/** Watch skill folders for changes and refresh the skills snapshot. */
watch?: boolean;
};
/** Skill installation preferences and upload policy. */
type SkillsInstallConfig = {
preferBrew?: boolean;
nodeManager?: "npm" | "pnpm" | "yarn" | "bun";
/** Allow gateway clients to install zip archives staged through skills.upload.*. */
allowUploadedArchives?: boolean;
};
/** Limits that bound skill discovery and model-facing prompt expansion. */
type SkillsLimitsConfig = {
/** Max number of immediate child directories to consider under a skills root before treating it as suspicious. */
maxCandidatesPerRoot?: number;
/** Max number of skills to load per skills source (bundled/managed/workspace/extra). */
maxSkillsLoadedPerSource?: number;
/** Max number of skills to include in the model-facing skills prompt. */
maxSkillsInPrompt?: number;
/** Max characters for the model-facing skills prompt block (approx). */
maxSkillsPromptChars?: number;
/** Max size (bytes) allowed for a SKILL.md file to be considered. */
maxSkillFileBytes?: number;
};
type SkillsWorkshopAutonomousMode = "off" | "propose" | "auto";
/** Autonomous and approval settings for generated skill proposals. */
type SkillsWorkshopConfig = {
/** Autonomous Skill Workshop behavior controlled separately from user-prompted proposals. */
autonomous?: {
/** Capture policy for durable conversation signals and substantial completed work. */
mode?: SkillsWorkshopAutonomousMode;
};
/** Allow Skill Workshop apply to write through trusted skill symlink targets. */
allowSymlinkTargetWrites?: boolean;
/** Whether proposal lifecycle actions need explicit approval. */
approvalPolicy?: "pending" | "auto";
/** Maximum pending/quarantined proposals retained per workspace. */
maxPending?: number;
/** Maximum generated skill proposal size in bytes. */
maxSkillBytes?: number;
};
/** Top-level skills config block in openclaw config. */
type SkillsConfig = {
/** Optional bundled-skill allowlist (only affects bundled skills). */
allowBundled?: string[];
load?: SkillsLoadConfig;
install?: SkillsInstallConfig;
limits?: SkillsLimitsConfig;
workshop?: SkillsWorkshopConfig;
entries?: Record<string, SkillConfig>;
};
//#endregion
//#region src/infra/exec-safe-bin-policy-profiles.d.ts
type SafeBinProfileFixture = {
minPositional?: number;
maxPositional?: number;
allowedValueFlags?: readonly string[];
deniedFlags?: readonly string[];
};
//#endregion
//#region src/config/types.provider-request.d.ts
/** Authentication override applied to provider requests after model/provider defaults resolve. */
type ConfiguredProviderRequestAuth = {
mode: "provider-default";
} | {
mode: "authorization-bearer";
token: SecretInput;
} | {
mode: "header";
headerName: string;
value: SecretInput;
prefix?: string;
};
/** TLS material and verification knobs for provider or proxy connections. */
type ConfiguredProviderRequestTls = {
ca?: SecretInput;
cert?: SecretInput;
key?: SecretInput;
passphrase?: SecretInput;
serverName?: string;
insecureSkipVerify?: boolean;
};
/** Proxy selection for provider requests, including optional TLS settings for proxy transport. */
type ConfiguredProviderRequestProxy = {
mode: "env-proxy";
tls?: ConfiguredProviderRequestTls;
} | {
mode: "explicit-proxy";
url: string;
tls?: ConfiguredProviderRequestTls;
};
/** Shared provider request overrides used by model providers and media/tool providers. */
type ConfiguredProviderRequest = {
headers?: Record<string, SecretInput>;
auth?: ConfiguredProviderRequestAuth;
proxy?: ConfiguredProviderRequestProxy;
tls?: ConfiguredProviderRequestTls;
};
/** Model-provider request overrides plus the private-network opt-in used by model transports. */
type ConfiguredModelProviderRequest = ConfiguredProviderRequest & {
allowPrivateNetwork?: boolean;
};
//#endregion
//#region src/config/types.ssrf.d.ts
type SsrFPolicyConfig = {
/** Permit private/internal network targets. Default: false. */
dangerouslyAllowPrivateNetwork?: boolean;
/** Allow RFC 2544 benchmark-range IPs (198.18.0.0/15). */
allowRfc2544BenchmarkRange?: boolean;
/** Allow IPv6 Unique Local Addresses (fc00::/7). */
allowIpv6UniqueLocalRange?: boolean;
/** Explicitly allowed exact hostnames or IP literals. */
allowedHostnames?: string[];
/** Deny exact hosts or wildcard subdomains; "*.example.com" excludes the apex. Overrides allows. */
blockedHostnames?: string[];
};
//#endregion
//#region src/config/types.tools.d.ts
type MediaUnderstandingScopeMatch = {
/** Channel/provider id to match before running media or link understanding. */
channel?: string;
/** Direct/group classification from the channel runtime, when available. */
chatType?: ChatType;
/** Attachment or link key prefix used for narrow per-source routing. */
keyPrefix?: string;
};
type MediaUnderstandingScopeRule = {
/** Policy applied when match criteria select this scope rule. */
action: SessionSendPolicyAction;
/** Optional match filter; omitted match behaves as a catch-all rule. */
match?: MediaUnderstandingScopeMatch;
};
type MediaUnderstandingScopeConfig = {
/** Fallback action when no scope rule matches. */
default?: SessionSendPolicyAction;
/** Ordered allow/block rules; first matching rule wins. */
rules?: MediaUnderstandingScopeRule[];
};
type MediaUnderstandingCapability$1 = "image" | "audio" | "video";
type MediaUnderstandingAttachmentsConfig = {
/** Select the first matching attachment or process multiple. */
mode?: "first" | "all";
/** Max number of attachments to process (default: 1). */
maxAttachments?: number;
/** Attachment ordering preference. */
prefer?: "first" | "last" | "path" | "url";
};
type MediaProviderRequestConfig = {
/** Optional provider-specific query params (merged into requests). */
providerOptions?: Record<string, Record<string, string | number | boolean>>;
/** Optional base URL override for provider requests. */
baseUrl?: string;
/** Optional headers merged into provider requests. */
headers?: Record<string, string>;
/** Optional request transport overrides for provider HTTP calls. */
request?: ConfiguredProviderRequest;
};
type MediaUnderstandingModelConfig = MediaProviderRequestConfig & {
/** provider API id (e.g. openai, google). */
provider?: string;
/** Model id for provider-based understanding. */
model?: string;
/** Optional capability tags for shared model lists. */
capabilities?: MediaUnderstandingCapability$1[];
/** Use a CLI command instead of provider API. */
type?: "provider" | "cli";
/** CLI binary (required when type=cli). */
command?: string;
/** CLI args (template-enabled). */
args?: string[];
/** Optional prompt override for this model entry. */
prompt?: string;
/** Optional max output characters for this model entry. */
maxChars?: number;
/** Optional max bytes for this model entry. */
maxBytes?: number;
/** Optional timeout override (seconds) for this model entry. */
timeoutSeconds?: number;
/** Optional language hint for audio transcription. */
language?: string;
/** Auth profile id to use for this provider. */
profile?: string;
/** Preferred profile id if multiple are available. */
preferredProfile?: string;
};
type MediaUnderstandingConfig = MediaProviderRequestConfig & {
/** Enable media understanding when models are configured. */
enabled?: boolean;
/** Prefer a matching shared model entry. */
preferredModel?: string;
/** Optional scope gating for understanding. */
scope?: MediaUnderstandingScopeConfig;
/** Default max bytes to send. */
maxBytes?: number;
/** Default max output characters. */
maxChars?: number;
/** Default prompt. */
prompt?: string;
/** Internal request-scoped prompt override injected by CLI/runtime wrappers. */
_requestPromptOverride?: string;
/** Default timeout (seconds). */
timeoutSeconds?: number;
/** Default language hint (audio). */
language?: string;
/** Internal request-scoped language override injected by CLI/runtime wrappers. */
_requestLanguageOverride?: string;
/** Attachment selection policy. */
attachments?: MediaUnderstandingAttachmentsConfig;
/** Ordered model list (fallbacks in order). */
models?: MediaUnderstandingModelConfig[];
/**
* Echo the audio transcript back to the originating chat before agent processing.
* Lets users verify what was heard. Default: false.
*/
echoTranscript?: boolean;
/**
* Format string for the echoed transcript. Use `{transcript}` as placeholder.
* Default: '📝 "{transcript}"'
*/
echoFormat?: string;
};
/** Per-capability defaults and policy. Models live only in tools.media.models. */
type MediaUnderstandingCapabilityConfig = Omit<MediaUnderstandingConfig, "models">;
type LinkModelConfig = {
/** Use a CLI command for link processing. */
type?: "cli";
/** CLI binary (required when type=cli). */
command: string;
/** CLI args (template-enabled). */
args?: string[];
/** Optional timeout override (seconds) for this model entry. */
timeoutSeconds?: number;
};
type LinkToolsConfig = {
/** Enable link understanding when models are configured. */
enabled?: boolean;
/** Optional scope gating for understanding. */
scope?: MediaUnderstandingScopeConfig;
/** Max number of links to process per message. */
maxLinks?: number;
/** Default timeout (seconds). */
timeoutSeconds?: number;
/** Ordered model list (fallbacks in order). */
models?: LinkModelConfig[];
};
type MediaToolsConfig = {
/** Canonical model list for image/audio/video, selected by capability tags. */
models?: MediaUnderstandingModelConfig[];
/** Max concurrent media understanding runs. */
concurrency?: number;
image?: MediaUnderstandingCapabilityConfig;
audio?: MediaUnderstandingCapabilityConfig;
video?: MediaUnderstandingCapabilityConfig;
};
type ToolProfileId = "minimal" | "coding" | "messaging" | "full";
type ToolLoopDetectionConfig = {
/** Enable tool-loop protection (default: false). */
enabled?: boolean;
};
type ToolSearchConfig = boolean | {
/** Enable compact search/call cataloging for large tool sets. */
enabled?: boolean;
/** Exposed model surface. "code" exposes tool_search_code; "tools" exposes structured fallback tools; "directory" keeps a bounded directory plus selected schemas visible while deferring the rest behind search/describe/call. */
mode?: "code" | "tools" | "directory";
/** Timeout in milliseconds for one tool_search_code execution. Runtime clamps to 1s..60s. */
codeTimeoutMs?: number;
/** Default search result count when the model omits a limit. Runtime clamps to maxSearchLimit. */
searchDefaultLimit?: number;
/** Maximum search result count. Runtime clamps to 1..50. */
maxSearchLimit?: number;
};
type CodeModeConfig = boolean | "auto" | {
/** OpenClaw Code Mode default, overridden by per-model codeMode. Default: false; "auto" engages catalog-preferred models. */
enabled?: boolean | "auto";
/** Guest runtime. Only quickjs-wasi is supported. */
runtime?: "quickjs-wasi";
/** Model-facing mode. Only "only" is supported: expose exec/wait and hide normal tools. */
mode?: "only";
/** Accepted source languages. */
languages?: Array<"javascript" | "typescript">;
/** Wall-clock limit in milliseconds for one exec or wait call. */
timeoutMs?: number;
/** QuickJS heap limit in bytes. */
memoryLimitBytes?: number;
/** Maximum serialized output bytes. */
maxOutputBytes?: number;
/** Maximum serialized snapshot bytes. */
maxSnapshotBytes?: number;
/** Maximum concurrent nested tool calls. */
maxPendingToolCalls?: number;
/** Retention for suspended snapshots. */
snapshotTtlSeconds?: number;
/** Default search result count for catalog.search. */
searchDefaultLimit?: number;
/** Maximum search result count for catalog.search. */
maxSearchLimit?: number;
};
type SwarmConfig = boolean | {
/** Enable collector-mode subagents and agents_wait. Default: true. */
enabled?: boolean;
/** Maximum concurrently running collector children per swarm group. */
maxConcurrent?: number;
/** Maximum live collector children per swarm group. */
maxChildrenPerGroup?: number;
/** Maximum lifetime collector spawns per swarm group. */
maxTotalPerGroup?: number;
/** Maximum agents_wait timeout in seconds. */
waitTimeoutSecondsMax?: number;
/** Default child agent id when sessions_spawn omits agentId. */
defaultAgentId?: string;
};
type SessionsToolsVisibility = "self" | "tree" | "agent" | "all";
type ToolAllowDenyPolicyConfig = {
/** Exact tool names allowed in this policy scope. */
allow?: string[];
/** Additional allowlist entries merged into the inherited policy. */
alsoAllow?: string[];
/** Exact tool names denied after allow expansion; deny wins. */
deny?: string[];
};
type ToolPolicyConfig = ToolAllowDenyPolicyConfig & {
/** Built-in profile used as the base policy before allow/deny merges. */
profile?: ToolProfileId;
};
type GroupToolPolicyConfig = ToolAllowDenyPolicyConfig;
/**
* Per-sender overrides.
*
* Prefer explicit key prefixes:
* - channel:<channelId>:<senderId>
* - id:<senderId>
* - e164:<phone>
* - username:<handle>
* - name:<display-name>
* - * (wildcard)
*
* Legacy unprefixed keys are supported for backward compatibility and are matched as senderId only.
*/
type GroupToolPolicyBySenderConfig = Record<string, GroupToolPolicyConfig>;
type ExecToolConfig = {
/** Exec host routing (default: auto). */
host?: "auto" | "sandbox" | "gateway" | "node";
/** Normalized exec policy mode. Prefer this over raw security/ask knobs. */
mode?: "deny" | "allowlist" | "ask" | "auto" | "full";
/** Legacy exec security mode retained when no canonical mode can preserve policy. */
security?: "deny" | "allowlist" | "full";
/** Legacy exec ask mode retained when no canonical mode can preserve policy. */
ask?: "off" | "on-miss" | "always";
/** Default node binding for exec.host=node (node id/name). */
node?: string;
/** Directories to prepend to PATH when running exec (gateway/sandbox). */
pathPrepend?: string[];
/** Safe stdin-only binaries that can run without allowlist entries. */
safeBins?: string[];
/**
* Require explicit approval for interpreter inline-eval forms (`python -c`, `node -e`, etc.).
* Prevents silent allowlist reuse and allow-always persistence for those forms.
*/
strictInlineEval?: boolean;
/** Render parser-derived command highlights in exec approval prompts (default: false). */
commandHighlighting?: boolean;
/**
* Default lifetime, in days, stamped onto standing grants minted by
* allow-always on automation approvals. Unset means grants live until
* revoked or the owning job changes. Terms freeze at mint; changing this
* affects only future grants.
*/
grantExpiryDays?: number;
/** Extra explicit directories trusted for safeBins path checks (never derived from PATH). */
safeBinTrustedDirs?: string[];
/** Optional custom safe-bin profiles for entries in tools.exec.safeBins. */
safeBinProfiles?: Record<string, SafeBinProfileFixture>;
/** Model-backed reviewer used by tools.exec.mode=auto before falling back to human approval. */
reviewer?: {
/** Optional reviewer model override (provider/model or agent model config). */
model?: AgentModelConfig;
/** Reviewer timeout in milliseconds (default: 30000). */
timeoutMs?: number;
};
/** Default time (ms) before an exec command auto-backgrounds. */
backgroundMs?: number;
/** Default timeout (seconds) before auto-killing exec commands. */
timeoutSeconds?: number;
/** Emit a running notice (ms) when approval-backed exec runs long (default: 10000, 0 = off). */
approvalRunningNoticeMs?: number;
/** How long to keep finished sessions in memory (ms). */
cleanupMs?: number;
/** Emit a system event and heartbeat when a backgrounded exec exits. */
notifyOnExit?: boolean;
/**
* Also emit success exit notifications when a backgrounded exec has no output.
* Default false to reduce context noise.
*/
notifyOnExitEmptySuccess?: boolean;
/** apply_patch subtool configuration. */
applyPatch?: {
/** Enable apply_patch for OpenAI models (default: true; set false to disable). */
enabled?: boolean;
/**
* Restrict apply_patch paths to the workspace directory.
* Default: true (safer; does not affect read/write/edit).
*/
workspaceOnly?: boolean;
/**
* Optional allowlist of model ids that can use apply_patch.
* Accepts either raw ids (e.g. "gpt-5.4") or full ids (e.g. "openai/gpt-5.4").
*/
allowModels?: string[];
};
};
type FsToolsConfig = {
/**
* Restrict filesystem tools (read/write/edit/apply_patch) to the agent workspace directory.
* Default: false (unrestricted, matches legacy behavior).
*/
workspaceOnly?: boolean;
};
type SessionsSpawnToolsConfig = {
attachments?: {
/** Enable inline attachments for sessions_spawn. */
enabled?: boolean;
maxTotalBytes?: number;
maxFiles?: number;
maxFileBytes?: number;
retainOnSessionKeep?: boolean;
};
};
type GitHubToolIdentityConfig = {
/** Opaque generated directory version for atomic credential rotation. */
profileId: string;
/** OAuth generations retain a separate rotating refresh credential. */
kind?: "oauth";
/** Optional process-local author identity for commits made by local tools. */
gitAuthor?: {
name?: string;
email?: string;
};
};
type AgentToolsConfig = {
/** Base tool profile applied before allow/deny lists. */
profile?: ToolProfileId;
allow?: string[];
/** Additional allowlist entries merged into allow and/or profile allowlist. */
alsoAllow?: string[];
deny?: string[];
/** Optional tool policy overrides keyed by provider id or "provider/model". */
byProvider?: Record<string, ToolPolicyConfig>;
/** Per-sender tool policy overrides keyed by sender identity. */
toolsBySender?: GroupToolPolicyBySenderConfig;
/** Per-agent code mode override; merges over the top-level tools.codeMode config. */
codeMode?: CodeModeConfig;
/** Per-agent swarm override; merges over the top-level tools.swarm config. */
swarm?: SwarmConfig;
/** Per-agent elevated exec gate (can only further restrict global tools.elevated). */
elevated?: {
/** Enable or disable elevated mode for this agent (default: true). */
enabled?: boolean;
/** Approved senders for /elevated (per-provider allowlists). */
allowFrom?: AgentElevatedAllowFromConfig;
};
/** Exec tool defaults for this agent. */
exec?: ExecToolConfig;
/** Complete per-agent GitHub CLI identity and Git author override. */
github?: GitHubToolIdentityConfig;
/** Filesystem tool path guards. */
fs?: FsToolsConfig;
/** Runtime loop detection for repetitive/ stuck tool-call patterns. */
loopDetection?: ToolLoopDetectionConfig;
/** Message tool configuration for this agent. */
message?: MessageToolsConfig;
sandbox?: {
tools?: ToolAllowDenyPolicyConfig;
};
};
type ToolsConfig = {
/** Base tool profile applied before allow/deny lists. */
profile?: ToolProfileId;
allow?: string[];
/** Additional allowlist entries merged into allow and/or profile allowlist. */
alsoAllow?: string[];
deny?: string[];
/** Optional tool policy overrides keyed by provider id or "provider/model". */
byProvider?: Record<string, ToolPolicyConfig>;
/** Managed local GitHub CLI identity and Git author; never overrides Git transport. */
github?: GitHubToolIdentityConfig;
/** Per-sender tool policy overrides keyed by sender identity. */
toolsBySender?: GroupToolPolicyBySenderConfig;
web?: {
search?: {
/** Enable managed web_search and optional Codex-native web search. */
enabled?: boolean;
/** Search provider id. */
provider?: string;
/** Default search results count (1-10). */
maxResults?: number;
/** Timeout in seconds for search requests. */
timeoutSeconds?: number;
/** Cache TTL in minutes for search results. */
cacheTtlMinutes?: number;
/** Optional native Codex web search for Codex-capable models. */
openaiCodex?: {
/** Enable native Codex web search for eligible models. */
enabled?: boolean;
/** Prefer cached or explicitly request live access. Unrestricted Codex turns resolve cached to live. */
mode?: "cached" | "live";
/** Native Codex search allowlist; also gates web_fetch on native-hosted-search turns. */
allowedDomains?: string[];
/** Optional Codex native search context size hint. */
contextSize?: "low" | "medium" | "high";
/** Optional approximate user location passed to the native Codex tool. */
userLocation?: {
country?: string;
region?: string;
city?: string;
timezone?: string;
};
};
};
fetch?: {
/** Enable web fetch tool (default: true). */
enabled?: boolean;
/** Web fetch fallback provider id. */
provider?: string;
/** Max characters to return from fetched content. */
maxChars?: number;
/** Hard cap for maxChars (tool or config), defaults to 20000. */
maxCharsCap?: number;
/** Max download size before truncation, defaults to 750000 bytes. */
maxResponseBytes?: number;
/** Timeout in seconds for fetch requests. */
timeoutSeconds?: number;
/** Cache TTL in minutes for fetched content. */
cacheTtlMinutes?: number;
/** Maximum number of redirects to follow (default: 3). */
maxRedirects?: number;
/** Override User-Agent header for fetch requests. */
userAgent?: string;
/**
* Extra request headers sent with direct web_fetch requests. Every value is
* treated as sensitive in exposed config. Entries a request cannot carry are
* dropped with a warning at request time.
*/
headers?: Record<string, string>;
/** Use Readability to extract main content (default: true). */
readability?: boolean;
/** Route web_fetch through a trusted HTTP(S) env proxy and let the proxy resolve DNS. Enable only when that proxy enforces outbound policy. */
useTrustedEnvProxy?: boolean;
/** SSRF policy configuration for web_fetch. */
ssrfPolicy?: SsrFPolicyConfig;
};
};
media?: MediaToolsConfig;
links?: LinkToolsConfig;
/** Message tool configuration. */
message?: MessageToolsConfig;
agentToAgent?: {
/** Default: true. False blocks ordinary cross-agent session tool access; requester-owned native subagent and ACP child sessions remain reachable under tree/all visibility. */
enabled?: boolean;
/**
* Agent ids or `*` glob patterns; the requesting and target agent must both match.
* Omitted or empty counts as unset: every agent pair is allowed by default; blank entries deny.
*/
allow?: string[];
};
/**
* Session tool visibility controls which sessions can be targeted by session tools
* (sessions_list, sessions_history, sessions_search, sessions_send, session_status).
*
* Default: "all" (all sessions on the Gateway, with cross-agent access scoped by agentToAgent).
*/
sessions?: {
/**
* - "self": only the current session
* - "tree": current session + sessions spawned by this session
* - "agent": any session belonging to the current agent id (can include other users)
* - "all": any session (default; cross-agent access is governed by tools.agentToAgent)
*/
visibility?: SessionsToolsVisibility;
};
/** Elevated exec permissions for the host machine. */
elevated?: {
/** Enable or disable elevated mode (default: true). */
enabled?: boolean;
/** Approved senders for /elevated (per-provider allowlists). */
allowFrom?: AgentElevatedAllowFromConfig;
};
/** Exec tool defaults. */
exec?: ExecToolConfig;
/** Filesystem tool path guards. */
fs?: FsToolsConfig;
/** Runtime loop detection for repetitive/ stuck tool-call patterns. */
loopDetection?: ToolLoopDetectionConfig;
/** Compact large OpenClaw, MCP, and client tool catalogs behind search/call tools. */
toolSearch?: ToolSearchConfig;
/** Global Code Mode defaults and limits; agent/model settings can override activation. */
codeMode?: CodeModeConfig;
/** Collector-mode subagents and wait controls. */
swarm?: SwarmConfig;
/** sessions_spawn tool configuration. */
sessions_spawn?: SessionsSpawnToolsConfig;
/** Sub-agent tool policy defaults (deny wins). */
subagents?: {
tools?: ToolAllowDenyPolicyConfig;
};
/** Sandbox tool policy defaults (deny wins). */
sandbox?: {
tools?: ToolAllowDenyPolicyConfig;
};
/** Unified progress_card status tool; enabled by default. Set false to opt out. */
updatePlan?: boolean;
};
type MessageToolsConfig = {
crossContext?: {
/** Allow sends to other channels within the same provider (default: true). */
allowWithinProvider?: boolean;
/** Allow sends across different providers (default: false). */
allowAcrossProviders?: boolean;
/** Cross-context marker configuration. */
marker?: {
/** Enable origin markers for cross-context sends (default: true). */
enabled?: boolean;
/** Text prefix template, supports {channel}. */
prefix?: string;
/** Text suffix template, supports {channel}. */
suffix?: string;
};
};
actions?: {
/** Message action names exposed and accepted by the message tool. */
allow?: string[];
};
broadcast?: {
/** Enable broadcast action (default: true). */
enabled?: boolean;
};
};
//#endregion
//#region src/config/types.tts.d.ts
type TtsProvider = string;
type TtsMode = "final" | "all";
type TtsAutoMode = "off" | "always" | "inbound" | "tagged";
type TtsModelOverrideConfig = {
/** Enable model-provided overrides for TTS. */
enabled?: boolean;
/** Allow model-provided TTS text blocks. */
allowText?: boolean;
/** Allow model-provided provider override (default: false). */
allowProvider?: boolean;
/** Allow model-provided voice/voiceId override. */
allowVoice?: boolean;
/** Allow model-provided modelId override. */
allowModelId?: boolean;
/** Allow model-provided voice settings override. */
allowVoiceSettings?: boolean;
/** Allow model-provided normalization or language overrides. */
allowNormalization?: boolean;
/** Allow model-provided seed override. */
allowSeed?: boolean;
};
type TtsProviderConfigMap = Record<string, Record<string, unknown>>;
type TtsPersonaFallbackPolicy = "preserve-persona" | "provider-defaults" | "fail";
type TtsPersonaConfig = {
label?: string;
description?: string;
/** Preferred provider for this persona. Explicit provider prefs still win. */
provider?: TtsProvider;
fallbackPolicy?: TtsPersonaFallbackPolicy;
/** Provider-specific persona bindings keyed by speech provider id. */
providers?: TtsProviderConfigMap;
};
type ResolvedTtsPersona = TtsPersonaConfig & {
id: string;
};
type TtsConfig = {
/** Auto-TTS mode (preferred). */
auto?: TtsAutoMode;
/** @deprecated Use auto. */
enabled?: boolean;
/** Apply TTS to final replies only or to all replies (tool/block/final). */
mode?: TtsMode;
/** Primary TTS provider (fallbacks are automatic). */
provider?: TtsProvider;
/** Active TTS persona id. */
persona?: string;
/** Named TTS personas. */
personas?: Record<string, TtsPersonaConfig>;
/** Optional model override for TTS auto-summary (provider/model or alias). */
summaryModel?: string;
/** Allow the model to override TTS parameters. */
modelOverrides?: TtsModelOverrideConfig;
/** Provider-specific TTS settings keyed by speech provider id. */
providers?: TtsProviderConfigMap;
/** Optional path for local TTS user preferences JSON. */
/** Hard cap for text sent to TTS (chars). */
maxTextLength?: number;
/** API request timeout (ms). */
timeoutMs?: number;
};
//#endregion
//#region src/config/types.agents.d.ts
type AgentRuntimeAcpConfig = {
/** ACP harness adapter id (for example codex, claude). */
agent?: string;
/** Optional ACP backend override for this agent runtime. */
backend?: string;
/** Optional ACP session mode override. */
mode?: "persistent" | "oneshot";
/** Optional runtime working directory override. */
cwd?: string;
};
type AgentRuntimeConfig = {
type: "embedded";
} | {
type: "acp";
acp?: AgentRuntimeAcpConfig;
};
type AgentBindingMatch = {
channel: string;
/**
* Channel account to match.
* - Omitted/empty: matches only the channel default account.
* - "*": matches every account on the channel.
* - Any other string: matches that specific account id.
*/
accountId?: string;
peer?: {
kind: ChatType;
id: string;
};
guildId?: string;
teamId?: string;
/** Discord role IDs used for role-based routing. */
roles?: string[];
};
type AgentRouteBinding = {
/** Missing type is interpreted as route for backward compatibility. */
type?: "route";
agentId: string;
comment?: string;
match: AgentBindingMatch;
session?: {
/** Optional session scoping override for conversations matched by this binding. */
dmScope?: DmScope;
groupScope?: GroupScope;
};
};
type AgentAcpBinding = {
type: "acp";
agentId: string;
comment?: string;
match: AgentBindingMatch;
acp?: {
mode?: "persistent" | "oneshot";
label?: string;
cwd?: string;
backend?: string;
};
};
type AgentBinding = AgentRouteBinding | AgentAcpBinding;
type AgentConfig = {
id: string;
/** @deprecated Raw legacy list compatibility only; canonical agents.entries rejects this key. */
default?: boolean;
name?: string;
/** Optional human-authored agent description. */
description?: string;
workspace?: string;
/** Working directory for agent reply runs; overrides agents.defaults.cwd. */
cwd?: string;
agentDir?: string;
model?: AgentModelConfig;
/** Optional per-agent model for short internal tasks such as generated session titles. */
utilityModel?: string;
/**
* @deprecated Legacy raw config accepted only by doctor/migration repair.
* Normal schema parsing rejects this key; use per-model agentRuntime instead.
*/
agentRuntime?: AgentModelEntryConfig["agentRuntime"];
/** Per-model metadata overrides for this agent. */
models?: Record<string, AgentModelEntryConfig>;
/** Per-agent model override policy. Replaces the default policy when allow is present. */
modelPolicy?: AgentModelPolicyConfig;
/** @deprecated Legacy per-agent compaction config is kept for raw doctor migration/repair. */
compaction?: AgentDefaultsConfig["compaction"];
/** Optional per-agent default thinking level (overrides agents.defaults.thinkingDefault). */
thinkingDefault?: AgentDefaultsConfig["thinkingDefault"];
/** Optional per-agent default verbosity level. */
verboseDefault?: "off" | "on" | "full";
/** Optional per-agent tool progress detail mode. */
toolProgressDetail?: AgentDefaultsConfig["toolProgressDetail"];
/** Optional per-agent default reasoning visibility. */
reasoningDefault?: "on" | "off" | "stream";
/** Optional per-agent default for fast mode. */
fastModeDefault?: FastMode;
/** Optional per-agent bootstrap/context injection mode override. */
contextInjection?: AgentDefaultsConfig["contextInjection"];
/** Optional per-agent max chars for each injected bootstrap file. */
bootstrapMaxChars?: AgentDefaultsConfig["bootstrapMaxChars"];
/** Optional per-agent max total chars across injected bootstrap files. */
bootstrapTotalMaxChars?: AgentDefaultsConfig["bootstrapTotalMaxChars"];
/** Optional per-agent experimental flags. Omitted fields inherit agents.defaults.experimental. */
experimental?: AgentDefaultsConfig["experimental"];
/** Optional allowlist of skills for this agent; omitting it inherits agents.defaults.skills when set, and an explicit list replaces defaults instead of merging. */
skills?: string[];
/** Per-agent overrides for the shared top-level memory configuration. */
memory?: {
search?: MemorySearchConfig;
};
/** Human-like delay between block replies for this agent. */
humanDelay?: HumanDelayConfig;
/** Optional per-agent typing start policy. */
typingMode?: AgentDefaultsConfig["typingMode"];
/** Optional per-agent TTS overrides, deep-merged over top-level tts. */
/** Per-agent TTS overrides. prefsPath remains scoped because agents may use distinct preference stores. */
tts?: TtsConfig & {
prefsPath?: string;
};
/** Optional per-agent skills subsystem overrides. */
skillsLimits?: Pick<SkillsLimitsConfig, "maxSkillsPromptChars">;
/** Optional per-agent overrides for selected context/token-heavy limits. */
contextLimits?: AgentContextLimitsConfig;
/** Optional per-agent heartbeat overrides. */
heartbeat?: Omit<NonNullable<AgentDefaultsConfig["heartbeat"]>, "agentId">;
identity?: IdentityConfig;
groupChat?: Omit<GroupChatConfig, "visibleReplies">;
subagents?: {
/** Prompt-only guidance for how strongly this agent should delegate work. */
delegationMode?: SubagentDelegationMode;
/** Allow spawning sub-agents under other agent ids. Use "*" to allow any configured target. */
allowAgents?: string[];
/** Per-agent default model for spawned sub-agents (string or {primary,fallbacks}). */
model?: AgentModelConfig;
/** Per-agent default thinking level for spawned sub-agents. */
thinking?: string;
/** Require explicit agentId in sessions_spawn (no default same-as-caller). */
requireAgentId?: boolean;
};
/** Optional per-agent embedded OpenClaw overrides. */
embeddedAgent?: {
/** Optional per-agent execution contract override. */
executionContract?: EmbeddedAgentExecutionContract;
};
/** Optional per-agent sandbox overrides. */
sandbox?: AgentSandboxConfig;
/** Optional per-agent stream params (e.g. cacheRetention, temperature). */
params?: Record<string, unknown>;
tools?: AgentToolsConfig;
/** Optional runtime descriptor for this agent. */
runtime?: AgentRuntimeConfig;
};
type AgentEntryConfig = Omit<AgentConfig, "id">;
type AgentsConfig = {
ownership?: "explicit";
defaults?: AgentDefaultsConfig;
entries?: Record<string, AgentEntryConfig>;
/** Internal non-serialized projection materialized by validation for ID-based runtime code. */
list?: AgentConfig[];
};
//#endregion
//#region packages/acp-core/src/runtime/types.d.ts
/** Runtime update tags emitted by ACP adapters; unknown backend tags are passed through. */
type AcpSessionUpdateTag = "agent_message_chunk" | "agent_thought_chunk" | "tool_call" | "tool_call_update" | "usage_update" | "available_commands_update" | "current_mode_update" | "config_option_update" | "session_info_update" | "plan" | (string & {});
//#endregion
//#region src/config/types.acp.d.ts
type AcpDispatchConfig = {
/** Master switch for ACP turn dispatch in the reply pipeline. */
enabled?: boolean;
};
type AcpStreamConfig = {
/** Suppresses repeated ACP status/tool projection lines within a turn. */
repeatSuppression?: boolean;
/** Live streams chunks or waits for terminal event before delivery. */
deliveryMode?: "live" | "final_only";
/**
* Per-sessionUpdate visibility overrides.
* Keys not listed here fall back to OpenClaw defaults.
*/
tagVisibility?: Partial<Record<AcpSessionUpdateTag, boolean>>;
};
type AcpRuntimeConfig = {
/** Optional operator install/setup command shown by `/acp install` and `/acp doctor`. */
installCommand?: string;
};
type AcpConfig = {
/** Global ACP runtime gate. */
enabled?: boolean;
dispatch?: AcpDispatchConfig;
/** Backend id registered by ACP runtime plugin (for example: acpx). */
backend?: string;
/** Fallback backend ids tried when the primary backend fails with UNAVAILABLE. */
fallbacks?: string[];
defaultAgent?: string;
allowedAgents?: string[];
stream?: AcpStreamConfig;
runtime?: AcpRuntimeConfig;
};
//#endregion
//#region src/config/types.access-groups.d.ts
type DiscordChannelAudienceAccessGroup = {
/**
* Discord dynamic audience backed by the users who can currently view a guild
* channel.
*/
type: "discord.channelAudience";
/** Guild ID that owns the channel. */
guildId: string;
/** Channel ID whose effective ViewChannel permission defines the audience. */
channelId: string;
/** Audience predicate. Defaults to canViewChannel. */
membership?: "canViewChannel";
};
type MessageSendersAccessGroup = {
/**
* Static sender allowlists that can be referenced by any message channel via
* accessGroup:<name>.
*/
type: "message.senders";
/** Sender entries by channel id, plus optional "*" entries shared by all channels. */
members: Record<string, string[]>;
};
type AccessGroupConfig = DiscordChannelAudienceAccessGroup | MessageSendersAccessGroup;
type AccessGroupsConfig = Record<string, AccessGroupConfig>;
//#endregion
//#region src/config/types.approvals.d.ts
type NativeExecApprovalEnableMode = boolean | "auto";
type ExecApprovalForwardingMode = "session" | "targets" | "both";
type ExecApprovalForwardTarget = {
/** Channel id (e.g. "discord", "slack", or plugin channel id). */
channel: string;
/** Destination id (channel id, user id, etc. depending on channel). */
to: string;
/** Optional account id for multi-account channels. */
accountId?: string;
/** Optional thread id to reply inside a thread. */
threadId?: string | number;
};
type ExecApprovalForwardingConfig = {
/** Enable forwarding exec approvals to chat channels. Default: false. */
enabled?: boolean;
/** Delivery mode (session=origin chat, targets=config targets, both=both). Default: session. */
mode?: ExecApprovalForwardingMode;
/** Only forward approvals for these agent IDs. Omit = all agents. */
agentFilter?: string[];
/** Only forward approvals matching these session key patterns (substring or regex). */
sessionFilter?: string[];
/** Explicit delivery targets (used when mode includes targets). */
targets?: ExecApprovalForwardTarget[];
};
type ApprovalsConfig = {
exec?: ExecApprovalForwardingConfig;
plugin?: ExecApprovalForwardingConfig;
};
//#endregion
//#region src/config/types.auth.d.ts
type AuthProfileConfig = {
/** Provider id this auth profile can satisfy. */
provider: string;
/**
* Auth route selected by this profile id.
* - api_key: static provider API key
* - oauth: refreshable OAuth credentials (access+refresh+expires)
* - token: static bearer-style token (optionally expiring; no refresh)
* - aws-sdk: AWS SDK default credential chain (no secret in auth-profiles.json)
*/
mode: "api_key" | "aws-sdk" | "oauth" | "token";
/** Optional account email shown in profile selection/status surfaces. */
email?: string;
/** Optional human-readable label shown in profile selection/status surfaces. */
displayName?: string;
};
type AuthConfig = {
/** Named auth profiles keyed by profile id. */
profiles?: Record<string, AuthProfileConfig>;
/** Preferred profile order per provider id. */
order?: Record<string, string[]>;
};
//#endregion
//#region src/config/types.browser.d.ts
type BrowserProfileConfig = {
/** @deprecated Doctor-only legacy input; canonical schema rejects this field. */
color?: string;
/** CDP port for this profile. Allocated once at creation, persisted permanently. */
cdpPort?: number;
/** CDP/DevTools endpoint URL for this profile (remote CDP or existing-session endpoint attach). */
cdpUrl?: string;
/** Explicit user data directory for existing-session Chrome MCP attachment. */
userDataDir?: string;
/** Override the Chrome MCP command for existing-session profiles. */
mcpCommand?: string;
/** Extra Chrome MCP arguments for existing-session profiles. */
mcpArgs?: string[];
/**
* Profile driver (default: openclaw). "extension" attaches to the user's
* signed-in browser through the OpenClaw Chrome extension relay.
*/
driver?: "openclaw" | "clawd" | "existing-session" | "extension";
/** If true, launch this profile in headless mode. Falls back to browser.headless. */
headless?: boolean;
/** Browser executable path for this profile. Falls back to browser.executablePath. */
executablePath?: string;
/** If true, never launch a browser for this profile; only attach. Falls back to browser.attachOnly. */
attachOnly?: boolean;
};
type BrowserSnapshotDefaults = {
/** Default snapshot mode (applies when mode is not provided). */
mode?: "efficient";
};
type BrowserTabCleanupConfig = {
/** Enable best-effort cleanup for tracked primary-agent browser tabs. Default: true */
enabled?: boolean;
};
type BrowserExtensionRelayConfig = {
/** Temporarily accept legacy relay bearer/basic/subprotocol auth. Default: true. */
allowLegacyAuth?: boolean;
};
type BrowserSsrFPolicyConfig = SsrFPolicyConfig;
type BrowserConfig = {
/** @deprecated Doctor-only legacy input; canonical schema rejects this field. */
color?: string;
enabled?: boolean;
/** Allow importing cookies from the user's real Chrome-family profile into a managed profile (macOS). Default: true. */
allowSystemProfileImport?: boolean;
/** If false, disable browser act:evaluate (arbitrary JS). Default: true */
evaluateEnabled?: boolean;
/** Base URL of the CDP endpoint (for remote browsers). Default: loopback CDP on the derived port. */
cdpUrl?: string;
/** Override the browser executable path (all platforms). */
executablePath?: string;
/** Start Chrome headless (best-effort). Default: false */
headless?: boolean;
/** Pass --no-sandbox to Chrome (Linux containers). Default: false */
noSandbox?: boolean;
/** If true: never launch; only attach to an existing browser. Default: false */
attachOnly?: boolean;
/** Default profile to use when profile param is omitted. Default: "openclaw" */
defaultProfile?: string;
/** Named browser profiles with explicit CDP ports or URLs. */
profiles?: Record<string, BrowserProfileConfig>;
/** Default snapshot options (applied by the browser tool/CLI when unset). */
snapshotDefaults?: BrowserSnapshotDefaults;
/** Best-effort cleanup policy for tabs opened by primary-agent browser sessions. */
tabCleanup?: BrowserTabCleanupConfig;
/** Chrome extension relay authentication compatibility settings. */
extensionRelay?: BrowserExtensionRelayConfig;
/** SSRF policy for browser navigation/open-tab operations. */
ssrfPolicy?: BrowserSsrFPolicyConfig;
/**
* Additional Chrome launch arguments.
* Useful for stealth flags, window size overrides, or custom user-agent strings.
* Example: ["--window-size=1920,1080", "--disable-infobars"]
*/
extraArgs?: string[];
};
//#endregion
//#region src/config/types.cloud-workers.d.ts
type CloudWorkerProfileConfig = {
/** Worker provider id registered by a plugin. */
provider: string;
/** Worker install method (default: bundle); npm requires a released gateway version. */
install?: "bundle" | "npm";
/** Reclaim an idle worker after this duration; omitted profiles stay running. */
suspendAfter?: string;
/** Provider-owned JSON settings; secret-bearing fields use SecretRef objects. */
settings?: Record<string, unknown>;
};
type CloudWorkersConfig = {
/** Experimental Labs gate for the cloud-worker desktop observer. */
desktop?: boolean;
/** Default worker profile names keyed by normalized repository identity. */
projectProfiles?: Record<string, string>;
/** Named opt-in worker profiles. Omit or leave empty to disable cloud workers. */
profiles?: Record<string, CloudWorkerProfileConfig>;
};
//#endregion
//#region src/config/types.desktop.d.ts
type DesktopHostConfig = {
/** Enables the gateway-host desktop source after a gateway restart. */
enabled: boolean;
/** Runs a gateway-supervised headless TigerVNC/XFCE desktop on Linux. */
managed?: boolean;
/** Loopback RFB port of an already-running VNC server (default: 5900). */
port?: number;
/** Absolute VNC password-file path; macOS ARD account credentials stay per-observation. */
passwordFile?: string;
};
type DesktopConfig = {
/** Experimental Labs gate for observing the gateway host desktop. */
host?: DesktopHostConfig;
};
//#endregion
//#region src/config/types.bot-loop-protection.d.ts
type ChannelBotLoopProtectionConfig = {
/** Enable pair loop protection for channels that support it. */
enabled?: boolean;
/** Maximum events a sender/receiver pair may exchange within the window. */
maxEventsPerWindow?: number;
/** Sliding window length in seconds. */
windowSeconds?: number;
/** Cooldown seconds applied to a pair after the limit is hit. */
cooldownSeconds?: number;
};
//#endregion
//#region src/config/types.channel-health.d.ts
type ChannelHeartbeatVisibilityConfig = {
/** Show HEARTBEAT_OK acknowledgments in chat (default: false). */
showOk?: boolean;
/** Show heartbeat alerts with actual content (default: true). */
showAlerts?: boolean;
/** Emit indicator events for UI status display (default: true). */
useIndicator?: boolean;
};
type ChannelHealthMonitorConfig = {
/**
* Enable channel-health-monitor restarts for this channel or account.
* Inherits the global gateway setting when omitted.
*/
enabled?: boolean;
};
//#endregion
//#region src/config/types.channel-messaging-common.d.ts
type CommonChannelMessagingConfig<TCapabilities = string[], TAllowFromEntry = string | number, TDefaultTo = string, TStreaming = ChannelDeliveryStreamingConfig> = {
/** Optional display name for this account (used in CLI/UI lists). */
name?: string;
/** Optional provider capability tags used for agent/runtime guidance. */
capabilities?: TCapabilities;
/** Markdown formatting overrides (tables). */
markdown?: MarkdownConfig;
/** Allow channel-initiated config writes (default: true). */
configWrites?: boolean;
/** If false, do not start this account. Default: true. */
enabled?: boolean;
/** Direct message access policy (default: pairing). */
dmPolicy?: DmPolicy;
/** Optional allowlist for inbound DM senders. */
allowFrom?: TAllowFromEntry[];
/** Default delivery target for CLI --deliver when no explicit --reply-to is provided. */
defaultTo?: TDefaultTo;
/** Optional allowlist for group/channel senders. */
groupAllowFrom?: TAllowFromEntry[];
/** Group/channel message handling policy. */
groupPolicy?: GroupPolicy;
/** Scope configured mention patterns to selected conversations. */
mentionPatterns?: MentionPatternsPolicyConfig;
/**
* Supplemental context visibility policy for fetched/group context.
* - "all": include all quoted/thread/history context
* - "allowlist": only include context from allowlisted senders
* - "allowlist_quote": same as allowlist, but keep explicit quote/reply context
*/
contextVisibility?: ContextVisibilityMode;
/** Max group/channel messages to keep as history context (0 disables). */
historyLimit?: number;
/** Max DM turns to keep as history context. */
dmHistoryLimit?: number;
/** Per-DM config overrides keyed by sender ID. */
dms?: Record<string, DmConfig>;
/** Outbound text chunk size (chars). */
textChunkLimit?: number;
/** Delivery streaming config: chunk mode plus block streaming controls. */
streaming?: TStreaming;
/** Heartbeat visibility settings for this channel. */
heartbeatVisibility?: ChannelHeartbeatVisibilityConfig;
/** @deprecated Doctor-only legacy input. */
heartbeat?: ChannelHeartbeatVisibilityConfig;
/** Channel health monitor overrides for this channel/account. */
healthMonitor?: ChannelHealthMonitorConfig;
/** Outbound response prefix override for this channel/account. */
responsePrefix?: string;
/** Max outbound media size in MB. */
mediaMaxMb?: number;
/** Native reply-threading mode for automatic replies. */
replyToMode?: ReplyToMode;
};
type ChannelExecApprovalTarget = "dm" | "channel" | "both";
type ChannelExecApprovalConfig<TApprover = string | number> = {
enabled?: NativeExecApprovalEnableMode;
approvers?: TApprover[];
agentFilter?: string[];
sessionFilter?: string[];
target?: ChannelExecApprovalTarget;
};
type ChannelBotInteractionConfig<TAllowBots = boolean | "mentions"> = {
allowBots?: TAllowBots;
botLoopProtection?: ChannelBotLoopProtectionConfig;
dangerouslyAllowNameMatching?: boolean;
};
type ChannelReadReceiptConfig = {
sendReadReceipts?: boolean;
};
type ChannelReactionConfig<TNotification = never, TLevel = never, TAckReaction = never, TAllowlist extends boolean = false> = {
reactionNotifications?: TNotification;
reactionLevel?: TLevel;
ackReaction?: TAckReaction;
} & (TAllowlist extends true ? {
reactionAllowlist?: Array<string | number>;
} : Record<never, never>);
//#endregion
//#region src/config/types.discord-presence.d.ts
type DiscordPresenceEventsConfig = {
/** Enable online-presence system events for this guild. Default: true when configured. */
enabled?: boolean;
/** Discord channel ID that receives the routed agent wake. */
channelId: string;
/** Optional immutable Discord user ID allowlist. Omit to include all human members. */
users?: string[];
/**
* Suppress presence-derived online events for this many seconds after a new Gateway
* session while guild presence state is rebuilt. 0 disables. Default: 300.
*/
reconnectSuppressSeconds?: number;
/** Maximum queued online events for this guild per burst window. Default: 8. */
burstLimit?: number;
/** Sliding burst-detection window in seconds. Default: 60. */
burstWindowSeconds?: number;
};
//#endregion
//#region src/config/types.discord.d.ts
type DiscordChannelStreamingConfig = Omit<ChannelPreviewStreamingConfig, "progress"> & {
progress?: ChannelStreamingProgressConfig;
};
type DiscordPluralKitConfig = {
enabled?: boolean;
token?: string;
};
type DiscordMentionAliasesConfig = Record<string, string>;
type DiscordDmConfig = {
/** If false, ignore all incoming Discord DMs. Default: true. */
enabled?: boolean;
/** If true, allow group DMs (default: false). */
groupEnabled?: boolean;
/** Optional allowlist for group DM channels (ids or slugs). */
groupChannels?: string[];
};
type DiscordGuildChannelConfig = {
requireMention?: boolean;
/**
* If true, drop messages addressed to another identity by mention or bot reply, but not this
* bot (not @everyone/@here).
* Default: false.
*/
ignoreOtherMentions?: boolean;
/** Optional tool policy overrides for this channel. */
tools?: GroupToolPolicyConfig;
toolsBySender?: GroupToolPolicyBySenderConfig;
/** If specified, only load these skills for this channel. Omit = all skills; empty = no skills. */
skills?: string[];
/** If false, disable the bot for this channel. */
enabled?: boolean;
/** Optional allowlist for channel senders (ids or names). */
users?: string[];
/** Optional allowlist for channel senders by role ID. */
roles?: string[];
/** Optional system prompt snippet for this channel. */
systemPrompt?: string;
/** If false, omit thread starter context for this channel (default: true). */
includeThreadStarter?: boolean;
/** If true, automatically create a thread for each new message in this channel. */
autoThread?: boolean;
/** Archive duration (minutes) for auto-created threads. Valid values: 60, 1440, 4320, 10080. */
autoArchiveDuration?: "60" | "1440" | "4320" | "10080" | 60 | 1440 | 4320 | 10080;
/** Naming strategy for auto-created threads. "message" uses message text; "generated" renames with an LLM title. */
autoThreadName?: "message" | "generated";
};
type DiscordReactionNotificationMode = "off" | "own" | "all" | "allowlist";
type DiscordGuildEntry = {
slug?: string;
requireMention?: boolean;
/**
* If true, drop messages addressed to another identity by mention or bot reply, but not this
* bot (not @everyone/@here).
* Default: false.
*/
ignoreOtherMentions?: boolean;
/** Optional tool policy overrides for this guild (used when channel override is missing). */
tools?: GroupToolPolicyConfig;
toolsBySender?: GroupToolPolicyBySenderConfig;
/** Reaction notification mode (off|own|all|allowlist). Default: own. */
reactionNotifications?: DiscordReactionNotificationMode;
/** Optional allowlist for guild senders (ids or names). */
users?: string[];
/** Optional allowlist for guild senders by role ID. */
roles?: string[];
presenceEvents?: DiscordPresenceEventsConfig;
channels?: Record<string, DiscordGuildChannelConfig>;
};
type DiscordActionConfig = {
reactions?: boolean;
stickers?: boolean;
polls?: boolean;
permissions?: boolean;
messages?: boolean;
threads?: boolean;
pins?: boolean;
search?: boolean;
memberInfo?: boolean;
roleInfo?: boolean;
roles?: boolean;
channelInfo?: boolean;
voiceStatus?: boolean;
events?: boolean;
moderation?: boolean;
emojiUploads?: boolean;
stickerUploads?: boolean;
channels?: boolean;
/** Enable bot presence/activity changes (default: false). */
presence?: boolean;
};
type DiscordIntentsConfig = {
/**
* Request the privileged Message Content intent. Disable only for mention-only guild operation;
* Discord still includes content in DMs and messages that explicitly mention the bot. Default: true.
*/
messageContent?: boolean;
/** Enable Guild Presences privileged intent (requires Portal opt-in). Default: false. */
presence?: boolean;
/** Enable Guild Members privileged intent (requires Portal opt-in). Default: false. */
guildMembers?: boolean;
/** Enable Guild Voice States intent. Defaults to voice.enabled, unless explicitly set. */
voiceStates?: boolean;
};
type DiscordVoiceAutoJoinConfig = {
/** Guild ID that owns the voice channel. */
guildId: string;
/** Voice channel ID to join. */
channelId: string;
/** Join and remain connected only while at least one human is in the channel. Default: false. */
whenOccupied?: boolean;
};
type DiscordVoiceAllowedChannelConfig = {
/** Guild ID that owns the voice channel. */
guildId: string;
/** Voice channel ID allowed for realtime voice sessions. */
channelId: string;
};
type DiscordVoiceMode = "stt-tts" | "agent-proxy" | "bidi";
type DiscordVoiceRealtimeConsultPolicy = "auto" | "always";
type DiscordVoiceRealtimeToolPolicy = "safe-read-only" | "owner" | "none";
type DiscordVoiceRealtimeBootstrapContextFile = "IDENTITY.md" | "USER.md" | "SOUL.md";
type DiscordVoiceRealtimeConfig = {
/** Realtime voice provider id, for example "openai". */
provider?: string;
/** Provider realtime session model, for example "gpt-realtime-2.1". */
model?: string;
/** Provider realtime output voice name, for example "cedar". */
speakerVoice?: string;
/** Provider realtime output voice id. */
speakerVoiceId?: string;
/** System instructions passed to the realtime provider. */
instructions?: string;
/** Tool policy for bidi realtime consult calls. */
toolPolicy?: DiscordVoiceRealtimeToolPolicy;
/** Whether bidi should force the OpenClaw agent brain for every substantive turn. */
consultPolicy?: DiscordVoiceRealtimeConsultPolicy;
/** OpenAI agent-proxy wake-name policy. Unset adapts to the room: off for one human, on for two or more. True always requires; false never requires. */
requireWakeName?: boolean;
/** Wake names that allow OpenAI agent-proxy realtime Discord voice to respond when the gate is active. Defaults to the routed agent name plus OpenClaw, or the agent id plus OpenClaw. */
wakeNames?: string[];
/** Agent profile bootstrap files to include in realtime provider instructions. Defaults to IDENTITY.md, USER.md, and SOUL.md; set [] to disable. */
bootstrapContextFiles?: DiscordVoiceRealtimeBootstrapContextFile[];
/** Allow Discord speaker-start events to interrupt active realtime playback. */
bargeIn?: boolean;
/** Minimum assistant playback duration before a barge-in truncates audio. Default: 250ms; set 0 for immediate interruption. */
minBargeInAudioEndMs?: number;
/** Debounce window before buffered transcripts are sent to the OpenClaw agent. */
debounceMs?: number;
/** Provider-specific realtime voice config keyed by provider id. */
providers?: Record<string, Record<string, unknown> | undefined>;
};
type DiscordVoiceAgentSessionConfig = {
/** Which OpenClaw conversation should receive voice turns. Default: "voice". */
mode?: "voice" | "target";
/** Discord target used when mode is "target", for example "channel:123". */
target?: string;
};
type DiscordVoiceConfig = {
/** Enable Discord voice channel conversations (default: true). */
enabled?: boolean;
/** Voice conversation mode. Default: agent-proxy. */
mode?: DiscordVoiceMode;
/** Route voice turns through an existing OpenClaw Discord conversation. */
agentSession?: DiscordVoiceAgentSessionConfig;
/** Optional LLM model override for Discord voice channel responses. */
model?: string;
/** Realtime provider settings for agent-proxy or bidi modes. */
realtime?: DiscordVoiceRealtimeConfig;
/** Voice channels to join automatically, optionally only while occupied. */
autoJoin?: DiscordVoiceAutoJoinConfig[];
/** If false, configured followUsers are ignored without removing the saved user list. */
followUsersEnabled?: boolean;
/** Discord user IDs whose current voice channel the bot should follow. */
followUsers?: string[];
/** Voice channels the bot is allowed to join or remain in. Unset means any voice channel is allowed. */
allowedChannels?: DiscordVoiceAllowedChannelConfig[];
/** Enable/disable DAVE end-to-end encryption (default: true; Discord may require this). */
daveEncryption?: boolean;
/** Consecutive decrypt failures before DAVE session reinitialization (default: 24). */
decryptionFailureTolerance?: number;
/** Initial @discordjs/voice Ready wait in milliseconds (default: 30000). */
connectTimeoutMs?: number;
/** Grace period for Discord voice reconnect signalling after a disconnect (default: 15000). */
reconnectGraceMs?: number;
/** Silence grace after Discord reports a speaker ended before finalizing STT capture (default: 2000). */
captureSilenceGraceMs?: number;
/** Optional TTS overrides for Discord voice output. */
tts?: TtsConfig;
};
type DiscordExecApprovalConfig = ChannelExecApprovalConfig<string> & {
/** Delete approval DMs after approval, denial, or timeout. Default: false. */
cleanupAfterResolve?: boolean;
};
type DiscordAgentComponentsConfig = {
/** Enable agent-controlled interactive components (buttons, select menus). Default: true. */
enabled?: boolean;
/** Time in milliseconds before sent Discord component callbacks expire. Default: 1800000. */
ttlMs?: number;
};
type DiscordThreadBindingsConfig = {
/** Enable Discord thread binding features. Overrides session.threadBindings.enabled. */
enabled?: boolean;
/** Inactivity window in hours. Set 0 to disable. Default: 24. */
idleHours?: number;
/** Hard max age in hours. Set 0 to disable. Default: 0. */
maxAgeHours?: number;
/** Allow session spawns to create and bind Discord threads. Default: true. */
spawnSessions?: boolean;
/** Default context mode for native subagents. Default: fork. */
defaultSpawnContext?: "isolated" | "fork";
};
type DiscordSlashCommandConfig = {
/** Reply ephemerally (default: true). */
ephemeral?: boolean;
};
type DiscordThreadConfig = {
/** If true, Discord thread sessions inherit the parent channel transcript. Default: false. */
inheritParent?: boolean;
};
type DiscordAutoPresenceConfig = {
/** Enable automatic runtime/quota-based Discord presence updates. Default: false. */
enabled?: boolean;
/** Poll interval for evaluating runtime availability state (ms). Default: 30000. */
intervalMs?: number;
/** Minimum spacing between actual gateway presence updates (ms). Default: 15000. */
minUpdateIntervalMs?: number;
/** Optional custom status text while runtime is healthy; supports plain text. */
/** Optional custom status text while runtime/quota state is degraded or unknown. */
/** Optional custom status text while runtime detects quota/token exhaustion. */
/** @deprecated Doctor-only legacy input. */
exhaustedText?: string;
};
type DiscordAccountConfig = Omit<CommonChannelMessagingConfig<string[], string, string, DiscordChannelStreamingConfig>, "groupAllowFrom"> & ChannelBotInteractionConfig & ChannelReactionConfig<never, never, string> & {
/** Post a room-specific introduction when joining a group. Default: true. */
joinIntro?: boolean;
/** Override native command registration for Discord (bool or "auto"). */
commands?: ProviderCommandsConfig;
token?: SecretInput;
/** Optional Discord application/client ID. Set this when REST application lookup is blocked. */
applicationId?: string;
activities?: {
clientSecret?: string;
applicationId?: string;
};
/** HTTP(S) proxy URL for Discord gateway WebSocket connections. */
proxy?: string;
/**
* Deterministic outbound @handle rewrites for known Discord users.
* Keys are handles without the leading @; values are Discord user IDs.
*/
mentionAliases?: DiscordMentionAliasesConfig;
/**
* Suppress Discord-generated link embeds for outbound messages. Default: true.
* Explicit `embeds` payloads are still sent normally.
*/
suppressEmbeds?: boolean;
/**
* Soft max line count per Discord message.
* Discord clients can clip/collapse very tall messages; splitting by lines
* keeps replies readable in-channel. Default: 17.
*/
maxLinesPerMessage?: number;
/** Per-action tool gating (default: true for all). */
actions?: DiscordActionConfig;
/** Thread session behavior. */
thread?: DiscordThreadConfig;
dm?: DiscordDmConfig;
/** New per-guild config keyed by guild id or slug. */
guilds?: Record<string, DiscordGuildEntry>;
/** Exec approval forwarding configuration. */
execApprovals?: DiscordExecApprovalConfig;
/** Agent-controlled interactive components (buttons, select menus). */
agentComponents?: DiscordAgentComponentsConfig;
/** Discord UI customization (components, modals, etc.). */
/** Slash command configuration. */
slashCommand?: DiscordSlashCommandConfig;
/** Thread binding lifecycle settings. */
threadBindings?: DiscordThreadBindingsConfig;
/** Privileged Gateway Intents (must also be enabled in Discord Developer Portal). */
intents?: DiscordIntentsConfig;
/** Voice channel conversation settings. */
voice?: DiscordVoiceConfig;
/** PluralKit identity resolution for proxied messages. */
pluralkit?: DiscordPluralKitConfig;
/** When to send ack reactions for this Discord account. Overrides messages.ackReactionScope. */
ackReactionScope?: "group-mentions" | "group-all" | "direct" | "all" | "off" | "none";
/** Bot activity status text (e.g. "Watching X"). */
activity?: string;
/** Bot status (online|dnd|idle|invisible). Defaults to online when presence is configured. */
status?: "online" | "dnd" | "idle" | "invisible";
/** Automatic runtime/quota presence signaling (status text + status mapping). */
autoPresence?: DiscordAutoPresenceConfig;
/** Activity type (0=Game, 1=Streaming, 2=Listening, 3=Watching, 4=Custom, 5=Competing). Defaults to 4 (Custom) when activity is set. */
activityType?: 0 | 1 | 2 | 3 | 4 | 5;
/** Streaming URL (Twitch/YouTube). Required when activityType=1. */
activityUrl?: string;
/**
* Legacy compatibility block. Discord no longer enforces channel-owned
* timeouts for queued inbound agent runs.
*/
inboundWorker?: {
/**
* Ignored. Queued Discord agent runs are governed by the session/tool/runtime
* lifecycle, not by Discord channel config.
*/
runTimeoutMs?: number;
};
};
type DiscordConfig = {
/** Optional per-account Discord configuration (multi-account). */
accounts?: Record<string, DiscordAccountConfig>;
/** Optional default account id when multiple accounts are configured. */
defaultAccount?: string;
} & DiscordAccountConfig;
//#endregion
//#region src/config/types.googlechat.d.ts
type GoogleChatDmConfig = {
/** If false, ignore all incoming Google Chat DMs. Default: true. */
enabled?: boolean;
};
type GoogleChatGroupConfig = {
/** If false, disable the bot in this space. */
enabled?: boolean;
/** Require mentioning the bot to trigger replies. */
requireMention?: boolean;
/** Sliding-window bot-pair loop guard for accepted bot-authored Google Chat messages. */
botLoopProtection?: ChannelBotLoopProtectionConfig;
/** Allowlist of users that can invoke the bot in this space. */
users?: Array<string | number>;
/** Optional system prompt for this space. */
systemPrompt?: string;
};
type GoogleChatAccountConfig = Omit<CommonChannelMessagingConfig, "mentionPatterns"> & ChannelBotInteractionConfig<boolean> & {
/** Default mention requirement for space messages (default: true). */
requireMention?: boolean;
/** Per-space configuration keyed by space id or name. */
groups?: Record<string, GoogleChatGroupConfig>;
/** Service account JSON (inline string, object, or secret reference). */
serviceAccount?: string | Record<string, unknown> | SecretRef;
/** Service account JSON file path. */
serviceAccountFile?: string;
/** Webhook audience type (app-url or project-number). */
audienceType?: "app-url" | "project-number";
/** Audience value (app URL or project number). */
audience?: string;
/** Exact add-on principal to accept when app-url delivery uses add-on tokens. */
appPrincipal?: string;
/** Google Chat webhook path (default: /googlechat). */
webhookPath?: string;
/** Google Chat webhook URL (used to derive the path). */
webhookUrl?: string;
/** Optional bot user resource name (users/...). */
botUser?: string;
/** If false, ignore all incoming Google Chat DMs. Default: true. */
dm?: GoogleChatDmConfig;
/**
* Typing indicator mode (default: "message").
* - "none": No indicator
* - "message": Send "_<name> is typing..._" then edit with response
* - "reaction": React with 👀 to user message, remove on reply
* NOTE: Reaction mode requires user OAuth (not supported with service account auth).
* If configured, falls back to message mode with a warning.
*/
typingIndicator?: "none" | "message" | "reaction";
};
type GoogleChatConfig = {
/** Optional per-account Google Chat configuration (multi-account). */
accounts?: Record<string, GoogleChatAccountConfig>;
/** Optional default account id when multiple accounts are configured. */
defaultAccount?: string;
} & GoogleChatAccountConfig;
//#endregion
//#region src/config/types.imessage.d.ts
/** Private-API and helper actions the iMessage runtime may expose to agents. */
type IMessageActionConfig = {
reactions?: boolean;
edit?: boolean;
unsend?: boolean;
reply?: boolean;
sendWithEffect?: boolean;
renameGroup?: boolean;
setGroupIcon?: boolean;
addParticipant?: boolean;
removeParticipant?: boolean;
leaveGroup?: boolean;
sendAttachment?: boolean;
polls?: boolean;
};
/** Inbound tapback notification policy. */
type IMessageReactionNotificationMode = "off" | "own" | "all";
type IMessageSendTransport = "auto" | "bridge" | "applescript";
/** Per-account iMessage runtime/config shape. */
type IMessageAccountConfig = Omit<CommonChannelMessagingConfig, "mentionPatterns" | "replyToMode"> & ChannelReadReceiptConfig & ChannelReactionConfig<IMessageReactionNotificationMode> & {
/** imsg CLI binary path (default: imsg). */
cliPath?: string;
/** Optional Messages db path override. */
dbPath?: string;
/** Remote SSH host token for SCP attachment fetches (`host` or `user@host`). */
remoteHost?: string;
/** Enable or disable private API message actions. */
actions?: IMessageActionConfig;
/** Optional default send service (imessage|sms|auto). */
service?: "imessage" | "sms" | "auto";
/** Preferred imsg RPC send transport. Default: auto. */
sendTransport?: IMessageSendTransport;
/** Optional default region (used when sending SMS). */
region?: string;
/** Include attachments + reactions in watch payloads. */
includeAttachments?: boolean;
/** Allowed local iMessage attachment roots (supports single-segment `*` wildcards). */
attachmentRoots?: string[];
/** Allowed remote iMessage attachment roots for SCP fetches (supports `*`). */
remoteAttachmentRoots?: string[];
/** Timeout for probe/RPC operations in milliseconds (default: 10000). */
probeTimeoutMs?: number;
/**
* Merge consecutive same-sender DM rows from `chat.db` into a single agent
* turn, so Apple's split-send (`<command> <URL>` arriving as two separate
* rows several seconds apart) lands as one merged message. DM-only — group chats
* keep instant per-message dispatch. Widens the default inbound debounce
* window to 7000 ms when enabled without an explicit
* `messages.inbound.byChannel.imessage` or global
* `messages.inbound.debounceMs`. Default: `false`.
*/
groups?: Record<string, {
requireMention?: boolean;
tools?: GroupToolPolicyConfig;
toolsBySender?: GroupToolPolicyBySenderConfig;
/**
* Per-group system prompt. Injected into the agent's system prompt on
* every turn that handles a message in that group. Matches the shape
* already supported by Discord, Telegram, IRC, Slack, GoogleChat, and
* other group-capable channels. The wildcard `groups["*"]` entry is
* also honored.
*/
systemPrompt?: string;
}>;
/**
* Catchup: replay inbound messages that arrived in `chat.db` while the
* gateway was offline (crash, restart, mac sleep). Disabled by default.
* See https://github.com/openclaw/openclaw/issues/78649.
*/
catchup?: {
/** Master switch. Default `false`. */
enabled?: boolean;
/**
* Maximum age of replayable messages in minutes. Messages older than
* `now - maxAgeMinutes` are skipped even when the cursor is older.
* Defense against runaway replay (the inverse of #62761). Default
* `120` (2 h). Clamp `[1, 720]`.
*/
maxAgeMinutes?: number;
/**
* Maximum messages to replay per catchup pass. Default `50`. Clamp
* `[1, 500]`.
*/
perRunLimit?: number;
/**
* On first run when no cursor exists, look back this many minutes.
* Default `30`.
*/
firstRunLookbackMinutes?: number;
/**
* Per-message retry ceiling. After this many consecutive failed
* dispatch attempts against the same message guid, catchup logs a
* `warn` and force-advances the cursor past the wedged message.
* Default `10`. Clamp `[1, 1000]`.
*/
maxFailureRetries?: number;
};
};
/** Top-level iMessage config, with optional account map layered over default account fields. */
type IMessageConfig = {
/** Optional per-account iMessage configuration (multi-account). */
accounts?: Record<string, IMessageAccountConfig>;
/** Optional default account id when multiple accounts are configured. */
defaultAccount?: string;
} & IMessageAccountConfig;
//#endregion
//#region src/config/types.implicit-mentions.d.ts
type ChannelImplicitMentionsConfig = {
/** Treat replies to the bot's own message as implicit mentions. */
replyToBot?: boolean;
/** Treat quoted bot messages as implicit mentions. */
quotedBot?: boolean;
/** Treat follow-ups in threads the bot participated in as implicit mentions. */
threadParticipation?: boolean;
};
//#endregion
//#region src/config/types.irc.d.ts
type IrcAccountConfig = Omit<CommonChannelMessagingConfig, "mentionPatterns"> & {
/** IRC server hostname (example: irc.example.com). */
host?: string;
/** IRC server port (default: 6697 with TLS, otherwise 6667). */
port?: number;
/** Use TLS for IRC connection (default: true). */
tls?: boolean;
/** IRC nickname to identify this bot. */
nick?: string;
/** IRC USER field username (defaults to nick). */
username?: string;
/** IRC USER field realname (default: OpenClaw). */
realname?: string;
/** Optional IRC server password (sensitive). */
password?: string;
/** Optional file path containing IRC server password. */
passwordFile?: string;
/** Optional NickServ identify/register settings. */
nickserv?: {
/** Enable NickServ identify/register after connect (default: enabled when password is set). */
enabled?: boolean;
/** NickServ service nick (default: NickServ). */
service?: string;
/** NickServ password (sensitive). */
password?: string;
/** Optional file path containing NickServ password. */
passwordFile?: string;
/** If true, send NickServ REGISTER on connect. */
register?: boolean;
/** Email used with NickServ REGISTER. */
registerEmail?: string;
};
/** Auto-join channel list at connect (example: ["#openclaw"]). */
channels?: string[];
/** Outbound text chunk size (chars). Default: 350. */
textChunkLimit?: number;
groups?: Record<string, {
requireMention?: boolean;
tools?: GroupToolPolicyConfig;
toolsBySender?: GroupToolPolicyBySenderConfig;
allowFrom?: Array<string | number>;
skills?: string[];
enabled?: boolean;
systemPrompt?: string;
}>;
};
type IrcConfig = {
/** Optional per-account IRC configuration (multi-account). */
accounts?: Record<string, IrcAccountConfig>;
/** Optional default account id when multiple accounts are configured. */
defaultAccount?: string;
} & IrcAccountConfig;
//#endregion
//#region src/config/types.msteams.d.ts
type MSTeamsWebhookConfig = {
/** Port for the webhook server. Default: 3978. */
port?: number;
/** Path for the messages endpoint. Default: /api/messages. */
path?: string;
};
/** Teams SDK cloud environment. Public cloud is the default. */
type MSTeamsCloudName = "Public" | "USGov" | "USGovDoD" | "China";
/**
* Bot Framework OAuth SSO configuration for Microsoft Teams.
*
* When enabled, the plugin handles the `signin/tokenExchange` and
* `signin/verifyState` invoke activities that Teams sends after an
* `oauthCard` is presented to the user. The exchanged user token is
* persisted via the Bot Framework User Token service so downstream
* tools can call Microsoft Graph with delegated permissions.
*
* Prerequisites (Azure portal):
* - The bot's Azure AD (Entra) app is configured with an exposed API
* scope (for example `access_as_user`) and lists the Teams client
* IDs in `knownClientApplications`.
* - The Bot Framework channel registration has an OAuth Connection
* Setting whose name matches `connectionName` below, pointing at
* the same Azure AD app.
*/
type MSTeamsSsoConfig = {
/** If true, handle signin/tokenExchange + signin/verifyState invokes. Default: false. */
enabled?: boolean;
/**
* Name of the OAuth connection configured on the Bot Framework channel
* registration (Azure Bot resource). Required when `enabled` is true.
*/
connectionName?: string;
};
/** Reply style for MS Teams messages. */
type MSTeamsReplyStyle = "thread" | "top-level";
/** Channel-level config for MS Teams. */
type MSTeamsChannelConfig = {
/** Require @mention to respond. Default: true. */
requireMention?: boolean;
/** Optional tool policy overrides for this channel. */
tools?: GroupToolPolicyConfig;
toolsBySender?: GroupToolPolicyBySenderConfig;
/** Reply style: "thread" replies to the message, "top-level" posts a new message. */
replyStyle?: MSTeamsReplyStyle;
};
/** Team-level config for MS Teams. */
type MSTeamsTeamConfig = {
/** Default requireMention for channels in this team. */
requireMention?: boolean;
/** Default tool policy for channels in this team. */
tools?: GroupToolPolicyConfig;
toolsBySender?: GroupToolPolicyBySenderConfig;
/** Default reply style for channels in this team. */
replyStyle?: MSTeamsReplyStyle;
/** Per-channel overrides. Key is conversation ID (e.g., "19:...@thread.tacv2"). */
channels?: Record<string, MSTeamsChannelConfig>;
};
type MSTeamsConfig = Omit<CommonChannelMessagingConfig<string[], string, string, ChannelPreviewStreamingConfig>, "mentionPatterns" | "name" | "replyToMode"> & Pick<ChannelBotInteractionConfig<boolean>, "dangerouslyAllowNameMatching"> & {
/** Azure Bot App ID (from Azure Bot registration). */
appId?: string;
/** Azure Bot App Password / Client Secret. */
appPassword?: SecretInput;
/** Azure AD Tenant ID (for single-tenant bots). */
tenantId?: string;
/** Teams SDK cloud environment. Default: Public. */
cloud?: MSTeamsCloudName;
/**
* Bot Connector service URL used by SDK proactive sends/edits/deletes.
* Set with `cloud` for USGov/DoD SDK clouds; set alone for GCC.
*/
serviceUrl?: string;
/**
* Authentication type.
* - `"secret"` (default): uses `appPassword` (client secret).
* - `"federated"`: uses workload identity / managed identity / certificate.
*/
authType?: "secret" | "federated";
/** Path to a PEM certificate file for certificate-based auth. Used when `authType` is `"federated"`. */
certificatePath?: string;
/** Certificate thumbprint (hex SHA-1) for certificate-based auth. */
certificateThumbprint?: string;
/** If `true`, use Azure Managed Identity (system- or user-assigned) instead of a certificate. */
useManagedIdentity?: boolean;
/** User-assigned managed-identity client ID. When omitted with `useManagedIdentity: true`, system-assigned identity is used. */
managedIdentityClientId?: string;
/** Webhook server configuration. */
webhook?: MSTeamsWebhookConfig;
/** Send native Teams typing indicator before replies. Default: true for groups/channels; DMs use informative stream status. */
typingIndicator?: boolean;
/**
* Allowed host suffixes for inbound attachment downloads.
* Use ["*"] to allow any host (not recommended).
*/
mediaAllowHosts?: Array<string>;
/**
* Allowed host suffixes for attaching Authorization headers to inbound media retries.
* Use specific hosts only; avoid multi-tenant suffixes.
*/
mediaAuthAllowHosts?: Array<string>;
/**
* Query Graph for channel/group media when Bot Framework HTML omits file markers.
* Requires the documented Graph permissions and adds one message lookup per
* otherwise unresolved HTML activity. Default: false.
*/
graphMediaFallback?: boolean;
/** Default: require @mention to respond in channels/groups. */
requireMention?: boolean;
/** Default reply style: "thread" replies to the message, "top-level" posts a new message. */
replyStyle?: MSTeamsReplyStyle;
/** Per-team config. Key is team ID (from the /team/ URL path segment). */
teams?: Record<string, MSTeamsTeamConfig>;
/** SharePoint site ID for file uploads in group chats/channels (e.g., "contoso.sharepoint.com,guid1,guid2"). */
sharePointSiteId?: string;
/** Show a welcome Adaptive Card when the bot is added to a 1:1 chat. Default: true. */
welcomeCard?: boolean;
/** Custom prompt starter labels shown on the welcome card. */
promptStarters?: string[];
/** Show a welcome message when the bot is added to a group chat. Default: false. */
groupWelcomeCard?: boolean;
/** Enable the Teams feedback loop (thumbs up/down) on AI-generated messages. Default: true. */
feedbackEnabled?: boolean;
/** Enable background reflection when a user gives negative feedback. Default: true. */
feedbackReflection?: boolean;
/** Minimum interval (ms) between reflections per session. Default: 300000 (5 min). */
feedbackReflectionCooldownMs?: number;
/** Delegated auth settings for user-scoped Graph API actions (e.g., reactions). */
delegatedAuth?: {
/** Enable delegated auth (user sign-in for Graph actions that need user scope). */
enabled?: boolean;
/** Additional scopes to request during OAuth consent. */
scopes?: string[];
};
/** Bot Framework OAuth SSO (signin/tokenExchange + signin/verifyState) settings. */
sso?: MSTeamsSsoConfig;
};
//#endregion
//#region src/config/types.signal.d.ts
type SignalReactionNotificationMode = "off" | "own" | "all" | "allowlist";
type SignalReactionLevel = "off" | "ack" | "minimal" | "extensive";
type SignalTransportConfig = {
kind: "managed-native";
/** Optional signal-cli config directory path (passed as --config). */
configPath?: string;
/** Native daemon connection URL when it differs from the managed bind endpoint. */
url?: string;
/** HTTP host for the managed signal-cli daemon (default 127.0.0.1). */
httpHost?: string;
/** HTTP port for the managed signal-cli daemon (default 8080). */
httpPort?: number;
/** signal-cli binary path (default: signal-cli). */
cliPath?: string;
/** Max time to wait for signal-cli daemon startup (ms, cap 120000). */
startupTimeoutMs?: number;
receiveMode?: "on-start" | "manual";
ignoreStories?: boolean;
} | {
kind: "external-native";
/** Base URL for an externally managed native signal-cli HTTP daemon. */
url: string;
} | {
kind: "container";
/** Base URL for bbernhard/signal-cli-rest-api. */
url: string;
};
type SignalGroupConfig = {
requireMention?: boolean;
/** Emit internal message hooks for mention-skipped group messages. */
ingest?: boolean;
tools?: GroupToolPolicyConfig;
toolsBySender?: GroupToolPolicyBySenderConfig;
};
type SignalAccountConfig = Omit<CommonChannelMessagingConfig, "mentionPatterns"> & ChannelReadReceiptConfig & ChannelReactionConfig<SignalReactionNotificationMode, SignalReactionLevel, never, true> & {
/** Optional explicit E.164 account for signal-cli. */
account?: string;
/** Optional account UUID for signal-cli (used for loop protection). */
accountUuid?: string;
/** Concrete transport owned by this account. Defaults to managed native signal-cli. */
transport?: SignalTransportConfig;
/** Skip downloading inbound Signal attachments. */
ignoreAttachments?: boolean;
/** OpenClaw-side target aliases keyed by friendly name. */
aliases?: Record<string, string>;
/** Per-group overrides keyed by Signal group id (or "*"). */
groups?: Record<string, SignalGroupConfig>;
/** Optional per-chat-type native reply quoting overrides. */
replyToModeByChatType?: Partial<Record<"direct" | "group", ReplyToMode>>;
/** Action toggles for message tool capabilities. */
actions?: {
/** Enable/disable sending reactions via message tool (default: true). */
reactions?: boolean;
};
};
type SignalConfig = {
/** Optional per-account Signal configuration (multi-account). */
accounts?: Record<string, SignalAccountConfig>;
/** Optional default account id when multiple accounts are configured. */
defaultAccount?: string;
} & SignalAccountConfig;
//#endregion
//#region src/config/types.slack.d.ts
type SlackDmConfig = {
/** If false, ignore all incoming Slack DMs. Default: true. */
enabled?: boolean;
/** If true, allow group DMs (default: false). */
groupEnabled?: boolean;
/** Optional allowlist for group DM channels (ids or slugs). */
groupChannels?: Array<string | number>;
};
type SlackChannelConfig = {
/** If false, disable the bot in this channel. */
enabled?: boolean;
/** Require mentioning the bot to trigger replies. */
requireMention?: boolean;
/**
* Ignore room messages that mention another user or user group but not this bot.
* Requires a resolved bot user ID. Default: false.
*/
ignoreOtherMentions?: boolean;
/** Override Slack reply/thread behavior for this channel. */
replyToMode?: ReplyToMode;
/** Optional tool policy overrides for this channel. */
tools?: GroupToolPolicyConfig;
toolsBySender?: GroupToolPolicyBySenderConfig;
/** Allow bot-authored messages to trigger replies (default: false). Set to "mentions" to only allow bot messages that @mention this bot. */
allowBots?: boolean | "mentions";
/** Sliding-window bot-pair loop guard for accepted bot-authored Slack messages. */
botLoopProtection?: ChannelBotLoopProtectionConfig;
/** Allowlist of users that can invoke the bot in this channel. */
users?: Array<string | number>;
/** Optional skill filter for this channel. */
skills?: string[];
/** Optional system prompt for this channel. */
systemPrompt?: string;
/** Slack presence polling and agent wake mode for this channel. */
presenceEvents?: SlackPresenceEventsConfig;
};
type SlackPresenceEventsMode = "off" | "auto" | "on";
type SlackPresenceEventsConfig = {
/** Presence wake mode. Default: off. */
mode?: SlackPresenceEventsMode;
/** Override the default presence-event guidance. Empty omits guidance. Maximum: 20,000 characters. */
prompt?: string;
};
type SlackReactionNotificationMode = "off" | "own" | "all" | "allowlist";
type SlackStreamingProgressConfig = ChannelStreamingProgressConfig & {
/** Slack progress presentation. "compact" keeps one editable text draft. Default: "card". */
style?: "card" | "compact";
/** Use Slack-native task cards for card-style progress. Default: true. */
nativeTaskCards?: boolean;
};
type SlackChannelStreamingConfig = ChannelStreamingConfig<SlackStreamingProgressConfig>;
type SlackExecApprovalConfig = ChannelExecApprovalConfig;
type SlackCapabilitiesConfig = string[];
type SlackActionConfig = {
reactions?: boolean;
messages?: boolean;
pins?: boolean;
search?: boolean;
permissions?: boolean;
memberInfo?: boolean;
channelInfo?: boolean;
emojiList?: boolean;
};
type SlackSlashCommandConfig = {
/** Enable handling for the configured slash command (default: false). */
enabled?: boolean;
/** Slash command name (default: "openclaw"). */
name?: string;
/** Session key prefix for slash commands (default: "slack:slash"). */
sessionPrefix?: string;
/** Reply ephemerally (default: true). */
ephemeral?: boolean;
};
type SlackThreadConfig = {
/** Scope for thread history context (thread|channel). Default: thread. */
historyScope?: "thread" | "channel";
/** If true, thread sessions inherit the parent channel transcript. Default: false. */
inheritParent?: boolean;
/** Maximum number of thread messages to fetch as context when starting a new thread session (default: 20). Set to 0 to disable thread history fetching. */
initialHistoryLimit?: number;
};
type SlackRelayConfig = {
/** Full relay websocket URL, including the route path. */
url?: string;
/** Bearer token used to authenticate the gateway websocket to the Slack relay. */
authToken?: SecretInput;
/** Gateway destination id registered with openclaw-slack-router. */
gatewayId?: string;
};
type SlackAccountConfig = Omit<CommonChannelMessagingConfig<SlackCapabilitiesConfig, string | number, string, SlackChannelStreamingConfig>, "groupAllowFrom"> & ChannelBotInteractionConfig & ChannelReactionConfig<SlackReactionNotificationMode, never, string, true> & {
/** Post a room-specific introduction when joining a group. Default: true. */
joinIntro?: boolean;
/** @deprecated Doctor-only legacy input. */
identity?: "bot" | "user";
/** @deprecated Doctor-only legacy input. */
socketMode?: {
clientPingTimeout?: number;
serverPingTimeout?: number;
pingPongLoggingEnabled?: boolean;
};
/** Slack author identity. Default: bot. */
postAs?: "bot" | "user";
/** Slack connection mode (socket|http|relay). Default: socket. */
mode?: "socket" | "http" | "relay";
/** Slack SDK Socket Mode transport options. Ignored in HTTP mode. */
/** Relay-delivered Slack event source. Used when mode is "relay". */
relay?: SlackRelayConfig;
/** Slack signing secret (required for HTTP mode). */
signingSecret?: SecretInput;
/** Slack Events API webhook path (default: /slack/events). */
webhookPath?: string;
/** Slack-native exec approval delivery + approver authorization. */
execApprovals?: SlackExecApprovalConfig;
/** Override native command registration for Slack (bool or "auto"). */
commands?: ProviderCommandsConfig;
botToken?: SecretInput;
appToken?: SecretInput;
userToken?: SecretInput;
/** If true, restrict user token to read operations only. Default: true. */
userTokenReadOnly?: boolean;
/** Default mention requirement for channel messages (default: true). */
requireMention?: boolean;
/** Implicit mention policy for replies, quotes, and participated threads. */
implicitMentions?: ChannelImplicitMentionsConfig;
/** Pass through Slack chat.postMessage link unfurl control. Default: false. */
unfurlLinks?: boolean;
/** Pass through Slack chat.postMessage media unfurl control. Omitted by default. */
unfurlMedia?: boolean;
/**
* Optional per-chat-type reply threading overrides.
* Example: { direct: "all", group: "first", channel: "off" }.
*/
replyToModeByChatType?: Partial<Record<"direct" | "group" | "channel", ReplyToMode>>;
/** Thread session behavior. */
thread?: SlackThreadConfig;
/** Poll Slack presence and wake the routed agent on away-to-active transitions. Default: off. */
presenceEvents?: SlackPresenceEventsConfig;
actions?: SlackActionConfig;
slashCommand?: SlackSlashCommandConfig;
dm?: SlackDmConfig;
channels?: Record<string, SlackChannelConfig>;
/** Reaction emoji added while processing a reply (e.g. "hourglass_flowing_sand"). Removed when done. Useful as a typing indicator fallback when assistant mode is not enabled. */
typingReaction?: string;
};
type SlackConfig = {
/** Optional per-account Slack configuration (multi-account). */
accounts?: Record<string, SlackAccountConfig>;
/** Optional default account id when multiple accounts are configured. */
defaultAccount?: string;
} & SlackAccountConfig;
//#endregion
//#region src/config/types.telegram.d.ts
type TelegramActionConfig = {
reactions?: boolean;
sendMessage?: boolean;
/** Enable poll creation. Requires sendMessage to also be enabled. */
poll?: boolean;
deleteMessage?: boolean;
editMessage?: boolean;
/** Enable sticker actions (send and search). */
sticker?: boolean;
/** Enable forum topic creation. */
createForumTopic?: boolean;
/** Enable forum topic editing (rename / change icon). */
editForumTopic?: boolean;
};
type TelegramThreadBindingsConfig = SessionThreadBindingsConfig;
type TelegramNetworkConfig = {
/** Override Node's autoSelectFamily behavior (true = enable, false = disable). */
autoSelectFamily?: boolean;
/**
* DNS result order for network requests ("ipv4first" | "verbatim").
* Set to "ipv4first" to prioritize IPv4 addresses and work around IPv6 issues.
* Default: "ipv4first" on Node 22+ to avoid common fetch failures.
*/
dnsResultOrder?: "ipv4first" | "verbatim";
/**
* Dangerous opt-in for Telegram media downloads in trusted fake-IP or
* transparent-proxy environments that resolve api.telegram.org to
* private/internal/special-use addresses.
*/
dangerouslyAllowPrivateNetwork?: boolean;
};
type TelegramInlineButtonsScope = "off" | "dm" | "group" | "all" | "allowlist";
type TelegramPreviewStreamingConfig = Omit<ChannelPreviewStreamingConfig, "preview"> & {
preview?: ChannelStreamingPreviewConfig;
};
type TelegramExecApprovalConfig = ChannelExecApprovalConfig;
type TelegramCapabilitiesConfig = string[] | {
inlineButtons?: TelegramInlineButtonsScope;
};
/** Custom command definition for Telegram bot menu. */
type TelegramCustomCommand = {
/** Command name (without leading /). */
command: string;
/** Description shown in Telegram command menu. */
description: string;
};
type TelegramAccountConfig = CommonChannelMessagingConfig<TelegramCapabilitiesConfig, string | number, string | number, TelegramPreviewStreamingConfig> & ChannelReactionConfig<"off" | "own" | "all", "off" | "ack" | "minimal" | "extensive", string> & {
/** Post a room-specific introduction when joining a group. Default: true. */
joinIntro?: boolean;
/** Telegram-native exec approval delivery + approver authorization. */
execApprovals?: TelegramExecApprovalConfig;
/** Override native command registration for Telegram (bool or "auto"). */
commands?: ProviderCommandsConfig;
/** Custom commands to register in Telegram's command menu (merged with native). */
customCommands?: TelegramCustomCommand[];
botToken?: SecretInput;
/** Path to a regular file containing the bot token; symlinks are rejected. */
tokenFile?: string;
groups?: Record<string, TelegramGroupConfig>;
/** Per-DM configuration for Telegram DM topics (key is chat ID). */
direct?: Record<string, TelegramDirectConfig>;
/**
* Use Telegram Bot API 10.3 rich messages for text sends and edits.
* When false (default), falls back to HTML/plain text formatting via sendMessage.
* Set to true to enable native tables, details, and rich media via sendRichMessage.
* Note: Some Telegram clients (Web, Desktop, older mobile) do NOT support
* sendRichMessage and will show "This message is not supported" errors.
* Default: false.
*/
richMessages?: boolean;
/** Network transport overrides for Telegram. */
network?: TelegramNetworkConfig;
proxy?: string;
webhookUrl?: string;
webhookSecret?: string;
webhookPath?: string;
/** Local webhook listener bind host (default: 127.0.0.1). */
webhookHost?: string;
/** Local webhook listener bind port (default: 8787). */
webhookPort?: number;
/** Path to the self-signed certificate (PEM) to upload to Telegram during webhook registration. */
webhookCertPath?: string;
/** Per-action tool gating (default: true for all). */
actions?: TelegramActionConfig;
/** Telegram thread/conversation binding overrides. */
threadBindings?: TelegramThreadBindingsConfig;
/**
* Controls which user reactions trigger notifications:
* - "off" (default): ignore all reactions
* - "own": notify when users react to bot messages
* - "all": notify agent of all reactions
*/
/**
* Controls agent's reaction capability:
* - "off": agent cannot react
* - "ack" (default): bot sends acknowledgment reactions (👀 while processing)
* - "minimal": agent can react sparingly (guideline: 1 per 5-10 exchanges)
* - "extensive": agent can react liberally when appropriate
*/
/** Controls whether link previews are shown in outbound messages. Default: true. */
linkPreview?: boolean;
/** Send Telegram bot error replies silently (no notification sound). Default: false. */
silentErrorReplies?: boolean;
/** Controls outbound error reporting: always, once per cooldown window, or silent. */
errorPolicy?: "always" | "once" | "silent";
/**
* Per-channel outbound response prefix override.
*
* Account values take precedence over the channel-level value.
* Use `""` to explicitly disable a global prefix for this channel.
* Use `"auto"` to derive `[{identity.name}]` from the routed agent.
*/
/**
* Per-channel ack reaction override.
* Telegram expects unicode emoji (e.g., "👀") rather than shortcodes.
*/
/** Custom Telegram Bot API root URL (e.g. "https://my-proxy.example.com" or a local Bot API server), not a /bot<TOKEN> endpoint. */
apiRoot?: string;
/** Trusted local filesystem roots for self-hosted Telegram Bot API absolute file_path values. */
trustedLocalFileRoots?: string[];
/** Auto-rename DM forum topics on first message using LLM. Default: true. */
autoTopicLabel?: AutoTopicLabelConfig;
};
type TelegramTopicConfig = {
requireMention?: boolean;
/** Emit internal message hooks for mention-skipped topic messages. */
ingest?: boolean;
/** Per-topic override for group message policy (open|disabled|allowlist). */
groupPolicy?: GroupPolicy;
/** If specified, only load these skills for this topic. Omit = all skills; empty = no skills. */
skills?: string[];
/** If false, disable the bot for this topic. */
enabled?: boolean;
/** Optional allowlist for topic senders (numeric Telegram user IDs). */
allowFrom?: Array<string | number>;
/** Optional system prompt snippet for this topic. */
systemPrompt?: string;
/** If true, skip automatic voice-note transcription for mention detection in this topic. */
disableAudioPreflight?: boolean;
/** Route this topic to a specific agent (overrides group-level and binding routing). */
agentId?: string;
/** Controls outbound error reporting for this topic. */
errorPolicy?: "always" | "once" | "silent";
};
type TelegramGroupConfig = {
requireMention?: boolean;
/** Emit internal message hooks for mention-skipped group messages. */
ingest?: boolean;
/** Per-group override for group message policy (open|disabled|allowlist). */
groupPolicy?: GroupPolicy;
/** Optional tool policy overrides for this group. */
tools?: GroupToolPolicyConfig;
toolsBySender?: GroupToolPolicyBySenderConfig;
/** If specified, only load these skills for this group (when no topic). Omit = all skills; empty = no skills. */
skills?: string[];
/** Per-topic configuration (key is message_thread_id as string, or "*" for topic defaults). */
topics?: Record<string, TelegramTopicConfig>;
/** If false, disable the bot for this group (and its topics). */
enabled?: boolean;
/** Optional allowlist for group senders (numeric Telegram user IDs). */
allowFrom?: Array<string | number>;
/** Optional system prompt snippet for this group. */
systemPrompt?: string;
/** If true, skip automatic voice-note transcription for mention detection in this group. */
disableAudioPreflight?: boolean;
/** Controls outbound error reporting for this group. */
errorPolicy?: "always" | "once" | "silent";
};
/** Config for LLM-based auto-topic labeling. */
type AutoTopicLabelConfig = boolean | {
enabled?: boolean;
/** Custom prompt for LLM-based topic naming. */
prompt?: string;
};
type TelegramDirectConfig = {
/** Per-DM override for DM message policy (open|disabled|allowlist). */
dmPolicy?: DmPolicy;
/** Optional tool policy overrides for this DM. */
tools?: GroupToolPolicyConfig;
toolsBySender?: GroupToolPolicyBySenderConfig;
/** If specified, only load these skills for this DM (when no topic). Omit = all skills; empty = no skills. */
skills?: string[];
/** Per-topic configuration for DM topics (key is message_thread_id as string, or "*" for topic defaults). */
topics?: Record<string, TelegramTopicConfig>;
/** If false, disable the bot for this DM (and its topics). */
enabled?: boolean;
/** If true, require messages to be from a topic when topics are enabled. */
requireTopic?: boolean;
/** Optional allowlist for DM senders (numeric Telegram user IDs). */
allowFrom?: Array<string | number>;
/** Optional system prompt snippet for this DM. */
systemPrompt?: string;
/** Controls outbound error reporting for this DM. */
errorPolicy?: "always" | "once" | "silent";
/** Auto-rename DM forum topics on first message using LLM. Default: true. */
autoTopicLabel?: AutoTopicLabelConfig;
};
type TelegramConfig = {
/** Optional per-account Telegram configuration (multi-account). */
accounts?: Record<string, TelegramAccountConfig>;
/** Optional default account id when multiple accounts are configured. */
defaultAccount?: string;
} & TelegramAccountConfig;
//#endregion
//#region src/utils/reaction-level.d.ts
/**
* Shared reaction-level resolver for channel plugins that expose ACK and agent reaction controls.
* Channel adapters supply defaults/fallbacks; this helper owns the common flag expansion.
*/
/** User-configurable reaction behavior level for channel delivery. */
type ReactionLevel = "off" | "ack" | "minimal" | "extensive";
//#endregion
//#region src/config/types.whatsapp.d.ts
type WhatsAppActionConfig = {
reactions?: boolean;
sendMessage?: boolean;
polls?: boolean;
/** Enable the experimental requester-bound voice-call tool. Default: false. */
calls?: boolean;
};
type WhatsAppReactionLevel = ReactionLevel;
type WhatsAppGroupConfig = {
requireMention?: boolean;
tools?: GroupToolPolicyConfig;
toolsBySender?: GroupToolPolicyBySenderConfig;
/** Optional system prompt for this group. */
systemPrompt?: string;
};
type WhatsAppDirectConfig = {
/** Optional system prompt for this direct chat. */
systemPrompt?: string;
};
type WhatsAppAckReactionConfig = {
/** Emoji to use for acknowledgment (e.g., "👀"). Empty = disabled. */
emoji?: string;
/** Send reactions in direct chats. Default: true. */
direct?: boolean;
/**
* Send reactions in group chats:
* - "always": react to all group messages
* - "mentions": react only when bot is mentioned
* - "never": never react in groups
* Default: "mentions"
*/
group?: "always" | "mentions" | "never";
};
type WhatsAppSharedConfig = CommonChannelMessagingConfig<string[], string> & ChannelReadReceiptConfig & ChannelReactionConfig<never, WhatsAppReactionLevel, WhatsAppAckReactionConfig> & {
/** Same-phone setup (bot uses your personal WhatsApp number). */
selfChatMode?: boolean;
groups?: Record<string, WhatsAppGroupConfig>;
/** Per-direct-chat prompt overrides keyed by user ID or `*` wildcard. */
direct?: Record<string, WhatsAppDirectConfig>;
};
type WhatsAppSpecificConfig = {
/** @deprecated Doctor-only legacy input. */
messagePrefix?: string;
};
type WhatsAppConfig = Omit<WhatsAppSharedConfig, "name"> & WhatsAppSpecificConfig & {
/** Optional per-account WhatsApp configuration (multi-account). */
accounts?: Record<string, WhatsAppAccountConfig>;
/** Optional default account id when multiple accounts are configured. */
defaultAccount?: string;
/** Per-action tool gating. Calls default to false; existing actions default to true. */
actions?: WhatsAppActionConfig;
/** Plugin hook opt-in configuration for privacy-sensitive inbound events. */
pluginHooks?: {
/** Enable message_received hooks to broadcast inbound WhatsApp messages to plugins. */
messageReceived?: boolean;
};
};
type WhatsAppAccountConfig = WhatsAppSpecificConfig & WhatsAppSharedConfig & {
/** Optional display name for this account (used in CLI/UI lists). */
name?: string;
/** Override auth directory (Baileys multi-file auth state). */
authDir?: string;
/** Plugin hook opt-in configuration for privacy-sensitive inbound events. */
pluginHooks?: {
/** Enable message_received hooks to broadcast inbound WhatsApp messages to plugins. */
messageReceived?: boolean;
};
};
//#endregion
//#region src/config/types.channels.d.ts
type ChannelDefaultsConfig = {
/** @deprecated Doctor-only legacy input. */
heartbeat?: ChannelHeartbeatVisibilityConfig;
/** Default group-chat admission policy inherited by channels that support groups. */
groupPolicy?: GroupPolicy;
/** Default history/context visibility inherited by channel configs. */
contextVisibility?: ContextVisibilityMode;
/** Default heartbeat visibility for all channels. */
heartbeatVisibility?: ChannelHeartbeatVisibilityConfig;
/** Default pair loop guard settings for channels that support bot loop protection. */
botLoopProtection?: ChannelBotLoopProtectionConfig;
/** Default implicit-mention policy inherited by supporting channels. */
implicitMentions?: ChannelImplicitMentionsConfig;
};
/** Provider/channel/target model override map used by channel dispatch. Keys are channel-specific group IDs, thread IDs, channel names, or DM peer identifiers (see docs/gateway/config-channels.md). */
type ChannelModelByChannelConfig = Record<string, Record<string, string>>;
/** JSON-compatible open-world channel section for plugin ids unknown to core. */
type OpenWorldChannelConfig = ReturnType<typeof JSON.parse>;
interface ChannelsConfig {
/** Shared defaults inherited by channel sections unless they override them. */
defaults?: ChannelDefaultsConfig;
/** Map provider -> channel id / DM peer id -> model override. See docs/gateway/config-channels.md for supported key forms. */
modelByChannel?: ChannelModelByChannelConfig;
discord?: DiscordConfig;
googlechat?: GoogleChatConfig;
imessage?: IMessageConfig;
irc?: IrcConfig;
msteams?: MSTeamsConfig;
signal?: SignalConfig;
slack?: SlackConfig;
telegram?: TelegramConfig;
whatsapp?: WhatsAppConfig;
/**
* Channel sections are plugin-owned and keyed by arbitrary channel ids.
* Open-world config keeps SDK/plugin-owned sections ergonomic for dynamic ids.
*/
[key: string]: OpenWorldChannelConfig;
}
//#endregion
//#region src/transcripts/config.d.ts
/**
* Configuration normalization for transcript capture/import.
*
* Raw config can contain optional auto-start provider locators; resolution
* returns bounded defaults and drops malformed entries before runtime startup.
*/
/** Raw auto-start transcript source entry from config. */
type TranscriptsAutoStartConfig = {
providerId: string;
whenOccupied?: boolean;
sessionId?: string;
title?: string;
accountId?: string;
guildId?: string;
channelId?: string;
meetingUrl?: string;
};
/** Raw transcripts config block. */
type TranscriptsConfig = {
enabled?: boolean;
autoStart?: TranscriptsAutoStartConfig[];
};
//#endregion
//#region src/config/includes.d.ts
type ConfigIncludeOwnership = {
path: readonly string[];
kind: "single" | "multiple";
hasSiblingOverrides: boolean;
targetPath?: string;
targetPaths?: readonly string[];
};
//#endregion
//#region src/config/types.cron.d.ts
type CronFailureAlertConfig = {
enabled?: boolean;
after?: number;
cooldownMs?: number;
includeSkipped?: boolean;
mode?: "announce" | "webhook";
accountId?: string;
channel?: string;
to?: string;
};
type CronConfig = {
enabled?: boolean;
/** Skip missed recurring slots at startup; one-shot catch-up is unchanged. Default: false. */
skipMissedJobs?: boolean;
triggers?: {
enabled?: boolean;
};
/** Bearer token for cron webhook POST delivery. */
webhookToken?: SecretInput;
/** SSRF policy for all outbound cron webhook deliveries. */
webhookSsrfPolicy?: SsrFPolicyConfig;
/**
* How long to retain completed cron run sessions before automatic pruning.
* Accepts a duration string (e.g. "24h", "7d", "1h30m") or `false` to disable pruning.
* A zero duration (e.g. "0h") also disables pruning; negative durations are invalid.
* Default: "24h".
*/
sessionRetention?: string | false;
failureAlert?: CronFailureAlertConfig;
};
//#endregion
//#region src/gateway/control-ui-bootstrap-contract.d.ts
declare const CONTROL_UI_ENVIRONMENT_COLORS: readonly ["teal", "amber", "purple", "coral", "pink", "blue", "green", "red", "gray"];
type ControlUiEnvironment = {
label: string;
color: (typeof CONTROL_UI_ENVIRONMENT_COLORS)[number];
};
//#endregion
//#region src/gateway/operator-scopes.d.ts
declare const ADMIN_SCOPE: "operator.admin";
declare const READ_SCOPE: "operator.read";
declare const WRITE_SCOPE: "operator.write";
declare const APPROVALS_SCOPE: "operator.approvals";
declare const QUESTIONS_SCOPE: "operator.questions";
declare const PAIRING_SCOPE: "operator.pairing";
declare const TALK_SCOPE: "operator.talk";
declare const TALK_SECRETS_SCOPE: "operator.talk.secrets";
/** Operator privileges advertised by gateway auth and checked by method policy. */
type OperatorScope = typeof ADMIN_SCOPE | typeof READ_SCOPE | typeof WRITE_SCOPE | typeof APPROVALS_SCOPE | typeof QUESTIONS_SCOPE | typeof PAIRING_SCOPE | typeof TALK_SCOPE | typeof TALK_SECRETS_SCOPE;
//#endregion
//#region src/config/types.gateway.d.ts
/** Gateway bind-address policy for local server startup. */
type GatewayBindMode = "auto" | "lan" | "loopback" | "custom" | "tailnet";
type GatewayTlsConfig = {
/** Enable TLS for the gateway server. */
enabled?: boolean;
/** Auto-generate a self-signed cert if cert/key are missing (default: true). */
autoGenerate?: boolean;
/** PEM certificate path for the gateway server. */
certPath?: string;
/** PEM private key path for the gateway server. */
keyPath?: string;
/** Optional PEM CA bundle for TLS clients (mTLS or custom roots). */
caPath?: string;
};
type WideAreaDiscoveryConfig = {
/** Optional unicast DNS-SD domain (e.g. "openclaw.internal"). */
domain?: string;
};
/** mDNS/Bonjour metadata exposure level for local gateway discovery. */
type MdnsDiscoveryMode = "off" | "minimal" | "full";
type MdnsDiscoveryConfig = {
/**
* mDNS/Bonjour discovery broadcast mode (default: minimal).
* - off: disable mDNS entirely
* - minimal: omit cliPath/sshPort from TXT records
* - full: include cliPath/sshPort in TXT records
*/
mode?: MdnsDiscoveryMode;
};
type DiscoveryConfig = {
/** Wide-area DNS-SD discovery settings. */
wideArea?: WideAreaDiscoveryConfig;
/** Local mDNS/Bonjour discovery settings. */
mdns?: MdnsDiscoveryConfig;
};
type TalkProviderConfig = {
/** Provider API key (optional; provider-specific env fallback may apply). */
apiKey?: SecretInput;
/** Provider-owned Talk config fields. */
[key: string]: unknown;
};
type TalkRealtimeConfig = {
/** Active realtime voice provider. */
provider?: string;
/** Provider-specific realtime voice config keyed by provider id. */
providers?: Record<string, TalkProviderConfig>;
/** Provider model override for realtime sessions. */
model?: string;
/** Provider speaker voice name override for realtime sessions. */
speakerVoice?: string;
/** Provider speaker voice id override for realtime sessions. */
speakerVoiceId?: string;
/** Additional system instructions appended to realtime Talk sessions. */
instructions?: string;
/** Realtime execution mode. */
mode?: "realtime" | "stt-tts" | "transcription";
/** Byte/session transport. */
transport?: "webrtc" | "provider-websocket" | "gateway-relay" | "managed-room";
/** Voice activity detection threshold from 0 (most sensitive) to 1 (least sensitive). */
vadThreshold?: number;
/** Milliseconds of silence before the current user turn is committed. */
silenceDurationMs?: number;
/** Milliseconds of audio retained before detected speech begins. */
prefixPaddingMs?: number;
/** Provider-specific realtime reasoning effort. */
reasoningEffort?: string;
/** Tool/agent strategy for realtime sessions. */
brain?: "agent-consult" | "direct-tools" | "none";
/** How Gateway relay handles final user transcripts when the provider skips a consult. */
consultRouting?: "provider-direct" | "force-agent-consult";
};
type TalkConfig = {
/** Agent that owns Talk sessions created without an agent-scoped session key. */
agentId?: string;
/** Active Talk TTS provider (for example "acme-speech"). */
provider?: string;
/** Provider-specific Talk config keyed by provider id. */
providers?: Record<string, TalkProviderConfig>;
/** Realtime Talk provider, model, voice, mode, transport, and brain config. */
realtime?: TalkRealtimeConfig;
/** Optional thinking level override for the agent run behind Talk realtime consults. */
consultThinkingLevel?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive" | "max" | "ultra";
/** Optional fast mode override for the agent run behind Talk realtime consults. */
consultFastMode?: boolean;
/** BCP 47 locale id used for Talk speech recognition on device nodes and the iOS system-voice fallback. */
speechLocale?: string;
/** Stop speaking when user starts talking (default: true). */
interruptOnSpeech?: boolean;
/** Milliseconds of user silence before Talk mode sends the transcript after a pause. */
silenceTimeoutMs?: number;
};
type GatewayControlUiConfig = {
/** @deprecated Doctor-only legacy input. */
chatMessageMaxWidth?: string;
/**
* @deprecated Upgrade-only transport input. Retained so releases that shipped
* this break-glass flag can migrate an unpaired browser safely.
*/
dangerouslyDisableDeviceAuth?: boolean;
/** If false, the Gateway will not serve the Control UI (default /). */
enabled?: boolean;
/** Optional base path prefix for the Control UI (e.g. "/openclaw"). */
basePath?: string;
experimental?: {
/** Allow native UI from user-installed plugins (default false; bundled UI stays available). */
customPlugins?: boolean;
};
/** Optional filesystem root for Control UI assets (defaults to dist/control-ui). */
root?: string;
/** Optional visual label and named color distinguishing this Gateway environment. */
environment?: ControlUiEnvironment;
/** Show the Discord community invitation in this Gateway's Control UI (default true). */
communityInvite?: boolean;
/** Optional service credential used only for Control UI GitHub previews and discovery. */
github?: {
token?: SecretInput;
};
/** Produce utility-model session status digests for subscribed Control UI clients (default true). */
sessionObserver?: boolean;
/**
* Embed sandbox mode for hosted Control UI previews.
* - strict: no script execution inside embeds
* - scripts: allow scripts while keeping embeds origin-isolated (default)
* - trusted: allow scripts and same-origin privileges
*/
embedSandbox?: "strict" | "scripts" | "trusted";
/**
* DANGEROUS: Allow hosted embeds to load absolute external http(s) URLs.
* Default off; prefer hosted /__openclaw__/canvas or /__openclaw__/a2ui content.
*/
allowExternalEmbedUrls?: boolean;
/** Fetch public-site favicons through the Gateway for Control UI links (default true). */
automaticallyFetchFavicons?: boolean;
/** Optional max-width for grouped Control UI chat messages (default: min(900px, 68%)). */
/** Allowed browser origins for Control UI/WebChat websocket connections. */
allowedOrigins?: string[];
/**
* DANGEROUS: Keep Host-header origin fallback behavior.
* Supported long-term for deployments that intentionally rely on this policy.
*/
dangerouslyAllowHostHeaderOriginFallback?: boolean;
};
/** Gateway authentication strategy for WebSocket and HTTP clients. */
type GatewayAuthMode = "none" | "token" | "password" | "trusted-proxy";
/**
* Configuration for trusted reverse proxy authentication.
* Used when Clawdbot runs behind an identity-aware proxy (Pomerium, Caddy + OAuth, etc.)
* that handles authentication and passes user identity via headers.
*/
type GatewayTrustedProxyConfig = {
/**
* Header name containing the authenticated user identity (required).
* Common values: "x-forwarded-user", "x-remote-user", "x-pomerium-claim-email"
*/
userHeader: string;
/**
* Additional headers that MUST be present for the request to be trusted.
* Use this to verify the request actually came through the proxy.
* Example: ["x-forwarded-proto", "x-forwarded-host"]
*/
requiredHeaders?: string[];
/**
* Optional allowlist of user identities that can access the gateway.
* If empty or omitted, all authenticated users from the proxy are allowed.
* Example: ["nick@example.com", "admin@company.org"]
*/
allowUsers?: string[];
/**
* Allow loopback proxy sources (127.0.0.1, ::1) in trusted-proxy mode.
* Default false; enable only when a same-host reverse proxy is the intended
* trust boundary and direct Gateway access is otherwise locked down.
*/
allowLoopback?: boolean;
/**
* Automatically approve new browser/native UI operator devices and same-key scope upgrades after
* trusted-proxy authentication. Disabled by default; configured scopes cap grants.
*/
deviceAutoApprove?: {
/** Enable automatic browser enrollment and same-key scope upgrades. @default false */
enabled?: boolean;
/**
* Maximum operator scopes granted by automatic approval. Listing
* operator.admin explicitly lets every proxy-authenticated user request
* automatic full-admin device grants. Requests without scopes receive the
* configured maximum. @default operator.read, operator.write,
* operator.approvals, operator.questions
*/
scopes?: string[];
};
};
type GatewayAuthConfig = {
/** Authentication mode for Gateway connections. Defaults to token when unset. */
mode?: GatewayAuthMode;
/** Shared token for token mode (plaintext or SecretRef). */
token?: SecretInput;
/** Shared password for password mode (consider env instead). */
password?: SecretInput;
/** Allow Tailscale identity headers when serve mode is enabled. */
allowTailscale?: boolean;
/** Operator scopes granted to verified trusted-proxy or Tailscale identities. */
identityScopes?: Record<string, OperatorScope[]>;
/** Rate-limit configuration for failed authentication attempts. */
rateLimit?: GatewayAuthRateLimitConfig;
/**
* Configuration for trusted-proxy auth mode.
* Required when mode is "trusted-proxy".
*/
trustedProxy?: GatewayTrustedProxyConfig;
};
type GatewayAuthRateLimitConfig = {
/** Maximum failed attempts per IP before blocking. @default 10 */
maxAttempts?: number;
/** Sliding window duration in milliseconds. @default 60000 (1 min) */
windowMs?: number;
/** Lockout duration in milliseconds after the limit is exceeded. @default 300000 (5 min) */
lockoutMs?: number;
/** Exempt localhost/loopback addresses from auth rate limiting. @default true */
exemptLoopback?: boolean;
};
/** Tailscale exposure mode for gateway HTTP/WebSocket surfaces. */
type GatewayTailscaleMode = "off" | "serve" | "funnel";
type GatewayTailscaleConfig = {
/** Tailscale exposure mode for the Gateway control UI. */
mode?: GatewayTailscaleMode;
/**
* Detect an external Funnel route left on the ordinary Gateway listener and
* leave exposure unchanged with migration guidance. Gateway-authenticated
* routes reject that ingress; plugin-authenticated webhooks keep their owner auth.
* @deprecated Migrate to `mode="funnel"`, which uses managed ingress.
*/
preserveFunnel?: boolean;
};
type GatewayRemoteConfig = {
/** Remote Gateway WebSocket URL (ws:// or wss://). */
url?: string;
/** Desktop companion transport (SSH tunnel or direct WS); core validates/preserves but does not read it. */
transport?: "ssh" | "direct";
/** Desktop companion remote SSH port (default 18789); core validates/preserves but does not read it. */
remotePort?: number;
/** Token for remote auth (when the gateway requires token auth). */
token?: SecretInput;
/** Password for remote auth (when the gateway requires password auth). */
password?: SecretInput;
/** Headers presented to an identity-aware proxy in front of the Gateway (values are secrets). */
edgeAuth?: Record<string, SecretInput>;
/** Expected TLS certificate fingerprint (sha256) for remote gateways. */
tlsFingerprint?: string;
/** SSH target for tunneling remote Gateway (user@host). */
sshTarget?: string;
/** SSH identity file path for tunneling remote Gateway. */
sshIdentity?: string;
/** macOS app-only; core validates/preserves but does not read it. Defaults to strict; see docs/platforms/mac/remote.md. */
sshHostKeyPolicy?: "strict" | "openssh";
};
/**
* Operator terminal surface served to Control UI and mobile clients.
*
* The terminal opens a PTY-backed shell on the gateway host, gated to
* admin-scope operator sessions. It starts in the target agent's workspace; if
* that agent is fully sandboxed (`sandbox.mode: "all"`) the terminal is refused
* rather than handed an unconfined host shell (workspace isolation is
* fail-closed). Under "non-main" the agent's main session runs on the host, so a
* host terminal is allowed.
*/
type GatewayTerminalConfig = {
/** Master switch for the operator terminal. Default: true; set false to opt out. */
enabled?: boolean;
/**
* Shell executable to launch. When unset the host login shell is used
* ($SHELL on Unix, %ComSpec% on Windows).
*/
shell?: string;
/**
* How long (seconds) a session survives after its connection drops, staying
* reattachable via terminal.attach. 0 kills sessions on disconnect
* immediately. Default: 300.
*/
detachedSessionTimeoutSeconds?: number;
};
/** Labs-gated external CLI session targets in the Control UI. */
type GatewayCliAgentsConfig = {
/** Show catalog-backed CLI agents in the new-session model picker. Default: false. */
enabled?: boolean;
};
/** Gateway config reload strategy for managed installs. */
type GatewayReloadMode = "off" | "restart" | "hot" | "hybrid";
type GatewayReloadConfig = {
/** Reload strategy for config changes (default: hybrid). */
mode?: GatewayReloadMode;
};
type GatewayHttpChatCompletionsConfig = {
/**
* If false, the Gateway will not serve `POST /v1/chat/completions`.
* Default: false when absent.
*/
enabled?: boolean;
/** Image input controls for `image_url` parts. */
images?: GatewayHttpChatCompletionsImagesConfig;
};
type GatewayHttpChatCompletionsImagesConfig = {
/** Allow URL fetches for `image_url` parts. Default: false. */
allowUrl?: boolean;
/**
* Optional hostname allowlist for URL fetches.
* Supports exact hosts and `*.example.com` wildcards.
*/
urlAllowlist?: string[];
/** Allowed MIME types (case-insensitive). */
allowedMimes?: string[];
/** Max bytes per image. Default: 10MB. */
maxBytes?: number;
/** Max redirects when fetching a URL. Default: 3. */
maxRedirects?: number;
/** Fetch timeout in ms. Default: 10s. */
timeoutMs?: number;
};
type GatewayHttpResponsesConfig = {
/**
* If false, the Gateway will not serve `POST /v1/responses` (OpenResponses API).
* Default: false when absent.
*/
enabled?: boolean;
/**
* Max number of URL-based `input_file` + `input_image` parts per request.
* Default: 8.
*/
maxUrlParts?: number;
/** File inputs (input_file). */
files?: GatewayHttpResponsesFilesConfig;
/** Image inputs (input_image). */
images?: GatewayHttpResponsesImagesConfig;
};
type GatewayHttpResponsesFilesConfig = {
/** Allow URL fetches for input_file. Default: true. */
allowUrl?: boolean;
/**
* Optional hostname allowlist for URL fetches.
* Supports exact hosts and `*.example.com` wildcards.
*/
urlAllowlist?: string[];
/** Allowed MIME types (case-insensitive). */
allowedMimes?: string[];
/** Max bytes per file. Default: 5MB. */
maxBytes?: number;
/** Max decoded characters per file. Default: 200k. */
maxChars?: number;
/** Max redirects when fetching a URL. Default: 3. */
maxRedirects?: number;
/** Fetch timeout in ms. Default: 10s. */
timeoutMs?: number;
/** PDF handling (application/pdf). */
pdf?: GatewayHttpResponsesPdfConfig;
};
type GatewayHttpResponsesPdfConfig = {
/** Max pages to parse/render. Default: 4. */
maxPages?: number;
/** Max pixels per rendered page. Default: 4M. */
maxPixels?: number;
/** Minimum extracted text length to skip rasterization. Default: 200 chars. */
minTextChars?: number;
};
type GatewayHttpResponsesImagesConfig = {
/** Allow URL fetches for input_image. Default: true. */
allowUrl?: boolean;
/**
* Optional hostname allowlist for URL fetches.
* Supports exact hosts and `*.example.com` wildcards.
*/
urlAllowlist?: string[];
/** Allowed MIME types (case-insensitive). */
allowedMimes?: string[];
/** Max bytes per image. Default: 10MB. */
maxBytes?: number;
/** Max redirects when fetching a URL. Default: 3. */
maxRedirects?: number;
/** Fetch timeout in ms. Default: 10s. */
timeoutMs?: number;
};
type GatewayHttpEndpointsConfig = {
/** OpenAI-compatible chat completions endpoint controls. */
chatCompletions?: GatewayHttpChatCompletionsConfig;
/** OpenResponses-compatible responses endpoint controls. */
responses?: GatewayHttpResponsesConfig;
};
type GatewayHttpSecurityHeadersConfig = {
/**
* Value for the Strict-Transport-Security response header.
* Set to false to disable explicitly.
*
* Example: "max-age=31536000; includeSubDomains"
*/
strictTransportSecurity?: string | false;
};
type GatewayHttpConfig = {
/** Per-endpoint HTTP API controls. */
endpoints?: GatewayHttpEndpointsConfig;
/** HTTP security header overrides. */
securityHeaders?: GatewayHttpSecurityHeadersConfig;
};
type GatewayPushApnsRelayConfig = {
/** Base HTTPS URL for the external iOS APNs relay service. */
baseUrl?: string;
/** Timeout in milliseconds for relay send requests (default: 10000). */
timeoutMs?: number;
};
type GatewayPushApnsConfig = {
/** External APNs relay used by iOS/mobile notification flows. */
relay?: GatewayPushApnsRelayConfig;
};
type GatewayPushConfig = {
/** Apple Push Notification Service settings. */
apns?: GatewayPushApnsConfig;
};
type GatewayNodePairingConfig = {
/**
* Silently approve trusted local device pairing and access upgrades.
* Set false to require explicit approval; metadata refreshes remain automatic.
* Default: true.
*/
autoApproveLocal?: boolean;
/**
* Opt-in CIDR/IP allowlist for auto-approving first-time node-role pairing.
* Only applies to fresh node pairing requests with no requested scopes.
* Default: unset/disabled.
*/
autoApproveCidrs?: string[];
/**
* SSH-verified auto-approval for first-time node-role pairing (default: enabled).
* The gateway connects back to the pairing host over SSH (BatchMode, strict
* host keys) and approves only when the remote `openclaw node identity`
* output matches the pending request's device key. Set false to disable SSH
* verification; this is independent of autoApproveCidrs, so unset that too for
* manual-only node pairing. The object form tunes the probe:
* - user: remote user (default: gateway process user)
* - identity: SSH identity file (default: standard SSH resolution)
* - timeoutMs: probe timeout (default: 7000)
* - cidrs: CIDRs/IPs eligible for probing (default: private/CGNAT ranges)
*/
sshVerify?: boolean | {
user?: string;
identity?: string;
timeoutMs?: number;
cidrs?: string[];
};
};
type GatewayNodesConfig = {
/** @deprecated Doctor-only legacy input. */
skills?: {
enabled?: boolean;
};
/** @deprecated Doctor-only legacy input. */
allowCommands?: string[];
/** @deprecated Doctor-only legacy input. */
denyCommands?: string[];
/** Browser routing policy for node-hosted browser proxies. */
browser?: {
/** Routing mode (default: auto). */
mode?: "auto" | "manual" | "off";
/** Pin to a specific node id/name (optional). */
node?: string;
};
/** Pairing policy for node-role gateway clients. */
pairing?: GatewayNodePairingConfig;
/** Controls whether paired nodes may publish agent-visible plugin tools (default: true). */
pluginTools?: {
/** Accept node-published plugin tool descriptors (default: true). */
enabled?: boolean;
};
/** Accept node-published skill descriptors (default: true). */
allowSkills?: boolean;
commands?: {
/** Additional node.invoke commands to allow on the gateway. */
allow?: string[];
/** Commands to deny even if they appear in the defaults or node claims. */
deny?: string[];
};
};
type GatewayToolsConfig = {
/** Tools to deny via gateway HTTP /tools/invoke (extends defaults). */
deny?: string[];
/** Tools to explicitly allow (removes from default deny list). */
allow?: string[];
};
/** Closed session, sandbox, agent, and operator-scope policy for one named team role. */
type GatewayOperatorRoleDefinition = {
sessions: {
/** Maximum access to another person's sessions without explicit membership. */
others: "none" | "view" | "suggest" | "write";
};
/** Require sandbox isolation for newly created sessions, or inherit agent policy by default. */
sandbox?: "inherit" | "required";
/** Agent IDs available for session creation and runs, or all agents when set to "*". */
agents: "*" | string[];
/** Ceiling applied to the authenticated profile's granted operator scopes. */
scopes: OperatorScope[];
};
/** Optional named operator-role policies for Gateway deployments shared by a team. */
type GatewayOperatorRolesConfig = {
/** Required validated default for profiles without a valid assigned role. */
default?: string;
/** Closed capability bundles indexed by administrator-selected role names. */
definitions: Record<string, GatewayOperatorRoleDefinition>;
};
type GatewayConfig = {
/** Single multiplexed port for Gateway WS + HTTP (default: 18789). */
port?: number;
/**
* Explicit gateway mode. When set to "remote", local gateway start is disabled.
* When set to "local", the CLI may start the gateway locally.
*/
mode?: "local" | "remote";
/**
* Bind address policy for the Gateway WebSocket + Control UI HTTP server.
* - auto: Loopback (127.0.0.1) if available, else 0.0.0.0 (fallback to all interfaces)
* - lan: 0.0.0.0 (all interfaces, no fallback, current BYOH path is IPv4-only)
* - loopback: 127.0.0.1 (local-only)
* - tailnet: Tailnet IPv4 plus 127.0.0.1 if available, else loopback only
* - custom: User-specified IPv4 address (requires customBindHost); specific IPv4s also bind 127.0.0.1
* IPv6-only BYOH is not natively supported on this path today. Use an IPv4 sidecar or proxy.
* Default: loopback (127.0.0.1).
*/
bind?: GatewayBindMode;
/** Custom IPv4 address for bind="custom" mode. IPv6-only BYOH requires an IPv4 sidecar or proxy. */
customBindHost?: string;
/** Externally reachable HTTPS origin for Gateway callback routes; HTTP only on loopback. */
publicOrigin?: string;
controlUi?: GatewayControlUiConfig;
cliAgents?: GatewayCliAgentsConfig;
terminal?: GatewayTerminalConfig;
auth?: GatewayAuthConfig;
/** Optional profile-bound operator roles; omitted preserves legacy authorization. */
roles?: GatewayOperatorRolesConfig;
tailscale?: GatewayTailscaleConfig;
remote?: GatewayRemoteConfig;
reload?: GatewayReloadConfig;
tls?: GatewayTlsConfig;
http?: GatewayHttpConfig;
push?: GatewayPushConfig;
nodes?: GatewayNodesConfig;
/**
* IPs of trusted reverse proxies (e.g. Traefik, nginx). When a connection
* arrives from one of these IPs, the Gateway trusts `x-forwarded-for`
* to determine the client IP for local pairing and HTTP checks.
*/
trustedProxies?: string[];
/**
* Allow `x-real-ip` as a fallback only when `x-forwarded-for` is missing.
* Default: false (safer fail-closed behavior).
*/
allowRealIpFallback?: boolean;
/** Tool access restrictions for HTTP /tools/invoke endpoint. */
tools?: GatewayToolsConfig;
};
//#endregion
//#region src/config/types.installs.d.ts
/** Base persisted install record shared by plugin and skill install tracking. */
type InstallRecordBase = {
source: "npm" | "archive" | "path" | "clawhub" | "git";
spec?: string;
sourcePath?: string;
installPath?: string;
version?: string;
resolvedName?: string;
resolvedVersion?: string;
resolvedSpec?: string;
integrity?: string;
shasum?: string;
resolvedAt?: string;
installedAt?: string;
clawhubUrl?: string;
clawhubPackage?: string;
clawhubFamily?: "code-plugin" | "bundle-plugin";
clawhubChannel?: "official" | "community" | "private";
clawhubTrustDisposition?: "clean" | "review-recommended" | "review-required" | "blocked";
clawhubTrustScanStatus?: string;
clawhubTrustModerationState?: string;
clawhubTrustReasons?: string[];
clawhubTrustPending?: boolean;
clawhubTrustStale?: boolean;
clawhubTrustCheckedAt?: string;
clawhubTrustAcknowledgedAt?: string;
artifactKind?: "legacy-zip" | "npm-pack";
artifactFormat?: "zip" | "tgz";
npmIntegrity?: string;
npmShasum?: string;
npmTarballName?: string;
clawpackSha256?: string;
clawpackSpecVersion?: number;
clawpackManifestSha256?: string;
clawpackSize?: number;
gitUrl?: string;
gitRef?: string;
gitCommit?: string;
};
//#endregion
//#region src/config/types.hooks.d.ts
type HookMappingMatch = {
path?: string;
source?: string;
};
type HookMappingTransform = {
module: string;
export?: string;
};
type HookSessionMode = "isolated" | "persistent";
type HookMappingConfig = {
id?: string;
match?: HookMappingMatch;
action?: "wake" | "agent";
wakeMode?: "now" | "next-heartbeat";
name?: string;
/** Route this hook to a specific agent (unknown ids fall back to the default agent). */
agentId?: string;
sessionKey?: string;
/** Reuse the resolved session key across runs instead of creating a fresh run session. */
sessionMode?: HookSessionMode;
messageTemplate?: string;
textTemplate?: string;
/**
* Fan the mapping out over a top-level payload array: one action per element,
* with templates/transforms seeing a payload whose array holds only that
* element. Example: the gmail preset uses `forEach: "messages"` so batched
* pushes dispatch one isolated run per email.
*/
forEach?: string;
deliver?: boolean;
/** DANGEROUS: Disable external content safety wrapping for this hook. */
allowUnsafeExternalContent?: boolean;
/**
* "last" or any runtime channel id (including plugin channels).
* Validation against configured/registered channels happens in gateway hooks runtime.
*/
channel?: "last" | (string & {});
to?: string;
/** Override model for this hook (provider/model or alias). */
model?: string;
thinking?: string;
timeoutSeconds?: number;
transform?: HookMappingTransform;
};
type HooksGmailTailscaleMode = "off" | "serve" | "funnel";
type HooksGmailConfig = {
account?: string;
label?: string;
topic?: string;
subscription?: string;
pushToken?: string;
hookUrl?: string;
includeBody?: boolean;
maxBytes?: number;
renewEveryMinutes?: number;
/** DANGEROUS: Disable external content safety wrapping for Gmail hooks. */
allowUnsafeExternalContent?: boolean;
serve?: {
bind?: string;
port?: number;
path?: string;
};
tailscale?: {
mode?: HooksGmailTailscaleMode;
path?: string;
/** Optional tailscale serve/funnel target (port, host:port, or full URL). */
target?: string;
};
/** Optional model override for Gmail hook processing (provider/model or alias). */
model?: string;
/** Optional thinking level override for Gmail hook processing. */
thinking?: "off" | "minimal" | "low" | "medium" | "high";
};
type HookConfig = {
enabled?: boolean;
env?: Record<string, string>;
[key: string]: unknown;
};
type InternalHooksConfig = {
/** Enable hooks system */
enabled?: boolean;
/** Per-hook configuration overrides */
entries?: Record<string, HookConfig>;
/** Load configuration */
load?: {
/** Additional hook directories to scan */
extraDirs?: string[];
};
};
type HooksConfig = {
enabled?: boolean;
path?: string;
token?: string;
/**
* Default session key used for hook agent runs when no request/mapping session key is used.
* If omitted, OpenClaw generates `hook:<uuid>` per request.
*/
defaultSessionKey?: string;
/**
* Allow `sessionKey` from external `/hooks/agent` and `/hooks/wake` request payloads.
* Default: false.
*/
allowRequestSessionKey?: boolean;
/**
* Optional allowlist for explicit session keys (request + mapping). Example: ["hook:"].
* Empty/omitted means no prefix restriction.
*/
allowedSessionKeyPrefixes?: string[];
/**
* Restrict hook execution to these effective agent ids, including
* default-agent routing when `agentId` is omitted. Omit or include `*` to
* allow any agent. Set `[]` to deny all agent routing.
*/
allowedAgentIds?: string[];
presets?: string[];
transformsDir?: string;
mappings?: HookMappingConfig[];
gmail?: HooksGmailConfig;
/** Internal agent event hooks */
internal?: InternalHooksConfig;
};
//#endregion
//#region src/config/types.mcp.d.ts
type McpCodexToolApprovalMode = "auto" | "prompt" | "approve";
type McpServerCodexConfig = {
/** OpenClaw agent ids that should receive this server in Codex app-server threads. */
agents?: string[];
/** Codex MCP tool approval mode emitted as default_tools_approval_mode. */
defaultToolsApprovalMode?: McpCodexToolApprovalMode;
};
type McpServerToolFilterConfig = {
/**
* Exact MCP tool names or simple "*" globs to expose from this server.
*
* When omitted, all server tools remain eligible unless excluded.
*/
include?: string[];
/** Exact MCP tool names or simple "*" globs to hide from this server. */
exclude?: string[];
};
type McpServerConfig = {
/** Set false to keep the saved definition while excluding it from runtime/probe sessions. */
enabled?: boolean;
/** Stdio transport: command to spawn. */
command?: string;
/** Stdio transport: arguments for the command. */
args?: string[];
/** Environment variables passed to the server process (stdio only). */
env?: Record<string, string | number | boolean>;
/** Working directory for stdio server. */
cwd?: string;
/** HTTP transport: URL of the remote MCP server (http or https). */
url?: string;
/** Transport type — "stdio" for command-bearing servers, "sse" or "streamable-http" for remote URLs. */
transport?: "stdio" | "sse" | "streamable-http";
/** HTTP transport: extra HTTP headers sent with every request. */
headers?: Record<string, string | number | boolean>;
/** Optional connection timeout in milliseconds. */
connectionTimeoutMs?: number;
/** Optional per-request timeout in milliseconds. */
requestTimeoutMs?: number;
/** Whether this server can safely handle concurrent tool calls. */
supportsParallelToolCalls?: boolean;
/** HTTP OAuth mode. Tokens are stored in OpenClaw state, not in config. */
auth?: "oauth";
/** Optional OAuth client metadata overrides for HTTP MCP servers. */
oauth?: {
/** Credential ownership for this server. Defaults to shared operator credentials. */
identity?: "shared" | "per-requester";
/** Refresh-capable auth profile used to inject the current bearer token. */
authProfileId?: string;
scope?: string;
redirectUrl?: string;
clientMetadataUrl?: string;
};
/** HTTP TLS verification, disabled only for explicitly trusted private endpoints. */
sslVerify?: boolean;
/** HTTP mutual TLS client certificate path. */
clientCert?: string;
/** HTTP mutual TLS client key path. */
clientKey?: string;
/** Optional per-server OpenClaw MCP tool selection. */
toolFilter?: McpServerToolFilterConfig;
/** Codex-specific projection controls for Codex app-server/runtime config. */
codex?: McpServerCodexConfig;
[key: string]: unknown;
};
type McpConfig = {
/** Named MCP server definitions managed by OpenClaw. */
servers?: Record<string, McpServerConfig>;
/** Opt-in MCP Apps rendering and app-to-server bridge. */
apps?: {
enabled?: boolean;
/** Dedicated public origin that proxies to the sandbox listener. */
sandboxOrigin?: string;
/** Dedicated listener port. Defaults to the Gateway port plus one. */
sandboxPort?: number;
};
};
//#endregion
//#region packages/llm-core/src/utils/diagnostics.d.ts
interface DiagnosticErrorInfo {
name?: string;
message: string;
stack?: string;
code?: string | number;
}
interface AssistantMessageDiagnostic {
type: string;
timestamp: number;
error?: DiagnosticErrorInfo;
details?: Record<string, unknown>;
}
//#endregion
//#region packages/llm-core/src/types.d.ts
/** Provider API families with first-class request/stream adapters in OpenClaw. */
type KnownApi = "openai-completions" | "mistral-conversations" | "openai-responses" | "azure-openai-responses" | "openai-chatgpt-responses" | "anthropic-messages" | "bedrock-converse-stream" | "google-generative-ai" | "google-vertex";
/** Provider API id; custom providers can use ids outside the built-in set. */
type Api = KnownApi | (string & {});
/** Provider id used for routing, diagnostics, and config lookups. */
type Provider = string;
/** Normalized reasoning-effort levels shared across provider-specific knobs. */
type ThinkingLevel = "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
/** Model thinking setting including explicit disabled state. */
type ModelThinkingLevel = "off" | ThinkingLevel;
/** Provider-specific values for normalized thinking levels. */
type ThinkingLevelMap = Partial<Record<ModelThinkingLevel, string | null>>;
/** Token budgets for each thinking level (token-based providers only) */
interface ThinkingBudgets {
minimal?: number;
low?: number;
medium?: number;
high?: number;
max?: number;
}
/** Prompt-cache retention preference shared by providers that expose cache controls. */
type CacheRetention = "none" | "short" | "long";
/** Streaming transport preference for providers that support multiple transports. */
type Transport = "sse" | "websocket" | "websocket-cached" | "auto";
/** Helper for hooks that may be synchronous or asynchronous. */
type MaybePromise$2<T> = T | Promise<T>;
/** Minimal HTTP response metadata surfaced through provider hooks. */
interface ProviderResponse {
status: number;
headers: Record<string, string>;
}
/** Request options shared by text streaming providers. */
interface StreamOptions {
temperature?: number;
maxTokens?: number;
/**
* Optional JSON Schema for the generated response. Providers that support
* constrained decoding map it to their native request shape; others ignore it.
*/
responseFormat?: Record<string, unknown>;
/**
* Stop sequences forwarded to providers that support them. Providers map this
* to their native request field, such as OpenAI `stop` or Anthropic
* `stop_sequences`.
*/
stop?: string[];
signal?: AbortSignal;
apiKey?: string;
/**
* Preferred transport for providers that support multiple transports.
* Providers that do not support this option ignore it.
*/
transport?: Transport;
/**
* Prompt cache retention preference. Providers map this to their supported values.
* Default: "short".
*/
cacheRetention?: CacheRetention;
/**
* Optional session identifier for providers that support session-based caching.
* Providers can use this to enable prompt caching, request routing, or other
* session-aware features. Ignored by providers that don't support it.
*/
sessionId?: string;
/**
* Opaque per-model-call identifier for provider transport correlation.
* Providers that do not expose request correlation ignore it.
*/
requestId?: string;
/**
* Optional provider prompt-cache affinity key, distinct from transcript/session identity.
* Providers that do not support separate cache affinity ignore it.
*/
promptCacheKey?: string;
/**
* Optional callback for inspecting or replacing provider payloads before sending.
* Return undefined to keep the payload unchanged.
*/
onPayload?: (payload: unknown, model: Model) => MaybePromise$2<unknown>;
/**
* Optional callback invoked after an HTTP response is received and before
* its body stream is consumed.
*/
onResponse?: (response: ProviderResponse, model: Model) => void | Promise<void>;
/**
* Observe a live response that accepts user input before generation finishes.
* `steer` resolves false only when the input was definitely not admitted;
* admitted input cannot be withdrawn. Providers settle pending submissions
* before closing the response and call the returned cleanup on closure.
*/
onActiveResponse?: (control: {
steer(messages: readonly UserMessage[]): Promise<boolean>;
/** Read-only after closure: deferred input still needs an explicit continuation request. */
needsContinuation?: () => boolean;
}) => (() => void) | void;
/**
* The caller can execute completed async calls before generation finishes.
* Providers advertise async tools only with this host capability; this is
* independent of parallel execution of an ordinary completed tool batch.
*/
asyncToolExecution?: boolean;
/**
* Optional custom HTTP headers to include in API requests.
* Merged with provider defaults; can override default headers.
* Not supported by all providers (e.g., AWS Bedrock uses SDK auth).
*/
headers?: Record<string, string>;
/**
* HTTP request timeout in milliseconds for providers/SDKs that support it.
* For example, OpenAI and Anthropic SDK clients default to 10 minutes.
*/
timeoutMs?: number;
/** @deprecated Ignored by built-in text transports; retries are owned by the host runner. */
maxRetries?: number;
/**
* Maximum delay in milliseconds to wait for a retry when the server requests a long wait.
* If the server's requested delay exceeds this value, the request fails immediately
* with an error containing the requested delay, allowing higher-level retry logic
* to handle it with user visibility.
* Default: 60000 (60 seconds). Set to 0 to disable the cap.
*/
maxRetryDelayMs?: number;
/**
* Optional metadata to include in API requests.
* Providers extract the fields they understand and ignore the rest.
* For example, Anthropic uses `user_id` for abuse tracking and rate limiting.
*/
metadata?: Record<string, unknown>;
}
/** Unified text options used by simple completion helpers. */
interface SimpleStreamOptions extends StreamOptions {
reasoning?: ModelThinkingLevel;
/** Custom token budgets for thinking levels (token-based providers only) */
thinkingBudgets?: ThinkingBudgets;
}
/** Plain assistant/user text content block. */
interface TextContent {
type: "text";
text: string;
textSignature?: string;
}
/** Provider reasoning/thinking content block, including opaque replay signatures. */
interface ThinkingContent {
type: "thinking";
thinking: string;
thinkingSignature?: string;
/** When true, the thinking content was redacted by safety filters. The opaque
* encrypted payload is stored in `thinkingSignature` so it can be passed back
* to the API for multi-turn continuity. */
redacted?: boolean;
}
/** Opaque provider-owned state that must survive transcript replay without being rendered. */
interface ProviderReplayState {
v: 1;
type: string;
id?: string;
data: string;
replayIndex?: number;
provider: Provider;
api: Api;
model: string;
baseUrlHash?: string;
sessionHash?: string;
authProfileHash?: string;
}
/** Base64 image content block with MIME type metadata. */
interface ImageContent$1 {
type: "image";
data: string;
mimeType: string;
}
/** Normalized assistant tool call emitted by providers or repaired from text. */
interface ToolCall {
/** The provider completed this call and permits generation to continue without its result. */
async?: true;
type: "toolCall";
id: string;
name: string;
arguments: Record<string, unknown>;
thoughtSignature?: string;
executionMode?: "sequential" | "parallel";
}
/** Normalized token and cost accounting for a provider response. */
interface Usage {
input: number;
output: number;
cacheRead: number;
cacheWrite: number;
/** Whether the provider reported a cache-read/write token split. */
cacheTelemetry?: {
state: "available" | "unavailable";
};
/** Subset of `cacheWrite` written with 1-hour retention when reported. */
cacheWrite1h?: number;
/** Exact context snapshot for the final provider iteration. */
contextUsage?: {
state: "available";
promptTokens: number;
totalTokens: number;
} | {
state: "unavailable";
};
totalTokens: number;
cost: {
input: number;
output: number;
cacheRead: number;
cacheWrite: number;
total: number;
/** Provenance for the recorded total cost; provider-billed totals are authoritative. */
totalOrigin?: "provider-billed";
};
}
/** Per-million-token rates for separately billed token buckets. */
type ModelCostRates = Pick<Usage["cost"], "input" | "output" | "cacheRead" | "cacheWrite">;
type RawPricingTier = ModelCostRates & {
/** `[start]` is an open-ended upper tier. */
range: [number, number] | [number];
};
type RawModelCostConfig = ModelCostRates & {
tieredPricing?: RawPricingTier[];
};
/** Normalized assistant stop reasons across text providers. */
type StopReason = "stop" | "length" | "toolUse" | "error" | "aborted";
/** User turn in a text-model conversation. */
interface UserMessage {
role: "user";
content: string | (TextContent | ImageContent$1)[];
timestamp: number;
/**
* Marks a user message carrying runtime context. Provider replay policy decides
* whether the carrier is transient or retained append-only; only retained
* carriers are stable prompt-cache anchors.
*/
runtimeContextCarrier?: boolean;
}
/** Assistant turn, including provider identity and final stop state. */
type AssistantDeliveryTtsFacts = {
tagged: true;
text?: string;
directives?: Array<{
provider?: string;
values: Record<string, string>;
}>;
};
interface AssistantMessage {
role: "assistant";
content: (TextContent | ThinkingContent | ToolCall)[];
openclawDelivery?: {
audioAsVoice?: true;
/** Exact media directives consumed by the managed-media transcript rewrite owner. */
mediaUrls?: string[];
replyToCurrent?: true;
replyToId?: string;
/** Provider text phase is unresolved until the assistant turn reaches terminal state. */
textPhaseRequiresTerminal?: true;
/** Parsed once at the assistant write boundary; delivery resolves policy from these facts. */
tts?: AssistantDeliveryTtsFacts;
};
api: Api;
provider: Provider;
model: string;
responseModel?: string;
responseId?: string;
providerReplay?: ProviderReplayState;
turnId?: string;
diagnostics?: AssistantMessageDiagnostic[];
usage: Usage;
stopReason: StopReason;
errorMessage?: string;
errorCode?: string;
errorType?: string;
errorBody?: string;
timestamp: number;
}
/** Tool result turn that answers a prior assistant tool call. */
interface ToolResultMessage<TDetails = unknown> {
role: "toolResult";
toolCallId: string;
toolName: string;
content: (TextContent | ImageContent$1)[];
details?: TDetails;
isError: boolean;
timestamp: number;
}
/** Any text-model conversation message supported by LLM core. */
type Message = UserMessage | AssistantMessage | ToolResultMessage;
/** Provider tool declaration with a TypeBox/JSON-schema parameter object. */
interface Tool<TParameters extends TSchema = TSchema> {
name: string;
description: string;
parameters: TParameters;
}
/** Text-model request context shared by provider adapters. */
interface Context {
systemPrompt?: string;
messages: Message[];
tools?: Tool[];
}
/**
* Event protocol for AssistantMessageEventStream.
*
* Streams should emit `start` before partial updates, then terminate with either:
* - `done` carrying the final successful AssistantMessage, or
* - `error` carrying the final AssistantMessage with stopReason "error" or "aborted"
* and errorMessage.
*/
type AssistantMessageEvent = {
type: "start";
partial: AssistantMessage;
} | {
type: "text_start";
contentIndex: number;
partial: AssistantMessage;
} |
/**
* Plain text deltas may omit `partial` to avoid retaining one full assistant
* snapshot per token. Consumers that need current text should replay `delta`
* from the latest start/end partial checkpoint.
*/
{
type: "text_delta";
contentIndex: number;
delta: string;
partial?: AssistantMessage;
} | {
type: "text_end";
contentIndex: number;
content: string;
partial: AssistantMessage;
} | {
type: "thinking_start";
contentIndex: number;
partial: AssistantMessage;
} | {
type: "thinking_delta";
contentIndex: number;
delta: string;
partial: AssistantMessage;
} | {
type: "thinking_end";
contentIndex: number;
content: string;
partial: AssistantMessage;
} | {
type: "toolcall_start";
contentIndex: number;
partial: AssistantMessage;
} | {
type: "toolcall_delta";
contentIndex: number;
delta: string;
partial: AssistantMessage;
} | {
type: "toolcall_end";
contentIndex: number;
toolCall: ToolCall;
partial: AssistantMessage;
} | {
type: "done";
reason: Extract<StopReason, "stop" | "length" | "toolUse">;
message: AssistantMessage;
} | {
type: "error";
reason: Extract<StopReason, "aborted" | "error">;
error: AssistantMessage;
};
interface AssistantMessageEventStreamContract extends AsyncIterable<AssistantMessageEvent> {
/** Queue one stream event for consumers. */
push(event: AssistantMessageEvent): void;
/** Complete the stream and optionally resolve the final message. */
end(result?: AssistantMessage): void;
/** Final assistant message produced by the stream. */
result(): Promise<AssistantMessage>;
}
/** Read-only stream contract accepted by consumers that do not need to push events. */
interface AssistantMessageEventStreamLike extends AsyncIterable<AssistantMessageEvent> {
result(): Promise<AssistantMessage>;
}
/**
* Compatibility settings for OpenAI-compatible completions APIs.
* Use this to override URL-based auto-detection for custom providers.
*/
interface OpenAICompletionsCompat {
/** Whether the provider supports the `store` field. Default: auto-detected from URL. */
supportsStore?: boolean;
/** Whether the provider supports the `developer` role (vs `system`). Default: auto-detected from URL. */
supportsDeveloperRole?: boolean;
/** Whether the provider supports `reasoning_effort`. Default: auto-detected from URL. */
supportsReasoningEffort?: boolean;
/** Per-level reasoning effort overrides, e.g. map "off" to "low" for models that cannot disable thinking. */
reasoningEffortMap?: Record<string, string>;
/** Whether the provider supports `stream_options: { include_usage: true }` for token usage in streaming responses. Default: true. */
supportsUsageInStreaming?: boolean;
/** Which field to use for max tokens. Default: auto-detected from URL. */
maxTokensField?: "max_completion_tokens" | "max_tokens";
/** Whether tool results require the `name` field. Default: auto-detected from URL. */
requiresToolResultName?: boolean;
/** Whether a user message after tool results requires an assistant message in between. Default: auto-detected from URL. */
requiresAssistantAfterToolResult?: boolean;
/** Whether thinking blocks must be converted to text blocks with <thinking> delimiters. Default: auto-detected from URL. */
requiresThinkingAsText?: boolean;
/** Whether all replayed assistant messages must include an empty reasoning_content field when reasoning is enabled. Default: auto-detected from URL. */
requiresReasoningContentOnAssistantMessages?: boolean;
/** Format for reasoning/thinking parameter. "openai" uses reasoning_effort, "openrouter" uses reasoning: { effort }, "deepseek" uses thinking: { type } plus reasoning_effort, "together" uses reasoning: { enabled } plus reasoning_effort when supported, "zai" uses top-level enable_thinking: boolean, "qwen" uses top-level enable_thinking: boolean, and "qwen-chat-template" uses chat_template_kwargs.enable_thinking. Default: "openai". */
thinkingFormat?: "openai" | "openrouter" | "deepseek" | "together" | "zai" | "qwen" | "qwen-chat-template";
/** OpenRouter-specific routing preferences. Only used when baseUrl points to OpenRouter. */
openRouterRouting?: OpenRouterRouting;
/** Vercel AI Gateway routing preferences. Only used when baseUrl points to Vercel AI Gateway. */
vercelGatewayRouting?: VercelGatewayRouting;
/** Whether z.ai supports top-level `tool_stream: true` for streaming tool call deltas. Default: false. */
zaiToolStream?: boolean;
/** Whether the provider supports the `strict` field in tool definitions. Default: true. */
supportsStrictMode?: boolean;
/** Whether the provider supports JSON Schema through `response_format`. Default: false for unknown compatible endpoints. */
supportsJsonSchemaResponseFormat?: boolean;
/** Cache control convention for prompt caching. "anthropic" applies Anthropic-style `cache_control` markers to the system prompt, last tool definition, and last user/assistant text content. */
cacheControlFormat?: "anthropic";
/** Whether to send known session-affinity headers (`session_id`, `x-client-request-id`, `x-session-affinity`) from `options.sessionId` when caching is enabled. Default: false. */
sendSessionAffinityHeaders?: boolean;
/** Whether the provider supports OpenAI-style `prompt_cache_key`. Default: false for third-party completions providers. */
supportsPromptCacheKey?: boolean;
/** Whether the provider supports long prompt cache retention (`prompt_cache_retention: "24h"` or Anthropic-style `cache_control.ttl: "1h"`, depending on format). Default: true. */
supportsLongCacheRetention?: boolean;
}
/** Compatibility settings for OpenAI Responses APIs. */
interface OpenAIResponsesCompat {
/** Whether the provider supports the `developer` role (vs `system`). Default: true. */
supportsDeveloperRole?: boolean;
/** Whether to send reasoning effort settings. Defaults to the model's known capabilities. */
supportsReasoningEffort?: boolean;
/** Provider-native reasoning efforts accepted by the model. Overrides known model defaults. */
supportedReasoningEfforts?: string[];
/** Whether the model accepts the `temperature` parameter. Default: true. */
supportsTemperature?: boolean;
/** Whether to send the OpenAI `session_id` cache-affinity header from `options.sessionId` when caching is enabled. Default: true. */
sendSessionIdHeader?: boolean;
/** Whether the provider supports `prompt_cache_retention: "24h"`. Default: true. */
supportsLongCacheRetention?: boolean;
/** Whether the provider honors top-level `instructions`. Defaults to true only for verified native routes (OpenAI, xAI); every other route defaults to false and embeds the system prompt in `input` unless set true here after verifying against that endpoint. */
supportsInstructions?: boolean;
}
/** Compatibility settings for Anthropic Messages-compatible APIs. */
interface AnthropicMessagesCompat {
/**
* Whether the provider accepts per-tool `eager_input_streaming`.
* When false, the Anthropic provider omits `tools[].eager_input_streaming`
* and sends the legacy `fine-grained-tool-streaming-2025-05-14` beta header
* for tool-enabled requests.
* Default: true.
*/
supportsEagerToolInputStreaming?: boolean;
/** Whether the provider supports Anthropic long cache retention (`cache_control.ttl: "1h"`). Default: true. */
supportsLongCacheRetention?: boolean;
/**
* Whether to send the `x-session-affinity` header from `options.sessionId`
* when caching is enabled. Required for providers like Fireworks that use
* session affinity for prompt cache routing (requests to the same replica
* maximize cache hits).
* Default: false.
*/
sendSessionAffinityHeaders?: boolean;
/**
* Whether the provider supports Anthropic-style `cache_control` markers on
* tool definitions. When false, `cache_control` is omitted from tool params.
* Some Anthropic-compatible providers (e.g., Fireworks) do not support this
* field on tools and may reject or ignore it.
* Default: true.
*/
supportsCacheControlOnTools?: boolean;
/** Whether empty thinking signatures can be replayed as native thinking blocks. Default: false. */
allowEmptySignature?: boolean;
}
/**
* OpenRouter provider routing preferences.
* Controls which upstream providers OpenRouter routes requests to.
* Sent as the `provider` field in the OpenRouter API request body.
* @see https://openrouter.ai/docs/guides/routing/provider-selection
*/
interface OpenRouterRouting {
/** Whether to allow backup providers to serve requests. Default: true. */
allow_fallbacks?: boolean;
/** Whether to filter providers to only those that support all parameters in the request. Default: false. */
require_parameters?: boolean;
/** Data collection setting. "allow" (default): allow providers that may store/train on data. "deny": only use providers that don't collect user data. */
data_collection?: "deny" | "allow";
/** Whether to restrict routing to only ZDR (Zero Data Retention) endpoints. */
zdr?: boolean;
/** Whether to restrict routing to only models that allow text distillation. */
enforce_distillable_text?: boolean;
/** An ordered list of provider names/slugs to try in sequence, falling back to the next if unavailable. */
order?: string[];
/** List of provider names/slugs to exclusively allow for this request. */
only?: string[];
/** List of provider names/slugs to skip for this request. */
ignore?: string[];
/** A list of quantization levels to filter providers by (e.g., ["fp16", "bf16", "fp8", "fp6", "int8", "int4", "fp4", "fp32"]). */
quantizations?: string[];
/** Sorting strategy. Can be a string (e.g., "price", "throughput", "latency") or an object with `by` and `partition`. */
sort?: string | {
/** The sorting metric: "price", "throughput", "latency". */
by?: string;
/** Partitioning strategy: "model" (default) or "none". */
partition?: string | null;
};
/** Maximum price per million tokens (USD). */
max_price?: {
/** Price per million prompt tokens. */
prompt?: number | string;
/** Price per million completion tokens. */
completion?: number | string;
/** Price per image. */
image?: number | string;
/** Price per audio unit. */
audio?: number | string;
/** Price per request. */
request?: number | string;
};
/** Preferred minimum throughput (tokens/second). Can be a number (applies to p50) or an object with percentile-specific cutoffs. */
preferred_min_throughput?: number | {
/** Minimum tokens/second at the 50th percentile. */
p50?: number;
/** Minimum tokens/second at the 75th percentile. */
p75?: number;
/** Minimum tokens/second at the 90th percentile. */
p90?: number;
/** Minimum tokens/second at the 99th percentile. */
p99?: number;
};
/** Preferred maximum latency (seconds). Can be a number (applies to p50) or an object with percentile-specific cutoffs. */
preferred_max_latency?: number | {
/** Maximum latency in seconds at the 50th percentile. */
p50?: number;
/** Maximum latency in seconds at the 75th percentile. */
p75?: number;
/** Maximum latency in seconds at the 90th percentile. */
p90?: number;
/** Maximum latency in seconds at the 99th percentile. */
p99?: number;
};
}
/**
* Vercel AI Gateway routing preferences.
* Controls which upstream providers the gateway routes requests to.
* @see https://vercel.com/docs/ai-gateway/models-and-providers/provider-options
*/
interface VercelGatewayRouting {
/** List of provider slugs to exclusively use for this request (e.g., ["bedrock", "anthropic"]). */
only?: string[];
/** List of provider slugs to try in order (e.g., ["anthropic", "openai"]). */
order?: string[];
}
interface Model<TApi extends Api = Api> {
id: string;
name: string;
api: TApi;
provider: Provider;
baseUrl: string;
reasoning: boolean;
/**
* Maps OpenClaw thinking levels to provider/model-specific values.
* Missing keys use provider defaults. null marks a level as unsupported.
*/
thinkingLevelMap?: ThinkingLevelMap;
input: ("text" | "image")[];
cost: RawModelCostConfig;
contextWindow?: number;
/**
* Optional effective runtime cap used for compaction/session budgeting.
* Keeps provider/native contextWindow metadata intact while allowing a
* smaller practical window.
*/
contextTokens?: number;
maxTokens: number;
/** Provider-specific request/runtime parameters passed through to provider plugins. */
params?: Record<string, unknown>;
headers?: Record<string, string>;
/** Sends runtime credentials as Authorization: Bearer instead of provider-specific key headers. */
authHeader?: boolean;
/** Compatibility overrides for OpenAI-compatible APIs. If not set, auto-detected from baseUrl. */
compat?: TApi extends "openai-completions" ? OpenAICompletionsCompat : TApi extends "openai-responses" | "azure-openai-responses" | "openai-codex-responses" ? OpenAIResponsesCompat : TApi extends "anthropic-messages" ? AnthropicMessagesCompat : never;
/** Provider-documented media input limits used by attachment preprocessing. */
mediaInput?: {
image?: {
maxBytes?: number;
maxPixels?: number;
maxSidePx?: number;
preferredSidePx?: number;
tokenMode?: "tile" | "detail" | "provider";
};
};
}
type StreamFn$1 = (model: Model, context: Context, options?: SimpleStreamOptions) => AssistantMessageEventStreamLike | Promise<AssistantMessageEventStreamLike>;
//#endregion
//#region src/config/types.models.d.ts
/** Provider API adapter ids accepted by model/provider config and schema generation. */
declare const MODEL_APIS: readonly ["openai-completions", "openai-responses", "openai-chatgpt-responses", "anthropic-messages", "google-generative-ai", "google-vertex", "github-copilot", "bedrock-converse-stream", "ollama", "azure-openai-responses"];
type ModelApi = (typeof MODEL_APIS)[number];
type SupportedOpenAICompatFields = Pick<OpenAICompletionsCompat, "supportsStore" | "supportsDeveloperRole" | "supportsReasoningEffort" | "reasoningEffortMap" | "supportsUsageInStreaming" | "supportsStrictMode" | "supportsJsonSchemaResponseFormat" | "maxTokensField" | "requiresToolResultName" | "requiresAssistantAfterToolResult" | "requiresThinkingAsText" | "requiresReasoningContentOnAssistantMessages" | "openRouterRouting" | "vercelGatewayRouting" | "zaiToolStream" | "cacheControlFormat" | "sendSessionAffinityHeaders" | "supportsLongCacheRetention">;
type SupportedOpenAIResponsesCompatFields = Pick<OpenAIResponsesCompat, "sendSessionIdHeader" | "supportsLongCacheRetention" | "supportsTemperature" | "supportsInstructions">;
type SupportedAnthropicMessagesCompatFields = Pick<AnthropicMessagesCompat, "supportsEagerToolInputStreaming" | "supportsLongCacheRetention">;
type SupportedThinkingFormat = NonNullable<OpenAICompletionsCompat["thinkingFormat"]> | "deepseek" | "openrouter" | "together";
/** Provider/model compatibility switches consumed by request builders and tool schema adapters. */
type ModelCompatConfig = SupportedOpenAICompatFields & SupportedOpenAIResponsesCompatFields & SupportedAnthropicMessagesCompatFields & {
/** Reasoning/thinking payload dialect for provider-compatible APIs. */
thinkingFormat?: SupportedThinkingFormat;
/** Provider-accepted reasoning effort labels. */
supportedReasoningEfforts?: string[];
/** Reasoning detail block types safe to expose in visible transcripts. */
visibleReasoningDetailTypes?: string[];
/** Whether this model supports tool/function calling. */
supportsTools?: boolean;
/** Code-mode tier consumed by `tools.codeMode.enabled: "auto"`; absent means "capable". */
codeMode?: "preferred" | "capable";
/** Whether provider accepts prompt-cache/session affinity keys. */
supportsPromptCacheKey?: boolean;
/** Whether all message parts must be coerced to plain strings. */
requiresStringContent?: boolean;
/** Whether unknown message payload keys must be stripped before requests. */
strictMessageKeys?: boolean;
/** Named tool-schema profile used by provider adapters. */
toolSchemaProfile?: string;
/** JSON Schema keywords rejected by this provider's tool schema validator. */
unsupportedToolSchemaKeywords?: string[];
/** Encoding expected for tool-call arguments in provider payloads. */
toolCallArgumentsEncoding?: string;
/** Whether OpenAI-style calls must be reshaped to Anthropic-compatible tool payloads. */
requiresOpenAiAnthropicToolPayload?: boolean;
};
type ModelImageInputConfig = {
/** Provider-documented maximum encoded image payload size. */
maxBytes?: number;
/** Provider-documented maximum accepted input pixels. */
maxPixels?: number;
/** Provider-documented maximum accepted width/height in pixels. */
maxSidePx?: number;
/** Preferred resize side for the default balanced compression policy. */
preferredSidePx?: number;
/** Token accounting style, used as documentation for provider-owned policy. */
tokenMode?: "tile" | "detail" | "provider";
};
type ModelMediaInputConfig = {
/** Image input limits and accounting hints for this model. */
image?: ModelImageInputConfig;
};
/** Authentication mode expected by a configured model provider. */
type ModelProviderAuthMode = "api-key" | "aws-sdk" | "oauth" | "token";
type ModelProviderLocalServiceConfig = {
/** Executable started before model requests are sent. */
command: string;
/** Arguments passed without shell expansion. */
args?: string[];
/** Working directory for the local service process. */
cwd?: string;
/** Environment variables added to the service process. */
env?: Record<string, string>;
/** Optional health endpoint polled before the provider is considered ready. */
healthUrl?: string;
/** Startup readiness timeout in milliseconds. */
readyTimeoutMs?: number;
/** Idle timeout in milliseconds before stopping the local service. */
idleStopMs?: number;
};
type ModelDefinitionConfig = {
/** Provider-facing model id. */
id: string;
/** Human-readable display name. */
name: string;
/** Optional API adapter override for this model. */
api?: ModelApi;
/** Optional base URL override for this model. */
baseUrl?: string;
/** Whether the model supports reasoning/thinking controls. */
reasoning: boolean;
/** Supported input modalities for routing and media-tool selection. */
input: Array<"text" | "image" | "video" | "audio">;
/** Token pricing in USD per million tokens. */
cost: RawModelCostConfig;
/** Provider/native maximum context window in tokens. */
contextWindow?: number;
/**
* Optional effective runtime cap used for compaction/session budgeting.
* Keeps provider/native contextWindow metadata intact while letting configs
* prefer a smaller practical window.
*/
contextTokens?: number;
/** Maximum completion/output token budget. */
maxTokens: number;
/** Maps OpenClaw thinking levels to provider/model-specific values. */
thinkingLevelMap?: ThinkingLevelMap;
/** Provider-specific request/runtime parameters passed through to provider plugins. */
params?: Record<string, unknown>;
/** Optional agent execution runtime override for this provider/model pair. */
agentRuntime?: AgentRuntimePolicyConfig;
/** Static headers merged into requests for this model. */
headers?: Record<string, string>;
/** Provider compatibility flags for payload shaping and feature gating. */
compat?: ModelCompatConfig;
/** Media input limits used by routing and preflight compression. */
mediaInput?: ModelMediaInputConfig;
/** Metadata source marker for models added by CLI/catalog tooling. */
metadataSource?: "models-add";
};
type ModelProviderConfig = {
/** Provider API base URL. */
baseUrl: string;
/** API key or secret reference for this provider. */
apiKey?: SecretInput;
/** Authentication mode used when resolving credentials for this provider. */
auth?: ModelProviderAuthMode;
/** Default API adapter for models under this provider. */
api?: ModelApi;
/** Provider-level default max output tokens. */
maxTokens?: number;
/** Provider request timeout in seconds. */
timeoutSeconds?: number;
/** Optional provider deployment/API region used by provider plugins that expose regional endpoints. */
region?: string;
injectNumCtxForOpenAICompat?: boolean;
/** Provider-specific runtime parameters interpreted by provider plugins. */
params?: Record<string, unknown>;
/** Optional default agent execution runtime for models under this provider. */
agentRuntime?: AgentRuntimePolicyConfig;
/** Optional local service to start before calling this provider. */
localService?: ModelProviderLocalServiceConfig;
/** Secret-bearing headers merged into provider requests. */
headers?: Record<string, SecretInput>;
/** Whether default Authorization header injection is enabled. */
authHeader?: boolean;
/** Provider request transport/retry overrides. */
request?: ConfiguredModelProviderRequest;
/** Model catalog entries exposed by this provider. */
models: ModelDefinitionConfig[];
};
/** Fully materialized provider declaration emitted by provider catalog plugins. */
type ModelProviderDeclarationConfig = ModelProviderConfig;
type ModelCatalogRefreshConfig = {
/** Fetch model catalog updates from the hosted OpenClaw catalog. Default: true. */
enabled?: boolean;
/** Override the hosted catalog URL (HTTPS mirrors, or localhost HTTP for testing). */
url?: string;
};
type ModelsConfig = {
/** Merge provider config with bundled catalogs or replace bundled catalogs entirely. */
mode?: "merge" | "replace";
/** Configured provider catalog keyed by provider id. */
providers?: Record<string, ModelProviderConfig>;
/** Hosted model catalog refresh settings. */
catalogRefresh?: ModelCatalogRefreshConfig;
};
//#endregion
//#region src/config/types.node-host.d.ts
type NodeHostBrowserProxyConfig = {
/** Enable the browser proxy on the node host (default: true). */
enabled?: boolean;
/** Optional allowlist of profile names exposed via the proxy; when set, create/delete profile routes are blocked on the proxy surface. */
allowProfiles?: string[];
};
type NodeHostConfig = {
/** Sensitive native agent execution exposed by the headless node host. */
agentRuns?: {
claude?: {
/** Advertise approval-gated Claude CLI turns when the binary is installed. */
enabled?: boolean;
};
};
/** Full OpenClaw session hosting from Gateway-managed worker bundles. */
workerRuns?: {
/** Allow this paired node to host worker sessions (default: false). */
enabled?: boolean;
/** Integer worker slots (default: one per available CPU core). */
capacity?: number;
/** Worker process boundary: direct host execution or a container (default: none). */
isolation?: "none" | "container";
/** Optional Node 22+ container image override for isolated worker sessions. */
containerImage?: string;
};
/** Browser proxy settings for node hosts. */
browserProxy?: NodeHostBrowserProxyConfig;
/** MCP servers started and exposed by the headless node host. */
mcp?: {
servers?: Record<string, McpServerConfig>;
};
/** Skills published by the headless node host. */
skills?: {
/** Scan and publish ~/.openclaw/skills (default: true). */
enabled?: boolean;
};
};
//#endregion
//#region src/config/types.plugins.d.ts
type PluginEntryConfig = {
enabled?: boolean;
hooks?: {
/** Controls prompt mutation via before_prompt_build. */
allowPromptInjection?: boolean;
/**
* Controls access to raw conversation content from conversation hooks including
* before_agent_run, before_model_resolve, before_agent_reply, llm_input, llm_output,
* before_agent_finalize, and agent_end.
* Non-bundled plugins must opt in explicitly; bundled plugins stay allowed unless disabled.
*/
allowConversationAccess?: boolean;
/** Default timeout in milliseconds for this plugin's typed hooks. */
timeoutMs?: number;
/** Per typed-hook timeout overrides in milliseconds. */
timeouts?: Record<string, number>;
};
subagent?: {
/** Explicitly allow this plugin to request per-run provider/model overrides for subagent runs. */
allowModelOverride?: boolean;
/**
* Allowed override targets as canonical provider/model refs.
* Use "*" to explicitly allow any model for this plugin.
*/
allowedModels?: string[];
};
llm?: {
/** Explicitly allow this plugin to request a model override for api.runtime.llm.complete. */
allowModelOverride?: boolean;
/**
* Allowed override targets as canonical provider/model refs.
* Use "*" to explicitly allow any model for this plugin.
*/
allowedModels?: string[];
/**
* Allowed models for every completion, including host-resolved defaults and overrides.
* Use "*" to explicitly allow any model for this plugin.
*/
allowedCompletionModels?: string[];
/** Allow explicit auth-profile selection for isolated agent-runtime completions. */
allowAuthProfileOverride?: boolean;
/** Explicitly allow this plugin to run completions against a non-default agent id. */
allowAgentIdOverride?: boolean;
};
config?: Record<string, unknown>;
};
type PluginSlotsConfig = {
/** Select which plugin owns the memory slot ("none" disables memory plugins). */
memory?: string;
/** Select which plugin owns the context-engine slot. */
contextEngine?: string;
};
type PluginsLoadConfig = {
/** Additional plugin/extension paths to load. */
paths?: string[];
};
type PluginAcceptedDeclaredSurface = {
channels: string[];
providers: string[];
tools: string[];
contracts: string[];
hooks: string[];
mcpServers: string[];
cliCommands: string[];
cliBackends: string[];
skills: string[];
dangerousConfigFlags: string[];
};
type PluginInstallRecord = Omit<InstallRecordBase, "source"> & {
source: InstallRecordBase["source"] | "marketplace";
marketplaceName?: string;
marketplaceSource?: string;
marketplacePlugin?: string;
/** Sorted, manifest-declared capability surface accepted by the operator. */
acceptedSurface?: PluginAcceptedDeclaredSurface;
/** SHA-256 hex digest of the canonical accepted capability surface. */
acceptedSurfaceHash?: string;
/** ISO timestamp when the operator accepted this capability surface. */
acceptedSurfaceAt?: string;
/** Installed artifact integrity or Git commit the acceptance is anchored to. */
acceptedSurfaceIntegrity?: string;
};
type PluginsConfig = {
/** Enable or disable plugin loading. */
enabled?: boolean;
/** Optional plugin allowlist (plugin ids). */
allow?: string[];
/** Optional plugin denylist (plugin ids). */
deny?: string[];
load?: PluginsLoadConfig;
slots?: PluginSlotsConfig;
entries?: Record<string, PluginEntryConfig>;
/**
* Internal transient carrier for plugin install records during command flows.
* This is intentionally omitted from the config schema and must not be
* persisted to openclaw.json.
*/
installs?: Record<string, PluginInstallRecord>;
};
//#endregion
//#region src/config/types.telemetry.d.ts
type TelemetryConfig = {
/** Shares anonymous feature counts with the daily update check when explicitly enabled. */
enabled?: boolean;
/** ISO timestamp recording when the operator accepted or declined feature statistics. */
consentedAt?: string;
};
//#endregion
//#region src/config/zod-schema.proxy.d.ts
declare const ProxyConfigSchema: z.ZodOptional<z.ZodObject<{
enabled: z.ZodOptional<z.ZodBoolean>;
proxyUrl: z.ZodOptional<z.ZodURL>;
tls: z.ZodOptional<z.ZodObject<{
caFile: z.ZodOptional<z.ZodString>;
}, z.core.$strict>>;
loopbackMode: z.ZodOptional<z.ZodEnum<{
block: "block";
"gateway-only": "gateway-only";
proxy: "proxy";
}>>;
}, z.core.$strict>>;
type ProxyConfig = z.infer<typeof ProxyConfigSchema>;
//#endregion
//#region src/config/types.openclaw.d.ts
/** One persisted suppression for a known security audit finding. */
type SecurityAuditSuppression = {
/** Exact security audit check id to suppress. */
checkId: string;
/** Optional case-insensitive substring required in the finding title. */
titleIncludes?: string;
/** Optional case-insensitive substring required in the finding detail. */
detailIncludes?: string;
/** Operator rationale for accepting this standing finding. */
reason?: string;
};
type SecurityConfig = {
/** Security audit policy and accepted standing findings. */
audit?: {
/** Accepted security audit findings to omit from active summary/findings. */
suppressions?: SecurityAuditSuppression[];
};
installPolicy?: {
/**
* Enable operator-owned install policy. When true without an exec command,
* install/update attempts fail closed for supported targets.
*/
enabled?: boolean;
/** Supported install targets. Omit to cover every supported target. */
targets?: Array<"skill" | "plugin">;
/**
* Trusted local policy command. Transport intentionally mirrors exec
* SecretRef provider fields: absolute command, no shell, bounded output,
* explicit env allowlist, and secure path checks.
*/
exec?: {
source: "exec";
command: string;
args?: string[];
timeoutMs?: number;
noOutputTimeoutMs?: number;
maxOutputBytes?: number;
env?: Record<string, string>;
passEnv?: string[];
trustedDirs?: string[];
};
};
};
type SurfaceConfigEntry = {
/** Surface-specific silent reply policy for channels or UI integrations. */
silentReply?: SilentReplyPolicyShape;
};
/** Top-level OpenClaw config as read from user/project config files. */
type OpenClawConfig = {
/** @deprecated Doctor-only legacy input. */
audit?: AuditConfig;
/** JSON schema URL used by editors and generated config files. */
$schema?: string;
meta?: {
/** Last OpenClaw version that wrote this config. */
lastTouchedVersion?: string;
/** One-time doctor migrations already applied to this config. */
migrations?: {
modelPolicyAllowlist?: true;
};
};
/** Authentication provider/profile configuration. */
auth?: AuthConfig;
/** Named access groups used by channel/provider policy allowlists. */
accessGroups?: AccessGroupsConfig;
/** ACP integration settings. */
acp?: AcpConfig;
env?: {
/** Opt-in: import missing secrets from a login shell environment (interactive for Bash). */
shellEnv?: {
enabled?: boolean;
/** Timeout for the login shell exec (ms). Default: 15000. */
timeoutMs?: number;
};
/** Inline env vars to apply when not already present in the process env. */
vars?: Record<string, string>;
/** Sugar: allow env vars directly under env (string values only). */
[key: string]: string | Record<string, string> | {
enabled?: boolean;
timeoutMs?: number;
} | undefined;
};
wizard?: {
/** Guided-onboarding discovery consent: "full" scans silently, "guarded" asks first. */
accessMode?: "full" | "guarded";
/** Offer installed-application plugin and skill recommendations during onboarding. */
appRecommendations?: boolean;
lastRunAt?: string;
lastRunVersion?: string;
lastRunCommit?: string;
lastRunCommand?: string;
lastRunMode?: "local" | "remote";
localModelLeanAutoModel?: string;
securityAcknowledgedAt?: string;
};
/** Diagnostics, tracing, and stability debugging settings. */
diagnostics?: DiagnosticsConfig;
/** Log sink, level, rotation, and redaction settings. */
logging?: LoggingConfig;
/** Security audit suppressions and security policy settings. */
security?: SecurityConfig;
update?: {
/** Update channel for git + npm installs ("stable", "extended-stable", "beta", or "dev"). */
channel?: "stable" | "extended-stable" | "beta" | "dev";
/** Check for updates on gateway start; disabling also prevents anonymous update pings. */
checkOnStart?: boolean;
/** Core auto-update policy for package installs. */
auto?: {
/** Enable background auto-update checks and apply logic. Default: false. */
enabled?: boolean;
};
};
/** Explicit operator consent for anonymous feature statistics in the daily update check. */
telemetry?: TelemetryConfig;
/** Browser automation and browser plugin integration settings. */
browser?: BrowserConfig;
ui?: {
/** Accent color for OpenClaw UI chrome (hex). */
seamColor?: string;
/**
* Operator display preferences. Canonical config home so agents can
* change them through the approval gate and clients stay in sync; the
* Control UI mirrors them into browser storage for instant boot.
*/
prefs?: {
/** Control UI theme. */
theme?: "claw" | "knot" | "dash" | "absolutely" | "tide" | "beacon" | "phosphor" | "crt" | "manuscript" | "rose" | "miami" | "custom";
/** Light/dark preference. */
themeMode?: "light" | "dark" | "system";
/** User-selected Control UI accent color (#RRGGBB). */
accent?: string;
/** BCP 47 UI locale, e.g. "en" or "pt-BR". */
locale?: string;
/** Show model thinking output in chat. */
chatShowThinking?: boolean;
/** Show tool call cards in chat. */
chatShowToolCalls?: boolean;
/** Keep model commentary in Control UI transcripts after a run. */
chatPersistCommentary?: boolean;
/** Chat send shortcut: Enter sends, or modifier+Enter sends. */
chatSendShortcut?: "enter" | "modifier-enter";
/** Follow-up handling while a run is active; unset uses the server queue mode. */
chatFollowUpMode?: "steer" | "queue";
/** Ordered page and pinned-session entries shown in the Control UI sidebar. */
sidebarEntries?: string[];
};
};
/** Secret providers, defaults, and ref-resolution settings. */
secrets?: SecretsConfig;
/** Skill loading and bundled skill configuration. */
skills?: SkillsConfig;
/** Plugin registry/install/runtime configuration. */
plugins?: PluginsConfig;
/** Per-surface policy keyed by channel/UI/runtime surface id. */
surfaces?: Record<string, SurfaceConfigEntry>;
/** Model providers, model catalog, pricing, and catalog merge policy. */
models?: ModelsConfig;
/** Node-host pairing and remote command node settings. */
nodeHost?: NodeHostConfig;
/** Agent definitions, defaults, bindings, and runtime policy. */
agents?: AgentsConfig;
/** Global root for new managed worktrees. Defaults to <state-dir>/worktrees; accepts ~. */
worktreeRoot?: string;
/** Tool exposure, policy, web/media tools, exec, and code-mode settings. */
tools?: ToolsConfig;
/** Legacy/direct agent bindings used by runtime resolution. */
bindings?: AgentBinding[];
/** Broadcast command and delivery settings. */
broadcast?: BroadcastConfig;
attachments?: {
/** Optional retention window for persisted inbound media cleanup. */
ttlHours?: number;
};
/** Message formatting, delivery, and action settings. */
messages?: MessagesConfig;
/** Shared text-to-speech defaults. Agent and channel overrides layer over this config. */
tts?: TtsConfig;
/** Chat command settings. */
commands?: CommandsConfig;
/** Human approval workflow settings. */
approvals?: ApprovalsConfig;
/** Session keying, reset, maintenance, send-policy, and thread-binding settings. */
session?: SessionConfig;
/** Channel defaults, built-in channel sections, and plugin-owned channel config. */
channels?: ChannelsConfig;
/** Cron schedule and retention settings. */
cron?: CronConfig;
/** Transcript persistence and export settings. */
transcripts?: TranscriptsConfig;
/** Runtime hook registration and queue behavior. */
hooks?: HooksConfig;
/** Network discovery and service advertisement settings. */
discovery?: DiscoveryConfig;
/** Voice/talk mode configuration. */
talk?: TalkConfig;
/** Gateway server, auth, UI, node-pairing, and dispatch settings. */
gateway?: GatewayConfig;
/** Opt-in cloud-worker provider profiles. */
cloudWorkers?: CloudWorkersConfig;
/** Experimental desktop sources owned by the gateway host. */
desktop?: DesktopConfig;
/** Memory indexing/search configuration. */
memory?: MemoryConfig;
/** MCP client/server and Codex MCP approval configuration. */
mcp?: McpConfig;
/** Network-level SSRF protection via an operator-managed forward proxy. */
proxy?: ProxyConfig;
};
declare const openClawConfigStateBrand: unique symbol;
type BrandedConfigState<TState extends string> = OpenClawConfig & {
readonly [openClawConfigStateBrand]?: TState;
};
/** Source config after includes/env substitution, before runtime defaults. */
type ResolvedSourceConfig = BrandedConfigState<"resolved-source">;
/** Runtime-materialized config with defaults/normalization applied. */
type RuntimeConfig = BrandedConfigState<"runtime">;
type ConfigValidationIssue = {
/** Dot-path to the invalid or legacy config value. */
path: string;
/** Structured validator path used internally for lossless source diagnostics. */
pathSegments?: Array<string | number>;
/** Human-readable validation message. */
message: string;
/** Optional allowed values shown to the operator. */
allowedValues?: string[];
/** Number of allowed values omitted from the display list. */
allowedValuesHiddenCount?: number;
};
type LegacyConfigIssue = {
/** Dot-path to the legacy config value. */
path: string;
/** Human-readable migration or rejection message. */
message: string;
};
type ConfigFileSnapshot = {
/** Config file path that was read. */
path: string;
/** Lexical and canonical file paths reached while resolving $include directives. */
includedPaths?: string[];
/** Exact authored ownership for every successfully resolved $include directive. */
includeProvenance?: readonly ConfigIncludeOwnership[];
/** Temporary roster-only projection retained until write preparation uses generic ownership. */
agentRosterIncludeOwned?: boolean;
bindingsIncludeOwned?: boolean;
/** Whether the config file exists on disk. */
exists: boolean;
/** Raw file contents before parsing; null when missing. */
raw: string | null;
/** Parsed JSON/JSONC/YAML value before schema normalization. */
parsed: unknown;
/** Include/env-resolved source before raw compatibility migrations. */
sourceConfigBeforeMigrations?: ResolvedSourceConfig;
/**
* Config authored on disk after $include resolution and ${ENV} substitution,
* but BEFORE runtime defaults are applied.
*/
sourceConfig: ResolvedSourceConfig;
/**
* Config after $include resolution and ${ENV} substitution, but BEFORE runtime
* defaults are applied. Use this for config set/unset operations to avoid
* leaking runtime defaults into the written config file.
*/
resolved: ResolvedSourceConfig;
valid: boolean;
/** Runtime-shaped config used by in-process readers. */
runtimeConfig: RuntimeConfig;
/** @deprecated Prefer runtimeConfig. */
config: RuntimeConfig;
hash?: string;
readError?: {
code: string | null;
};
issues: ConfigValidationIssue[];
warnings: ConfigValidationIssue[];
legacyIssues: LegacyConfigIssue[];
};
//#endregion
//#region src/channels/ids.d.ts
/**
* Canonical chat channel id used by core routing, plugin config, and channel catalogs.
*/
type ChatChannelId = string;
//#endregion
//#region src/channels/plugins/channel-id.types.d.ts
/**
* Channel id accepted by plugin helpers, covering built-in chat ids and external plugin ids.
*/
type ChannelId$1 = ChatChannelId | (string & {});
//#endregion
//#region src/config/group-policy.d.ts
type GroupPolicyChannel = ChannelId$1;
type ChannelGroupConfig = {
requireMention?: boolean;
ingest?: boolean;
tools?: GroupToolPolicyConfig;
toolsBySender?: GroupToolPolicyBySenderConfig;
};
type ChannelGroupPolicy = {
allowlistEnabled: boolean;
allowed: boolean;
groupConfig?: ChannelGroupConfig;
defaultConfig?: ChannelGroupConfig;
};
declare function resolveChannelGroupPolicy(params: {
cfg: OpenClawConfig;
channel: GroupPolicyChannel;
groupId?: string | null;
accountId?: string | null;
groupIdCaseInsensitive?: boolean;
/** When true, sender-level filtering (groupAllowFrom) is configured upstream. */
hasGroupAllowFrom?: boolean;
}): ChannelGroupPolicy;
declare function resolveChannelGroupRequireMention(params: {
cfg: OpenClawConfig;
channel: GroupPolicyChannel;
groupId?: string | null;
accountId?: string | null;
groupIdCaseInsensitive?: boolean;
requireMentionOverride?: boolean;
configuredGroupDefaultsToNoMention?: boolean;
overrideOrder?: "before-config" | "after-config";
}): boolean;
//#endregion
//#region packages/gateway-protocol/src/schema/skill-library.d.ts
declare const SkillLibraryFileSchema: Type.TObject<{
path: Type.TString;
content: Type.TString;
encoding: Type.TOptional<Type.TUnion<[Type.TLiteral<"utf8">, Type.TLiteral<"base64">]>>;
executable: Type.TOptional<Type.TBoolean>;
}>;
declare const SkillLibrarySelectionSchema: Type.TObject<{
skillId: Type.TString;
revision: Type.TString;
/** Persisted command identity: library collisions never shadow workspace names. */
name: Type.TString;
ownerProfileId: Type.TUnion<[Type.TString, Type.TNull]>;
}>;
type SkillLibraryFile = Static<typeof SkillLibraryFileSchema>;
type SkillLibrarySelection = Static<typeof SkillLibrarySelectionSchema>;
type SkillLibraryEntry = {
skillId: string;
slug: string;
name: string;
description: string;
ownerProfileId: string | null;
ownerLabel: string;
authorProfileId: string;
shared: boolean;
enabled: boolean;
removed: boolean;
revision: string;
createdAt: number;
updatedAt: number;
canEdit: boolean;
};
type SkillsLibraryListResult = {
entries: SkillLibraryEntry[];
profileId: string | null;
multipleProfiles: boolean;
defaultTarget: "workspace" | "personal" | "unavailable";
canManageWorkspace: boolean;
defaultSelectionLimit: number;
defaultSelectionNotice?: string;
session?: {
sessionKey: string;
selections: Array<SkillLibrarySelection & {
slug: string;
description: string;
ownerLabel: string;
}>;
attachable: SkillLibraryEntry[];
};
};
type SkillsLibraryReadResult = {
entry: SkillLibraryEntry;
content: string;
files: SkillLibraryFile[];
revisions: Array<{
revision: string;
createdAt: number;
}>;
};
type SkillsLibraryReceipt = {
state: "published" | "unchanged" | "removed";
target: "personal" | "team";
entry: SkillLibraryEntry;
sessionActivation: "new-sessions";
nextAction: string;
};
type SkillsLibraryActivateResult = {
sessionKey: string;
selections: SkillLibrarySelection[];
sessionActivation: "next-turn";
};
//#endregion
//#region src/config/sessions/session-diff-baseline-capture.d.ts
type SessionDiffBaselineCapture = {
version: 1;
captureId: string;
status: "pending" | "unavailable";
};
//#endregion
//#region packages/acp-core/src/types.d.ts
type SessionAcpIdentitySource = "ensure" | "status" | "event";
type SessionAcpIdentityState = "pending" | "resolved";
type SessionAcpIdentity = {
/** Pending identities may expose provisional ids; resolved identities are safe for resume output. */
state: SessionAcpIdentityState;
acpxRecordId?: string;
acpxSessionId?: string;
agentSessionId?: string;
/** Runtime lifecycle point that last supplied the identity fields. */
source: SessionAcpIdentitySource;
lastUpdatedAt: number;
};
type AcpSessionRuntimeOptions = {
/**
* ACP runtime mode set via session/set_mode (for example: "plan", "normal", "auto").
*/
runtimeMode?: string;
/** ACP runtime config option: model id. */
model?: string;
/** ACP runtime config option: thinking/reasoning effort. */
thinking?: string;
/** Working directory override for ACP session turns. */
cwd?: string;
/** ACP runtime config option: permission profile id. */
permissionProfile?: string;
/** ACP runtime config option: per-turn timeout in seconds. */
timeoutSeconds?: number;
/** Backend-specific option bag mapped through session/set_config_option. */
backendExtras?: Record<string, string>;
};
type SessionAcpMeta = {
backend: string;
agent: string;
runtimeSessionName: string;
/** Canonical backend/agent ids used for resume hints and thread/status details. */
identity?: SessionAcpIdentity;
mode: "persistent" | "oneshot";
runtimeOptions?: AcpSessionRuntimeOptions;
cwd?: string;
state: "idle" | "running" | "error";
lastActivityAt: number;
lastError?: string;
};
//#endregion
//#region packages/gateway-protocol/src/schema/frames.d.ts
/** Initial client hello/connect payload sent before the gateway accepts frames. */
declare const ConnectParamsSchema: Type.TObject<{
minProtocol: Type.TInteger;
maxProtocol: Type.TInteger;
client: Type.TObject<{
id: Type.TEnum<["openclaw-android", "openclaw-browser-copilot", "cli", "openclaw-control-ui", "fingerprint", "gateway-client", "openclaw-ios", "openclaw-linux", "openclaw-macos", "node-host", "openclaw-probe", "test", "openclaw-tui", "openclaw-watchos", "webchat", "webchat-ui", "openclaw-worker"]>;
displayName: Type.TOptional<Type.TString>;
version: Type.TString;
buildId: Type.TOptional<Type.TString>;
platform: Type.TString;
deviceFamily: Type.TOptional<Type.TString>;
modelIdentifier: Type.TOptional<Type.TString>;
/** Self-reported IANA zone. Bounded because the longest real name is well under this cap. */
timeZone: Type.TOptional<Type.TString>;
mode: Type.TEnum<["backend", "cli", "node", "probe", "test", "ui", "webchat", "worker"]>;
instanceId: Type.TOptional<Type.TString>;
}>;
caps: Type.TOptional<Type.TArray<Type.TString>>;
commands: Type.TOptional<Type.TArray<Type.TString>>;
/** Additive Computer Use declaration; the owning core contract validates its bounded shape. */
computerUse: Type.TOptional<Type.TUnknown>;
/** @deprecated Accepted for the shipped v1 node-host envelope; current hosts use runner inventory. */
workerRuns: Type.TOptional<Type.TObject<{
bundleHash: Type.TString;
openclawVersion: Type.TString;
protocolFeatures: Type.TArray<Type.TString>;
bundlePrewarm: Type.TOptional<Type.TInteger>;
}>>;
permissions: Type.TOptional<Type.TRecord<"^.*$", Type.TBoolean>>;
pathEnv: Type.TOptional<Type.TString>;
role: Type.TOptional<Type.TString>;
scopes: Type.TOptional<Type.TArray<Type.TString>>;
device: Type.TOptional<Type.TObject<{
id: Type.TString;
publicKey: Type.TString;
signature: Type.TString;
signedAt: Type.TInteger;
nonce: Type.TString;
}>>;
auth: Type.TOptional<Type.TObject<{
token: Type.TOptional<Type.TString>;
bootstrapToken: Type.TOptional<Type.TString>;
deviceToken: Type.TOptional<Type.TString>;
password: Type.TOptional<Type.TString>;
approvalRuntimeToken: Type.TOptional<Type.TString>;
agentRuntimeIdentityToken: Type.TOptional<Type.TString>;
}>>;
locale: Type.TOptional<Type.TString>;
userAgent: Type.TOptional<Type.TString>;
}>;
/** Standard structured error shape used in response frames and connect failures. */
declare const ErrorShapeSchema: Type.TObject<{
code: Type.TString;
message: Type.TString;
details: Type.TOptional<Type.TUnknown>;
retryable: Type.TOptional<Type.TBoolean>;
retryAfterMs: Type.TOptional<Type.TInteger>;
}>;
/** Client request frame envelope; `method` selects the payload validator. */
declare const RequestFrameSchema: Type.TObject<{
type: Type.TLiteral<"req">;
id: Type.TString;
method: Type.TString;
params: Type.TOptional<Type.TUnknown>;
traceparent: Type.TOptional<Type.TString>;
}>;
type ConnectParams = Static<typeof ConnectParamsSchema>;
type ErrorShape = Static<typeof ErrorShapeSchema>;
type RequestFrame = Static<typeof RequestFrameSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/session-github-publication.d.ts
declare const GitHubPublicationPublisherSchema: Type.TObject<{
accountId: Type.TInteger;
login: Type.TString;
source: Type.TUnion<[Type.TLiteral<"personal">, Type.TLiteral<"system-detected">, Type.TLiteral<"system-configured">, Type.TLiteral<"agent-override">]>;
}>;
declare const SessionGitHubPublishParamsSchema: Type.TObject<{
sessionKey: Type.TOptional<Type.TString>;
agentId: Type.TOptional<Type.TString>;
idempotencyKey: Type.TString;
title: Type.TOptional<Type.TString>;
body: Type.TOptional<Type.TString>;
selection: Type.TOptional<Type.TUnion<[Type.TObject<{
source: Type.TLiteral<"shared">;
expected: Type.TOptional<Type.TObject<{
accountId: Type.TInteger;
login: Type.TString;
source: Type.TUnion<[Type.TLiteral<"system-detected">, Type.TLiteral<"system-configured">, Type.TLiteral<"agent-override">]>;
}>>;
}>, Type.TObject<{
source: Type.TLiteral<"personal">;
generation: Type.TString;
account: Type.TObject<{
accountId: Type.TInteger;
login: Type.TString;
}>;
}>]>>;
}>;
declare const SessionGitHubPublicationResultSchema: Type.TUnion<[Type.TObject<{
requestId: Type.TString;
publisher: Type.TOptional<Type.TObject<{
accountId: Type.TInteger;
login: Type.TString;
source: Type.TUnion<[Type.TLiteral<"personal">, Type.TLiteral<"system-detected">, Type.TLiteral<"system-configured">, Type.TLiteral<"agent-override">]>;
}>>;
effect: Type.TOptional<Type.TObject<{
kind: Type.TUnion<[Type.TLiteral<"push">, Type.TLiteral<"pull_request">]>;
status: Type.TUnion<[Type.TLiteral<"dispatched">, Type.TLiteral<"observed">]>;
headCommit: Type.TOptional<Type.TString>;
url: Type.TOptional<Type.TString>;
}>>;
status: Type.TLiteral<"requested">;
message: Type.TString;
}>, Type.TObject<{
requestId: Type.TString;
publisher: Type.TOptional<Type.TObject<{
accountId: Type.TInteger;
login: Type.TString;
source: Type.TUnion<[Type.TLiteral<"personal">, Type.TLiteral<"system-detected">, Type.TLiteral<"system-configured">, Type.TLiteral<"agent-override">]>;
}>>;
effect: Type.TOptional<Type.TObject<{
kind: Type.TUnion<[Type.TLiteral<"push">, Type.TLiteral<"pull_request">]>;
status: Type.TUnion<[Type.TLiteral<"dispatched">, Type.TLiteral<"observed">]>;
headCommit: Type.TOptional<Type.TString>;
url: Type.TOptional<Type.TString>;
}>>;
status: Type.TLiteral<"publishing">;
message: Type.TString;
}>, Type.TObject<{
requestId: Type.TString;
publisher: Type.TOptional<Type.TObject<{
accountId: Type.TInteger;
login: Type.TString;
source: Type.TUnion<[Type.TLiteral<"personal">, Type.TLiteral<"system-detected">, Type.TLiteral<"system-configured">, Type.TLiteral<"agent-override">]>;
}>>;
effect: Type.TOptional<Type.TObject<{
kind: Type.TUnion<[Type.TLiteral<"push">, Type.TLiteral<"pull_request">]>;
status: Type.TUnion<[Type.TLiteral<"dispatched">, Type.TLiteral<"observed">]>;
headCommit: Type.TOptional<Type.TString>;
url: Type.TOptional<Type.TString>;
}>>;
status: Type.TLiteral<"published">;
url: Type.TString;
repository: Type.TString;
branch: Type.TString;
headCommit: Type.TString;
}>, Type.TObject<{
requestId: Type.TString;
publisher: Type.TOptional<Type.TObject<{
accountId: Type.TInteger;
login: Type.TString;
source: Type.TUnion<[Type.TLiteral<"personal">, Type.TLiteral<"system-detected">, Type.TLiteral<"system-configured">, Type.TLiteral<"agent-override">]>;
}>>;
effect: Type.TOptional<Type.TObject<{
kind: Type.TUnion<[Type.TLiteral<"push">, Type.TLiteral<"pull_request">]>;
status: Type.TUnion<[Type.TLiteral<"dispatched">, Type.TLiteral<"observed">]>;
headCommit: Type.TOptional<Type.TString>;
url: Type.TOptional<Type.TString>;
}>>;
status: Type.TLiteral<"failed">;
code: Type.TUnion<[Type.TLiteral<"identity_changed">, Type.TLiteral<"identity_unavailable">, Type.TLiteral<"session_changed">, Type.TLiteral<"workspace_changed">, Type.TLiteral<"not_git">, Type.TLiteral<"not_github">, Type.TLiteral<"no_changes">, Type.TLiteral<"push_rejected">, Type.TLiteral<"github_rejected">, Type.TLiteral<"unavailable">]>;
message: Type.TString;
nextAction: Type.TString;
}>, Type.TObject<{
requestId: Type.TString;
publisher: Type.TOptional<Type.TObject<{
accountId: Type.TInteger;
login: Type.TString;
source: Type.TUnion<[Type.TLiteral<"personal">, Type.TLiteral<"system-detected">, Type.TLiteral<"system-configured">, Type.TLiteral<"agent-override">]>;
}>>;
effect: Type.TOptional<Type.TObject<{
kind: Type.TUnion<[Type.TLiteral<"push">, Type.TLiteral<"pull_request">]>;
status: Type.TUnion<[Type.TLiteral<"dispatched">, Type.TLiteral<"observed">]>;
headCommit: Type.TOptional<Type.TString>;
url: Type.TOptional<Type.TString>;
}>>;
status: Type.TLiteral<"needs_confirmation">;
message: Type.TString;
}>]>;
declare const SessionGitHubConfirmParamsSchema: Type.TObject<{
sessionKey: Type.TString;
agentId: Type.TOptional<Type.TString>;
requestId: Type.TString;
generation: Type.TString;
account: Type.TObject<{
accountId: Type.TInteger;
login: Type.TString;
}>;
requestDigest: Type.TString;
}>;
type GitHubPublicationPublisher = Static<typeof GitHubPublicationPublisherSchema>;
type SessionGitHubConfirmParams = Static<typeof SessionGitHubConfirmParamsSchema>;
type SessionGitHubPublishParams = Static<typeof SessionGitHubPublishParamsSchema>;
type SessionGitHubPublicationResult = Static<typeof SessionGitHubPublicationResultSchema>;
//#endregion
//#region packages/gateway-protocol/src/session-agent-status.d.ts
declare const SESSION_AGENT_ATTENTION_ICON_IDS: readonly ["hand", "key", "alert", "flag", "lock", "hourglass"];
type SessionAgentAttentionIconId = (typeof SESSION_AGENT_ATTENTION_ICON_IDS)[number];
type SessionAgentStatus = {
note: string;
expiresAt: number;
attention?: SessionAgentAttentionIconId;
};
//#endregion
//#region packages/gateway-protocol/src/schema/approvals.d.ts
/**
* Owner-declared blast-radius facts for a pending approval. Variants are
* named schemas so native protocol generators emit the discriminated union.
*/
declare const ApprovalScopeSchema: Type.TUnion<[Type.TObject<{
kind: Type.TLiteral<"message-send">;
target: Type.TString;
recipientCount: Type.TInteger;
recipients: Type.TOptional<Type.TArray<Type.TString>>;
audience: Type.TOptional<Type.TUnion<[Type.TLiteral<"internal">, Type.TLiteral<"external">]>>;
}>, Type.TObject<{
kind: Type.TLiteral<"payment">;
amount: Type.TString;
currency: Type.TString;
target: Type.TString;
}>, Type.TObject<{
kind: Type.TLiteral<"external-post">;
target: Type.TString;
visibility: Type.TUnion<[Type.TLiteral<"public">, Type.TLiteral<"restricted">]>;
}>, Type.TObject<{
kind: Type.TLiteral<"standing-grant">;
automation: Type.TString;
command: Type.TString;
expiresInDays: Type.TOptional<Type.TInteger>;
}>]>;
/** Reviewer-safe presentation discriminated by the approval owner. */
declare const ApprovalPresentationSchema: Type.TUnion<[Type.TObject<{
kind: Type.TLiteral<"exec">;
commandText: Type.TString;
commandPreview: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
warningText: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
host: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
nodeId: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
agentId: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
scope: Type.TOptional<Type.TUnion<[Type.TObject<{
kind: Type.TLiteral<"message-send">;
target: Type.TString;
recipientCount: Type.TInteger;
recipients: Type.TOptional<Type.TArray<Type.TString>>;
audience: Type.TOptional<Type.TUnion<[Type.TLiteral<"internal">, Type.TLiteral<"external">]>>;
}>, Type.TObject<{
kind: Type.TLiteral<"payment">;
amount: Type.TString;
currency: Type.TString;
target: Type.TString;
}>, Type.TObject<{
kind: Type.TLiteral<"external-post">;
target: Type.TString;
visibility: Type.TUnion<[Type.TLiteral<"public">, Type.TLiteral<"restricted">]>;
}>, Type.TObject<{
kind: Type.TLiteral<"standing-grant">;
automation: Type.TString;
command: Type.TString;
expiresInDays: Type.TOptional<Type.TInteger>;
}>]>>;
allowedDecisions: Type.TArray<Type.TUnion<[Type.TLiteral<"allow-once">, Type.TLiteral<"allow-always">, Type.TLiteral<"deny">]>>;
}>, Type.TObject<{
kind: Type.TLiteral<"plugin">;
title: Type.TString;
description: Type.TString;
detail: Type.TOptional<Type.TString>;
severity: Type.TUnion<[Type.TLiteral<"info">, Type.TLiteral<"warning">, Type.TLiteral<"critical">]>;
pluginId: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
toolName: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
agentId: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
scope: Type.TOptional<Type.TUnion<[Type.TObject<{
kind: Type.TLiteral<"message-send">;
target: Type.TString;
recipientCount: Type.TInteger;
recipients: Type.TOptional<Type.TArray<Type.TString>>;
audience: Type.TOptional<Type.TUnion<[Type.TLiteral<"internal">, Type.TLiteral<"external">]>>;
}>, Type.TObject<{
kind: Type.TLiteral<"payment">;
amount: Type.TString;
currency: Type.TString;
target: Type.TString;
}>, Type.TObject<{
kind: Type.TLiteral<"external-post">;
target: Type.TString;
visibility: Type.TUnion<[Type.TLiteral<"public">, Type.TLiteral<"restricted">]>;
}>, Type.TObject<{
kind: Type.TLiteral<"standing-grant">;
automation: Type.TString;
command: Type.TString;
expiresInDays: Type.TOptional<Type.TInteger>;
}>]>>;
allowedDecisions: Type.TArray<Type.TUnion<[Type.TLiteral<"allow-once">, Type.TLiteral<"allow-always">, Type.TLiteral<"deny">]>>;
externalResolution: Type.TOptional<Type.TObject<{
label: Type.TString;
decisions: Type.TArray<Type.TUnion<[Type.TLiteral<"allow-once">, Type.TLiteral<"allow-always">]>>;
}>>;
}>, Type.TObject<{
kind: Type.TLiteral<"system-agent">;
title: Type.TString;
description: Type.TString;
proposalHash: Type.TString;
agentId: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
allowedDecisions: Type.TTuple<[Type.TLiteral<"allow-once">, Type.TLiteral<"deny">]>;
}>]>;
/** Authoritative pending approval set returned when a session stream subscribes. */
declare const SessionApprovalReplaySchema: Type.TObject<{
sessionKey: Type.TString;
updatedAtMs: Type.TInteger;
approvals: Type.TArray<Type.TObject<{
id: Type.TString;
urlPath: Type.TString;
createdAtMs: Type.TInteger;
expiresAtMs: Type.TInteger;
presentation: Type.TUnion<[Type.TObject<{
kind: Type.TLiteral<"exec">;
commandText: Type.TString;
commandPreview: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
warningText: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
host: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
nodeId: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
agentId: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
scope: Type.TOptional<Type.TUnion<[Type.TObject<{
kind: Type.TLiteral<"message-send">;
target: Type.TString;
recipientCount: Type.TInteger;
recipients: Type.TOptional<Type.TArray<Type.TString>>;
audience: Type.TOptional<Type.TUnion<[Type.TLiteral<"internal">, Type.TLiteral<"external">]>>;
}>, Type.TObject<{
kind: Type.TLiteral<"payment">;
amount: Type.TString;
currency: Type.TString;
target: Type.TString;
}>, Type.TObject<{
kind: Type.TLiteral<"external-post">;
target: Type.TString;
visibility: Type.TUnion<[Type.TLiteral<"public">, Type.TLiteral<"restricted">]>;
}>, Type.TObject<{
kind: Type.TLiteral<"standing-grant">;
automation: Type.TString;
command: Type.TString;
expiresInDays: Type.TOptional<Type.TInteger>;
}>]>>;
allowedDecisions: Type.TArray<Type.TUnion<[Type.TLiteral<"allow-once">, Type.TLiteral<"allow-always">, Type.TLiteral<"deny">]>>;
}>, Type.TObject<{
kind: Type.TLiteral<"plugin">;
title: Type.TString;
description: Type.TString;
detail: Type.TOptional<Type.TString>;
severity: Type.TUnion<[Type.TLiteral<"info">, Type.TLiteral<"warning">, Type.TLiteral<"critical">]>;
pluginId: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
toolName: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
agentId: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
scope: Type.TOptional<Type.TUnion<[Type.TObject<{
kind: Type.TLiteral<"message-send">;
target: Type.TString;
recipientCount: Type.TInteger;
recipients: Type.TOptional<Type.TArray<Type.TString>>;
audience: Type.TOptional<Type.TUnion<[Type.TLiteral<"internal">, Type.TLiteral<"external">]>>;
}>, Type.TObject<{
kind: Type.TLiteral<"payment">;
amount: Type.TString;
currency: Type.TString;
target: Type.TString;
}>, Type.TObject<{
kind: Type.TLiteral<"external-post">;
target: Type.TString;
visibility: Type.TUnion<[Type.TLiteral<"public">, Type.TLiteral<"restricted">]>;
}>, Type.TObject<{
kind: Type.TLiteral<"standing-grant">;
automation: Type.TString;
command: Type.TString;
expiresInDays: Type.TOptional<Type.TInteger>;
}>]>>;
allowedDecisions: Type.TArray<Type.TUnion<[Type.TLiteral<"allow-once">, Type.TLiteral<"allow-always">, Type.TLiteral<"deny">]>>;
externalResolution: Type.TOptional<Type.TObject<{
label: Type.TString;
decisions: Type.TArray<Type.TUnion<[Type.TLiteral<"allow-once">, Type.TLiteral<"allow-always">]>>;
}>>;
}>, Type.TObject<{
kind: Type.TLiteral<"system-agent">;
title: Type.TString;
description: Type.TString;
proposalHash: Type.TString;
agentId: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
allowedDecisions: Type.TTuple<[Type.TLiteral<"allow-once">, Type.TLiteral<"deny">]>;
}>]>;
status: Type.TLiteral<"pending">;
/** Canonical raising session when projected into a session-scoped reviewer surface. */
sourceSessionKey: Type.TOptional<Type.TString>;
}>>;
truncated: Type.TBoolean;
}>;
type ApprovalPresentation = Static<typeof ApprovalPresentationSchema>;
type SessionApprovalReplay = Static<typeof SessionApprovalReplaySchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/worker-inference.d.ts
declare const WorkerInferenceModelRefSchema: Type.TObject<{
readonly provider: Type.TString;
readonly model: Type.TString;
}>;
declare const WorkerInferenceOptionsSchema: Type.TObject<{
readonly temperature: Type.TOptional<Type.TNumber>;
readonly maxTokens: Type.TOptional<Type.TInteger>;
readonly reasoning: Type.TOptional<Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"minimal">, Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">, Type.TLiteral<"xhigh">, Type.TLiteral<"adaptive">, Type.TLiteral<"max">]>>;
readonly thinkingBudgets: Type.TOptional<Type.TObject<{
readonly minimal: Type.TOptional<Type.TInteger>;
readonly low: Type.TOptional<Type.TInteger>;
readonly medium: Type.TOptional<Type.TInteger>;
readonly high: Type.TOptional<Type.TInteger>;
readonly max: Type.TOptional<Type.TInteger>;
}>>;
}>;
type WorkerInferenceModelRef = Static<typeof WorkerInferenceModelRefSchema>;
type WorkerInferenceOptions = Static<typeof WorkerInferenceOptionsSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/sessions-row.d.ts
declare const SessionPermissionModeSchema: Type.TUnion<[Type.TLiteral<"read-only">, Type.TLiteral<"guarded">, Type.TLiteral<"workspace">, Type.TLiteral<"full">]>;
declare const SessionRunStatusSchema: Type.TUnion<[Type.TLiteral<"queued">, Type.TLiteral<"running">, Type.TLiteral<"done">, Type.TLiteral<"failed">, Type.TLiteral<"killed">, Type.TLiteral<"timeout">]>;
declare const SessionEntryArchiveReasonSchema: Type.TUnion<[Type.TLiteral<"manual">, Type.TLiteral<"active-session-cap">, Type.TLiteral<"stale-dashboard">, Type.TLiteral<"restart-recovery">]>;
/** Stable Gateway session row fields; mutation envelopes may add null tombstones. */
declare const SessionRowSchema: Type.TObject<{
key: Type.TString;
sessionId: Type.TOptional<Type.TString>;
incognito: Type.TOptional<Type.TLiteral<true>>;
kind: Type.TUnion<[Type.TLiteral<"direct">, Type.TLiteral<"group">, Type.TLiteral<"global">, Type.TLiteral<"unknown">]>;
label: Type.TOptional<Type.TString>;
icon: Type.TOptional<Type.TString>;
/** Named sidebar tint from SESSION_COLOR_IDS; clients map names to theme hues. */
color: Type.TOptional<Type.TString>;
channelAvatarUrl: Type.TOptional<Type.TString>;
boardFace: Type.TOptional<Type.TUnion<[Type.TLiteral<"chat">, Type.TLiteral<"dashboard">]>>;
displayName: Type.TOptional<Type.TString>;
derivedTitle: Type.TOptional<Type.TString>;
lastMessagePreview: Type.TOptional<Type.TString>;
channel: Type.TOptional<Type.TString>;
/** Stable non-sensitive facts derived from the canonical session route. */
classification: Type.TOptional<Type.TString>;
agentId: Type.TOptional<Type.TString>;
accountId: Type.TOptional<Type.TString>;
peerKind: Type.TOptional<Type.TString>;
isMain: Type.TOptional<Type.TBoolean>;
isBackground: Type.TOptional<Type.TBoolean>;
chatType: Type.TOptional<Type.TUnion<[Type.TLiteral<"direct">, Type.TLiteral<"group">, Type.TLiteral<"channel">]>>;
updatedAt: Type.TOptional<Type.TUnion<[Type.TNumber, Type.TNull]>>;
archived: Type.TOptional<Type.TBoolean>;
archivedAt: Type.TOptional<Type.TNumber>;
archivedBy: Type.TOptional<Type.TObject<{
type: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"agent">, Type.TLiteral<"system">]>;
id: Type.TOptional<Type.TString>;
label: Type.TOptional<Type.TString>;
/** Durable profile avatar route; absent for actors without a stored profile avatar. */
avatarUrl: Type.TOptional<Type.TString>;
/** Display identity is separate from the actor fields used by ownership policy. */
identity: Type.TOptional<Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"profile">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"agent">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"remote">;
pluginId: Type.TString;
domain: Type.TString;
idKind: Type.TString;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"observation">;
pluginId: Type.TUnion<[Type.TString, Type.TNull]>;
accountId: Type.TUnion<[Type.TString, Type.TNull]>;
senderKind: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"bot">, Type.TLiteral<"unknown">]>;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"legacy">;
actorType: Type.TString;
source: Type.TUnion<[Type.TString, Type.TNull]>;
id: Type.TString;
}>]>>;
}>>;
archiveReason: Type.TOptional<Type.TUnion<[Type.TLiteral<"manual">, Type.TLiteral<"active-session-cap">, Type.TLiteral<"stale-dashboard">, Type.TLiteral<"restart-recovery">]>>;
pinned: Type.TOptional<Type.TBoolean>;
pinnedAt: Type.TOptional<Type.TNumber>;
unread: Type.TOptional<Type.TBoolean>;
lastReadAt: Type.TOptional<Type.TNumber>;
markedUnreadAt: Type.TOptional<Type.TNumber>;
lastActivityAt: Type.TOptional<Type.TNumber>;
lastInteractionAt: Type.TOptional<Type.TNumber>;
status: Type.TOptional<Type.TUnion<[Type.TLiteral<"queued">, Type.TLiteral<"running">, Type.TLiteral<"done">, Type.TLiteral<"failed">, Type.TLiteral<"killed">, Type.TLiteral<"timeout">]>>;
lastRunError: Type.TOptional<Type.TString>;
/** Exact run that produced the latest terminal lifecycle projection. */
lastRunId: Type.TOptional<Type.TString>;
restartRecoveryStatus: Type.TOptional<Type.TLiteral<"tombstoned">>;
activeLeafEntryId: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
spawnedBy: Type.TOptional<Type.TString>;
parentSessionKey: Type.TOptional<Type.TString>;
controlOwnerSessionKey: Type.TOptional<Type.TString>;
childSessions: Type.TOptional<Type.TArray<Type.TString>>;
forkedFromParent: Type.TOptional<Type.TBoolean>;
spawnDepth: Type.TOptional<Type.TNumber>;
subagentRole: Type.TOptional<Type.TUnion<[Type.TLiteral<"orchestrator">, Type.TLiteral<"leaf">]>>;
subagentControlScope: Type.TOptional<Type.TUnion<[Type.TLiteral<"children">, Type.TLiteral<"none">]>>;
swarmGroupId: Type.TOptional<Type.TString>;
worktree: Type.TOptional<Type.TObject<{
id: Type.TString;
branch: Type.TString;
repoRoot: Type.TString;
}>>;
execNode: Type.TOptional<Type.TString>;
execCwd: Type.TOptional<Type.TString>;
spawnedWorkspaceDir: Type.TOptional<Type.TString>;
spawnedCwd: Type.TOptional<Type.TString>;
permissionMode: Type.TOptional<Type.TUnion<[Type.TLiteral<"read-only">, Type.TLiteral<"guarded">, Type.TLiteral<"workspace">, Type.TLiteral<"full">]>>;
permissionModePending: Type.TOptional<Type.TBoolean>;
sessionRoot: Type.TOptional<Type.TString>;
createdVia: Type.TOptional<Type.TUnion<[Type.TLiteral<"operator">, Type.TLiteral<"spawn">, Type.TLiteral<"channel">, Type.TLiteral<"cron">, Type.TLiteral<"talk">, Type.TLiteral<"run">, Type.TLiteral<"plugin">, Type.TLiteral<"internal">]>>;
createdActor: Type.TOptional<Type.TObject<{
type: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"agent">, Type.TLiteral<"system">]>;
id: Type.TOptional<Type.TString>;
label: Type.TOptional<Type.TString>;
/** Durable profile avatar route; absent for actors without a stored profile avatar. */
avatarUrl: Type.TOptional<Type.TString>;
/** Display identity is separate from the actor fields used by ownership policy. */
identity: Type.TOptional<Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"profile">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"agent">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"remote">;
pluginId: Type.TString;
domain: Type.TString;
idKind: Type.TString;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"observation">;
pluginId: Type.TUnion<[Type.TString, Type.TNull]>;
accountId: Type.TUnion<[Type.TString, Type.TNull]>;
senderKind: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"bot">, Type.TLiteral<"unknown">]>;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"legacy">;
actorType: Type.TString;
source: Type.TUnion<[Type.TString, Type.TNull]>;
id: Type.TString;
}>]>>;
}>>;
owner: Type.TOptional<Type.TObject<{
actor: Type.TObject<{
type: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"agent">, Type.TLiteral<"system">]>;
id: Type.TOptional<Type.TString>;
label: Type.TOptional<Type.TString>;
/** Durable profile avatar route; absent for actors without a stored profile avatar. */
avatarUrl: Type.TOptional<Type.TString>;
/** Display identity is separate from the actor fields used by ownership policy. */
identity: Type.TOptional<Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"profile">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"agent">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"remote">;
pluginId: Type.TString;
domain: Type.TString;
idKind: Type.TString;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"observation">;
pluginId: Type.TUnion<[Type.TString, Type.TNull]>;
accountId: Type.TUnion<[Type.TString, Type.TNull]>;
senderKind: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"bot">, Type.TLiteral<"unknown">]>;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"legacy">;
actorType: Type.TString;
source: Type.TUnion<[Type.TString, Type.TNull]>;
id: Type.TString;
}>]>>;
}>;
assignedBy: Type.TOptional<Type.TObject<{
type: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"agent">, Type.TLiteral<"system">]>;
id: Type.TOptional<Type.TString>;
label: Type.TOptional<Type.TString>;
/** Durable profile avatar route; absent for actors without a stored profile avatar. */
avatarUrl: Type.TOptional<Type.TString>;
/** Display identity is separate from the actor fields used by ownership policy. */
identity: Type.TOptional<Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"profile">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"agent">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"remote">;
pluginId: Type.TString;
domain: Type.TString;
idKind: Type.TString;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"observation">;
pluginId: Type.TUnion<[Type.TString, Type.TNull]>;
accountId: Type.TUnion<[Type.TString, Type.TNull]>;
senderKind: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"bot">, Type.TLiteral<"unknown">]>;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"legacy">;
actorType: Type.TString;
source: Type.TUnion<[Type.TString, Type.TNull]>;
id: Type.TString;
}>]>>;
}>>;
assignedAt: Type.TOptional<Type.TNumber>;
}>>;
participants: Type.TOptional<Type.TArray<Type.TObject<{
identity: Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"profile">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"agent">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"remote">;
pluginId: Type.TString;
domain: Type.TString;
idKind: Type.TString;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"observation">;
pluginId: Type.TUnion<[Type.TString, Type.TNull]>;
accountId: Type.TUnion<[Type.TString, Type.TNull]>;
senderKind: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"bot">, Type.TLiteral<"unknown">]>;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"legacy">;
actorType: Type.TString;
source: Type.TUnion<[Type.TString, Type.TNull]>;
id: Type.TString;
}>]>;
label: Type.TOptional<Type.TString>;
avatarUrl: Type.TOptional<Type.TString>;
}>>>;
expandedParticipants: Type.TOptional<Type.TArray<Type.TObject<{
identity: Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"profile">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"agent">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"remote">;
pluginId: Type.TString;
domain: Type.TString;
idKind: Type.TString;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"observation">;
pluginId: Type.TUnion<[Type.TString, Type.TNull]>;
accountId: Type.TUnion<[Type.TString, Type.TNull]>;
senderKind: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"bot">, Type.TLiteral<"unknown">]>;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"legacy">;
actorType: Type.TString;
source: Type.TUnion<[Type.TString, Type.TNull]>;
id: Type.TString;
}>]>;
label: Type.TOptional<Type.TString>;
avatarUrl: Type.TOptional<Type.TString>;
}>>>;
participantCount: Type.TOptional<Type.TInteger>;
visibility: Type.TOptional<Type.TUnion<[Type.TLiteral<"shared">, Type.TLiteral<"read-only">, Type.TLiteral<"suggest">, Type.TLiteral<"draft">]>>;
sharingRole: Type.TOptional<Type.TUnion<[Type.TLiteral<"admin">, Type.TLiteral<"owner">, Type.TLiteral<"member">, Type.TLiteral<"viewer">]>>;
createdAt: Type.TOptional<Type.TNumber>;
forkSource: Type.TOptional<Type.TObject<{
sessionKey: Type.TString;
sessionId: Type.TString;
entryId: Type.TOptional<Type.TString>;
}>>;
previousSessionId: Type.TOptional<Type.TString>;
inputTokens: Type.TOptional<Type.TNumber>;
outputTokens: Type.TOptional<Type.TNumber>;
totalTokens: Type.TOptional<Type.TNumber>;
totalTokensFresh: Type.TOptional<Type.TBoolean>;
contextTokens: Type.TOptional<Type.TNumber>;
estimatedCostUsd: Type.TOptional<Type.TNumber>;
model: Type.TOptional<Type.TString>;
modelProvider: Type.TOptional<Type.TString>;
/** Runtime model serving this session while it differs from the selected model. */
activeModel: Type.TOptional<Type.TString>;
activeModelProvider: Type.TOptional<Type.TString>;
/** Persisted override provenance; null means inherited, omission means not projected. */
modelOverrideSource: Type.TOptional<Type.TUnion<[Type.TLiteral<"user">, Type.TLiteral<"auto">, Type.TNull]>>;
toolOverrides: Type.TOptional<Type.TObject<{
mcpServers: Type.TOptional<Type.TRecord<"^.*$", Type.TBoolean>>;
mcpToolsDeny: Type.TOptional<Type.TRecord<"^.*$", Type.TArray<Type.TString>>>;
skills: Type.TOptional<Type.TRecord<"^.*$", Type.TBoolean>>;
webSearch: Type.TOptional<Type.TBoolean>;
}>>;
}>;
type SessionPermissionMode = Static<typeof SessionPermissionModeSchema>;
type SessionRunStatus = Static<typeof SessionRunStatusSchema>;
type SessionRow = Static<typeof SessionRowSchema>;
type SessionEntryArchiveReason = Static<typeof SessionEntryArchiveReasonSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/session-participant.d.ts
/** Product identity, independent of display metadata and authorization. */
declare const SessionParticipantIdentitySchema: Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"profile">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"agent">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"remote">;
pluginId: Type.TString;
domain: Type.TString;
idKind: Type.TString;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"observation">;
pluginId: Type.TUnion<[Type.TString, Type.TNull]>;
accountId: Type.TUnion<[Type.TString, Type.TNull]>;
senderKind: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"bot">, Type.TLiteral<"unknown">]>;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"legacy">;
actorType: Type.TString;
source: Type.TUnion<[Type.TString, Type.TNull]>;
id: Type.TString;
}>]>;
declare const SessionParticipantSchema: Type.TObject<{
identity: Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"profile">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"agent">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"remote">;
pluginId: Type.TString;
domain: Type.TString;
idKind: Type.TString;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"observation">;
pluginId: Type.TUnion<[Type.TString, Type.TNull]>;
accountId: Type.TUnion<[Type.TString, Type.TNull]>;
senderKind: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"bot">, Type.TLiteral<"unknown">]>;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"legacy">;
actorType: Type.TString;
source: Type.TUnion<[Type.TString, Type.TNull]>;
id: Type.TString;
}>]>;
label: Type.TOptional<Type.TString>;
avatarUrl: Type.TOptional<Type.TString>;
}>;
type SessionParticipantIdentity = Static<typeof SessionParticipantIdentitySchema>;
type SessionParticipant = Static<typeof SessionParticipantSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/sessions-goal.d.ts
declare const SessionGoalSchema: Type.TObject<{
schemaVersion: Type.TLiteral<1>;
id: Type.TString;
objective: Type.TString;
status: Type.TUnion<[Type.TLiteral<"active">, Type.TLiteral<"paused">, Type.TLiteral<"blocked">, Type.TLiteral<"usage_limited">, Type.TLiteral<"budget_limited">, Type.TLiteral<"complete">]>;
createdAt: Type.TNumber;
updatedAt: Type.TNumber;
tokenStart: Type.TNumber;
tokenStartFresh: Type.TOptional<Type.TBoolean>;
tokensUsed: Type.TNumber;
tokenBudget: Type.TOptional<Type.TNumber>;
continuationTurns: Type.TNumber;
lastStatusNote: Type.TOptional<Type.TString>;
pausedAt: Type.TOptional<Type.TNumber>;
blockedAt: Type.TOptional<Type.TNumber>;
completedAt: Type.TOptional<Type.TNumber>;
usageLimitedAt: Type.TOptional<Type.TNumber>;
budgetLimitedAt: Type.TOptional<Type.TNumber>;
}>;
type SessionGoal = Static<typeof SessionGoalSchema>;
declare const SessionsGoalMutationResultSchema: Type.TObject<{
operationId: Type.TString;
action: Type.TUnion<[Type.TLiteral<"start">, Type.TLiteral<"edit">, Type.TLiteral<"pause">, Type.TLiteral<"resume">, Type.TLiteral<"complete">, Type.TLiteral<"block">, Type.TLiteral<"clear">]>;
sessionId: Type.TString;
goalId: Type.TString;
goal: Type.TOptional<Type.TObject<{
schemaVersion: Type.TLiteral<1>;
id: Type.TString;
objective: Type.TString;
status: Type.TUnion<[Type.TLiteral<"active">, Type.TLiteral<"paused">, Type.TLiteral<"blocked">, Type.TLiteral<"usage_limited">, Type.TLiteral<"budget_limited">, Type.TLiteral<"complete">]>;
createdAt: Type.TNumber;
updatedAt: Type.TNumber;
tokenStart: Type.TNumber;
tokenStartFresh: Type.TOptional<Type.TBoolean>;
tokensUsed: Type.TNumber;
tokenBudget: Type.TOptional<Type.TNumber>;
continuationTurns: Type.TNumber;
lastStatusNote: Type.TOptional<Type.TString>;
pausedAt: Type.TOptional<Type.TNumber>;
blockedAt: Type.TOptional<Type.TNumber>;
completedAt: Type.TOptional<Type.TNumber>;
usageLimitedAt: Type.TOptional<Type.TNumber>;
budgetLimitedAt: Type.TOptional<Type.TNumber>;
}>>;
runId: Type.TOptional<Type.TString>;
replayed: Type.TOptional<Type.TLiteral<true>>;
status: Type.TUnion<[Type.TLiteral<"started">, Type.TLiteral<"updated">, Type.TLiteral<"cleared">]>;
}>;
type SessionsGoalMutationResult = Static<typeof SessionsGoalMutationResultSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/sessions-catalog.d.ts
declare const SessionCatalogShareRouteSchema: Type.TObject<{
kind: Type.TLiteral<"thread-id-prefix">;
routeSegment: Type.TString;
hostId: Type.TString;
identifierAlphabet: Type.TLiteral<"lowercase-hex">;
fullLength: Type.TLiteral<32>;
minPrefixLength: Type.TLiteral<12>;
lookup: Type.TLiteral<"catalog-list-search-by-thread-id-prefix">;
ambiguity: Type.TLiteral<"multiple-results-or-next-cursor">;
}>;
declare const SessionCatalogHostSchema: Type.TObject<{
hostId: Type.TString;
label: Type.TString;
kind: Type.TUnion<[Type.TLiteral<"gateway">, Type.TLiteral<"node">]>;
connected: Type.TBoolean;
nodeId: Type.TOptional<Type.TString>;
canStartTerminal: Type.TOptional<Type.TBoolean>;
sessions: Type.TArray<Type.TObject<{
threadId: Type.TString;
sourceHomeId: Type.TOptional<Type.TString>;
name: Type.TOptional<Type.TString>;
/** Named tint imported from the source CLI session (SESSION_COLOR_IDS). */
color: Type.TOptional<Type.TString>;
cwd: Type.TOptional<Type.TString>;
status: Type.TString;
createdAt: Type.TOptional<Type.TNumber>;
updatedAt: Type.TOptional<Type.TNumber>;
recencyAt: Type.TOptional<Type.TNumber>;
source: Type.TOptional<Type.TString>;
modelProvider: Type.TOptional<Type.TString>;
cliVersion: Type.TOptional<Type.TString>;
gitBranch: Type.TOptional<Type.TString>;
customGroup: Type.TOptional<Type.TString>;
pullRequest: Type.TOptional<Type.TObject<{
numbers: Type.TArray<Type.TInteger>;
state: Type.TUnion<[Type.TLiteral<"open">, Type.TLiteral<"draft">, Type.TLiteral<"merged">, Type.TLiteral<"closed">]>;
}>>;
archived: Type.TBoolean;
sessionKey: Type.TOptional<Type.TString>;
createdActor: Type.TOptional<Type.TObject<{
type: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"agent">, Type.TLiteral<"system">]>;
id: Type.TOptional<Type.TString>;
label: Type.TOptional<Type.TString>;
avatarUrl: Type.TOptional<Type.TString>;
identity: Type.TOptional<Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"profile">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"agent">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"remote">;
pluginId: Type.TString;
domain: Type.TString;
idKind: Type.TString;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"observation">;
pluginId: Type.TUnion<[Type.TString, Type.TNull]>;
accountId: Type.TUnion<[Type.TString, Type.TNull]>;
senderKind: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"bot">, Type.TLiteral<"unknown">]>;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"legacy">;
actorType: Type.TString;
source: Type.TUnion<[Type.TString, Type.TNull]>;
id: Type.TString;
}>]>>;
}>>;
canContinue: Type.TBoolean;
canArchive: Type.TBoolean;
canOpenTerminal: Type.TOptional<Type.TBoolean>;
}>>;
nextCursor: Type.TOptional<Type.TString>;
error: Type.TOptional<Type.TObject<{
code: Type.TString;
message: Type.TString;
}>>;
}>;
declare const SessionsCatalogReadParamsSchema: Type.TObject<{
catalogId: Type.TString;
hostId: Type.TString;
threadId: Type.TString;
agentId: Type.TOptional<Type.TString>;
sourceHomeId: Type.TOptional<Type.TString>;
limit: Type.TOptional<Type.TInteger>;
cursor: Type.TOptional<Type.TString>;
}>;
declare const SessionsCatalogReadResultSchema: Type.TObject<{
hostId: Type.TString;
label: Type.TOptional<Type.TString>;
threadId: Type.TString;
items: Type.TArray<Type.TObject<{
id: Type.TOptional<Type.TString>;
type: Type.TUnion<[Type.TLiteral<"userMessage">, Type.TLiteral<"agentMessage">, Type.TLiteral<"reasoning">, Type.TLiteral<"toolCall">, Type.TLiteral<"toolResult">, Type.TLiteral<"other">]>;
text: Type.TOptional<Type.TString>;
timestamp: Type.TOptional<Type.TString>;
model: Type.TOptional<Type.TString>;
/** Source-supplied attribution, independent of the viewer and session adopter. */
sender: Type.TOptional<Type.TObject<{
identity: Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"profile">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"agent">;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"remote">;
pluginId: Type.TString;
domain: Type.TString;
idKind: Type.TString;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"observation">;
pluginId: Type.TUnion<[Type.TString, Type.TNull]>;
accountId: Type.TUnion<[Type.TString, Type.TNull]>;
senderKind: Type.TUnion<[Type.TLiteral<"human">, Type.TLiteral<"bot">, Type.TLiteral<"unknown">]>;
id: Type.TString;
}>, Type.TObject<{
type: Type.TLiteral<"legacy">;
actorType: Type.TString;
source: Type.TUnion<[Type.TString, Type.TNull]>;
id: Type.TString;
}>]>;
label: Type.TOptional<Type.TString>;
avatarUrl: Type.TOptional<Type.TString>;
}>>;
truncated: Type.TOptional<Type.TBoolean>;
raw: Type.TOptional<Type.TUnknown>;
}>>;
nextCursor: Type.TOptional<Type.TString>;
}>;
declare const SessionsCatalogContinueParamsSchema: Type.TObject<{
catalogId: Type.TString;
hostId: Type.TString;
threadId: Type.TString;
agentId: Type.TOptional<Type.TString>;
sourceHomeId: Type.TOptional<Type.TString>;
}>;
declare const SessionsCatalogArchiveParamsSchema: Type.TObject<{
catalogId: Type.TString;
hostId: Type.TString;
threadId: Type.TString;
agentId: Type.TOptional<Type.TString>;
sourceHomeId: Type.TOptional<Type.TString>;
confirmNoOtherRunner: Type.TLiteral<true>;
}>;
type SessionCatalogShareRoute = Static<typeof SessionCatalogShareRouteSchema>;
type SessionCatalogHost = Static<typeof SessionCatalogHostSchema>;
type SessionsCatalogReadParams = Static<typeof SessionsCatalogReadParamsSchema>;
type SessionsCatalogReadResult = Static<typeof SessionsCatalogReadResultSchema>;
type SessionsCatalogContinueParams = Static<typeof SessionsCatalogContinueParamsSchema>;
type SessionsCatalogArchiveParams = Static<typeof SessionsCatalogArchiveParamsSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/agent.d.ts
/** Waits for a submitted agent run to complete or time out. */
declare const AgentWaitParamsSchema: Type.TObject<{
runId: Type.TString;
timeoutMs: Type.TOptional<Type.TInteger>;
}>;
type AgentWaitParams = Static<typeof AgentWaitParamsSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/agents-models-skills.d.ts
declare const ToolsGitHubAuthorizeStartResultSchema: Type.TObject<{
requestId: Type.TString;
userCode: Type.TString;
verificationUri: Type.TLiteral<"https://github.com/login/device">;
expiresInMs: Type.TInteger;
pollAfterMs: Type.TInteger;
}>;
declare const ToolsGitHubAuthorizePollResultSchema: Type.TUnion<[Type.TObject<{
status: Type.TLiteral<"pending">;
retryAfterMs: Type.TInteger;
}>, Type.TObject<{
status: Type.TLiteral<"slow_down">;
retryAfterMs: Type.TInteger;
}>, Type.TObject<{
status: Type.TLiteral<"access_denied">;
}>, Type.TObject<{
status: Type.TLiteral<"expired">;
}>, Type.TObject<{
status: Type.TLiteral<"incorrect_device_code">;
}>, Type.TObject<{
status: Type.TLiteral<"network_error">;
retryAfterMs: Type.TInteger;
}>, Type.TObject<{
status: Type.TLiteral<"failed">;
reason: Type.TUnion<[Type.TLiteral<"identity_changed">, Type.TLiteral<"setup_failed">]>;
}>, Type.TObject<{
status: Type.TLiteral<"success">;
githubStatus: Type.TObject<{
agentId: Type.TString;
selectedScope: Type.TUnion<[Type.TLiteral<"system">, Type.TLiteral<"agent">]>;
selected: Type.TObject<{
scope: Type.TUnion<[Type.TLiteral<"system">, Type.TLiteral<"agent">]>;
configured: Type.TBoolean;
identity: Type.TUnion<[Type.TObject<{
source: Type.TUnion<[Type.TLiteral<"system-detected">, Type.TLiteral<"system-configured">, Type.TLiteral<"agent-override">]>;
credentialKind: Type.TUnion<[Type.TLiteral<"native">, Type.TLiteral<"managed-pat">, Type.TLiteral<"managed-oauth">]>;
credentialState: Type.TUnion<[Type.TLiteral<"available">, Type.TLiteral<"unavailable">, Type.TLiteral<"configured_unavailable">, Type.TLiteral<"unverified">, Type.TLiteral<"rate_limited">]>;
account: Type.TUnion<[Type.TObject<{
login: Type.TString;
}>, Type.TNull]>;
gitAuthor: Type.TObject<{
name: Type.TUnion<[Type.TString, Type.TNull]>;
email: Type.TUnion<[Type.TString, Type.TNull]>;
}>;
evidence: Type.TUnion<[Type.TLiteral<"github-api">, Type.TLiteral<"none">, Type.TLiteral<"unverified">, Type.TLiteral<"rate-limited">]>;
accessExpiresAtMs: Type.TUnion<[Type.TInteger, Type.TNull]>;
refreshState: Type.TUnion<[Type.TLiteral<"not_applicable">, Type.TLiteral<"available">, Type.TLiteral<"expired">, Type.TLiteral<"unavailable">, Type.TLiteral<"refreshing">, Type.TLiteral<"failed">]>;
oauthScopes: Type.TArray<Type.TString>;
repositoryGrants: Type.TLiteral<"unknown">;
}>, Type.TNull]>;
}>;
effective: Type.TObject<{
source: Type.TUnion<[Type.TLiteral<"system-detected">, Type.TLiteral<"system-configured">, Type.TLiteral<"agent-override">]>;
credentialKind: Type.TUnion<[Type.TLiteral<"native">, Type.TLiteral<"managed-pat">, Type.TLiteral<"managed-oauth">]>;
credentialState: Type.TUnion<[Type.TLiteral<"available">, Type.TLiteral<"unavailable">, Type.TLiteral<"configured_unavailable">, Type.TLiteral<"unverified">, Type.TLiteral<"rate_limited">]>;
account: Type.TUnion<[Type.TObject<{
login: Type.TString;
}>, Type.TNull]>;
gitAuthor: Type.TObject<{
name: Type.TUnion<[Type.TString, Type.TNull]>;
email: Type.TUnion<[Type.TString, Type.TNull]>;
}>;
evidence: Type.TUnion<[Type.TLiteral<"github-api">, Type.TLiteral<"none">, Type.TLiteral<"unverified">, Type.TLiteral<"rate-limited">]>;
accessExpiresAtMs: Type.TUnion<[Type.TInteger, Type.TNull]>;
refreshState: Type.TUnion<[Type.TLiteral<"not_applicable">, Type.TLiteral<"available">, Type.TLiteral<"expired">, Type.TLiteral<"unavailable">, Type.TLiteral<"refreshing">, Type.TLiteral<"failed">]>;
oauthScopes: Type.TArray<Type.TString>;
repositoryGrants: Type.TLiteral<"unknown">;
}>;
}>;
}>]>;
type ToolsGitHubAuthorizeStartResult = Static<typeof ToolsGitHubAuthorizeStartResultSchema>;
type ToolsGitHubAuthorizePollResult = Static<typeof ToolsGitHubAuthorizePollResultSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/users.d.ts
declare const UsersListModelAccountsResultSchema: Type.TObject<{
profileId: Type.TString;
accounts: Type.TArray<Type.TObject<{
authProfileId: Type.TString;
provider: Type.TString;
label: Type.TString;
authType: Type.TUnion<[Type.TLiteral<"api_key">, Type.TLiteral<"oauth">, Type.TLiteral<"token">]>;
selected: Type.TBoolean;
}>>;
nextCursor: Type.TOptional<Type.TString>;
links: Type.TArray<Type.TObject<{
provider: Type.TString;
authProfileId: Type.TString;
updatedAt: Type.TInteger;
}>>;
}>;
declare const UsersSelectModelAccountResultSchema: Type.TObject<{
links: Type.TArray<Type.TObject<{
provider: Type.TString;
authProfileId: Type.TString;
updatedAt: Type.TInteger;
}>>;
}>;
/** Configured preference only; provider failover can use a different account. */
declare const ChatAccountSelectionSchema: Type.TUnion<[Type.TObject<{
kind: Type.TLiteral<"automatic">;
label: Type.TString;
}>, Type.TObject<{
kind: Type.TLiteral<"personal">;
label: Type.TString;
authProfileId: Type.TOptional<Type.TString>;
source: Type.TOptional<Type.TUnion<[Type.TLiteral<"auto">, Type.TLiteral<"user">, Type.TLiteral<"user-link">]>>;
}>, Type.TObject<{
kind: Type.TLiteral<"shared">;
label: Type.TString;
authProfileId: Type.TString;
source: Type.TOptional<Type.TUnion<[Type.TLiteral<"auto">, Type.TLiteral<"user">, Type.TLiteral<"user-link">]>>;
}>]>;
declare const UsersListAuthLinksResultSchema: Type.TObject<{
links: Type.TArray<Type.TObject<{
provider: Type.TString;
authProfileId: Type.TString;
updatedAt: Type.TInteger;
}>>;
}>;
declare const UsersLinkAuthProfileResultSchema: Type.TObject<{
links: Type.TArray<Type.TObject<{
provider: Type.TString;
authProfileId: Type.TString;
updatedAt: Type.TInteger;
}>>;
}>;
declare const UsersUnlinkAuthProfileResultSchema: Type.TObject<{
links: Type.TArray<Type.TObject<{
provider: Type.TString;
authProfileId: Type.TString;
updatedAt: Type.TInteger;
}>>;
}>;
declare const UsersAuthConnectCatalogResultSchema: Type.TObject<{
providers: Type.TArray<Type.TObject<{
id: Type.TString;
label: Type.TString;
methods: Type.TArray<Type.TObject<{
id: Type.TString;
label: Type.TString;
hint: Type.TOptional<Type.TString>;
}>>;
}>>;
}>;
declare const UsersAuthConnectStartResultSchema: Type.TObject<{
connectId: Type.TString;
expiresAtMs: Type.TInteger;
}>;
declare const UsersAuthConnectStatusResultSchema: Type.TUnion<[Type.TObject<{
status: Type.TLiteral<"pending">;
step: Type.TOptional<Type.TObject<{
id: Type.TString;
type: Type.TUnion<[Type.TLiteral<"note">, Type.TLiteral<"select">, Type.TLiteral<"text">, Type.TLiteral<"confirm">, Type.TLiteral<"multiselect">, Type.TLiteral<"progress">, Type.TLiteral<"action">]>;
title: Type.TOptional<Type.TString>;
message: Type.TOptional<Type.TString>;
format: Type.TOptional<Type.TUnion<[Type.TLiteral<"plain">]>>;
options: Type.TOptional<Type.TArray<Type.TObject<{
value: Type.TUnknown;
label: Type.TString;
hint: Type.TOptional<Type.TString>;
}>>>;
initialValue: Type.TOptional<Type.TUnknown>;
placeholder: Type.TOptional<Type.TString>;
sensitive: Type.TOptional<Type.TBoolean>;
executor: Type.TOptional<Type.TUnion<[Type.TLiteral<"gateway">, Type.TLiteral<"client">]>>;
externalUrl: Type.TOptional<Type.TString>;
deviceCode: Type.TOptional<Type.TObject<{
code: Type.TString;
expiresInMinutes: Type.TOptional<Type.TInteger>;
message: Type.TOptional<Type.TString>;
}>>;
}>>;
error: Type.TOptional<Type.TString>;
}>, Type.TObject<{
status: Type.TLiteral<"connected">;
authProfileId: Type.TString;
links: Type.TArray<Type.TObject<{
provider: Type.TString;
authProfileId: Type.TString;
updatedAt: Type.TInteger;
}>>;
}>, Type.TObject<{
status: Type.TLiteral<"cancelled">;
}>, Type.TObject<{
status: Type.TLiteral<"expired">;
}>, Type.TObject<{
status: Type.TLiteral<"failed">;
reason: Type.TUnion<[Type.TLiteral<"exchange">, Type.TLiteral<"identity">, Type.TLiteral<"authority">, Type.TLiteral<"unavailable">]>;
}>]>;
type UsersListModelAccountsResult = Static<typeof UsersListModelAccountsResultSchema>;
type UsersSelectModelAccountResult = Static<typeof UsersSelectModelAccountResultSchema>;
type ChatAccountSelection = Static<typeof ChatAccountSelectionSchema>;
type UsersAuthConnectStartResult = Static<typeof UsersAuthConnectStartResultSchema>;
type UsersAuthConnectCatalogResult = Static<typeof UsersAuthConnectCatalogResultSchema>;
type UsersAuthConnectStatusResult = Static<typeof UsersAuthConnectStatusResultSchema>;
type UsersListAuthLinksResult = Static<typeof UsersListAuthLinksResultSchema>;
type UsersLinkAuthProfileResult = Static<typeof UsersLinkAuthProfileResultSchema>;
type UsersUnlinkAuthProfileResult = Static<typeof UsersUnlinkAuthProfileResultSchema>;
declare const UsersGitHubAuthorizeStartResultSchema: Type.TObject<{
requestId: Type.TString;
userCode: Type.TString;
verificationUri: Type.TLiteral<"https://github.com/login/device">;
expiresInMs: Type.TInteger;
pollAfterMs: Type.TInteger;
}>;
declare const PersonalGitHubStatusSchema: Type.TObject<{
state: Type.TUnion<[Type.TLiteral<"connected">, Type.TLiteral<"disconnected">, Type.TLiteral<"unavailable">]>;
generation: Type.TUnion<[Type.TString, Type.TNull]>;
account: Type.TUnion<[Type.TObject<{
accountId: Type.TInteger;
login: Type.TString;
}>, Type.TNull]>;
accessExpiresAtMs: Type.TUnion<[Type.TInteger, Type.TNull]>;
refreshState: Type.TUnion<[Type.TLiteral<"available">, Type.TLiteral<"refreshing">, Type.TLiteral<"expired">, Type.TLiteral<"failed">, Type.TLiteral<"not_applicable">]>;
pending: Type.TUnion<[Type.TObject<{
requestId: Type.TString;
userCode: Type.TString;
verificationUri: Type.TLiteral<"https://github.com/login/device">;
expiresInMs: Type.TInteger;
pollAfterMs: Type.TInteger;
}>, Type.TNull]>;
}>;
declare const UsersGitHubAuthorizePollResultSchema: Type.TUnion<[Type.TObject<{
status: Type.TLiteral<"pending">;
retryAfterMs: Type.TInteger;
}>, Type.TObject<{
status: Type.TLiteral<"slow_down">;
retryAfterMs: Type.TInteger;
}>, Type.TObject<{
status: Type.TLiteral<"access_denied">;
}>, Type.TObject<{
status: Type.TLiteral<"expired">;
}>, Type.TObject<{
status: Type.TLiteral<"incorrect_device_code">;
}>, Type.TObject<{
status: Type.TLiteral<"network_error">;
retryAfterMs: Type.TInteger;
}>, Type.TObject<{
status: Type.TLiteral<"failed">;
reason: Type.TUnion<[Type.TLiteral<"identity_changed">, Type.TLiteral<"setup_failed">]>;
}>, Type.TObject<{
status: Type.TLiteral<"success">;
personal: Type.TObject<{
state: Type.TUnion<[Type.TLiteral<"connected">, Type.TLiteral<"disconnected">, Type.TLiteral<"unavailable">]>;
generation: Type.TUnion<[Type.TString, Type.TNull]>;
account: Type.TUnion<[Type.TObject<{
accountId: Type.TInteger;
login: Type.TString;
}>, Type.TNull]>;
accessExpiresAtMs: Type.TUnion<[Type.TInteger, Type.TNull]>;
refreshState: Type.TUnion<[Type.TLiteral<"available">, Type.TLiteral<"refreshing">, Type.TLiteral<"expired">, Type.TLiteral<"failed">, Type.TLiteral<"not_applicable">]>;
pending: Type.TUnion<[Type.TObject<{
requestId: Type.TString;
userCode: Type.TString;
verificationUri: Type.TLiteral<"https://github.com/login/device">;
expiresInMs: Type.TInteger;
pollAfterMs: Type.TInteger;
}>, Type.TNull]>;
}>;
}>]>;
type PersonalGitHubStatus = Static<typeof PersonalGitHubStatusSchema>;
type UsersGitHubAuthorizeStartResult = Static<typeof UsersGitHubAuthorizeStartResultSchema>;
type UsersGitHubAuthorizePollResult = Static<typeof UsersGitHubAuthorizePollResultSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/openclaw.d.ts
declare const SystemAgentWizardCancelSchema: Type.TObject<{
/** The visible step this action belongs to; stale controls must not affect a newer step. */
stepId: Type.TString;
}>;
/**
* Structured choice attached to a chat reply. Card-capable clients render the
* options and send back `reply` (default: `label`) as the next message; text
* clients ignore this and use the reply prose, which always stands alone.
*/
declare const SystemAgentChatQuestionSchema: Type.TObject<{
id: Type.TString;
header: Type.TString;
question: Type.TString;
options: Type.TArray<Type.TObject<{
label: Type.TString;
description: Type.TOptional<Type.TString>;
recommended: Type.TOptional<Type.TBoolean>;
/** Message text a client sends when this option is chosen; defaults to label. */
reply: Type.TOptional<Type.TString>;
}>>;
/** Free-text answers are also accepted for this question. */
isOther: Type.TOptional<Type.TBoolean>;
/** Client-owned action for the visible skip control; omitted means send a reply. */
skipAction: Type.TOptional<Type.TLiteral<"exit">>;
}>;
type SystemAgentWizardCancel = Static<typeof SystemAgentWizardCancelSchema>;
type SystemAgentChatQuestion = Static<typeof SystemAgentChatQuestionSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/cron.d.ts
/** One persisted cron run history entry. */
declare const CronRunLogEntrySchema: Type.TObject<{
ts: Type.TInteger;
jobId: Type.TString;
action: Type.TLiteral<"finished">;
status: Type.TOptional<Type.TUnion<[Type.TLiteral<"ok">, Type.TLiteral<"error">, Type.TLiteral<"skipped">]>>;
completionStatus: Type.TOptional<Type.TUnion<[Type.TLiteral<"succeeded">, Type.TLiteral<"failed">, Type.TLiteral<"unknown">]>>;
error: Type.TOptional<Type.TString>;
errorReason: Type.TOptional<Type.TUnion<[Type.TLiteral<"auth">, Type.TLiteral<"auth_permanent">, Type.TLiteral<"format">, Type.TLiteral<"rate_limit">, Type.TLiteral<"overloaded">, Type.TLiteral<"billing">, Type.TLiteral<"server_error">, Type.TLiteral<"timeout">, Type.TLiteral<"tls_certificate">, Type.TLiteral<"context_overflow">, Type.TLiteral<"model_not_found">, Type.TLiteral<"session_expired">, Type.TLiteral<"empty_response">, Type.TLiteral<"no_error_details">, Type.TLiteral<"unclassified">, Type.TLiteral<"unknown">]>>;
summary: Type.TOptional<Type.TString>;
diagnostics: Type.TOptional<Type.TObject<{
summary: Type.TOptional<Type.TString>;
entries: Type.TArray<Type.TObject<{
ts: Type.TInteger;
source: Type.TUnion<[Type.TLiteral<"cron-preflight">, Type.TLiteral<"cron-setup">, Type.TLiteral<"model-preflight">, Type.TLiteral<"agent-run">, Type.TLiteral<"tool">, Type.TLiteral<"exec">, Type.TLiteral<"delivery">]>;
severity: Type.TUnion<[Type.TLiteral<"info">, Type.TLiteral<"warn">, Type.TLiteral<"error">]>;
message: Type.TString;
toolName: Type.TOptional<Type.TString>;
exitCode: Type.TOptional<Type.TUnion<[Type.TNumber, Type.TNull]>>;
truncated: Type.TOptional<Type.TBoolean>;
}>>;
}>>;
delivered: Type.TOptional<Type.TBoolean>;
deliveryStatus: Type.TOptional<Type.TUnion<[Type.TLiteral<"delivered">, Type.TLiteral<"not-delivered">, Type.TLiteral<"unknown">, Type.TLiteral<"not-requested">]>>;
deliveryError: Type.TOptional<Type.TString>;
deliverySuppressionReason: Type.TOptional<Type.TString>;
failureNotificationDelivery: Type.TOptional<Type.TObject<{
delivered: Type.TOptional<Type.TBoolean>;
status: Type.TUnion<[Type.TLiteral<"delivered">, Type.TLiteral<"not-delivered">, Type.TLiteral<"unknown">, Type.TLiteral<"not-requested">]>;
error: Type.TOptional<Type.TString>;
}>>;
delivery: Type.TOptional<Type.TObject<{
intended: Type.TOptional<Type.TObject<{
channel: Type.TOptional<Type.TString>;
to: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
accountId: Type.TOptional<Type.TString>;
threadId: Type.TOptional<Type.TUnion<[Type.TString, Type.TNumber]>>;
source: Type.TOptional<Type.TUnion<[Type.TLiteral<"explicit">, Type.TLiteral<"last">]>>;
}>>;
resolved: Type.TOptional<Type.TObject<{
channel: Type.TOptional<Type.TString>;
to: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
accountId: Type.TOptional<Type.TString>;
threadId: Type.TOptional<Type.TUnion<[Type.TString, Type.TNumber]>>;
source: Type.TOptional<Type.TUnion<[Type.TLiteral<"explicit">, Type.TLiteral<"last">]>>;
ok: Type.TBoolean;
error: Type.TOptional<Type.TString>;
}>>;
messageToolSentTo: Type.TOptional<Type.TArray<Type.TObject<{
channel: Type.TString;
to: Type.TOptional<Type.TString>;
accountId: Type.TOptional<Type.TString>;
threadId: Type.TOptional<Type.TString>;
}>>>;
fallbackUsed: Type.TOptional<Type.TBoolean>;
delivered: Type.TOptional<Type.TBoolean>;
}>>;
sessionId: Type.TOptional<Type.TString>;
sessionKey: Type.TOptional<Type.TString>;
runId: Type.TOptional<Type.TString>;
runAtMs: Type.TOptional<Type.TInteger>;
durationMs: Type.TOptional<Type.TInteger>;
nextRunAtMs: Type.TOptional<Type.TInteger>;
triggerFired: Type.TOptional<Type.TBoolean>;
model: Type.TOptional<Type.TString>;
provider: Type.TOptional<Type.TString>;
usage: Type.TOptional<Type.TObject<{
input_tokens: Type.TOptional<Type.TNumber>;
output_tokens: Type.TOptional<Type.TNumber>;
total_tokens: Type.TOptional<Type.TNumber>;
cache_read_tokens: Type.TOptional<Type.TNumber>;
cache_write_tokens: Type.TOptional<Type.TNumber>;
}>>;
jobName: Type.TOptional<Type.TString>;
}>;
//#endregion
//#region packages/gateway-protocol/src/schema/cron.types.d.ts
type CronRunLogEntry = Static<typeof CronRunLogEntrySchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/environments.d.ts
/** Durable lifecycle states for plugin-provisioned worker environments. */
declare const WorkerEnvironmentStateSchema: Type.TUnion<[Type.TLiteral<"requested">, Type.TLiteral<"provisioning">, Type.TLiteral<"bootstrapping">, Type.TLiteral<"ready">, Type.TLiteral<"attached">, Type.TLiteral<"idle">, Type.TLiteral<"draining">, Type.TLiteral<"destroying">, Type.TLiteral<"destroyed">, Type.TLiteral<"failed">, Type.TLiteral<"orphaned">]>;
/** Process-local SSH tunnel connectivity for a worker environment. */
declare const WorkerTunnelStatusSchema: Type.TUnion<[Type.TLiteral<"stopped">, Type.TLiteral<"connecting">, Type.TLiteral<"connected">, Type.TLiteral<"reconnecting">]>;
type WorkerEnvironmentState = Static<typeof WorkerEnvironmentStateSchema>;
type WorkerTunnelStatus = Static<typeof WorkerTunnelStatusSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/devices.d.ts
/** Returns the terminal scope-upgrade state to the identity-bound waiter. */
declare const ScopeUpgradeResultSchema: Type.TUnion<[Type.TObject<{
status: Type.TLiteral<"approved">;
requestId: Type.TString;
deviceToken: Type.TString;
scopes: Type.TArray<Type.TString>;
}>, Type.TObject<{
status: Type.TLiteral<"rejected">;
requestId: Type.TString;
}>, Type.TObject<{
status: Type.TLiteral<"expired">;
requestId: Type.TString;
}>]>;
type ScopeUpgradeResult = Static<typeof ScopeUpgradeResultSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/human-mentions.d.ts
/** Explicit selections bound to UTF-16 offsets in the submitted message text. */
declare const HumanMentionSchema: Type.TObject<{
profileId: Type.TString;
start: Type.TInteger;
end: Type.TInteger;
}>;
declare const UsersMentionableParamsSchema: Type.TUnion<[Type.TObject<{
sessionKey: Type.TString;
agentId: Type.TOptional<Type.TString>;
query: Type.TOptional<Type.TString>;
}>, Type.TObject<{
agentId: Type.TString;
visibility: Type.TOptional<Type.TUnion<[Type.TLiteral<"shared">, Type.TLiteral<"read-only">, Type.TLiteral<"suggest">, Type.TLiteral<"draft">]>>;
query: Type.TOptional<Type.TString>;
}>]>;
declare const UsersMentionableResultSchema: Type.TObject<{
users: Type.TArray<Type.TObject<{
profileId: Type.TString;
displayName: Type.TString;
avatarUrl: Type.TOptional<Type.TString>;
online: Type.TBoolean;
}>>;
truncated: Type.TBoolean;
}>;
declare const MentionsListResultSchema: Type.TObject<{
gatewayInstanceId: Type.TString;
revision: Type.TInteger;
items: Type.TArray<Type.TObject<{
id: Type.TString;
senderProfileId: Type.TString;
senderLabel: Type.TString;
senderAvatarUrl: Type.TOptional<Type.TString>;
sessionKey: Type.TString;
agentId: Type.TString;
sessionTitle: Type.TString;
messageId: Type.TString;
createdAt: Type.TInteger;
expiresAt: Type.TInteger;
excerpt: Type.TOptional<Type.TString>;
}>>;
}>;
type HumanMention = Static<typeof HumanMentionSchema>;
type UsersMentionableParams = Static<typeof UsersMentionableParamsSchema>;
type UsersMentionableResult = Static<typeof UsersMentionableResultSchema>;
type MentionsListResult = Static<typeof MentionsListResultSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/nodes.d.ts
declare const NodeHostStatsPayloadSchema: Type.TRefine<Type.TObject<{
cpuCount: Type.TInteger;
loadAverage: Type.TOptional<Type.TTuple<[Type.TNumber, Type.TNumber, Type.TNumber]>>;
memoryTotalBytes: Type.TInteger;
memoryFreeBytes: Type.TInteger;
diskTotalBytes: Type.TOptional<Type.TInteger>;
diskAvailableBytes: Type.TOptional<Type.TInteger>;
}>>;
/** Agent-visible tool descriptor advertised by a connected node. */
declare const NodePluginToolDescriptorSchema: Type.TObject<{
pluginId: Type.TString;
name: Type.TString;
description: Type.TString;
parameters: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
command: Type.TOptional<Type.TString>;
mcp: Type.TOptional<Type.TObject<{
server: Type.TString;
tool: Type.TString;
}>>;
}>;
type NodePluginToolDescriptor = Static<typeof NodePluginToolDescriptorSchema>;
/** Agent-visible skill descriptor advertised by a connected node. */
declare const NodeSkillDescriptorSchema: Type.TObject<{
name: Type.TString;
description: Type.TString;
content: Type.TString;
}>;
type NodeSkillDescriptor = Static<typeof NodeSkillDescriptorSchema>;
type NodeHostStatsPayload = Static<typeof NodeHostStatsPayloadSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/questions.d.ts
/** Canonical normalized question shown to an operator. */
declare const QuestionSchema: Type.TObject<{
questionId: Type.TString;
header: Type.TString;
question: Type.TString;
options: Type.TArray<Type.TObject<{
label: Type.TString;
description: Type.TOptional<Type.TString>;
}>>;
multiSelect: Type.TOptional<Type.TBoolean>;
isOther: Type.TOptional<Type.TBoolean>;
isSecret: Type.TOptional<Type.TBoolean>;
secretStore: Type.TOptional<Type.TObject<{
name: Type.TString;
kind: Type.TUnion<[Type.TLiteral<"secret">, Type.TLiteral<"env">]>;
allowedHosts: Type.TOptional<Type.TArray<Type.TString>>;
reason: Type.TOptional<Type.TString>;
}>>;
secretStoreExisting: Type.TOptional<Type.TObject<{
updatedAtMs: Type.TInteger;
updatedBy: Type.TOptional<Type.TString>;
}>>;
}>;
declare const QuestionAnswersSchema: Type.TObject<{
answers: Type.TRecord<"^.*$", Type.TArray<Type.TString>>;
}>;
/**
* One pending or recently resolved transient question request. Flat object with
* optional terminal fields (exec-approval record precedent): native protocol
* codegen cannot emit per-status object unions, and the manager owns the
* status/answers invariant (answers present only when status is "answered").
*/
declare const QuestionRecordSchema: Type.TObject<{
id: Type.TString;
questions: Type.TArray<Type.TObject<{
questionId: Type.TString;
header: Type.TString;
question: Type.TString;
options: Type.TArray<Type.TObject<{
label: Type.TString;
description: Type.TOptional<Type.TString>;
}>>;
multiSelect: Type.TOptional<Type.TBoolean>;
isOther: Type.TOptional<Type.TBoolean>;
isSecret: Type.TOptional<Type.TBoolean>;
secretStore: Type.TOptional<Type.TObject<{
name: Type.TString;
kind: Type.TUnion<[Type.TLiteral<"secret">, Type.TLiteral<"env">]>;
allowedHosts: Type.TOptional<Type.TArray<Type.TString>>;
reason: Type.TOptional<Type.TString>;
}>>;
secretStoreExisting: Type.TOptional<Type.TObject<{
updatedAtMs: Type.TInteger;
updatedBy: Type.TOptional<Type.TString>;
}>>;
}>>;
agentId: Type.TOptional<Type.TString>;
sessionKey: Type.TOptional<Type.TString>;
runId: Type.TOptional<Type.TString>;
createdAtMs: Type.TInteger;
expiresAtMs: Type.TInteger;
status: Type.TUnion<[Type.TLiteral<"pending">, Type.TLiteral<"answered">, Type.TLiteral<"cancelled">, Type.TLiteral<"expired">]>;
answers: Type.TOptional<Type.TObject<{
answers: Type.TRecord<"^.*$", Type.TArray<Type.TString>>;
}>>;
resolvedBy: Type.TOptional<Type.TString>;
}>;
declare const QuestionWaitAnswerResultSchema: Type.TUnion<[Type.TObject<{
status: Type.TLiteral<"pending">;
}>, Type.TObject<{
status: Type.TLiteral<"answered">;
answers: Type.TObject<{
answers: Type.TRecord<"^.*$", Type.TArray<Type.TString>>;
}>;
resolutionId: Type.TOptional<Type.TString>;
}>, Type.TObject<{
status: Type.TLiteral<"cancelled">;
}>, Type.TObject<{
status: Type.TLiteral<"expired">;
}>]>;
declare const QuestionResolveResultSchema: Type.TUnion<[Type.TObject<{
status: Type.TLiteral<"answered">;
answers: Type.TObject<{
answers: Type.TRecord<"^.*$", Type.TArray<Type.TString>>;
}>;
}>, Type.TObject<{
status: Type.TLiteral<"cancelled">;
}>]>;
declare const QuestionResolvedEventSchema: Type.TUnion<[Type.TObject<{
id: Type.TString;
status: Type.TLiteral<"answered">;
answers: Type.TObject<{
answers: Type.TRecord<"^.*$", Type.TArray<Type.TString>>;
}>;
}>, Type.TObject<{
id: Type.TString;
status: Type.TLiteral<"cancelled">;
}>, Type.TObject<{
id: Type.TString;
status: Type.TLiteral<"expired">;
}>]>;
type Question = Static<typeof QuestionSchema>;
type QuestionAnswers = Static<typeof QuestionAnswersSchema>;
type QuestionRecord = Static<typeof QuestionRecordSchema>;
type QuestionWaitAnswerResult = Static<typeof QuestionWaitAnswerResultSchema>;
type QuestionResolveResult = Static<typeof QuestionResolveResultSchema>;
type QuestionResolvedEvent = Static<typeof QuestionResolvedEventSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/session-placement.d.ts
declare const SessionPlacementDiskSpaceSchema: Type.TObject<{
status: Type.TUnion<[Type.TLiteral<"ok">, Type.TLiteral<"warning">, Type.TLiteral<"critical">]>;
availableBytes: Type.TInteger;
totalBytes: Type.TInteger;
observedAtMs: Type.TInteger;
}>;
declare const SessionPlacementRunnerSchema: Type.TObject<{
kind: Type.TLiteral<"device">;
status: Type.TUnion<[Type.TLiteral<"available">, Type.TLiteral<"offline">]>;
deviceId: Type.TOptional<Type.TString>;
}>;
/** Closed destination union for session placement moves. */
declare const SessionMoveTargetSchema: Type.TUnion<[Type.TObject<{
kind: Type.TLiteral<"gateway">;
}>, Type.TObject<{
kind: Type.TLiteral<"profile">;
profileId: Type.TString;
machineClass: Type.TOptional<Type.TString>;
}>, Type.TObject<{
kind: Type.TLiteral<"device">;
deviceId: Type.TString;
}>]>;
type SessionPlacementDiskSpace = Static<typeof SessionPlacementDiskSpaceSchema>;
type SessionPlacementRunner = Static<typeof SessionPlacementRunnerSchema>;
type SessionMoveTarget = Static<typeof SessionMoveTargetSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/sessions.d.ts
/** Live session status judgment broadcast to subscribed operator clients. */
declare const SessionObserverDigestSchema: Type.TObject<{
sessionKey: Type.TString;
agentId: Type.TOptional<Type.TString>;
runId: Type.TOptional<Type.TString>;
revision: Type.TInteger;
updatedAt: Type.TInteger;
headline: Type.TString;
assessment: Type.TOptional<Type.TString>;
health: Type.TUnion<[Type.TLiteral<"on-track">, Type.TLiteral<"grinding">, Type.TLiteral<"stuck">, Type.TLiteral<"waiting-on-user">, Type.TLiteral<"wrapping-up">, Type.TLiteral<"done">, Type.TLiteral<"failed">]>;
planProgress: Type.TOptional<Type.TObject<{
completed: Type.TInteger;
total: Type.TInteger;
}>>;
}>;
/** Companion answer returned only to the requesting operator. */
declare const SessionsCompanionAskResultSchema: Type.TObject<{
answer: Type.TString;
ts: Type.TInteger;
}>;
/** Current bounded exchanges for one session companion thread. */
declare const SessionsCompanionStateResultSchema: Type.TObject<{
exchanges: Type.TArray<Type.TObject<{
question: Type.TString;
answer: Type.TString;
ts: Type.TInteger;
}>>;
}>;
type SessionObserverDigest = Static<typeof SessionObserverDigestSchema>;
type SessionsCompanionAskResult = Static<typeof SessionsCompanionAskResultSchema>;
type SessionsCompanionStateResult = Static<typeof SessionsCompanionStateResultSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/snapshot.d.ts
/** Initial and incremental gateway state snapshot payload. */
declare const SnapshotSchema: Type.TObject<{
suspension: Type.TOptional<Type.TObject<{
phase: Type.TUnion<[Type.TLiteral<"accepting">, Type.TLiteral<"preparing">, Type.TLiteral<"draining">, Type.TLiteral<"prepared">]>;
}>>;
presence: Type.TArray<Type.TObject<{
host: Type.TOptional<Type.TString>;
ip: Type.TOptional<Type.TString>;
version: Type.TOptional<Type.TString>;
platform: Type.TOptional<Type.TString>;
deviceFamily: Type.TOptional<Type.TString>;
modelIdentifier: Type.TOptional<Type.TString>;
timeZone: Type.TOptional<Type.TString>;
mode: Type.TOptional<Type.TString>;
lastInputSeconds: Type.TOptional<Type.TInteger>;
reason: Type.TOptional<Type.TString>;
tags: Type.TOptional<Type.TArray<Type.TString>>;
text: Type.TOptional<Type.TString>;
/** Heartbeat freshness, not online duration or user activity. */
ts: Type.TInteger;
/** Server timestamps for the person's continuous online interval and last accepted activity. */
onlineSince: Type.TOptional<Type.TInteger>;
lastActivityAt: Type.TOptional<Type.TInteger>;
deviceId: Type.TOptional<Type.TString>;
roles: Type.TOptional<Type.TArray<Type.TString>>;
scopes: Type.TOptional<Type.TArray<Type.TString>>;
instanceId: Type.TOptional<Type.TString>;
user: Type.TOptional<Type.TObject<{
/** Canonical profile id when resolved, otherwise authenticated identity; grouping also uses identity qualification. */
id: Type.TString;
identity: Type.TOptional<Type.TObject<{
type: Type.TLiteral<"profile">;
id: Type.TString;
}>>;
email: Type.TOptional<Type.TString>;
name: Type.TOptional<Type.TString>;
avatarUrl: Type.TOptional<Type.TString>;
}>>;
/** Sessions this connection declares it is viewing, independent of transport subscriptions. Sorted lexicographically. */
watchedSessions: Type.TOptional<Type.TArray<Type.TString>>;
}>>;
health: Type.TObject<{
ok: Type.TOptional<Type.TLiteral<true>>;
ts: Type.TOptional<Type.TInteger>;
durationMs: Type.TOptional<Type.TInteger>;
eventLoop: Type.TOptional<Type.TObject<{
degraded: Type.TBoolean;
degradedSinceMs: Type.TOptional<Type.TUnion<[Type.TInteger, Type.TNull]>>;
reasons: Type.TArray<Type.TUnion<[Type.TLiteral<"event_loop_delay">, Type.TLiteral<"event_loop_utilization">, Type.TLiteral<"cpu">]>>;
intervalMs: Type.TNumber;
delayP99Ms: Type.TNumber;
delayMaxMs: Type.TNumber;
utilization: Type.TNumber;
cpuCoreRatio: Type.TNumber;
}>>;
plugins: Type.TOptional<Type.TObject<{
loaded: Type.TArray<Type.TString>;
errors: Type.TArray<Type.TObject<{
id: Type.TString;
origin: Type.TString;
activated: Type.TBoolean;
activationSource: Type.TOptional<Type.TString>;
activationReason: Type.TOptional<Type.TString>;
failurePhase: Type.TOptional<Type.TString>;
error: Type.TString;
}>>;
unavailable: Type.TOptional<Type.TArray<Type.TObject<{
id: Type.TString;
state: Type.TLiteral<"configured-unavailable">;
diagnostic: Type.TObject<{
kind: Type.TLiteral<"plugin-verification">;
reason: Type.TString;
detail: Type.TString;
}>;
}>>>;
}>>;
contextEngines: Type.TOptional<Type.TObject<{
quarantined: Type.TArray<Type.TObject<{
engineId: Type.TString;
owner: Type.TOptional<Type.TString>;
operation: Type.TString;
reason: Type.TString;
failedAt: Type.TInteger;
}>>;
}>>;
deliveryQueues: Type.TOptional<Type.TObject<{
failed: Type.TArray<Type.TObject<{
queueName: Type.TString;
count: Type.TInteger;
oldestFailedAt: Type.TOptional<Type.TInteger>;
}>>;
ingressFailed: Type.TOptional<Type.TArray<Type.TObject<{
channelId: Type.TString;
accountId: Type.TString;
count: Type.TInteger;
oldestFailedAt: Type.TOptional<Type.TInteger>;
}>>>;
ingressPressure: Type.TOptional<Type.TArray<Type.TObject<{
channelId: Type.TString;
accountId: Type.TString;
laneCount: Type.TInteger;
pendingCount: Type.TInteger;
claimedCount: Type.TInteger;
blockedCount: Type.TInteger;
oldestReceivedAt: Type.TInteger;
}>>>;
}>>;
modelPricing: Type.TOptional<Type.TObject<{
state: Type.TUnion<[Type.TLiteral<"ok">, Type.TLiteral<"degraded">, Type.TLiteral<"disabled">]>;
sources: Type.TArray<Type.TObject<{
source: Type.TUnion<[Type.TLiteral<"openrouter">, Type.TLiteral<"litellm">, Type.TLiteral<"bootstrap">, Type.TLiteral<"refresh">]>;
state: Type.TUnion<[Type.TLiteral<"ok">, Type.TLiteral<"degraded">]>;
lastFailureAt: Type.TOptional<Type.TInteger>;
detail: Type.TOptional<Type.TString>;
}>>;
lastFailureAt: Type.TOptional<Type.TInteger>;
detail: Type.TOptional<Type.TString>;
}>>;
configReload: Type.TOptional<Type.TObject<{
hotReloadStatus: Type.TUnion<[Type.TLiteral<"active">, Type.TLiteral<"disabled">]>;
}>>;
channels: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
channelOrder: Type.TOptional<Type.TArray<Type.TString>>;
channelLabels: Type.TOptional<Type.TRecord<"^.*$", Type.TString>>;
heartbeatSeconds: Type.TOptional<Type.TInteger>;
defaultAgentId: Type.TOptional<Type.TString>;
agents: Type.TOptional<Type.TArray<Type.TObject<{
agentId: Type.TString;
name: Type.TOptional<Type.TString>;
isDefault: Type.TBoolean;
heartbeat: Type.TObject<{
enabled: Type.TBoolean;
every: Type.TString;
everyMs: Type.TUnion<[Type.TInteger, Type.TNull]>;
prompt: Type.TString;
target: Type.TString;
model: Type.TOptional<Type.TString>;
session: Type.TOptional<Type.TString>;
ackMaxChars: Type.TInteger;
}>;
sessions: Type.TObject<{
path: Type.TString;
count: Type.TInteger;
recent: Type.TArray<Type.TObject<{
key: Type.TString;
updatedAt: Type.TUnion<[Type.TInteger, Type.TNull]>;
age: Type.TUnion<[Type.TInteger, Type.TNull]>;
}>>;
}>;
}>>>;
sessions: Type.TOptional<Type.TObject<{
path: Type.TString;
count: Type.TInteger;
recent: Type.TArray<Type.TObject<{
key: Type.TString;
updatedAt: Type.TUnion<[Type.TInteger, Type.TNull]>;
age: Type.TUnion<[Type.TInteger, Type.TNull]>;
}>>;
}>>;
}>;
stateVersion: Type.TObject<{
presence: Type.TInteger;
health: Type.TInteger;
}>;
uptimeMs: Type.TInteger;
/** Resolved source-config revision accepted by the active Gateway runtime. */
appliedConfigHash: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
configPath: Type.TOptional<Type.TString>;
stateDir: Type.TOptional<Type.TString>;
sessionDefaults: Type.TOptional<Type.TObject<{
defaultAgentId: Type.TString;
modelConfigured: Type.TOptional<Type.TBoolean>;
ownership: Type.TOptional<Type.TUnion<[Type.TLiteral<"sole">, Type.TLiteral<"legacy">, Type.TLiteral<"explicit">]>>;
selectionRequired: Type.TOptional<Type.TBoolean>;
mainKey: Type.TString;
mainSessionKey: Type.TString;
scope: Type.TOptional<Type.TString>;
}>>;
/** Credential-free browser sign-in endpoint advertised to authenticated operators. */
controlUiIdentityUrl: Type.TOptional<Type.TString>;
authMode: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"token">, Type.TLiteral<"password">, Type.TLiteral<"trusted-proxy">]>>;
updateAvailable: Type.TOptional<Type.TObject<{
currentVersion: Type.TString;
latestVersion: Type.TString;
channel: Type.TString;
currentSha: Type.TOptional<Type.TString>;
upstreamRef: Type.TOptional<Type.TString>;
upstreamSha: Type.TOptional<Type.TString>;
commitsBehind: Type.TOptional<Type.TInteger>;
commits: Type.TOptional<Type.TArray<Type.TObject<{
sha: Type.TString;
subject: Type.TString;
}>>>;
}>>;
updateSchedule: Type.TOptional<Type.TObject<{
channel: Type.TString;
autoEnabled: Type.TBoolean;
install: Type.TOptional<Type.TObject<{
kind: Type.TUnion<[Type.TLiteral<"package">, Type.TLiteral<"git">, Type.TLiteral<"unknown">]>;
git: Type.TOptional<Type.TUnion<[Type.TObject<{
currentSha: Type.TOptional<Type.TString>;
commitAtMs: Type.TOptional<Type.TInteger>;
installedAtMs: Type.TOptional<Type.TInteger>;
status: Type.TLiteral<"current">;
}>, Type.TObject<{
currentSha: Type.TOptional<Type.TString>;
commitAtMs: Type.TOptional<Type.TInteger>;
installedAtMs: Type.TOptional<Type.TInteger>;
status: Type.TLiteral<"behind">;
commitsBehind: Type.TInteger;
}>, Type.TObject<{
currentSha: Type.TOptional<Type.TString>;
commitAtMs: Type.TOptional<Type.TInteger>;
installedAtMs: Type.TOptional<Type.TInteger>;
status: Type.TLiteral<"ahead">;
commitsAhead: Type.TInteger;
}>, Type.TObject<{
currentSha: Type.TOptional<Type.TString>;
commitAtMs: Type.TOptional<Type.TInteger>;
installedAtMs: Type.TOptional<Type.TInteger>;
status: Type.TLiteral<"diverged">;
commitsAhead: Type.TInteger;
commitsBehind: Type.TInteger;
}>, Type.TObject<{
currentSha: Type.TOptional<Type.TString>;
commitAtMs: Type.TOptional<Type.TInteger>;
installedAtMs: Type.TOptional<Type.TInteger>;
status: Type.TLiteral<"unavailable">;
reason: Type.TUnion<[Type.TLiteral<"fetch-failed">, Type.TLiteral<"no-upstream">, Type.TLiteral<"no-upstream-sha">, Type.TLiteral<"comparison-failed">, Type.TLiteral<"git-unavailable">]>;
}>]>>;
}>>;
target: Type.TOptional<Type.TUnion<[Type.TObject<{
kind: Type.TLiteral<"package">;
version: Type.TString;
}>, Type.TObject<{
kind: Type.TLiteral<"git">;
upstreamRef: Type.TString;
upstreamSha: Type.TString;
commitsBehind: Type.TInteger;
}>]>>;
campaign: Type.TOptional<Type.TObject<{
id: Type.TString;
state: Type.TUnion<[Type.TLiteral<"waiting-for-idle">, Type.TLiteral<"countdown">, Type.TLiteral<"applying">]>;
announcedAtMs: Type.TInteger;
applyAtMs: Type.TOptional<Type.TInteger>;
holdUntilMs: Type.TOptional<Type.TInteger>;
forceAtMs: Type.TInteger;
updatedAtMs: Type.TInteger;
}>>;
}>>;
}>;
type Snapshot = Static<typeof SnapshotSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/portals.d.ts
declare const PortalSummarySchema: Type.TObject<{
id: Type.TString;
title: Type.TString;
port: Type.TInteger;
listenPort: Type.TInteger;
publicUrl: Type.TString;
path: Type.TOptional<Type.TString>;
description: Type.TOptional<Type.TString>;
origin: Type.TOptional<Type.TString>;
createdAtMs: Type.TInteger;
tokenQuery: Type.TOptional<Type.TString>;
url: Type.TOptional<Type.TString>;
}>;
declare const PortalOpenResultSchema: Type.TObject<{
id: Type.TString;
title: Type.TString;
port: Type.TInteger;
listenPort: Type.TInteger;
publicUrl: Type.TString;
path: Type.TOptional<Type.TString>;
description: Type.TOptional<Type.TString>;
origin: Type.TOptional<Type.TString>;
createdAtMs: Type.TInteger;
tokenQuery: Type.TString;
url: Type.TString;
}>;
type PortalSummary = Static<typeof PortalSummarySchema>;
type PortalOpenResult = Static<typeof PortalOpenResultSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/wizard.d.ts
/** Client answer payload for the current wizard step. */
declare const WizardAnswerSchema: Type.TObject<{
stepId: Type.TString;
value: Type.TOptional<Type.TUnknown>;
}>;
/** UI contract for one wizard step rendered by gateway clients. */
declare const WizardStepSchema: Type.TObject<{
id: Type.TString;
type: Type.TUnion<[Type.TLiteral<"note">, Type.TLiteral<"select">, Type.TLiteral<"text">, Type.TLiteral<"confirm">, Type.TLiteral<"multiselect">, Type.TLiteral<"progress">, Type.TLiteral<"action">]>;
title: Type.TOptional<Type.TString>;
message: Type.TOptional<Type.TString>;
format: Type.TOptional<Type.TUnion<[Type.TLiteral<"plain">]>>;
options: Type.TOptional<Type.TArray<Type.TObject<{
value: Type.TUnknown;
label: Type.TString;
hint: Type.TOptional<Type.TString>;
}>>>;
initialValue: Type.TOptional<Type.TUnknown>;
placeholder: Type.TOptional<Type.TString>;
sensitive: Type.TOptional<Type.TBoolean>;
executor: Type.TOptional<Type.TUnion<[Type.TLiteral<"gateway">, Type.TLiteral<"client">]>>;
externalUrl: Type.TOptional<Type.TString>;
deviceCode: Type.TOptional<Type.TObject<{
code: Type.TString;
expiresInMinutes: Type.TOptional<Type.TInteger>;
message: Type.TOptional<Type.TString>;
}>>;
}>;
/** Result after advancing a wizard session. */
declare const WizardNextResultSchema: Type.TObject<{
done: Type.TBoolean;
step: Type.TOptional<Type.TObject<{
id: Type.TString;
type: Type.TUnion<[Type.TLiteral<"note">, Type.TLiteral<"select">, Type.TLiteral<"text">, Type.TLiteral<"confirm">, Type.TLiteral<"multiselect">, Type.TLiteral<"progress">, Type.TLiteral<"action">]>;
title: Type.TOptional<Type.TString>;
message: Type.TOptional<Type.TString>;
format: Type.TOptional<Type.TUnion<[Type.TLiteral<"plain">]>>;
options: Type.TOptional<Type.TArray<Type.TObject<{
value: Type.TUnknown;
label: Type.TString;
hint: Type.TOptional<Type.TString>;
}>>>;
initialValue: Type.TOptional<Type.TUnknown>;
placeholder: Type.TOptional<Type.TString>;
sensitive: Type.TOptional<Type.TBoolean>;
executor: Type.TOptional<Type.TUnion<[Type.TLiteral<"gateway">, Type.TLiteral<"client">]>>;
externalUrl: Type.TOptional<Type.TString>;
deviceCode: Type.TOptional<Type.TObject<{
code: Type.TString;
expiresInMinutes: Type.TOptional<Type.TInteger>;
message: Type.TOptional<Type.TString>;
}>>;
}>>;
status: Type.TOptional<Type.TUnion<[Type.TLiteral<"running">, Type.TLiteral<"done">, Type.TLiteral<"cancelled">, Type.TLiteral<"error">]>>;
error: Type.TOptional<Type.TString>;
channels: Type.TOptional<Type.TArray<Type.TString>>;
accounts: Type.TOptional<Type.TArray<Type.TObject<{
channel: Type.TString;
accountId: Type.TString;
}>>>;
preparedModelRef: Type.TOptional<Type.TString>;
modelActivation: Type.TOptional<Type.TObject<{
modelRef: Type.TString;
gatewayRestartRequired: Type.TOptional<Type.TLiteral<true>>;
}>>;
activationRejection: Type.TOptional<Type.TObject<{
disposition: Type.TLiteral<"rejected-before-promotion">;
status: Type.TUnion<[Type.TLiteral<"auth">, Type.TLiteral<"rate_limit">, Type.TLiteral<"billing">, Type.TLiteral<"timeout">, Type.TLiteral<"format">, Type.TLiteral<"unavailable">, Type.TLiteral<"unknown">]>;
}>>;
}>;
type WizardAnswer = Static<typeof WizardAnswerSchema>;
type WizardStep$1 = Static<typeof WizardStepSchema>;
type WizardNextResult$1 = Static<typeof WizardNextResultSchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/worker-admission.d.ts
/** Dedicated first-frame payload accepted only on the worker ingress. */
declare const WorkerConnectParamsSchema: Type.TObject<{
minProtocol: Type.TInteger;
maxProtocol: Type.TInteger;
client: Type.TObject<{
id: Type.TLiteral<"openclaw-worker">;
version: Type.TString;
platform: Type.TString;
mode: Type.TLiteral<"worker">;
}>;
role: Type.TLiteral<"worker">;
admission: Type.TUnion<[Type.TObject<{
environmentId: Type.TString;
credential: Type.TString;
ownerEpoch: Type.TInteger;
rpcSetVersion: Type.TInteger;
handshake: Type.TObject<{
bundleHash: Type.TString;
openclawVersion: Type.TString;
protocolFeatures: Type.TArray<Type.TString>;
bundlePrewarm: Type.TOptional<Type.TInteger>;
}>;
sessionId: Type.TNull;
runId: Type.TNull;
}>, Type.TObject<{
environmentId: Type.TString;
credential: Type.TString;
ownerEpoch: Type.TInteger;
rpcSetVersion: Type.TInteger;
handshake: Type.TObject<{
bundleHash: Type.TString;
openclawVersion: Type.TString;
protocolFeatures: Type.TArray<Type.TString>;
bundlePrewarm: Type.TOptional<Type.TInteger>;
}>;
sessionId: Type.TString;
runId: Type.TString;
}>]>;
}>;
declare const WorkerTranscriptMessageSchema: Type.TUnion<[Type.TObject<{
role: Type.TLiteral<"user">;
content: Type.TArray<Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"text">;
text: Type.TString;
textSignature: Type.TOptional<Type.TString>;
}>, Type.TObject<{
type: Type.TLiteral<"image">;
data: Type.TString;
mimeType: Type.TString;
}>]>>;
timestamp: Type.TInteger;
}>, Type.TObject<{
role: Type.TLiteral<"assistant">;
content: Type.TArray<Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"text">;
text: Type.TString;
textSignature: Type.TOptional<Type.TString>;
}>, Type.TObject<{
type: Type.TLiteral<"thinking">;
thinking: Type.TString;
thinkingSignature: Type.TOptional<Type.TString>;
redacted: Type.TOptional<Type.TBoolean>;
}>, Type.TObject<{
type: Type.TLiteral<"toolCall">;
id: Type.TString;
name: Type.TString;
arguments: Type.TRecord<"^.*$", Type.TUnknown>;
thoughtSignature: Type.TOptional<Type.TString>;
executionMode: Type.TOptional<Type.TUnion<[Type.TLiteral<"sequential">, Type.TLiteral<"parallel">]>>;
}>]>>;
api: Type.TString;
provider: Type.TString;
model: Type.TString;
responseModel: Type.TOptional<Type.TString>;
responseId: Type.TOptional<Type.TString>;
providerReplay: Type.TOptional<Type.TObject<{
v: Type.TLiteral<1>;
type: Type.TString;
id: Type.TOptional<Type.TString>;
data: Type.TString;
replayIndex: Type.TOptional<Type.TInteger>;
provider: Type.TString;
api: Type.TString;
model: Type.TString;
baseUrlHash: Type.TOptional<Type.TString>;
sessionHash: Type.TOptional<Type.TString>;
authProfileHash: Type.TOptional<Type.TString>;
}>>;
diagnostics: Type.TOptional<Type.TArray<Type.TObject<{
type: Type.TString;
timestamp: Type.TInteger;
error: Type.TOptional<Type.TObject<{
name: Type.TOptional<Type.TString>;
message: Type.TString;
stack: Type.TOptional<Type.TString>;
code: Type.TOptional<Type.TUnion<[Type.TString, Type.TNumber]>>;
}>>;
details: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
}>>>;
usage: Type.TObject<{
input: Type.TNumber;
output: Type.TNumber;
cacheRead: Type.TNumber;
cacheWrite: Type.TNumber;
contextUsage: Type.TOptional<Type.TUnion<[Type.TObject<{
state: Type.TLiteral<"available">;
promptTokens: Type.TNumber;
totalTokens: Type.TNumber;
}>, Type.TObject<{
state: Type.TLiteral<"unavailable">;
}>]>>;
totalTokens: Type.TNumber;
cost: Type.TObject<{
input: Type.TNumber;
output: Type.TNumber;
cacheRead: Type.TNumber;
cacheWrite: Type.TNumber;
total: Type.TNumber;
totalOrigin: Type.TOptional<Type.TLiteral<"provider-billed">>;
}>;
}>;
stopReason: Type.TUnion<[Type.TLiteral<"stop">, Type.TLiteral<"length">, Type.TLiteral<"toolUse">, Type.TLiteral<"error">, Type.TLiteral<"aborted">]>;
errorMessage: Type.TOptional<Type.TString>;
errorCode: Type.TOptional<Type.TString>;
errorType: Type.TOptional<Type.TString>;
errorBody: Type.TOptional<Type.TString>;
timestamp: Type.TInteger;
}>, Type.TObject<{
role: Type.TLiteral<"toolResult">;
toolCallId: Type.TString;
toolName: Type.TString;
content: Type.TArray<Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"text">;
text: Type.TString;
textSignature: Type.TOptional<Type.TString>;
}>, Type.TObject<{
type: Type.TLiteral<"image">;
data: Type.TString;
mimeType: Type.TString;
}>]>>;
details: Type.TOptional<Type.TUnknown>;
isError: Type.TBoolean;
timestamp: Type.TInteger;
}>]>;
declare const WorkerTranscriptCommitParamsSchema: Type.TObject<{
runEpoch: Type.TInteger;
seq: Type.TInteger;
baseLeafId: Type.TUnion<[Type.TString, Type.TNull]>;
messages: Type.TArray<Type.TUnion<[Type.TObject<{
role: Type.TLiteral<"user">;
content: Type.TArray<Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"text">;
text: Type.TString;
textSignature: Type.TOptional<Type.TString>;
}>, Type.TObject<{
type: Type.TLiteral<"image">;
data: Type.TString;
mimeType: Type.TString;
}>]>>;
timestamp: Type.TInteger;
}>, Type.TObject<{
role: Type.TLiteral<"assistant">;
content: Type.TArray<Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"text">;
text: Type.TString;
textSignature: Type.TOptional<Type.TString>;
}>, Type.TObject<{
type: Type.TLiteral<"thinking">;
thinking: Type.TString;
thinkingSignature: Type.TOptional<Type.TString>;
redacted: Type.TOptional<Type.TBoolean>;
}>, Type.TObject<{
type: Type.TLiteral<"toolCall">;
id: Type.TString;
name: Type.TString;
arguments: Type.TRecord<"^.*$", Type.TUnknown>;
thoughtSignature: Type.TOptional<Type.TString>;
executionMode: Type.TOptional<Type.TUnion<[Type.TLiteral<"sequential">, Type.TLiteral<"parallel">]>>;
}>]>>;
api: Type.TString;
provider: Type.TString;
model: Type.TString;
responseModel: Type.TOptional<Type.TString>;
responseId: Type.TOptional<Type.TString>;
providerReplay: Type.TOptional<Type.TObject<{
v: Type.TLiteral<1>;
type: Type.TString;
id: Type.TOptional<Type.TString>;
data: Type.TString;
replayIndex: Type.TOptional<Type.TInteger>;
provider: Type.TString;
api: Type.TString;
model: Type.TString;
baseUrlHash: Type.TOptional<Type.TString>;
sessionHash: Type.TOptional<Type.TString>;
authProfileHash: Type.TOptional<Type.TString>;
}>>;
diagnostics: Type.TOptional<Type.TArray<Type.TObject<{
type: Type.TString;
timestamp: Type.TInteger;
error: Type.TOptional<Type.TObject<{
name: Type.TOptional<Type.TString>;
message: Type.TString;
stack: Type.TOptional<Type.TString>;
code: Type.TOptional<Type.TUnion<[Type.TString, Type.TNumber]>>;
}>>;
details: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
}>>>;
usage: Type.TObject<{
input: Type.TNumber;
output: Type.TNumber;
cacheRead: Type.TNumber;
cacheWrite: Type.TNumber;
contextUsage: Type.TOptional<Type.TUnion<[Type.TObject<{
state: Type.TLiteral<"available">;
promptTokens: Type.TNumber;
totalTokens: Type.TNumber;
}>, Type.TObject<{
state: Type.TLiteral<"unavailable">;
}>]>>;
totalTokens: Type.TNumber;
cost: Type.TObject<{
input: Type.TNumber;
output: Type.TNumber;
cacheRead: Type.TNumber;
cacheWrite: Type.TNumber;
total: Type.TNumber;
totalOrigin: Type.TOptional<Type.TLiteral<"provider-billed">>;
}>;
}>;
stopReason: Type.TUnion<[Type.TLiteral<"stop">, Type.TLiteral<"length">, Type.TLiteral<"toolUse">, Type.TLiteral<"error">, Type.TLiteral<"aborted">]>;
errorMessage: Type.TOptional<Type.TString>;
errorCode: Type.TOptional<Type.TString>;
errorType: Type.TOptional<Type.TString>;
errorBody: Type.TOptional<Type.TString>;
timestamp: Type.TInteger;
}>, Type.TObject<{
role: Type.TLiteral<"toolResult">;
toolCallId: Type.TString;
toolName: Type.TString;
content: Type.TArray<Type.TUnion<[Type.TObject<{
type: Type.TLiteral<"text">;
text: Type.TString;
textSignature: Type.TOptional<Type.TString>;
}>, Type.TObject<{
type: Type.TLiteral<"image">;
data: Type.TString;
mimeType: Type.TString;
}>]>>;
details: Type.TOptional<Type.TUnknown>;
isError: Type.TBoolean;
timestamp: Type.TInteger;
}>]>>;
}>;
type WorkerConnectParams = Static<typeof WorkerConnectParamsSchema>;
type WorkerTranscriptMessage = Static<typeof WorkerTranscriptMessageSchema>;
type WorkerTranscriptCommitParams = Static<typeof WorkerTranscriptCommitParamsSchema>;
//#endregion
//#region src/cron/scheduled-tool-policy.d.ts
/** Closed, server-authored origin of an account-scoped scheduled tool cap. */
type CronScheduledToolCallerOrigin = {
kind: "external";
channel: string;
} | {
kind: "local";
} | {
kind: "unknown";
};
/**
* Restrict-only execution target for a job's exec grant, captured from a
* creator surface whose only exec capability was host-pinned. New pinned jobs
* persist this as part of a grant-coupled envelope; unmarked legacy jobs keep
* baseline exec behavior.
*/
type CronToolsAllowExecTarget = {
version: 1;
host: "gateway";
/** Mandatory approval floor inherited from the captured creator surface. */
ask?: "always";
};
/** Persisted proof that this job was created with an exact exec restriction. */
type CronToolsAllowExecTargetRequirement = {
version: 1;
target: CronToolsAllowExecTarget;
grantIndex: number;
recoveryRequired?: never;
} | {
version: 1;
target?: never;
recoveryRequired: true;
};
/** Server-authored provenance for a persisted scheduled tool-cap authority envelope. */
type CronScheduledToolPolicy = {
version: 1;
mode: "trusted";
ownerSessionKey?: never;
ownerAccountId?: never;
} | {
version: 1;
mode: "account";
ownerSessionKey: string;
ownerAccountId: string;
};
//#endregion
//#region src/plugin-sdk/channel-route.d.ts
/** Coarse chat shape used when a channel can distinguish direct, group, and broadcast targets. */
type ChannelRouteChatType = "direct" | "group" | "channel";
/** Provider-specific thread kind carried with normalized channel routes. */
type ChannelRouteThreadKind = "topic" | "thread" | "reply";
/** Describes which runtime surface supplied a channel route thread id. */
type ChannelRouteThreadSource = "explicit" | "target" | "session" | "turn";
/** Normalized channel route used for comparison, binding, and dedupe helpers. */
type ChannelRouteRef = {
/** Lowercase channel id such as `slack`, `telegram`, or `discord`. */
channel?: string;
/** Normalized account/profile id when a channel supports multiple accounts. */
accountId?: string;
target?: {
/** Canonical destination id used for route equality and delivery. */
to: string;
/** Original destination text when provider target grammar differs from the canonical id. */
rawTo?: string;
/** Coarse destination shape used by channels with different direct/group/broadcast rules. */
chatType?: ChannelRouteChatType;
};
thread?: {
/** Provider thread/topic/root id; strings are preserved when providers use opaque ids. */
id: string | number;
/** Provider-specific thread family for channels that distinguish topics, replies, and threads. */
kind?: ChannelRouteThreadKind;
/** Runtime source that supplied the thread id, used when callers need route provenance. */
source?: ChannelRouteThreadSource;
};
};
/** Loose route input accepted at SDK boundaries before normalization. */
type ChannelRouteRefInput = {
/** Raw channel id; normalized to lowercase. */
channel?: unknown;
/** Raw account/profile id; normalized with account-id rules when string. */
accountId?: unknown;
/** Raw destination id before trimming and route-key normalization. */
to?: unknown;
/** Provider-specific target text retained when different from `to`. */
rawTo?: unknown;
/** Coarse destination shape supplied by channels that distinguish target kinds. */
chatType?: ChannelRouteChatType;
/** Raw provider thread/topic/root id before route-key normalization. */
threadId?: unknown;
/** Provider-specific thread family carried with the normalized thread id. */
threadKind?: ChannelRouteThreadKind;
/** Runtime surface that supplied the thread id. */
threadSource?: ChannelRouteThreadSource;
};
/** Raw outbound target input shape used by helpers that do not need thread metadata source. */
type ChannelRouteTargetInput = Pick<ChannelRouteRefInput, "channel" | "accountId" | "to" | "rawTo" | "chatType" | "threadId">;
//#endregion
//#region src/shared/session-types.d.ts
/** Per-session Control UI face preference carried by session list rows. */
type SessionBoardFace = "chat" | "dashboard";
//#endregion
//#region src/utils/delivery-context.types.d.ts
/** Deferred outbound delivery intent attached to a session or task. */
type DeliveryIntentRef = {
/** Stable queue/work item id. */
id: string;
/** Intent family; currently scoped to outbound queue delivery. */
kind: "outbound_queue";
/** Whether queueing is mandatory or best-effort for this delivery. */
queuePolicy?: "required" | "best_effort";
};
/** Canonical channel delivery target shared by sessions, cron, tasks, and plugins. */
type DeliveryContext = Pick<ChannelRouteTargetInput, "accountId" | "channel" | "threadId" | "to"> & {
/** Channel/plugin id that owns the delivery target. */
channel?: string;
/** Channel-local destination id, preserved with channel-specific casing. */
to?: string;
/** Optional channel account/workspace id. */
accountId?: string;
/** Optional thread/topic id nested under `to`. */
threadId?: string | number;
/** Optional queued-delivery intent associated with this context. */
deliveryIntent?: DeliveryIntentRef;
};
//#endregion
//#region src/config/sessions/main-session-recovery.types.d.ts
type MainRestartRecoveryState = {
/** Stable identity for one interrupted episode; prevents clear-and-rewedge ABA matches. */
cycleId: string;
/** Monotonic identity for observations within the current recovery cycle. */
revision: number;
/** Attempts charged when their reservation is persisted, before dispatch. */
chargedAttempts: number;
/** Last attempt observed starting a backend turn; later startup failures get a fresh budget. */
startedAttempt?: number;
/** Private safe token for one recovered outer turn; raw identity refs never enter session state. */
executionIdentity?: {
tokenVersion: 1;
contextId: string;
executionId: string;
runId: string;
createdAt: number;
};
reservation?: {
runId: string;
attempt: number;
lifecycleGeneration: string;
};
foregroundClaims?: {
lifecycleGeneration: string;
tokens: string[];
/** Run identity for claims that have crossed the actual agent-run boundary. */
runIdsByClaimId?: Record<string, string>;
};
tombstone?: {
reason: string;
/** Durable successor returned when an explicit rollover request is retried. */
recoveredSessionId?: string;
recoveredSessionKey?: string;
};
};
//#endregion
//#region src/config/sessions/pending-final-delivery-types.d.ts
type PendingFinalDeliveryState = {
createdAt: number;
context?: DeliveryContext;
intentId?: string;
deliveries?: Array<{
id: string;
state: "prepared" | "queued" | "delivered" | "suppressed" | "unknown";
}>;
} & ({
kind: "replayable";
text: string;
} | {
kind: "transport-only";
});
/**
* Owed user-visible notice that a final's delivery outcome stayed unknown.
* Settled unknown custody records the debt here; the next same-route turn
* sends it once, so an ambiguous loss never ends silently.
*/
type PendingDeliveryNoticeState = {
createdAt: number;
context: DeliveryContext;
intentId: string;
state: "owed" | "unresolved" | "acknowledged";
};
//#endregion
//#region src/auto-reply/source-reply-delivery-mode.types.d.ts
/** Per-turn authority for automatic replies versus explicit message-tool sends. */
type SourceReplyDeliveryMode = "automatic" | "message_tool_only";
//#endregion
//#region src/config/sessions/restart-recovery-types.d.ts
type RestartRecoveryBeforeAgentReplyState = "admitted" | "pending" | "continue" | "handled-silent" | "handled-reply" | "handled-unrecoverable";
type RestartRecoveryTerminalDeliveryEvidenceResult = {
/** The terminal result was captured even when it contained no visible or delivery evidence. */
captured?: true;
payloads?: Array<{
mediaUrls?: string[];
visible?: boolean;
}>;
payloadsTruncated?: true;
deliveryStatus?: {
status: "failed" | "partial_failed" | "sent" | "suppressed";
errorMessage?: string;
payloadOutcomes?: Array<{
index: number;
status: "failed" | "sent" | "suppressed";
sentBeforeError?: boolean;
}>;
};
messagingToolSentTargets?: Array<{
provider?: string;
accountId?: string;
to?: string;
threadId?: string;
threadImplicit?: boolean;
threadSuppressed?: boolean;
mediaUrls?: string[];
visible?: boolean;
}>;
messagingToolSentTargetsTruncated?: true;
/** Aggregate committed sends were not all represented by route-checkable target records. */
messagingToolAggregateEvidenceUnaccounted?: true;
/** The terminal run reported a committed effect that makes fresh replay unsafe. */
restartUnsafeSideEffectsDetected?: true;
};
type RestartRecoveryTerminalDeliveryEvidence = RestartRecoveryTerminalDeliveryEvidenceResult & {
runId: string;
};
/** Durable ownership and idempotency state for gateway restart recovery. */
type SessionRestartRecoveryState = {
restartRecoveryBeforeAgentReplyState?: RestartRecoveryBeforeAgentReplyState;
/** Durable pre/post boundary around the terminal external send. */
restartRecoveryDeliveryReceiptState?: "terminal-pending" | "delivered-terminal";
/** Exact agent tool call whose terminal external send owns the receipt. */
restartRecoveryDeliveryToolCallId?: string;
restartRecoveryDeliveryContext?: DeliveryContext;
/** Exact host-owned media allowlist for a generated-media recovery run. */
restartRecoveryDeliveryMediaUrls?: string[];
/** Keeps the message tool absent while a generated-media recovery run is resumed. */
restartRecoveryDisableMessageTool?: true;
/** Suppresses visible text when a recovery attempt repairs only missing media. */
restartRecoverySuppressTextDelivery?: true;
restartRecoveryDeliveryRequestFingerprint?: string;
restartRecoveryDeliveryRunId?: string;
restartRecoveryDeliverySourceRunId?: string;
restartRecoveryRequesterAccountId?: string;
restartRecoveryRequesterSenderId?: string;
restartRecoverySameChannelThreadRequired?: true;
restartRecoverySourceIngress?: "channel" | "control-ui" | "internal";
restartRecoverySourceReplyDeliveryMode?: SourceReplyDeliveryMode;
restartRecoveryTerminalDeliveryEvidence?: RestartRecoveryTerminalDeliveryEvidence[];
restartRecoveryTerminalRunIds?: string[];
};
//#endregion
//#region src/security/external-content-source.d.ts
/** Hook session sources that carry untrusted external content into agent prompts. */
type HookExternalContentSource = "email" | "gmail" | "webhook";
//#endregion
//#region src/config/sessions/session-entry-provenance.d.ts
/** Kept aligned with SessionStateActorType (src/sessions/session-state-event-kinds.ts); not imported to avoid layering config/sessions onto src/sessions. */
type SessionActor = {
type: "human" | "agent" | "system";
id?: string;
label?: string;
};
/** Only trusted creation owners may stamp a Gateway profile namespace. */
type SessionCreatedActor = SessionActor & ({
type: "human";
source: "profile" | "channel" | "unknown";
} | {
type: "agent" | "system";
});
type SessionOwnerAssignment = {
actor: SessionActor;
assignedBy?: SessionActor;
assignedAt?: number;
};
type SessionCreatedVia = "operator" | "spawn" | "channel" | "cron" | "talk" | "run" | "plugin" | "internal";
type SessionEntryProvenance = {
/** Plugin id that owns this session through a trusted runtime creation seam. */
pluginOwnerId?: string;
/** External hook source that has contributed content to this transcript. */
hookExternalContentSource?: HookExternalContentSource;
};
//#endregion
//#region src/config/sessions/session-model-fallback.d.ts
type AgentPatchedSessionModelFallback = {
prevModel: string;
prevProvider: string;
prevModelOverride?: string;
prevProviderOverride?: string;
prevModelOverrideSource?: "auto" | "user";
prevModelOverrideRouteResolution?: "resolved";
prevModelOverrideFallbackOriginProvider?: string;
prevModelOverrideFallbackOriginModel?: string;
prevAuthProfileOverride?: string;
prevAuthProfileOverrideSource?: "auto" | "user" | "user-link";
prevAuthProfileOverrideCompactionCount?: number;
prevContextWindow?: string;
prevThinkingLevel?: string;
lastValidatedPatchTs?: number;
ts: number;
source: "agent-patch";
};
//#endregion
//#region src/agents/sessions/source-info.d.ts
type SourceScope = "user" | "project" | "temporary";
type SourceOrigin = "package" | "top-level";
interface SourceInfo {
path: string;
source: string;
scope: SourceScope;
origin: SourceOrigin;
baseDir?: string;
}
//#endregion
//#region src/skills/loading/skill-contract.d.ts
interface Skill {
name: string;
/** Human-readable title from the first Markdown H1, falling back to the identifier. */
displayName?: string;
description: string;
/** Additional loading guidance rendered with the location in full and compact catalogs. */
locationNote?: string;
/** Prepared instructions for transferred bundles or non-filesystem locators such as node://. */
readContent?: string;
filePath: string;
baseDir: string;
sourceInfo: SourceInfo;
disableModelInvocation: boolean;
source: string;
}
//#endregion
//#region src/config/sessions/session-prompt-types.d.ts
type SessionSkillPromptRef = {
version: 1;
algorithm: "sha256";
hash: string;
bytes: number;
};
type SessionSkillSnapshot = {
librarySelections?: SkillLibrarySelection[];
prompt: string;
/** Persisted stores may replace large duplicate prompts with a content-addressed blob ref. */
promptRef?: SessionSkillPromptRef;
skills: Array<{
name: string;
primaryEnv?: string;
requiredEnv?: string[];
}>;
/** Normalized agent-level filter used to build this snapshot; undefined means unrestricted. */
skillFilter?: string[];
/** Effective node-exec eligibility used to select connected node-hosted skills. */
nodeSkillsEligibility?: {
canExec: boolean;
node?: string;
};
/**
* Runtime-only, never persisted. Carries the full parsed Skill[] (including
* each SKILL.md body) so the embedded runner can skip a workspace skill
* scan within a turn. Persistence projections strip it before committing
* session state. On a cold session resume this is undefined and
* src/skills/runtime/embedded-run-entries.ts rebuilds it from disk.
*/
resolvedSkills?: Skill[];
version?: number;
};
//#endregion
//#region src/config/sessions/session-system-prompt-report.d.ts
/** Persisted size and provenance summary for one assembled system prompt. */
type SessionSystemPromptReport = {
source: "run" | "estimate";
generatedAt: number;
sessionId?: string;
sessionKey?: string;
provider?: string;
model?: string;
workspaceDir?: string;
bootstrapMaxChars?: number;
bootstrapTotalMaxChars?: number;
bootstrapTruncation?: {
warningMode?: "off" | "once" | "always";
warningShown?: boolean;
promptWarningSignature?: string;
warningSignaturesSeen?: string[];
truncatedFiles?: number;
nearLimitFiles?: number;
totalNearLimit?: boolean;
};
sandbox?: {
mode?: string;
sandboxed?: boolean;
};
systemPrompt: {
chars: number;
projectContextChars: number;
nonProjectContextChars: number;
hash?: string;
};
currentTurn?: {
kind?: "user_request" | "room_event";
promptChars: number;
runtimeContextChars: number;
modelOnlyPromptChars?: number;
};
injectedWorkspaceFiles: Array<{
name: string;
path: string;
missing: boolean;
rawChars: number;
} & ({
injectionStatus?: "verified";
injectedChars: number;
truncated: boolean;
} | {
injectionStatus: "native_unverified";
injectedChars: null;
truncated: null;
})>;
skills: {
promptChars: number;
hash?: string;
entries: Array<{
name: string;
blockChars: number;
}>;
};
tools: {
listChars: number;
schemaChars: number;
entries: Array<{
name: string;
summaryChars: number;
summaryHash?: string;
schemaChars: number;
schemaHash?: string;
propertiesCount?: number | null;
}>;
};
};
//#endregion
//#region src/config/sessions/session-tool-overrides.d.ts
type SessionToolOverrides = {
mcpServers?: Record<string, boolean>;
mcpToolsDeny?: Record<string, string[]>;
skills?: Record<string, boolean>;
webSearch?: boolean;
};
//#endregion
//#region src/config/sessions/types.d.ts
type SessionChatType = ChatType;
declare const SESSION_TOTAL_TOKENS_VERSION: 1;
type SessionVisibility = "shared" | "read-only" | "suggest" | "draft";
type SessionOrigin = {
label?: string;
provider?: string;
surface?: string;
chatType?: SessionChatType;
from?: string;
to?: string;
nativeChannelId?: string;
nativeDirectUserId?: string;
avatar?: string;
accountId?: string;
threadId?: string | number;
};
/** Canonical persisted delivery ownership for one session. */
type SessionDeliveryState = {
kind: "none";
} | {
kind: "internal";
} | {
kind: "external";
route: ChannelRouteRef;
context: DeliveryContext;
origin: SessionOrigin;
};
/**
* Durable transcript-repair record: an assistant final that was delivered to
* the user but could not be appended to the canonical transcript. Kept
* separate from `pendingFinalDelivery` so transport-replay cleanup never drops
* the only copy of the missing assistant turn.
*/
type PendingTranscriptRepairState = {
/** Stable identity for retry-safe transcript insertion. */
id: string;
text: string;
provider?: string;
model?: string;
createdAt: number;
};
type FallbackNoticeState = {
kind: "active";
selectedModel: string;
activeModel: string;
reason?: string;
};
type MemoryFlushState = {
kind: "succeeded";
compactionCount: number;
} | {
kind: "failed";
compactionCount?: number;
failureCount: number;
};
type CliSessionReseedReceipt = {
version: 1;
promptHash: string;
localSessionId: string;
userTurnDisposition: "persisted" | "omitted";
};
type SessionDiffBaseline = {
version: 1;
sessionId: string;
root: string;
files: Array<{
path: string;
fingerprint: string;
}>;
/** Some checkout entries could not be fingerprinted without exceeding diff safety caps. */
truncated?: true;
};
type CliSessionBinding = {
sessionId: string;
/** Last successful assistant boundary accepted by the backend's resume contract. */
resumeCheckpointId?: string;
/** Resume with the backend's fork argument once, then clear before process start. */
forkNextResume?: true;
/** Trust an explicitly attached CLI session even when auth, prompt, or MCP fingerprints drift. */
forceReuse?: boolean;
authProfileId?: string;
authEpoch?: string;
authEpochVersion?: number;
extraSystemPromptHash?: string;
messageToolPolicyHash?: string;
promptToolNamesHash?: string;
cwdHash?: string;
mcpConfigHash?: string;
mcpResumeHash?: string;
/** Identifies one synthetic history prompt and the trusted local handling of its user turn. */
reseedReceipt?: CliSessionReseedReceipt;
};
type AcpSessionBinding = {
acpBackendId: string;
acpAgentId: string;
agentSessionId: string;
};
type SessionCompactionCheckpointReason = "manual" | "auto-threshold" | "overflow-retry" | "timeout-retry";
type SessionCompactionTranscriptReference = {
sessionId: string;
sessionFile?: string;
leafId?: string;
entryId?: string;
};
type SessionCompactionCheckpoint = {
checkpointId: string;
sessionKey: string;
sessionId: string;
createdAt: number;
reason: SessionCompactionCheckpointReason;
tokensBefore?: number;
tokensAfter?: number;
tokensVersion?: typeof SESSION_TOTAL_TOKENS_VERSION;
summary?: string;
firstKeptEntryId?: string;
preCompaction: SessionCompactionTranscriptReference;
postCompaction: SessionCompactionTranscriptReference;
};
type SessionContextBudgetStatusRoute = "fits" | "compact_only" | "truncate_tool_results_only" | "compact_then_truncate";
type SessionContextBudgetStatus = {
schemaVersion: 1;
source: "pre-prompt-estimate";
updatedAt: number;
provider: string;
model: string;
route: SessionContextBudgetStatusRoute;
shouldCompact: boolean;
estimatedPromptTokens: number;
contextTokenBudget: number;
promptBudgetBeforeReserve: number;
reserveTokens: number;
effectiveReserveTokens: number;
remainingPromptBudgetTokens: number;
overflowTokens: number;
toolResultReducibleChars: number;
messageCount: number;
unwindowedMessageCount: number;
sessionId?: string;
};
type AmbientTranscriptWatermark = {
sessionId: string;
messageId: string;
timestampMs?: number;
updatedAt: number;
};
type SessionPluginDebugEntry = {
pluginId: string;
lines: string[];
};
type SessionPluginJsonValue = string | number | boolean | null | SessionPluginJsonValue[] | {
[key: string]: SessionPluginJsonValue;
};
type SessionPluginNextTurnInjection = {
id: string;
pluginId: string;
pluginName?: string;
text: string;
idempotencyKey?: string;
placement: "prepend_context" | "append_context";
ttlMs?: number;
createdAt: number;
metadata?: SessionPluginJsonValue;
};
type SubagentRecoveryState = {
/** Consecutive accepted automatic orphan-recovery resumes in the rapid re-wedge window. */
automaticAttempts?: number;
/** Timestamp (ms) of the latest accepted automatic orphan-recovery resume. */
lastAttemptAt?: number;
/** Registry run id that triggered the latest automatic orphan-recovery resume. */
lastRunId?: string;
/** Timestamp (ms) when automatic recovery was tombstoned for this session. */
wedgedAt?: number;
/** Human-readable reason automatic recovery was tombstoned. */
wedgedReason?: string;
};
type LaneExecutionState = "active" | "draining" | "suspended" | "resuming" | "circuit_open" | "failed_handoff";
interface QuotaSuspension {
schemaVersion: 1;
suspendedAt: number;
reason: "quota_exhausted" | "manual" | "circuit_open";
failedProvider: string;
failedModel: string;
/** Recovery briefing text injected into the next attempt when state === "resuming". */
summary?: string;
/** Opaque pointer to an external snapshot blob (path/key); not the briefing text itself. */
snapshotRef?: string;
/**
* @deprecated Lane suspension was removed; nothing writes this anymore. Kept only to
* hold the shipped SDK surface stable; drop at the next surface window.
*/
laneId?: string;
expectedResumeBy?: number;
state: LaneExecutionState;
}
type RestartRecoveryRun = {
runId: string;
lifecycleGeneration: string;
};
type SessionEntryCore = SessionRestartRecoveryState & SessionEntryProvenance & Pick<SessionRow, "permissionMode" | "sessionRoot"> & {
/** Collaboration mode. Missing legacy values are equivalent to "shared". */
visibility?: SessionVisibility;
/**
* Last delivered heartbeat payload (used to suppress duplicate heartbeat notifications).
* Stored on the main session entry.
*/
lastHeartbeatText?: string;
/** Timestamp (ms) when lastHeartbeatText was delivered. */
lastHeartbeatSentAt?: number;
/**
* Base session key for heartbeat-created isolated sessions.
* When present, `<base>:heartbeat` is a synthetic isolated session rather than
* a real user/session-scoped key that merely happens to end with `:heartbeat`.
*/
heartbeatIsolatedBaseSessionKey?: string;
/** Legacy heartbeat task timestamps consumed and cleared only by doctor migration. */
heartbeatTaskState?: Record<string, number>;
/** Plugin-owned session state, grouped by plugin id then extension namespace. */
pluginExtensions?: Record<string, Record<string, SessionPluginJsonValue>>;
/** Trusted session initialization is incomplete; all work admission stays blocked. */
initializationPending?: true;
/** Top-level SessionEntry mirror slots owned by plugin session extensions. */
pluginExtensionSlotKeys?: Record<string, Record<string, string>>;
/** Durable one-shot prompt additions drained before the next agent turn. */
pluginNextTurnInjections?: Record<string, SessionPluginNextTurnInjection[]>;
sessionId: string;
updatedAt: number;
/** Process-lifetime session whose entry and transcript stay in the in-memory agent database. */
incognito?: true;
/** Opaque owner revision used to reject stale lifecycle mutations. */
lifecycleRevision?: string;
/** Timestamp (ms) when the session was archived from active session lists. */
archivedAt?: number;
/** Actor that archived the session; cleared when the session is restored. */
archivedBy?: SessionActor;
/** Stable lifecycle cause; absent values are legacy archives and remain manually protected. */
archiveReason?: SessionEntryArchiveReason;
/** Timestamp (ms) when the session was pinned for quick access. */
pinnedAt?: number;
/** Timestamp (ms) when an operator client last marked the session read. */
lastReadAt?: number;
/** Agent-declared sidebar presence; projection drops it after expiresAt. */
agentStatus?: SessionAgentStatus;
/** Latest utility-model status judgment for idle session status surfaces. */
observerDigest?: SessionObserverDigest;
/** Timestamp (ms) when an operator explicitly marked the session unread; cleared on read. */
markedUnreadAt?: number;
/** Timestamp (ms) of the latest completed agent run; metadata patches do not update it. */
lastActivityAt?: number;
/** Parent session key that spawned this session (used for sandbox session-tool scoping). */
spawnedBy?: string;
/** Immutable session key authorized to receive this child's completion handoff. */
completionOwnerSessionKey?: string;
/** Workspace inherited by spawned sessions and reused on later turns for the same child session. */
spawnedWorkspaceDir?: string;
/** Task working directory inherited by spawned sessions and reused on later turns. */
spawnedCwd?: string;
/** Content-free fingerprints for checkout changes that predate this session generation. */
sessionDiffBaseline?: SessionDiffBaseline;
/**
* Managed worktree bound to this session; set with spawnedCwd at worktree
* creation and cleared together when a plain New Chat detaches the checkout.
*/
worktree?: {
id: string;
branch: string;
repoRoot: string;
/** Durable skill workspace prepared when this session runs from a managed worktree. */
canonicalWorkspaceDir?: string;
};
/** Project registry id selected when this logical session node was created. */
projectId?: string;
/** Explicit parent session linkage for dashboard-created child sessions. */
parentSessionKey?: string;
/** Exact parent incarnation captured when this child was created. */
parentSessionId?: string;
/** How this session node came to exist; written once and retained across sessionId rotations. */
createdVia?: SessionCreatedVia;
/** Actor that caused node creation, with an optional profile, session, or sender id; written once. */
createdActor?: SessionCreatedActor;
/** Creation-only sandbox requirement; existing unstamped sessions always remain unstamped. */
sandbox?: "required";
/** Mutable responsibility, projected from SQLite; absent means createdActor owns the session. */
owner?: SessionOwnerAssignment;
/** Retained identities, projected from the participant table before display truncation. */
participants?: SessionParticipant[];
/** Raw retained identity count, including the owner, for admission-bound coverage. */
participantCount?: number;
/** Node creation time (ms); unlike sessionStartedAt, survives sessionId rotations. */
createdAt?: number;
/** Exact source generation and optional cut entry for an actual transcript-copy fork. */
forkSource?: {
sessionKey: string;
sessionId: string;
entryId?: string;
};
/** Session id of the prior transcript generation under this same session key. */
previousSessionId?: string;
/** Thread parent-seeding settled marker; also set when seeding is deliberately skipped. */
forkedFromParent?: boolean;
/** Subagent spawn depth (0 = main, 1 = sub-agent, 2 = sub-sub-agent). */
spawnDepth?: number;
/** Explicit role assigned at spawn time for subagent tool policy/control decisions. */
subagentRole?: "orchestrator" | "leaf";
/** Explicit control scope assigned at spawn time for subagent control decisions. */
subagentControlScope?: "children" | "none";
/** Version of the requester tool-policy snapshot captured when this child was spawned. */
inheritedToolPolicyVersion?: 1;
/** Session-scoped tool deny entries inherited from the caller that created this session. */
inheritedToolDeny?: string[];
/** Session-scoped tool allow entries inherited from the caller that created this session. */
inheritedToolAllow?: string[];
systemSent?: boolean;
abortedLastRun?: boolean;
/** Interrupted run generations whose late lifecycle events must be ignored. */
restartRecoveryRuns?: RestartRecoveryRun[];
/** Keeps automatic restart recovery limited to replay-safe tools until the run terminates. */
restartRecoveryForceSafeTools?: true;
/** Durable guard state for automatic subagent orphan recovery. */
subagentRecovery?: SubagentRecoveryState;
/** Quota cascade protection and state-aware failover status. */
quotaSuspension?: QuotaSuspension;
/** Core-owned durable goal state for this thread/session. */
goal?: SessionGoal;
/** Timestamp (ms) when the current sessionId first became active. */
sessionStartedAt?: number;
/** Stable usage lineage key for transcript-backed rollups across sessionId rotations. */
usageFamilyKey?: string;
/** Session ids known to belong to this usage lineage, including archived predecessors. */
usageFamilySessionIds?: string[];
/** Timestamp (ms) of the last user/channel interaction that should extend idle lifetime. */
lastInteractionAt?: number;
/** Stable first-run start time for subagent sessions, persisted after completion. */
startedAt?: number;
/** Latest completed run end time for subagent sessions, persisted after completion. */
endedAt?: number;
/** Accumulated runtime across subagent follow-up runs, persisted after completion. */
runtimeMs?: number;
/** Final persisted subagent run status, used after in-memory run archival. */
status?: SessionRunStatus;
/** Compact user-facing reason for the latest failed or timed-out run. */
lastRunError?: string;
/**
* Session-level stop cutoff captured when /stop is received.
* Messages at/before this boundary are skipped to avoid replaying
* queued pre-stop backlog.
*/
abortCutoffMessageSid?: string;
/** Epoch ms cutoff paired with abortCutoffMessageSid when available. */
abortCutoffTimestamp?: number;
chatType?: SessionChatType;
contextWindow?: string;
thinkingLevel?: string;
/**
* Exact isolated-cron continuation policy. Only hidden `:run:` session rows
* carry this while detached generated-media work may still wake the run.
*/
cronRunContinuation?: {
lifecycleRevision: string;
phase: "running" | "ready" | "continuing";
/** True only after this row's session changes were projected to the stable cron row. */
basePersisted?: boolean;
ownerRunId?: string;
/** Gateway lifecycle generation that owns a continuing claim. */
ownerLifecycleGeneration?: string;
/** CLI backend whose native session must exist before media work detaches. */
cliExecutionProvider?: string;
toolsAllow?: string[];
toolsAllowIsDefault?: boolean;
/** Exact server-stamped authority provenance copied from the owning cron job. */
scheduledToolPolicy?: CronScheduledToolPolicy;
/** Restrict-only exec pin copied from the owning cron job's cap. */
toolsAllowExecTarget?: CronToolsAllowExecTarget;
/** Expected pin copied with the cap so detached continuation loss fails closed. */
toolsAllowExecTargetRequirement?: CronToolsAllowExecTargetRequirement;
/** Store-private origin paired with an account scheduled-tool policy. */
scheduledToolCallerOrigin?: CronScheduledToolCallerOrigin;
cliSessionBindingFacts?: {
extraSystemPromptStatic?: string;
sourceReplyDeliveryMode?: "automatic" | "message_tool_only";
requireExplicitMessageTarget?: boolean;
};
};
fastMode?: FastMode;
toolOverrides?: SessionToolOverrides;
/** Swarm group for collector-mode child sessions. */
swarmGroupId?: string;
/** Marks non-interactive collector-mode child sessions. */
swarmCollector?: boolean;
/** JSON Schema exposed through the synthetic structured_output tool. */
swarmOutputSchema?: Record<string, unknown>;
verboseLevel?: string;
traceLevel?: string;
reasoningLevel?: string;
elevatedLevel?: string;
ttsAuto?: TtsAutoMode;
/** Hash of the latest assistant reply that was sent through `/tts latest`. */
lastTtsReadLatestHash?: string;
/** Timestamp (ms) when `/tts latest` last sent audio for this session. */
lastTtsReadLatestAt?: number;
execHost?: string;
execNode?: string;
/** Working directory interpreted only by the bound exec node. */
execCwd?: string;
responseUsage?: "on" | "off" | "tokens" | "full";
providerOverride?: string;
modelOverride?: string;
/** Session-scoped agent runtime/harness override selected with the model picker. */
agentRuntimeOverride?: string;
/**
* Tracks whether the persisted model override came from an explicit user
* action (`/model`, `sessions.patch`) or from a temporary runtime fallback.
* Resets only preserve user-driven overrides.
*/
modelOverrideSource?: "auto" | "user";
/** Present only when providerOverride/modelOverride are a canonical route pair. */
modelOverrideRouteResolution?: "resolved";
/** Selected model that produced the current auto fallback override. */
modelOverrideFallbackOriginProvider?: string;
modelOverrideFallbackOriginModel?: string;
/** One-run rollback guard for a model selected by the agent sessions tool. */
modelFallback?: AgentPatchedSessionModelFallback;
authProfileOverride?: string;
authProfileOverrideSource?: "auto" | "user" | "user-link";
authProfileOverrideCompactionCount?: number;
/**
* Set on explicit user-driven session model changes (for example `/model`
* and `sessions.patch`) during an active run. The embedded runner checks
* this flag to decide whether to throw `LiveSessionModelSwitchError`.
* System-initiated fallbacks (rate-limit retry rotation) never set this
* flag, so they are never mistaken for user-initiated switches.
*/
liveModelSwitchPending?: boolean;
groupActivation?: "mention" | "always";
groupActivationNeedsSystemIntro?: boolean;
sendPolicy?: "allow" | "deny";
queueMode?: QueueMode;
queueDebounceMs?: number;
queueCap?: number;
queueDrop?: "old" | "new" | "summarize";
inputTokens?: number;
outputTokens?: number;
totalTokens?: number;
pendingFinalDelivery?: PendingFinalDeliveryState;
pendingDeliveryNotice?: PendingDeliveryNoticeState;
/**
* Ordered durable backlog of delivered assistant finals that failed to
* reach the canonical transcript. Session admission restores each item
* before another turn can extend that transcript. Kept as a list so
* independently admitted writers never overwrite an earlier reply.
*/
pendingTranscriptRepair?: PendingTranscriptRepairState[];
/**
* Whether totalTokens reflects a fresh context snapshot for the latest run.
* Undefined means legacy/unknown freshness; false forces consumers to treat
* totalTokens as stale/unknown for context-utilization displays.
*/
totalTokensFresh?: boolean;
/** Version 1 records totalTokens as the current prompt/context snapshot only. */
totalTokensVersion?: typeof SESSION_TOTAL_TOKENS_VERSION;
estimatedCostUsd?: number;
cacheRead?: number;
cacheWrite?: number;
modelProvider?: string;
model?: string;
/**
* Prevents OpenClaw model changes and automatic maintenance eviction until
* the owning harness explicitly retires the session.
*/
modelSelectionLocked?: boolean;
/**
* Embedded agent harness selected for this session id.
* Prevents config/env changes from moving an existing transcript between
* incompatible runtime harnesses.
*/
agentHarnessId?: string;
fallbackNotice?: FallbackNoticeState;
contextTokens?: number;
/** Origin of the persisted context window; `resolved` is legacy/unverified. */
contextTokensSource?: "runtime" | "runtime-configured" | "resolved" | "resolved-v1";
contextBudgetStatus?: SessionContextBudgetStatus;
compactionCount?: number;
compactionCheckpoints?: SessionCompactionCheckpoint[];
memoryFlush?: MemoryFlushState;
cliSessionIds?: Record<string, string>;
cliSessionBindings?: Record<string, CliSessionBinding>;
/** Initialization fence for seeding canonical ACP metadata; cleared after creation. */
acpSessionBinding?: AcpSessionBinding;
claudeCliSessionId?: string;
label?: string;
/** Persistent operator/agent-set sidebar emoji icon (single grapheme). */
icon?: string;
/** Named sidebar tint (SESSION_COLOR_IDS); palette mirrors Claude Code /color for import. */
color?: string;
/** User-defined organization bucket for session lists; unrelated to chat groupId/groupChannel. */
category?: string;
/** Preferred Control UI face when a caller opens this session without explicit face intent. */
boardFace?: SessionBoardFace;
displayName?: string;
/** Canonical delivery state. Legacy delivery fields are migrated by `openclaw doctor --fix`. */
delivery?: SessionDeliveryState;
groupId?: string;
subject?: string;
groupChannel?: string;
space?: string;
/** Last ambient room message durably appended to this transcript, keyed by channel scope. */
ambientTranscriptWatermarks?: Record<string, AmbientTranscriptWatermark>;
skillsSnapshot?: SessionSkillSnapshot;
/** Explicit authorized immutable library pins; current speakers never replace this selection. */
skillLibrarySelections?: SkillLibrarySelection[];
systemPromptReport?: SessionSystemPromptReport;
/**
* Generic plugin-owned runtime debug entries shown in verbose status surfaces.
* Each plugin owns and may overwrite only its own entry between turns.
*/
pluginDebugEntries?: SessionPluginDebugEntry[];
acp?: SessionAcpMeta;
};
interface SessionEntry$1 extends SessionEntryCore {}
/** Internal durable fields excluded from public/plugin session projections. */
type InternalSessionEntryCore = SessionEntryCore & {
/** Run that owns the current non-terminal Gateway lifecycle projection. */
lifecycleRunId?: string;
/** Exact run that produced the latest terminal Gateway lifecycle projection. */
lastRunId?: string;
/** Run admitted by the session lane; overwritten at admission and checked by transcript writes. */
activeWriterRunId?: string;
/** Canonical remote repository awaiting preparation by this exact session generation. */
pendingProjectGitUrl?: string;
/** Authorized worktree intent awaiting preparation by an admitted turn. */
pendingWorktree?: {
workspace?: string;
name?: string;
baseRef?: string;
titleSource: string;
};
/** Suppresses repeated byte-triggered compaction after an oversized successor was observed. */
transcriptByteCompactionLatch?: {
activeBytes: number;
sessionId: string;
maxBytes: number;
};
/** Private per-generation ownership for the pre-runtime checkout baseline capture. */
sessionDiffBaselineCapture?: SessionDiffBaselineCapture;
mainRestartRecovery?: MainRestartRecoveryState;
};
interface InternalSessionEntry extends InternalSessionEntryCore {}
type GroupKeyResolution = {
key: string;
channel?: string;
id?: string;
chatType?: SessionChatType;
};
//#endregion
//#region src/channels/plugins/message-action-names.d.ts
/**
* Deliberately closed, core-owned vocabulary so every transport can render every action.
* Plugins add names through a core PR; runtime registration is intentionally unsupported.
*/
declare const CHANNEL_MESSAGE_ACTION_NAMES: readonly ["send", "broadcast", "poll", "poll-vote", "react", "reactions", "read", "edit", "unsend", "reply", "sendWithEffect", "renameGroup", "setGroupIcon", "addParticipant", "removeParticipant", "leaveGroup", "sendAttachment", "delete", "pin", "unpin", "list-pins", "permissions", "thread-create", "thread-list", "thread-reply", "search", "sticker", "sticker-search", "member-info", "role-info", "emoji-list", "emoji-upload", "sticker-upload", "role-add", "role-remove", "channel-info", "channel-list", "channel-create", "conversation-open", "channel-edit", "channel-delete", "channel-move", "category-create", "category-edit", "category-delete", "topic-create", "topic-edit", "voice-status", "event-list", "event-create", "timeout", "kick", "ban", "set-profile", "set-presence", "download-file", "upload-file"];
/**
* Message action name union derived from the canonical action list.
*/
type ChannelMessageActionName$1 = (typeof CHANNEL_MESSAGE_ACTION_NAMES)[number];
//#endregion
//#region packages/gateway-protocol/src/client-info.d.ts
/** Canonical client ids accepted in gateway hello/connect payloads. */
declare const GATEWAY_CLIENT_IDS: {
readonly WEBCHAT_UI: "webchat-ui";
readonly CONTROL_UI: "openclaw-control-ui";
readonly BROWSER_COPILOT: "openclaw-browser-copilot";
readonly TUI: "openclaw-tui";
readonly WEBCHAT: "webchat";
readonly CLI: "cli";
readonly GATEWAY_CLIENT: "gateway-client";
readonly MACOS_APP: "openclaw-macos";
readonly LINUX_APP: "openclaw-linux";
readonly IOS_APP: "openclaw-ios";
readonly WATCHOS_APP: "openclaw-watchos";
readonly ANDROID_APP: "openclaw-android";
readonly NODE_HOST: "node-host";
readonly WORKER: "openclaw-worker";
readonly TEST: "test";
readonly FINGERPRINT: "fingerprint";
readonly PROBE: "openclaw-probe";
};
/** Stable gateway client ids used on the wire during hello/connect handshakes. */
type GatewayClientId = (typeof GATEWAY_CLIENT_IDS)[keyof typeof GATEWAY_CLIENT_IDS];
/** Compatibility alias for internal callers that still use "name" terminology. */
type GatewayClientName = GatewayClientId;
/** Coarse modes let policy group clients without matching every product id. */
declare const GATEWAY_CLIENT_MODES: {
readonly WEBCHAT: "webchat";
readonly CLI: "cli";
readonly UI: "ui";
readonly BACKEND: "backend";
readonly NODE: "node";
readonly WORKER: "worker";
readonly PROBE: "probe";
readonly TEST: "test";
};
/** Coarse client category used for gateway policy and diagnostics. */
type GatewayClientMode = (typeof GATEWAY_CLIENT_MODES)[keyof typeof GATEWAY_CLIENT_MODES];
//#endregion
//#region packages/agent-core/src/types.d.ts
/**
* Stream function used by the agent loop.
*
* Contract:
* - Must not throw or return a rejected promise for request/model/runtime failures.
* - Must return an AssistantMessageEventStream.
* - Failures must be encoded in the returned stream via protocol events and a
* final AssistantMessage with stopReason "error" or "aborted" and errorMessage.
*/
type StreamFn = StreamFn$1;
/**
* Configuration for how tool calls from a single assistant message are executed.
*
* - "sequential": each tool call is prepared, checked for steering, executed, and finalized before the next one starts.
* - "parallel": tool calls are prepared sequentially, checked for steering once, then allowed tools execute concurrently.
* `tool_execution_end` is emitted in tool completion order after each tool is finalized,
* while tool-result message artifacts are emitted later in assistant source order.
*/
type ToolExecutionMode = "sequential" | "parallel";
/** Bucketed feedback for an admitted call, not a veto or recovery attempt. */
interface ToolLoopWarning {
kind: "tool-loop-warning";
toolCallId: string;
count: number;
}
interface BashExecutionMessage {
/** Harness role for shell command transcripts. */
role: "bashExecution";
/** Command line that was executed. */
command: string;
/** Captured command output, usually already truncated for context. */
output: string;
/** Process exit code when the command reached process exit. */
exitCode: number | undefined;
/** True when the command was interrupted before normal completion. */
cancelled: boolean;
/** True when output was shortened for transcript/context storage. */
truncated: boolean;
/** Optional path containing the complete output when truncation occurred. */
fullOutputPath?: string;
/** Millisecond timestamp for transcript ordering. */
timestamp: number;
/** Exclude this command transcript from model context while keeping it in session history. */
excludeFromContext?: boolean;
}
interface CustomMessage<T = unknown> {
/** Harness role for application-defined transcript content. */
role: "custom";
/** Application-defined discriminator for rendering or handling this message. */
customType: string;
/** Content replayed into model context when this message is included. */
content: string | (TextContent | ImageContent$1)[];
/** Whether UI surfaces should display this message. */
display: boolean;
/** Keep display-only application activity out of future model context. */
excludeFromContext?: boolean;
/** Optional application-specific metadata. */
details?: T;
/** Millisecond timestamp for transcript ordering. */
timestamp: number;
}
interface BranchSummaryMessage {
/** Harness role for summaries produced when returning from another branch. */
role: "branchSummary";
/** Summary text inserted back into model context. */
summary: string;
/** Entry id of the branch root or source leaf being summarized. */
fromId: string;
/** Millisecond timestamp for transcript ordering. */
timestamp: number;
}
interface CompactionSummaryMessage {
/** Harness role for summaries that replace compacted transcript history. */
role: "compactionSummary";
/** Summary text inserted back into model context. */
summary: string;
/** Estimated context tokens before compaction. */
tokensBefore: number;
/** Timestamp may be numeric in memory or string when loaded from older persisted rows. */
timestamp: number | string;
/** Optional estimated context tokens after compaction. */
tokensAfter?: number;
/** Optional first retained entry id from the compaction range. */
firstKeptEntryId?: string;
/** Optional implementation-specific compaction metadata. */
details?: unknown;
}
/**
* Extensible interface for custom app and harness messages.
* Apps can extend via declaration merging.
*/
interface CustomAgentMessages {
bashExecution: BashExecutionMessage;
custom: CustomMessage;
branchSummary: BranchSummaryMessage;
compactionSummary: CompactionSummaryMessage;
}
/**
* AgentMessage: Union of LLM messages + custom messages.
* This abstraction allows apps to add custom message types while maintaining
* type safety and compatibility with the base LLM messages.
*/
type AgentMessage = Message | CustomAgentMessages[keyof CustomAgentMessages];
/** Channel-safe progress text emitted by a running tool. */
interface AgentToolProgress {
/** Public text suitable for user-facing progress surfaces. */
text: string;
/** Tool progress is rendered by channel progress UIs. */
visibility: "channel";
/** Progress text must not contain secrets, private args, or fetched content. */
privacy: "public";
/** Optional stable id for progress line replacement. */
id?: string;
}
/** Final or partial result produced by a tool. */
interface AgentToolResult<T> {
/** Text or image content returned to the model. */
content: (TextContent | ImageContent$1)[];
/** Arbitrary structured details for logs or UI rendering. */
details: T;
/** Optional public progress hint for partial tool updates; never model content. */
progress?: AgentToolProgress;
/**
* Hint that the agent should stop after the current tool batch.
* Early termination only happens when every finalized tool result in the batch sets this to true.
*/
terminate?: boolean;
}
/** Callback used by tools to stream partial execution updates. */
type AgentToolUpdateCallback<T = unknown> = (partialResult: AgentToolResult<T>) => void;
/** Origin class for tool output that can taint later model-authored content in the same turn. */
type ToolResultContentSource = "network";
/** Tool definition used by the agent runtime. */
interface AgentTool<TParameters extends TSchema = TSchema, TDetails = unknown> extends Tool<TParameters> {
/** Human-readable label for UI display. */
label: string;
/** Optional schema for the structured `AgentToolResult.details` value. */
outputSchema?: TSchema;
/** Preserve lifecycle telemetry without rendering transient channel progress. */
hideFromChannelProgress?: boolean;
/** Tool results contain externally controlled network content. */
resultContentSource?: ToolResultContentSource;
/**
* Optional compatibility shim for raw tool-call arguments before schema validation.
* Must return an object that matches `TParameters`.
*/
prepareArguments?: (args: unknown) => Static<TParameters>;
/** Execute the tool call. Throw on failure instead of encoding errors in `content`. */
execute: (toolCallId: string, params: Static<TParameters>, signal?: AbortSignal, onUpdate?: AgentToolUpdateCallback<TDetails>) => Promise<AgentToolResult<TDetails>>;
/**
* Per-tool execution mode override.
* - "sequential": this tool must execute one at a time with other tool calls.
* - "parallel": this tool can execute concurrently with other tool calls.
*
* If omitted, the default execution mode applies.
*/
executionMode?: ToolExecutionMode;
}
//#endregion
//#region packages/normalization-core/src/result.d.ts
/** Result of a fallible operation. Expected failures use the `ok: false` arm. */
type Result<TValue, TError> = {
ok: true;
value: TValue;
} | {
ok: false;
error: TError;
};
//#endregion
//#region packages/agent-core/src/harness/compaction/compaction.d.ts
/** Generated compaction data ready to be persisted as a compaction entry. */
interface CompactionResult<T = unknown> {
/** Summary text that replaces compacted history in future context. */
summary: string;
/** Entry id where retained history starts. */
firstKeptEntryId: string;
/** Estimated context tokens before compaction. */
tokensBefore: number;
/** Optional implementation-specific details stored with the compaction entry. */
details?: T;
}
//#endregion
//#region src/channels/location.d.ts
/** Normalized source kind for channel-provided geographic locations. */
type LocationSource = "pin" | "place" | "live";
/** Channel-neutral location payload passed from plugins into shared prompt rendering. */
type NormalizedLocation = {
latitude: number;
longitude: number;
accuracy?: number;
name?: string;
address?: string;
isLive?: boolean;
source?: LocationSource;
caption?: string;
};
/** Portable outbound location fields supported by channel send adapters. */
type OutboundLocation = Pick<NormalizedLocation, "latitude" | "longitude" | "accuracy" | "name" | "address">;
//#endregion
//#region src/infra/approval-scope.d.ts
type ApprovalScope = Static<typeof ApprovalScopeSchema>;
//#endregion
//#region src/infra/command-analysis/explain.d.ts
/** Compact command explanation summary shown in approval UI. */
type CommandExplanationSummary = {
commandCount: number;
nestedCommandCount: number;
riskKinds: string[];
warningLines: string[];
};
//#endregion
//#region src/infra/exec-approval-policy-snapshot.d.ts
type ExecApprovalPolicyRule = {
pattern: string;
argPattern?: string;
source?: "allow-always";
};
type ExecApprovalPolicySnapshot = {
security: "deny" | "allowlist" | "full";
ask: "off" | "on-miss" | "always";
askFallback: "deny" | "allowlist" | "full";
autoAllowSkills: boolean;
allowlistRules: readonly ExecApprovalPolicyRule[];
};
//#endregion
//#region src/infra/exec-approvals-core.d.ts
type ExecHost = "sandbox" | "gateway" | "node";
type ExecTarget = "auto" | ExecHost;
type ExecSecurity = "deny" | "allowlist" | "full";
type ExecAsk = "off" | "on-miss" | "always";
type ExecMode = "deny" | "allowlist" | "ask" | "auto" | "full";
type ExecApprovalDecision = "allow-once" | "allow-always" | "deny";
type ExecApprovalUnavailableDecision = "allow-always";
type SystemRunApprovalBinding = {
argv: string[];
cwd: string | null;
agentId: string | null;
sessionKey: string | null;
envHash: string | null;
};
type SystemRunApprovalFileOperand = {
argvIndex: number;
path: string;
sha256: string;
};
type SystemRunApprovalPlan = {
argv: string[];
cwd: string | null;
commandText: string;
commandPreview?: string | null;
agentId: string | null;
sessionKey: string | null;
policySnapshot?: ExecApprovalPolicySnapshot;
mutableFileOperand?: SystemRunApprovalFileOperand | null;
};
type ExecApprovalCommandSpan = {
startIndex: number;
endIndex: number;
};
/** Cron job identity recorded at approval creation for a cron isolated run. */
type ExecApprovalCronExecutionSource = {
jobId: string;
jobConfigRevision: string;
};
type ExecApprovalRequestPayload = {
command: string;
commandPreview?: string | null;
commandArgv?: string[];
envKeys?: string[];
systemRunBinding?: SystemRunApprovalBinding | null;
systemRunPlan?: SystemRunApprovalPlan | null;
cwd?: string | null;
nodeId?: string | null;
host?: string | null;
security?: string | null;
ask?: string | null;
warningText?: string | null;
/** Owner-declared blast-radius facts; display-only, never authorization. */
scope?: ApprovalScope | null;
commandAnalysis?: CommandExplanationSummary | null;
commandSpans?: ExecApprovalCommandSpan[];
unavailableDecisions?: readonly ExecApprovalUnavailableDecision[];
allowedDecisions?: readonly ExecApprovalDecision[];
agentId?: string | null;
resolvedPath?: string | null;
sessionKey?: string | null;
sessionId?: string | null;
runId?: string | null;
toolCallId?: string | null;
turnSourceChannel?: string | null;
turnSourceTo?: string | null;
turnSourceAccountId?: string | null;
turnSourceThreadId?: string | number | null;
/** Gateway-recorded cron source; never taken from client request params. */
cronExecutionSource?: ExecApprovalCronExecutionSource | null;
/** Exact operation binding prepared at creation for standing-grant minting. */
cronOperationBinding?: string | null;
};
type ExecApprovalRequest = {
/** Descriptive wire metadata; readers derive it from the payload when absent. */
approvalKind?: "exec";
id: string;
request: ExecApprovalRequestPayload;
createdAtMs: number;
expiresAtMs: number;
};
type ExecApprovalResolved = {
id: string;
decision: ExecApprovalDecision;
resolvedBy?: string | null;
ts: number;
request?: ExecApprovalRequest["request"];
};
//#endregion
//#region src/infra/sqlite-wal.d.ts
type SqliteWalCheckpointMode = "PASSIVE" | "FULL" | "RESTART" | "TRUNCATE";
type SqliteWalMaintenance = {
checkpoint: () => boolean;
close: (options?: {
checkpointMode?: SqliteWalCheckpointMode;
}) => boolean;
};
//#endregion
//#region src/state/openclaw-state-db-contract.d.ts
/** Open shared SQLite database handle plus WAL maintenance lifecycle. */
type OpenClawStateDatabase = {
db: DatabaseSync;
path: string;
walMaintenance: SqliteWalMaintenance;
};
/** Options for resolving or overriding the shared state database path. */
type OpenClawStateDatabaseOptions = {
env?: NodeJS.ProcessEnv;
path?: string;
database?: OpenClawStateDatabase;
readOnly?: boolean;
};
//#endregion
//#region src/infra/plugin-approvals.d.ts
/** Button/action metadata shown with a plugin approval request. */
type PluginApprovalActionView = {
kind?: "command" | "decision";
label: string;
command: string;
decision?: ExecApprovalDecision;
style?: "primary" | "secondary" | "success" | "danger";
};
/** Gateway-minted placement identity; plugin and RPC callers never supply this authority. */
type PluginApprovalPlacementGrantBinding = {
pluginId: string;
command: string;
approvalScope: string;
agentId: string;
sessionKey: string;
sessionId: string;
nodeId: string;
pairingGeneration: string;
environmentId: string;
ownerEpoch: number;
placementGeneration: number;
cwd: string;
};
/** Request payload supplied by plugin approval callers. */
type PluginApprovalRequestPayload = {
pluginId?: string | null;
title: string;
description: string;
detail?: string | null;
severity?: "info" | "warning" | "critical" | null;
/** Owner-declared blast-radius facts; display-only, never authorization. */
scope?: ApprovalScope | null;
toolName?: string | null;
toolCallId?: string | null;
/** Exact MCP persistence intent; the host separately binds live tool-call proof. */
mcpTool?: {
server: string;
tool: string;
};
allowedDecisions?: readonly ExecApprovalDecision[] | null;
/** Trusted in-process metadata; public Gateway callers cannot submit this field. */
externalResolution?: {
label: string;
decisions?: readonly ("allow-once" | "allow-always")[];
} | null;
actions?: readonly PluginApprovalActionView[] | null;
agentId?: string | null;
sessionKey?: string | null;
/** Host-derived source run; never accepted from plugin approval RPC params. */
runId?: string | null;
/** Host-derived grant binding; never accepted from plugin approval RPC params. */
placementGrant?: PluginApprovalPlacementGrantBinding | null;
turnSourceChannel?: string | null;
turnSourceTo?: string | null;
turnSourceAccountId?: string | null;
turnSourceThreadId?: string | number | null;
};
/** Timed plugin approval request persisted while awaiting a decision. */
type PluginApprovalRequest$1 = {
/** Descriptive wire metadata; readers derive it from the payload when absent. */
approvalKind?: "plugin";
id: string;
request: PluginApprovalRequestPayload;
createdAtMs: number;
expiresAtMs: number;
};
/** Resolved plugin approval decision plus optional request snapshot. */
type PluginApprovalResolved = {
id: string;
decision: ExecApprovalDecision;
resolvedBy?: string | null;
ts: number;
request?: PluginApprovalRequestPayload;
};
//#endregion
//#region src/infra/system-agent-approvals.d.ts
type SystemAgentApprovalRequestPayload = {
title: string;
description: string;
command: string;
proposalHash: string;
allowedDecisions: readonly ExecApprovalDecision[];
agentId?: string | null;
sessionKey?: string | null;
sessionId: string;
runId?: string | null;
turnSourceChannel?: string | null;
turnSourceTo?: string | null;
turnSourceAccountId?: string | null;
turnSourceThreadId?: string | number | null;
};
type SystemAgentApprovalRequest = {
approvalKind?: "system-agent";
id: string;
request: SystemAgentApprovalRequestPayload;
createdAtMs: number;
expiresAtMs: number;
};
type SystemAgentApprovalApplicationStatus = "applied" | "not-applied";
type SystemAgentApprovalResolved = {
id: string;
decision: ExecApprovalDecision;
resolvedBy?: string | null;
ts: number;
request?: SystemAgentApprovalRequestPayload;
applicationStatus?: SystemAgentApprovalApplicationStatus;
terminalStatus?: "expired" | "cancelled";
};
//#endregion
//#region src/infra/approval-types.d.ts
type ChannelApprovalKind = "exec" | "plugin" | "system-agent";
/** Backward-compatible request shape accepted from Gateway events and replay. */
type ApprovalRequestInput = ExecApprovalRequest | PluginApprovalRequest$1 | SystemAgentApprovalRequest;
//#endregion
//#region src/interactive/payload.d.ts
type InteractiveButtonStyle = "primary" | "secondary" | "success" | "danger";
/** Visual tone for a portable message presentation. */
type MessagePresentationTone = "info" | "success" | "warning" | "danger" | "neutral";
type QuestionPresentationAction = {
/** Resolve one declared choice. */
type: "question";
questionId: string;
optionValue: string;
} | {
/** Switch this question to its free-text answer path. */
type: "question";
questionId: string;
intent: "custom-input";
};
/** Core-owned model-picker action; channels serialize it only inside private envelopes. */
type ModelPickerAction = ({
type: "model-picker";
version: 1;
snapshotToken: string;
intent: "show-providers";
cursor?: string;
} | {
type: "model-picker";
version: 1;
snapshotToken: string;
intent: "show-models";
providerToken: string;
cursor?: string;
} | {
type: "model-picker";
version: 1;
snapshotToken: string;
intent: "show-recents";
cursor?: string;
} | {
type: "model-picker";
version: 1;
snapshotToken: string;
intent: "choose-model";
providerToken: string;
modelToken: string;
} | {
type: "model-picker";
version: 1;
snapshotToken: string;
intent: "choose-runtime";
providerToken: string;
modelToken: string;
runtimeToken: string;
} | {
type: "model-picker";
version: 1;
snapshotToken: string;
intent: "reset";
} | {
type: "model-picker";
version: 1;
snapshotToken: string;
intent: "cancel";
}) & {
/** Legacy command/callback payload fields are deliberately unavailable on picker actions. */
readonly command?: never;
readonly value?: never;
};
/** Portable typed action behind a button or select option. */
type MessagePresentationAction = {
/** Run a core/plugin slash command through the target channel's native command path. */
type: "command";
command: string;
} | {
/** Opaque callback value interpreted by the target channel/plugin. */
type: "callback";
value: string;
} | ModelPickerAction | {
/** Resolve one durable operator approval without exposing transport callback data. */
type: "approval";
approvalId: string;
approvalKind: ChannelApprovalKind;
decision: "allow-once" | "allow-always" | "deny";
} | QuestionPresentationAction | {
/** Open a normal external link. */
type: "url";
url: string;
} | {
/** Launch a channel-native web app. */
type: "web-app";
/** External web app URL for channels that launch web apps by URL. */
url: string;
/** OpenClaw hosted-widget ID whose launch mechanics are owned by the channel. */
widgetId?: string;
} | {
/** Launch a channel-native web app. */
type: "web-app";
/** External web app URL for channels that launch web apps by URL. */
url?: string;
/** OpenClaw hosted-widget ID whose launch mechanics are owned by the channel. */
widgetId: string;
};
/** Portable action control rendered as a button or link by channel adapters. */
type MessagePresentationButton = {
/** User-visible button label. */
label: string;
/** Typed action sent when the button is pressed. */
action?: MessagePresentationAction;
/**
* Legacy opaque callback value sent when the button is pressed.
* Prefer action for new presentation controls.
* @deprecated Use action.
*/
value?: string;
/** @deprecated Use an action with type "url". */
url?: string;
/** @deprecated Use an action with type "web-app". */
webApp?: {
url: string;
};
/**
* @deprecated Use an action with type "web-app". Accepted for legacy JSON payloads only.
*/
web_app?: {
url: string;
};
/** Higher-priority buttons are kept first when channel limits require truncation. */
priority?: number;
/** Disable the button when the target channel supports disabled controls. */
disabled?: boolean;
/** Keep this action available after a successful interaction when the target channel supports it. */
reusable?: boolean;
/** Optional visual style hint; unsupported channels ignore or normalize it. */
style?: InteractiveButtonStyle;
};
/** Portable select/menu option. */
type MessagePresentationOption = {
/** User-visible option label. */
label: string;
/** Typed action sent when the option is selected. */
action?: Extract<MessagePresentationAction, {
type: "command" | "callback" | "model-picker";
}>;
/** @deprecated Use action. */
value?: string;
};
type LegacyInteractiveReplyOption = MessagePresentationOption;
type LegacyInteractiveReplyTextBlock = {
type: "text";
text: string;
};
type LegacyInteractiveReplySelectBlock = {
type: "select";
placeholder?: string;
options: LegacyInteractiveReplyOption[];
};
type LegacyInteractiveReplyBlock = LegacyInteractiveReplyTextBlock | MessagePresentationButtonsBlock | LegacyInteractiveReplySelectBlock;
type LegacyInteractiveReply = {
blocks: LegacyInteractiveReplyBlock[];
};
/** @deprecated Use MessagePresentation. */
type InteractiveReply = LegacyInteractiveReply;
type MessagePresentationTextBlock = {
type: "text";
/** Primary markdown-ish text rendered in the message body. */
text: string;
};
type MessagePresentationContextBlock = {
type: "context";
/** Lower-emphasis contextual text, or normal text on channels without context support. */
text: string;
};
type MessagePresentationDividerBlock = {
type: "divider";
};
type MessagePresentationButtonsBlock = {
type: "buttons";
/** Button row candidates; core may split or truncate them for channel limits. */
buttons: MessagePresentationButton[];
};
type MessagePresentationSelectBlock = {
type: "select";
/** Optional prompt shown above or inside the select control. */
placeholder?: string;
/** Menu options; core may truncate them for channel limits. */
options: MessagePresentationOption[];
};
type MessagePresentationChartSegment = {
/** Category label shown in the chart legend. */
label: string;
/** Positive segment magnitude. */
value: number;
};
type MessagePresentationChartSeries = {
/** Unique series name shown in the chart legend. */
name: string;
/** One finite value for each chart category, in category order. */
values: number[];
};
type MessagePresentationChartBlock = {
type: "chart";
chartType: "pie";
/** Short chart heading. */
title: string;
segments: MessagePresentationChartSegment[];
} | {
type: "chart";
chartType: "bar" | "area" | "line";
/** Short chart heading. */
title: string;
/** Ordered categories shared by every series. */
categories: string[];
series: MessagePresentationChartSeries[];
xLabel?: string;
yLabel?: string;
};
/** Scalar cell value supported by portable table presentations. */
type MessagePresentationTableCell = string | number;
/** Portable table rendered natively where supported and linearly elsewhere. */
type MessagePresentationTableBlock = {
type: "table";
/** Short table heading used by native renderers and fallback text. */
caption: string;
/** Unique ordered column labels shared by every row. */
headers: string[];
/** Rows whose width exactly matches the header count. */
rows: MessagePresentationTableCell[][];
/** Optional column whose cells should be rendered as row headers. */
rowHeaderColumnIndex?: number;
};
type MessagePresentationBlock = MessagePresentationTextBlock | MessagePresentationContextBlock | MessagePresentationDividerBlock | MessagePresentationButtonsBlock | MessagePresentationSelectBlock | MessagePresentationChartBlock | MessagePresentationTableBlock;
type MessagePresentation = {
/** Optional short heading rendered before blocks when the channel supports it. */
title?: string;
/** Optional severity/status tone for renderers that support toned presentations. */
tone?: MessagePresentationTone;
/** Ordered portable blocks rendered or downgraded by the target channel adapter. */
blocks: MessagePresentationBlock[];
};
type ReplyPayloadDeliveryPin = {
enabled: boolean;
notify?: boolean;
required?: boolean;
};
type ReplyPayloadDelivery = {
pin?: boolean | ReplyPayloadDeliveryPin;
};
//#endregion
//#region src/auto-reply/reply-payload.d.ts
type ReplyMediaAttachment = {
type?: "image" | "audio" | "video" | "file";
path?: string;
url?: string;
mediaUrl?: string;
filePath?: string;
mimeType?: string;
name?: string;
sizeBytes?: number;
durationMs?: number;
width?: number;
height?: number;
/** Internal per-URL trust carried until mixed media is split for history projection. */
trustedLocalMedia?: boolean;
};
/** Channel-agnostic assistant reply payload. */
type ReplyPayload = {
text?: string;
/** Visible body a channel adapter may use when native structured content requires text. */
fallbackText?: {
text: string;
/** Batch payload replaced when the adapter adopts this fallback body. */
replacesPayloadIndex?: number;
};
mediaUrl?: string;
mediaUrls?: string[];
/** Prepared metadata aligned with mediaUrls for client-facing history projection. */
attachments?: ReplyMediaAttachment[];
/** Internal-only trust signal for gateway webchat local media embedding. */
trustedLocalMedia?: boolean;
/** Treat media as live-only content and avoid persisting the underlying media reference. */
sensitiveMedia?: boolean;
/** Channel-agnostic rich presentation. Core degrades or asks the channel renderer to map it. */
presentation?: MessagePresentation;
/** Runtime-authored text is the exact fallback, not additional native presentation content. */
presentationTextMode?: "fallback";
/** Channel-agnostic delivery preferences, e.g. pin the sent message when supported. */
delivery?: ReplyPayloadDelivery;
/**
* @deprecated Use presentation.
*
* Internal legacy representation used by existing approval/reply helpers during migration.
*/
interactive?: InteractiveReply;
btw?: {
question: string;
};
replyToId?: string;
replyToTag?: boolean;
/** True when [[reply_to_current]] was present but not yet mapped to a message id. */
replyToCurrent?: boolean;
/** Send audio as voice message (bubble) instead of audio file. Defaults to false. */
audioAsVoice?: boolean;
/** Send video media as a round video note when the channel supports it. */
videoAsNote?: boolean;
/** Channel-neutral geographic location or named place. */
location?: OutboundLocation;
/**
* Text synthesized into an audio-only TTS payload. Exposed to hooks for
* archival/search use when no visible channel text is sent.
*/
spokenText?: string;
/**
* Marks a TTS media payload as supplemental audio for assistant text that is
* already visible through streaming or transcript projection.
*/
ttsSupplement?: ReplyPayloadTtsSupplement;
isError?: boolean;
/** Marks this payload as a reasoning/thinking block. Channels that do not
* have a dedicated reasoning lane (e.g. WhatsApp, web) should suppress it. */
isReasoning?: boolean;
/** Marks pre-tool commentary (💬) — a display lane, suppressed unless the channel opts in. */
isCommentary?: boolean;
/** Reasoning stream text is a complete replacement snapshot, not a delta. */
isReasoningSnapshot?: boolean;
/** Marks this payload as a compaction status notice (start/end).
* Should be excluded from TTS transcript accumulation so compaction
* status lines are not synthesised into the spoken assistant reply. */
isCompactionNotice?: boolean;
/** Marks this payload as a model-fallback transition/recovery notice. */
isFallbackNotice?: boolean;
/** Marks this payload as transient status, not assistant answer content. */
isStatusNotice?: boolean;
/** Channel-specific payload data (per-channel envelope). */
channelData?: Record<string, unknown>;
};
/** Metadata for audio-only media that supplements already-visible assistant text. */
type ReplyPayloadTtsSupplement = {
spokenText: string;
visibleTextAlreadyDelivered?: boolean;
};
/** Reply policy facts that provider adapters use to resolve the final transport route. */
type ReplyDeliveryContext = {
chatType?: "direct" | "group" | "channel" | null;
replyToMode: ReplyToMode;
};
/** WeakMap-backed metadata attached to payload objects without changing wire shape. */
type SessionWriterDeliveryAuthority = {
agentId?: string;
expectedLifecycleRevision?: string;
expectedSessionId: string;
expectedWriterRunId?: string;
sessionKey: string;
storePath?: string;
};
//#endregion
//#region src/channels/inbound-event/kind.d.ts
/**
* High-level inbound event class used to separate actionable user requests from room activity.
*/
type InboundEventKind = "user_request" | "room_event";
//#endregion
//#region packages/media-understanding-common/src/types.d.ts
/** Kind of media-understanding output produced for an attachment. */
type MediaUnderstandingKind = "audio.transcription" | "video.description" | "image.description";
/** Capability exposed by a media-understanding provider. */
type MediaUnderstandingCapability = "image" | "audio" | "video";
/** Normalized text output produced by media understanding. */
type MediaUnderstandingOutput = {
kind: MediaUnderstandingKind;
attachmentIndex: number;
text: string;
provider: string;
model?: string;
requestedBackend?: string;
observedBackend?: string;
};
//#endregion
//#region src/agents/auth-profiles/credential-schema.d.ts
/** Provider-owned fields retained with OAuth material through storage and refresh. */
declare const oauthCredentialMetadataSchema: z.ZodObject<{
idToken: z.ZodOptional<z.ZodString>;
clientId: z.ZodOptional<z.ZodString>;
enterpriseUrl: z.ZodOptional<z.ZodString>;
projectId: z.ZodOptional<z.ZodString>;
accountId: z.ZodOptional<z.ZodString>;
chatgptPlanType: z.ZodOptional<z.ZodString>;
subscriptionType: z.ZodOptional<z.ZodString>;
rateLimitTier: z.ZodOptional<z.ZodString>;
tokenEndpoint: z.ZodOptional<z.ZodString>;
deviceAuthorizationEndpoint: z.ZodOptional<z.ZodString>;
issuer: z.ZodOptional<z.ZodString>;
authFlow: z.ZodOptional<z.ZodString>;
}, z.core.$strict>;
type OAuthCredentialMetadata = z.infer<typeof oauthCredentialMetadataSchema>;
//#endregion
//#region src/agents/auth-profiles/legacy-oauth-ref.d.ts
/** Legacy OAuth ref source persisted by older credential stores. */
declare const LEGACY_OAUTH_REF_SOURCE = "openclaw-credentials";
/** Legacy OAuth ref provider persisted by older credential stores. */
declare const LEGACY_OAUTH_REF_PROVIDER = "openai-codex";
type LegacyOAuthRef = {
source: typeof LEGACY_OAUTH_REF_SOURCE;
provider: typeof LEGACY_OAUTH_REF_PROVIDER;
id: string;
};
//#endregion
//#region src/agents/auth-profiles/types.d.ts
/** Provider identifier recorded on auth profile credentials. */
type OAuthProvider = string;
/** Refreshable OAuth credential fields persisted for provider auth profiles. */
type OAuthCredentials$1 = OAuthCredentialMetadata & {
access: string;
refresh: string;
expires: number;
provider?: OAuthProvider;
email?: string;
};
/** API-key credential with optional secret reference indirection. */
type ApiKeyCredential$1 = {
type: "api_key";
provider: string;
key?: string;
keyRef?: SecretRef;
/** Explicit opt-out for copying this profile when creating another agent. */
copyToAgents?: boolean;
email?: string;
displayName?: string;
/** Optional provider-specific metadata (e.g., account IDs, gateway IDs). */
metadata?: Record<string, string>;
};
/** Static token credential that OpenClaw does not refresh. */
type TokenCredential$1 = {
/**
* Static bearer-style token (often OAuth access token / PAT).
* Not refreshable by OpenClaw (unlike `type: "oauth"`).
*/
type: "token";
provider: string;
token?: string;
tokenRef?: SecretRef;
/** Explicit opt-out for copying this profile when creating another agent. */
copyToAgents?: boolean;
/** Optional expiry timestamp (ms since epoch). */
expires?: number;
email?: string;
displayName?: string;
};
/** Refreshable OAuth credential plus provider metadata and legacy references. */
type OAuthCredential$1 = OAuthCredentials$1 & {
type: "oauth";
provider: string;
oauthRef?: LegacyOAuthRef;
/**
* OAuth refresh tokens are not portable by default. Provider-owned flows may
* set this only when copying refresh material across agents is known safe.
*/
copyToAgents?: boolean;
email?: string;
displayName?: string;
};
/** Credential variants supported by auth profiles. */
type AuthProfileCredential = ApiKeyCredential$1 | TokenCredential$1 | OAuthCredential$1;
/** Closed reasons that drive cooldown, disable, and failure counters. */
type AuthProfileFailureReason = "auth" | "auth_permanent" | "format" | "overloaded" | "rate_limit" | "billing" | "timeout" | "model_not_found" | "session_expired" | "empty_response" | "no_error_details" | "unclassified" | "unknown";
/** Optional host diagnostic attached to a canonical cooldown reason. */
type AuthProfileCooldownClassification = "wham_token_expired" | "wham_account_dead";
/** Profile-wide blocked reason reported by provider usage probes. */
type AuthProfileBlockedReason = "subscription_limit";
/** Source that marked a profile as blocked. */
type AuthProfileBlockedSource = "codex_rate_limits" | "wham";
/** Per-profile usage statistics for round-robin and cooldown tracking */
type ProfileUsageStats = {
lastUsed?: number;
blockedUntil?: number;
blockedReason?: AuthProfileBlockedReason;
blockedSource?: AuthProfileBlockedSource;
blockedModel?: string;
blockedScope?: "model";
cooldownUntil?: number;
cooldownReason?: AuthProfileFailureReason;
cooldownClassification?: AuthProfileCooldownClassification;
cooldownModel?: string;
disabledUntil?: number;
disabledReason?: AuthProfileFailureReason;
errorCount?: number;
failureCounts?: Partial<Record<AuthProfileFailureReason, number>>;
lastFailureAt?: number;
lastProbeAt?: number;
};
/** Durable, non-secret auth profile selection state. */
type AuthProfileState = {
/**
* Optional per-agent preferred profile order overrides.
* This lets you lock/override auth rotation for a specific agent without
* changing the global config.
*/
order?: Record<string, string[]>;
lastGood?: Record<string, string>;
/** Usage statistics per profile for round-robin rotation */
usageStats?: Record<string, ProfileUsageStats>;
};
/** Persisted credential payload without runtime-only selection state. */
type AuthProfileSecretsStore = {
version: number;
profiles: Record<string, AuthProfileCredential>;
};
/** Effective in-memory auth store combining credentials, state, and overlays. */
type AuthProfileStore = AuthProfileSecretsStore & AuthProfileState & {
/** Runtime-only provenance for credentials cloned from persisted auth stores. */
runtimePersistedProfileIds?: string[];
/** Runtime-only provenance for external OAuth profiles overlaid onto this store. */
runtimeExternalProfileIds?: string[];
/** True when the runtime external profile set was freshly resolved, even if empty. */
runtimeExternalProfileIdsAuthoritative?: boolean;
};
//#endregion
//#region src/media-understanding/types.d.ts
/** Agent-owned runtime handle carried opaquely through media provider requests. */
type MediaPreparedModelRuntime = Readonly<{
agentDir: string;
workspaceDir?: string;
config: OpenClawConfig;
createStores: () => unknown;
}>;
type MediaUnderstandingDecisionOutcome = "success" | "failed" | "skipped" | "disabled" | "no-attachment" | "scope-deny";
type MediaUnderstandingModelDecision = {
provider?: string;
model?: string;
requestedBackend?: string;
observedBackend?: string;
type: "provider" | "cli";
outcome: "success" | "skipped" | "failed";
reason?: string;
};
type MediaUnderstandingAttachmentDecision = {
attachmentIndex: number;
attempts: MediaUnderstandingModelDecision[];
chosen?: MediaUnderstandingModelDecision;
};
type MediaAttachmentDisposition = {
kind: "handled";
} | {
kind: "handed-to-native-vision";
} | {
kind: "not-selected";
} | {
kind: "capability-disabled";
} | {
kind: "no-model";
} | {
kind: "scope-denied";
} | {
kind: "failed";
reason?: string;
};
type MediaUnderstandingDecision = {
capability: MediaUnderstandingCapability;
outcome: MediaUnderstandingDecisionOutcome;
attachments: MediaUnderstandingAttachmentDecision[];
attachmentDispositions?: Record<number, MediaAttachmentDisposition>;
nativeVisionActive?: boolean;
};
type MediaUnderstandingProviderRequestAuthOverride = {
mode: "provider-default";
} | {
mode: "authorization-bearer";
token: string;
} | {
mode: "header";
headerName: string;
value: string;
prefix?: string;
};
type MediaUnderstandingProviderRequestTlsOverride = {
ca?: string;
cert?: string;
key?: string;
passphrase?: string;
serverName?: string;
insecureSkipVerify?: boolean;
};
type MediaUnderstandingProviderRequestProxyOverride = {
mode: "env-proxy";
tls?: MediaUnderstandingProviderRequestTlsOverride;
} | {
mode: "explicit-proxy";
url: string;
tls?: MediaUnderstandingProviderRequestTlsOverride;
};
type MediaUnderstandingProviderRequestTransportOverrides = {
headers?: Record<string, string>;
auth?: MediaUnderstandingProviderRequestAuthOverride;
proxy?: MediaUnderstandingProviderRequestProxyOverride;
tls?: MediaUnderstandingProviderRequestTlsOverride;
/** Runtime-only flag from trusted model-provider config; media config rejects it. */
allowPrivateNetwork?: boolean;
};
type MediaUnderstandingProviderRequestAuth = {
kind: "api-key";
apiKey: string;
source?: string;
} | {
kind: "none";
source: string;
};
type AudioTranscriptionRequest = {
buffer: Buffer;
fileName: string;
mime?: string;
/** Compatibility field for existing providers; prefer auth.kind/apiKey. */
apiKey: string;
auth?: MediaUnderstandingProviderRequestAuth;
baseUrl?: string;
headers?: Record<string, string>;
request?: MediaUnderstandingProviderRequestTransportOverrides;
model?: string;
language?: string;
prompt?: string;
query?: Record<string, string | number | boolean>;
timeoutMs: number;
signal?: AbortSignal;
fetchFn?: typeof fetch;
};
type AudioTranscriptionResult = {
text: string;
model?: string;
};
type AudioTranscriptionContext = Omit<AudioTranscriptionRequest, "apiKey" | "auth"> & {
cfg: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
profile?: string;
preferredProfile?: string;
};
type VideoDescriptionRequest = {
buffer: Buffer;
fileName: string;
mime?: string;
/** Compatibility field for existing providers; prefer auth.kind/apiKey. */
apiKey: string;
auth?: MediaUnderstandingProviderRequestAuth;
baseUrl?: string;
headers?: Record<string, string>;
request?: MediaUnderstandingProviderRequestTransportOverrides;
model?: string;
prompt?: string;
timeoutMs: number;
signal?: AbortSignal;
fetchFn?: typeof fetch;
};
type VideoDescriptionResult = {
text: string;
model?: string;
};
type ImageDescriptionRequest = {
buffer: Buffer;
fileName: string;
mime?: string;
prompt?: string;
maxTokens?: number;
timeoutMs: number;
signal?: AbortSignal;
profile?: string;
preferredProfile?: string;
authStore?: AuthProfileStore;
agentId?: string;
agentDir: string;
workspaceDir?: string;
preparedModelRuntime?: MediaPreparedModelRuntime;
cfg: OpenClawConfig;
model: string;
provider: string;
};
type ImagesDescriptionInput = {
buffer: Buffer;
fileName: string;
mime?: string;
};
type ImagesDescriptionRequest = {
images: ImagesDescriptionInput[];
model: string;
provider: string;
prompt?: string;
maxTokens?: number;
timeoutMs: number;
signal?: AbortSignal;
profile?: string;
preferredProfile?: string;
authStore?: AuthProfileStore;
agentId?: string;
agentDir: string;
workspaceDir?: string;
preparedModelRuntime?: MediaPreparedModelRuntime;
cfg: OpenClawConfig;
};
type ImageDescriptionResult = {
text: string;
model?: string;
};
type ImagesDescriptionResult = {
text: string;
model?: string;
};
type StructuredExtractionTextInput = {
type: "text";
text: string;
};
type StructuredExtractionImageInput = {
type: "image";
buffer: Buffer;
fileName: string;
mime?: string;
};
type StructuredExtractionInput = StructuredExtractionTextInput | StructuredExtractionImageInput;
type StructuredExtractionRequest = {
/** Image-first extraction input; callers must include at least one image. */
input: StructuredExtractionInput[];
instructions: string;
schemaName?: string;
jsonSchema?: unknown;
jsonMode?: boolean;
timeoutMs: number;
signal?: AbortSignal;
profile?: string;
preferredProfile?: string;
authStore?: AuthProfileStore;
agentDir: string;
cfg: OpenClawConfig;
model: string;
provider: string;
};
type StructuredExtractionResult = {
text: string;
parsed?: unknown;
model?: string;
provider?: string;
contentType?: "json" | "text";
};
type MediaUnderstandingDocumentModelDefaults = {
textExtraction?: string;
image?: string | false;
};
type MediaUnderstandingProviderAuthContext = {
config?: OpenClawConfig;
provider: string;
providerConfig?: ModelProviderConfig;
};
type MediaUnderstandingProviderAuthResult = {
kind: "none";
source: string;
} | {
kind: "api-key";
apiKey: string;
source: string;
mode?: "api-key";
};
type MediaUnderstandingProviderSyntheticAuthResult = {
apiKey: string;
source: string;
mode: "api-key";
};
type MediaUnderstandingProvider = {
id: string;
capabilities?: MediaUnderstandingCapability[];
defaultModels?: Partial<Record<MediaUnderstandingCapability, string>>;
autoPriority?: Partial<Record<MediaUnderstandingCapability, number>>;
nativeDocumentInputs?: Array<"pdf">;
documentModels?: Partial<Record<"pdf", MediaUnderstandingDocumentModelDefaults>>;
resolveAuth?: (ctx: MediaUnderstandingProviderAuthContext) => MediaUnderstandingProviderAuthResult | null | undefined;
/** @deprecated Use resolveAuth. */
resolveSyntheticAuth?: (ctx: MediaUnderstandingProviderAuthContext) => MediaUnderstandingProviderSyntheticAuthResult | null | undefined;
transcribeAudio?: (req: AudioTranscriptionRequest) => Promise<AudioTranscriptionResult>;
/** Called after file loading. Result.error is only a rejection before audio upload;
* upload/HTTP failures must throw and stop automatic provider selection. */
transcribeAudioWithContext?: (req: AudioTranscriptionContext) => Promise<Result<AudioTranscriptionResult, unknown>>;
describeVideo?: (req: VideoDescriptionRequest) => Promise<VideoDescriptionResult>;
describeImage?: (req: ImageDescriptionRequest) => Promise<ImageDescriptionResult>;
describeImages?: (req: ImagesDescriptionRequest) => Promise<ImagesDescriptionResult>;
extractStructured?: (req: StructuredExtractionRequest) => Promise<StructuredExtractionResult>;
};
//#endregion
//#region packages/media-core/src/constants.d.ts
/** Canonical media families used by attachment facts, routing, and MIME classification. */
type MediaKind = "image" | "audio" | "video" | "document" | "sticker" | "unknown";
/** Maps a MIME type to the media family used for size limits and routing. */
declare function mediaKindFromMime(mime?: string | null): MediaKind | undefined;
//#endregion
//#region src/media/prompt-image-order.d.ts
/** Tracks whether prompt images stayed inline or were offloaded while preserving model order. */
type PromptImageOrderEntry = "inline" | "offloaded";
//#endregion
//#region src/media/media-facts.d.ts
/** One ordered runtime attachment; array position is its alignment identity. */
type MediaFact = {
path?: string;
url?: string;
contentType?: string;
kind?: MediaKind;
fileName?: string;
sizeBytes?: number;
durationMs?: number;
width?: number;
height?: number;
transcribed?: boolean;
messageId?: string;
workspaceDir?: string;
/** Internal proof that this exact fact was covered by a legacy staged projection. */
staged?: boolean;
hydrationSuppressed?: boolean;
};
type MediaFactInput = { [Key in keyof MediaFact]?: MediaFact[Key] | null; };
declare const LEGACY_MEDIA_CONTEXT_KEYS: readonly ["MediaPath", "MediaPaths", "MediaUrl", "MediaUrls", "MediaType", "MediaTypes", "MediaDir", "MediaTranscribedIndexes", "MediaStaged", "MediaWorkspaceDir"];
type LegacyMediaContextKey = (typeof LEGACY_MEDIA_CONTEXT_KEYS)[number];
//#endregion
//#region src/plugins/hook-channel-context.types.d.ts
interface PluginHookChannelSenderContext {
/** Channel-scoped sender ID, matching `ctx.senderId` when both are present. */
id?: string;
[key: string]: unknown;
}
interface PluginHookChannelChatContext {
/** Transport-native conversation ID, matching `ctx.chatId` when both are present. */
id?: string;
[key: string]: unknown;
}
interface PluginHookChannelContext {
/** Sender metadata supplied by the originating channel. */
sender?: PluginHookChannelSenderContext;
/** Chat/conversation metadata supplied by the originating channel. */
chat?: PluginHookChannelChatContext;
}
//#endregion
//#region src/sessions/input-provenance.d.ts
declare const INPUT_PROVENANCE_KIND_VALUES: readonly ["external_user", "inter_session", "internal_system"];
type InputProvenanceKind = (typeof INPUT_PROVENANCE_KIND_VALUES)[number];
type InputProvenance = {
kind: InputProvenanceKind;
originSessionId?: string;
sourceSessionKey?: string;
sourceChannel?: string;
sourceTool?: string;
};
//#endregion
//#region src/auto-reply/command-turn-context.d.ts
type CommandTurnKind = "native" | "text-slash" | "normal";
type BaseCommandTurnContext = {
commandName?: string;
body?: string;
};
type NativeCommandTurnContext = BaseCommandTurnContext & {
kind: "native";
source: "native";
authorized: boolean;
};
type TextSlashCommandTurnContext = BaseCommandTurnContext & {
kind: "text-slash";
source: "text";
authorized: boolean;
};
type NormalCommandTurnContext = BaseCommandTurnContext & {
kind: "normal";
source: "message";
authorized: false;
};
type CommandTurnContext = NativeCommandTurnContext | TextSlashCommandTurnContext | NormalCommandTurnContext;
//#endregion
//#region src/auto-reply/commands-args.types.d.ts
/** Primitive values accepted by parsed auto-reply command args. */
type CommandArgValue = string | number | boolean | bigint;
/** Named parsed auto-reply command values. */
type CommandArgValues = Record<string, CommandArgValue>;
/** Parsed command argument bundle with raw source and structured values. */
type CommandArgs = {
raw?: string;
values?: CommandArgValues;
};
//#endregion
//#region src/auto-reply/reply/history.types.d.ts
/** Normalized history message used when building reply context. */
type HistoryEntry = {
sender: string;
body: string;
timestamp?: number;
messageId?: string;
media?: HistoryMediaEntry[];
};
/** Media metadata attached to a normalized history message. */
type HistoryMediaEntry = Pick<MediaFact, "contentType" | "durationMs" | "height" | "kind" | "messageId" | "path" | "url" | "width">;
//#endregion
//#region src/agents/run-timeout-attribution.d.ts
/** Agent run phases used when attributing timeout/cancellation sources. */
declare const AGENT_RUN_TIMEOUT_PHASES: readonly ["queue", "preflight", "provider", "post_turn", "gateway_draining"];
/** Timeout attribution phase for agent run lifecycle spans. */
type AgentRunTimeoutPhase = (typeof AGENT_RUN_TIMEOUT_PHASES)[number];
//#endregion
//#region src/agents/agent-run-terminal-outcome.types.d.ts
/** Wait status reported by agent run terminal wait paths. */
type AgentRunWaitStatus = "ok" | "error" | "timeout";
/** Normalized terminal reason for an agent run. */
type AgentRunTerminalReason = "completed" | "hard_timeout" | "timed_out" | "superseded" | "cancelled" | "aborted" | "blocked" | "abandoned" | "failed";
/** Normalized terminal outcome for an agent run. */
type AgentRunTerminalOutcome = {
reason: AgentRunTerminalReason;
status: AgentRunWaitStatus;
error?: string;
stopReason?: string;
livenessState?: string;
timeoutPhase?: AgentRunTimeoutPhase;
providerStarted?: boolean;
startedAt?: number;
endedAt?: number;
};
//#endregion
//#region src/agents/agent-run-terminal-outcome.d.ts
type AgentRunAttemptFailureSource = "prompt" | "compaction" | "precheck" | "hook:before_agent_run";
type AgentRunAttemptFailure = {
source: AgentRunAttemptFailureSource;
error: unknown;
};
type AgentRunAttemptTimeoutObservation = "compaction" | "tool_execution";
type AgentRunAttemptTimeoutSource = "runtime" | "run_budget" | "idle" | "external";
type AgentRunAttemptTerminal = {
kind: "ok";
} | {
kind: "aborted";
source: "runtime" | "external" | "yield_cleanup";
failure?: AgentRunAttemptFailure;
timeoutObservation?: AgentRunAttemptTimeoutObservation;
} | {
kind: "timeout";
/** Non-terminal observations preserve timeout detail without interrupting the attempt. */
phase: AgentRunAttemptTimeoutObservation;
source: "observation";
failure?: AgentRunAttemptFailure;
} | {
kind: "timeout";
phase: "prompt" | AgentRunAttemptTimeoutObservation;
source: AgentRunAttemptTimeoutSource;
/** Present only when timeout handling also aborted the live harness run. */
aborted?: true;
failure?: AgentRunAttemptFailure;
} | {
kind: "failed";
source: AgentRunAttemptFailureSource;
error: unknown;
timeoutObservation?: AgentRunAttemptTimeoutObservation;
};
//#endregion
//#region src/audit/execution-identity-admission.d.ts
declare const ExecutionIdentityAdmissionEnvelopeSchema: Type.TObject<{
envelopeVersion: Type.TLiteral<1>;
contextId: Type.TString;
executionId: Type.TString;
runId: Type.TString;
createdAt: Type.TInteger;
runtimeInstanceId: Type.TString;
agentId: Type.TString;
ingress: Type.TObject<{
kind: Type.TUnion<[Type.TLiteral<"local-cli">, Type.TLiteral<"gateway-client">, Type.TLiteral<"channel">, Type.TLiteral<"api">, Type.TLiteral<"schedule">, Type.TLiteral<"webhook">, Type.TLiteral<"task">, Type.TLiteral<"subagent">, Type.TLiteral<"acp">, Type.TLiteral<"worker">, Type.TLiteral<"plugin">, Type.TLiteral<"recovery">, Type.TLiteral<"system">]>;
boundary: Type.TString;
state: Type.TUnion<[Type.TLiteral<"present">, Type.TLiteral<"absent">, Type.TLiteral<"unknown">, Type.TLiteral<"unsupported">]>;
rawSourceRef: Type.TOptional<Type.TString>;
}>;
runtime: Type.TObject<{
kind: Type.TUnion<[Type.TLiteral<"gateway">, Type.TLiteral<"embedded">, Type.TLiteral<"worker">, Type.TLiteral<"plugin-harness">, Type.TLiteral<"acp">]>;
}>;
invoker: Type.TOptional<Type.TUnion<[Type.TObject<{
state: Type.TLiteral<"present">;
kind: Type.TUnion<[Type.TLiteral<"person">, Type.TLiteral<"agent">, Type.TLiteral<"service">, Type.TLiteral<"schedule">, Type.TLiteral<"webhook">, Type.TLiteral<"system">, Type.TLiteral<"local-account">, Type.TLiteral<"runtime">]>;
rawPrincipalRef: Type.TString;
displayLabel: Type.TOptional<Type.TString>;
}>, Type.TObject<{
state: Type.TLiteral<"unknown">;
}>]>>;
applicableGrants: Type.TArray<Type.TObject<{
rawGrantRef: Type.TString;
state: Type.TUnion<[Type.TLiteral<"present">, Type.TLiteral<"absent">, Type.TLiteral<"unknown">, Type.TLiteral<"unsupported">]>;
}>>;
assurance: Type.TArray<Type.TObject<{
kind: Type.TUnion<[Type.TLiteral<"durable-profile">, Type.TLiteral<"trusted-proxy">, Type.TLiteral<"tailscale-whois">, Type.TLiteral<"device-proof">, Type.TLiteral<"channel-admission">, Type.TLiteral<"local-process">, Type.TLiteral<"spawn-lineage">, Type.TLiteral<"worker-admission">, Type.TLiteral<"runtime-binding">, Type.TLiteral<"other">]>;
rawEvidenceRef: Type.TString;
strength: Type.TUnion<[Type.TLiteral<"self-asserted">, Type.TLiteral<"boundary-verified">, Type.TLiteral<"cryptographic">]>;
}>>;
}>;
declare const ExecutionIdentityAdmissionTokenSchema: Type.TObject<{
tokenVersion: Type.TLiteral<1>;
contextId: Type.TString;
executionId: Type.TString;
runId: Type.TString;
createdAt: Type.TInteger;
}>;
type ExecutionIdentityAdmissionEnvelope = Static<typeof ExecutionIdentityAdmissionEnvelopeSchema>;
type ExecutionIdentityAdmissionFacts = Omit<ExecutionIdentityAdmissionEnvelope, "envelopeVersion" | "contextId" | "executionId" | "createdAt" | "runtimeInstanceId" | "ingress" | "applicableGrants" | "assurance"> & {
ingress: Omit<ExecutionIdentityAdmissionEnvelope["ingress"], "state"> & {
state?: ExecutionIdentityAdmissionEnvelope["ingress"]["state"];
};
applicableGrants?: ExecutionIdentityAdmissionEnvelope["applicableGrants"];
assurance?: ExecutionIdentityAdmissionEnvelope["assurance"];
};
type ExecutionIdentityAdmissionToken = Static<typeof ExecutionIdentityAdmissionTokenSchema>;
//#endregion
//#region src/channels/streaming.d.ts
type AgentPlanStepStatus = "pending" | "in_progress" | "completed";
type AgentPlanStep = {
step: string;
status: AgentPlanStepStatus;
};
//#endregion
//#region src/config/sessions/transcript-entry-anchor.d.ts
/** Immutable transcript identity issued by the SQLite append transaction. */
type TranscriptEntryAnchor = Readonly<{
agentId: string;
sessionId: string;
sessionKey: string;
storePath: string;
generation: string;
entryId: string;
rawSeq: number;
effectiveParentId: string | null;
activeMessagePosition: number;
idempotencyKey?: string;
}>;
/** Current user row bound to one recorder-owned logical turn. */
type TranscriptTurnAdmission = TranscriptEntryAnchor & Readonly<{
logicalTurnId: string;
role: "user";
}>;
/** Exact accepted transcript range, inclusive of admission and terminal. */
type TranscriptTurnBoundary = Readonly<{
admission: TranscriptTurnAdmission;
terminal: TranscriptEntryAnchor;
}>;
//#endregion
//#region src/chat/sender-identity.d.ts
type TranscriptSenderIdentity = Extract<SessionParticipantIdentity, {
type: "profile" | "remote" | "observation";
}>;
//#endregion
//#region src/config/sessions/goals-operations.types.d.ts
type SessionGoalOperationResult = Omit<SessionsGoalMutationResult, "replayed">;
type SessionTranscriptTurnMutationResult = {
result: SessionGoalOperationResult;
replayed: boolean;
};
//#endregion
//#region src/config/sessions/session-transcript-turn-lifecycle.types.d.ts
/** Authoritative lifecycle snapshot required for an atomic transcript admission. */
type SessionTranscriptTurnExpectedState = {
/** Rejects a run-owned turn after another admitted run takes writer ownership. */
expectedWriterRunId?: string;
abortedLastRun: boolean | undefined;
/** Fences recovery-only transcript writes against concurrent ownership changes. */
mainRestartRecoveryCycleId: string | undefined;
mainRestartRecoveryRevision: number | undefined;
restartRecoveryBeforeAgentReplyState: SessionRestartRecoveryState["restartRecoveryBeforeAgentReplyState"];
restartRecoveryDeliveryReceiptState: SessionRestartRecoveryState["restartRecoveryDeliveryReceiptState"];
restartRecoveryDeliveryToolCallId: SessionRestartRecoveryState["restartRecoveryDeliveryToolCallId"];
restartRecoveryDeliveryRequestFingerprint: SessionRestartRecoveryState["restartRecoveryDeliveryRequestFingerprint"];
restartRecoveryDeliveryRunId: SessionRestartRecoveryState["restartRecoveryDeliveryRunId"];
restartRecoveryDeliverySourceRunId: SessionRestartRecoveryState["restartRecoveryDeliverySourceRunId"];
restartRecoveryRequesterAccountId: SessionRestartRecoveryState["restartRecoveryRequesterAccountId"];
restartRecoveryRequesterSenderId: SessionRestartRecoveryState["restartRecoveryRequesterSenderId"];
restartRecoverySameChannelThreadRequired: SessionRestartRecoveryState["restartRecoverySameChannelThreadRequired"];
restartRecoverySourceIngress: SessionRestartRecoveryState["restartRecoverySourceIngress"];
restartRecoverySourceReplyDeliveryMode: SessionRestartRecoveryState["restartRecoverySourceReplyDeliveryMode"];
restartRecoveryTerminalRunIds: SessionRestartRecoveryState["restartRecoveryTerminalRunIds"];
status: SessionRunStatus | undefined;
};
/** Lifecycle fields committed with an accepted transcript turn. */
type SessionTranscriptTurnLifecyclePatch = {
abortedLastRun?: boolean;
endedAt?: number;
lifecycleRunId?: InternalSessionEntry["lifecycleRunId"];
lastRunId?: InternalSessionEntry["lastRunId"];
lastRunError?: InternalSessionEntry["lastRunError"];
pendingFinalDelivery?: InternalSessionEntry["pendingFinalDelivery"];
mainRestartRecovery?: InternalSessionEntry["mainRestartRecovery"];
restartRecoveryBeforeAgentReplyState?: SessionRestartRecoveryState["restartRecoveryBeforeAgentReplyState"];
restartRecoveryDeliveryReceiptState?: SessionRestartRecoveryState["restartRecoveryDeliveryReceiptState"];
restartRecoveryDeliveryToolCallId?: SessionRestartRecoveryState["restartRecoveryDeliveryToolCallId"];
restartRecoveryDeliveryContext?: SessionRestartRecoveryState["restartRecoveryDeliveryContext"];
restartRecoveryDeliveryRequestFingerprint?: SessionRestartRecoveryState["restartRecoveryDeliveryRequestFingerprint"];
restartRecoveryDeliveryRunId?: SessionRestartRecoveryState["restartRecoveryDeliveryRunId"];
restartRecoveryDeliverySourceRunId?: SessionRestartRecoveryState["restartRecoveryDeliverySourceRunId"];
restartRecoveryRequesterAccountId?: SessionRestartRecoveryState["restartRecoveryRequesterAccountId"];
restartRecoveryRequesterSenderId?: SessionRestartRecoveryState["restartRecoveryRequesterSenderId"];
restartRecoverySameChannelThreadRequired?: SessionRestartRecoveryState["restartRecoverySameChannelThreadRequired"];
restartRecoverySourceIngress?: SessionRestartRecoveryState["restartRecoverySourceIngress"];
restartRecoverySourceReplyDeliveryMode?: SessionRestartRecoveryState["restartRecoverySourceReplyDeliveryMode"];
restartRecoveryForceSafeTools?: InternalSessionEntry["restartRecoveryForceSafeTools"];
restartRecoveryRuns?: InternalSessionEntry["restartRecoveryRuns"];
/** Durable tombstones merged with the fresh row inside the SQLite write transaction. */
restartRecoveryTerminalRunIds?: SessionRestartRecoveryState["restartRecoveryTerminalRunIds"];
runtimeMs?: number;
startedAt?: number;
status?: SessionRunStatus;
updatedAt?: number;
};
//#endregion
//#region src/sessions/user-turn-transcript.types.d.ts
type UserTurnSessionEntry = SessionEntry$1;
type PersistedUserTurnMediaInput = Pick<MediaFactInput, "contentType" | "durationMs" | "fileName" | "height" | "hydrationSuppressed" | "messageId" | "path" | "sizeBytes" | "transcribed" | "url" | "width"> & {
kind?: string | null;
workspaceDir?: string | null;
};
type PersistedUserTurnMessage = Extract<AgentMessage, {
role: "user";
}> & {
display?: false;
excludeFromContext?: true;
/** Private transcript correlation; never authorizes an execution. */
idempotencyKey?: string;
provenance?: InputProvenance;
__openclaw?: Record<string, unknown> & {
humanMentions?: readonly HumanMention[];
};
};
type UserTurnInput = Pick<PersistedUserTurnMessage, "display" | "excludeFromContext"> & {
text?: string | null;
/** Explicit human selections bound to UTF-16 offsets in text. */
mentions?: readonly HumanMention[];
media?: readonly PersistedUserTurnMediaInput[] | null;
/** Restart-safe native image placement; model-visible prompt bytes remain separate. */
mediaImageLayout?: {
slots: readonly {
kind: "inline" | "offloaded";
factIndex?: number;
}[];
suppressedFactIndexes?: readonly number[];
} | null;
timestamp?: number;
idempotencyKey?: string;
/** Durable transcript message reference used to render and hydrate replies. */
replyToId?: string;
/** Bounded display fallback for replies whose target is outside loaded history. */
replyToPreview?: {
text: string;
senderLabel?: string | null;
} | null;
senderIsOwner?: boolean;
provenance?: InputProvenance;
/** Identity is producer-owned attribution; labels remain editable display metadata. */
sender?: {
id?: string | null;
name?: string | null;
username?: string | null;
identity?: TranscriptSenderIdentity;
} | null;
/** Durable transport correlation; stored privately and never rendered into model input. */
transport?: {
channel?: string;
conversationRef?: string;
messageId?: string;
replyToId?: string;
threadId?: string;
};
};
type UserTurnTranscriptUpdateMode = "inline" | "none";
type UserTurnBeforeMessageWrite = (params: {
message: PersistedUserTurnMessage;
agentId?: string;
sessionKey?: string;
}) => AgentMessage | null;
type UserTurnTranscriptPersistenceTarget = {
sessionId: string;
expectedSessionId?: string;
initialSessionEntry?: SessionEntry$1;
sessionKey: string;
sessionEntry: UserTurnSessionEntry | undefined;
sessionStore?: Record<string, UserTurnSessionEntry>;
storePath?: string;
agentId: string;
threadId?: string | number;
cwd?: string;
config?: unknown;
beforeMessageWrite?: UserTurnBeforeMessageWrite;
};
type UserTurnTranscriptTarget = UserTurnTranscriptPersistenceTarget;
type UserTurnTranscriptAdmissionReceipt = TranscriptTurnAdmission;
/** Native producer facts for the current host-admitted prompt; never a message replacement. */
type UserTurnTranscriptAnnotation = Readonly<{
mirrorIdentity: string;
upstreamUserText: string;
mirrorOrigin: string;
mirrorSourceFingerprint: string;
}>;
type UserTurnTranscriptPersistResult = {
sessionTurnMutationResult?: SessionTranscriptTurnMutationResult;
/** True only when this call inserted the transcript message. */
appended?: boolean;
sessionFile: string;
sessionEntry: UserTurnSessionEntry | undefined;
messageId: string;
message: PersistedUserTurnMessage;
admission: UserTurnTranscriptAdmissionReceipt;
};
type UserTurnTranscriptTargetResolver = UserTurnTranscriptTarget | (() => UserTurnTranscriptTarget | undefined | Promise<UserTurnTranscriptTarget | undefined>);
type UserTurnTranscriptRecorder = {
readonly message: PersistedUserTurnMessage | undefined;
resolveMessage: () => Promise<PersistedUserTurnMessage | undefined>;
/** Durable input custody leaves the active transcript unchanged until execution owns it. */
stageApproved?: (options: {
runId: string;
assertCurrent: () => void;
}) => Promise<boolean>;
getPendingInputMessage?: () => PersistedUserTurnMessage | undefined;
isPendingInputConsumed?: () => boolean;
withPendingInput?: <T>(run: () => T) => T;
finishPendingInput?: (disposition: "cancelled" | "interrupted") => void;
/** Replaces generated current-turn text before runtime persistence/provider submission. */
replaceTextBeforePersistence?: (text: string) => void;
/** Confirms exact-run steering provenance after transcript commitment is proven. */
confirmSteerTargetRunIdForPersistence?: (targetRunId: string) => Promise<void>;
getPersistedMessage?: () => PersistedUserTurnMessage | undefined;
getAdmissionReceipt: () => UserTurnTranscriptAdmissionReceipt | undefined;
setAdmissionHandler?: (handler: (admission: UserTurnTranscriptAdmissionReceipt) => void) => void;
markSentToProvider?: () => void;
markRuntimePersistencePending: (pending: Promise<void>) => void;
markRuntimePersisted: (message?: PersistedUserTurnMessage, anchor?: TranscriptEntryAnchor | UserTurnTranscriptAdmissionReceipt, persistence?: {
appended: boolean;
}) => void;
markBlocked: () => void;
hasPersisted: () => boolean;
isBlocked: () => boolean;
hasRuntimePersistencePending: () => boolean;
waitForRuntimePersistence: () => Promise<void>;
persistApproved: (params?: {
target?: UserTurnTranscriptTargetResolver;
updateMode?: UserTurnTranscriptUpdateMode;
cwd?: string;
expectedSessionId?: string;
expectedSessionState?: SessionTranscriptTurnExpectedState;
sessionLifecyclePatch?: SessionTranscriptTurnLifecyclePatch;
/** Allow a later explicit persistence attempt when this attempt appends nothing. */
retryIfUnpersisted?: boolean;
}) => Promise<UserTurnTranscriptPersistResult | undefined>;
persistBlocked: (message: PersistedUserTurnMessage, params?: {
target?: UserTurnTranscriptTargetResolver;
updateMode?: UserTurnTranscriptUpdateMode;
cwd?: string;
}) => Promise<UserTurnTranscriptPersistResult | undefined>;
persistFallback: (params?: {
target?: UserTurnTranscriptTargetResolver;
updateMode?: UserTurnTranscriptUpdateMode;
cwd?: string;
}) => Promise<UserTurnTranscriptPersistResult | undefined>;
};
//#endregion
//#region src/auto-reply/reply/typing.d.ts
/** Controller for channel typing indicator lifecycle during a reply run. */
type TypingController = {
onReplyStart: () => Promise<void>;
startTypingLoop: () => Promise<void>;
startTypingOnText: (text?: string) => Promise<void>;
refreshTypingTtl: () => void;
isActive: () => boolean;
markRunComplete: () => void;
markDispatchIdle: () => void;
cleanup: () => void;
};
//#endregion
//#region src/auto-reply/get-reply-options.types.d.ts
/** A successful runtime append, independent of optional active-path projection anchors. */
type ReplyDispatchAssistantTranscript = Pick<TranscriptEntryAnchor, "agentId" | "sessionId" | "sessionKey" | "storePath"> & {
messageId: string;
anchor?: TranscriptEntryAnchor;
idempotencyKey: string;
};
type ReplyDispatchRun = {
completionSource: "reply-dispatch";
getResult: () => {
assistantTranscript?: ReplyDispatchAssistantTranscript;
terminalOutcome?: AgentRunTerminalOutcome;
};
};
type BlockReplyContext = {
abortSignal?: AbortSignal;
timeoutMs?: number;
/** Source assistant message index from the upstream stream, when available. */
assistantMessageIndex?: number;
/** @internal Stable durable outbound intent owned by the producing runtime. */
deliveryIntentId?: string;
};
/** Context passed to onModelSelected callback with actual model used. */
type ModelSelectedContext = {
provider: string;
model: string;
thinkLevel: string | undefined;
};
/** Typing indicator class for channel-owned UX policy. */
type TypingPolicy = "auto" | "user_message" | "system_event" | "internal_webchat" | "heartbeat";
/** Per-turn policy for source-message reply threading. */
type ReplyThreadingPolicy = {
/** Override implicit reply-to-current behavior for the current turn. */
implicitCurrentMessage?: "default" | "allow" | "deny";
};
/** Action sink available for model-proposed follow-up tasks during this turn. */
type TaskSuggestionDeliveryMode = "gateway";
/** Correlates queued reply ownership transfer with later delivery drains. */
type QueuedReplyDeliveryCorrelation = {
begin: () => (() => void) | void;
};
/**
* Exclusive: each lifecycle is its own collect-admission identity.
* Cancel-only: share collect identity via ownerKey (gateway chat.send).
*/
type TurnAdoptionAdmission = "exclusive" | "cancel-only";
/**
* Canonical turn-ownership lifecycle (adopt / defer / abandon / settle).
* Single surface for durable ingress, gateway cancel identity, and reply-lane transfer.
*/
type TurnAdoptionLifecycle = {
/**
* Admission isolation mode (closed). Exclusive isolates collect identity per
* lifecycle; cancel-only shares via ownerKey. Never inferred from onAbandoned.
* Durable ingress sets exclusive; gateway cancel identity sets cancel-only.
*/
admission?: TurnAdoptionAdmission;
/** Transcript branch leaf from which this turn was admitted. */
originatingLeafEntryId?: string | null;
onAdopted: () => void | Promise<void>;
/** Return false to reject followup enqueue. */
onDeferred?: () => boolean | void;
/** Reports that a deferred turn is still queued behind an active turn. */
onDeferredHeartbeat?: () => void;
/** Deferred turn finished without owning the reply lane. */
onAbandoned?: () => void;
/** Always fires when the followup ownership cycle ends (admitted or not). Gateway cleanup. */
onSettled?: () => void;
/** Retires cancellation ownership while retaining live identity. */
onCancellationRetired?: () => void;
/** Stable cancellation owner for collect-mode batches. */
ownerKey?: string;
abortSignal?: AbortSignal;
/** Ephemeral fact: a direct local operator turn lost fresh cron authority when queued. */
cronCreatorAuthorityUnavailable?: "queued-local-operator";
};
/** Partial assistant payload emitted during streaming or replacement updates. */
type PartialReplyPayload = {
/**
* Sanitized text, which may be an enumerable memoized getter. Content materializes on first
* read: direct-delivery consumers pay per partial, while throttled consumers pay per flush.
*/
text?: ReplyPayload["text"];
mediaUrls?: ReplyPayload["mediaUrls"];
delta?: string;
replace?: true;
};
type ReasoningStreamPayload$1 = Pick<ReplyPayload, "text" | "mediaUrls" | "isReasoning" | "isReasoningSnapshot"> & {
requiresReasoningProgressOptIn?: boolean;
};
type ReasoningProgressPayload = {
progressTokens: number;
};
/** Return false until the channel has accepted operator-visible progress. */
type ProgressCallbackResult = boolean | void;
/** Reply generation options shared by auto-reply, webchat, channels, and tests. */
type GetReplyOptions = {
/** Override run id for agent events (defaults to random UUID). */
runId?: string;
/** Stable provider prompt-cache affinity key; distinct from run id/idempotency. */
promptCacheKey?: string;
/** Abort signal for the underlying agent run. */
abortSignal?: AbortSignal;
/** Ephemeral channel owner check for a targeted Stop; never serialized as authority. */
isCommandTargetCurrent?: () => boolean;
/** Optional inbound images (used for webchat attachments). */
images?: ImageContent$1[];
/** Original inline/offloaded attachment order for inbound images. */
imageOrder?: PromptImageOrderEntry[];
/** Ordered media facts whose model-facing text projection is already present in the prompt. */
media?: MediaFact[];
/**
* Notifies when an agent run starts. Return "reply-dispatch" synchronously to accept
* completion ownership offered in options; all other legacy callback results are ignored.
*/
onAgentRunStart?: (runId: string, executionIdentityToken?: ExecutionIdentityAdmissionToken, options?: ReplyDispatchRun) => unknown;
/** Reports the terminal agent-run classification to the shared dispatch owner. */
onAgentRunTerminalOutcome?: (outcome: "completed" | "failed") => void;
/**
* Canonical adoption lifecycle (adopted / deferred / abandoned / settled + pre-adoption abort).
*/
turnAdoptionLifecycle?: TurnAdoptionLifecycle;
/** Shared lifecycle owner for the current user-turn transcript append. */
userTurnTranscriptRecorder?: UserTurnTranscriptRecorder;
/** Gateway-owned start-or-steer decision for this turn. */
messageInjectionDisposition?: "none" | "accepted" | "rejected";
/** Current user turn is already durable; replay it without appending another copy. */
suppressNextUserMessagePersistence?: boolean;
onReplyStart?: () => Promise<void> | void;
/** Called when the typing controller cleans up (e.g., run ended with NO_REPLY). */
onTypingCleanup?: () => void;
onTypingController?: (typing: TypingController) => void;
/** If false, send only the initial typing signal without periodic keepalive refreshes. */
typingKeepalive?: boolean;
isHeartbeat?: boolean;
/** Policy-level typing control for run classes (user/system/internal/heartbeat). */
typingPolicy?: TypingPolicy;
/** Force-disable typing indicators for this run (system/internal/cross-channel routes). */
suppressTyping?: boolean;
/** Resolved heartbeat model override (provider/model string from merged per-agent config). */
heartbeatModelOverride?: string;
/** One-shot thinking level override for this run; does not persist to the session. */
thinkingLevelOverride?: string;
/** One-shot fast-mode override for this run; does not persist to the session. */
fastModeOverride?: FastMode;
/** One-shot auto fast-mode cutoff override in seconds; does not persist to the session. */
fastModeAutoOnSecondsOverride?: number;
/** Controls bootstrap workspace context injection (default: full). */
bootstrapContextMode?: "full" | "lightweight";
/** If true, run the model without OpenClaw tools for this turn. */
disableTools?: boolean;
/** Runtime tool allow-list for this turn. Empty means no tools. */
toolsAllow?: string[];
/** If true, include the heartbeat response tool for structured heartbeat outcomes. */
enableHeartbeatTool?: boolean;
/** If true, keep the heartbeat response tool available even under narrow tool profiles. */
forceHeartbeatTool?: boolean;
/**
* @deprecated Ignored. The tool-failure warning is delivered whenever a run ends
* without a reply and cannot be suppressed. Kept only so plugin-sdk callers that
* still pass it keep compiling; removed in the first stable release after 2026.10.
*/
suppressToolErrorWarnings?: boolean;
/**
* If true, dispatch skips default tool/progress text messages and expects the
* channel to surface progress via its own streaming/edit UX.
*/
suppressDefaultToolProgressMessages?: boolean;
/** Suppress standalone tool/progress text even when verbose progress is enabled. */
suppressToolProgressMessages?: boolean;
/** Allow channel-owned tool lifecycle feedback while text progress remains hidden. */
allowToolLifecycleWhenProgressHidden?: boolean;
/**
* Called before dispatch with a live getter for whether verbose standalone
* progress messages are active for this run. Channels that render tool or
* commentary progress inside an ephemeral streaming draft should yield those
* draft lines while the getter returns true, so progress is not rendered in
* both lanes at once.
*/
onVerboseProgressVisibility?: (isActive: () => boolean) => void;
/** Preserve source-event callback start order for stateful channel progress renderers. */
preserveProgressCallbackStartOrder?: boolean;
onPartialReply?: (payload: PartialReplyPayload) => Promise<ProgressCallbackResult> | ProgressCallbackResult;
onReasoningStream?: (payload: ReasoningStreamPayload$1) => Promise<ProgressCallbackResult> | ProgressCallbackResult;
onReasoningProgress?: (payload: ReasoningProgressPayload) => Promise<void> | void;
streamReasoningInNonStreamModes?: boolean;
/** Called when a thinking/reasoning block ends. */
onReasoningEnd?: () => Promise<ProgressCallbackResult> | ProgressCallbackResult;
/** Called when a new assistant message starts (e.g., after tool call or thinking block). */
onAssistantMessageStart?: () => Promise<ProgressCallbackResult> | ProgressCallbackResult;
/** Called synchronously when a block reply is logically emitted, before async
* delivery drains. Useful for channels that need to rotate preview state at
* block boundaries without waiting for transport acks. */
onBlockReplyQueued?: (payload: ReplyPayload, context?: BlockReplyContext) => Promise<ProgressCallbackResult> | ProgressCallbackResult;
onBlockReply?: (payload: ReplyPayload, context?: BlockReplyContext) => Promise<void> | void;
onToolResult?: (payload: ReplyPayload) => Promise<ProgressCallbackResult> | ProgressCallbackResult;
/** Called when a tool phase starts/updates, before summary payloads are emitted. */
onToolStart?: (payload: {
itemId?: string;
toolCallId?: string;
name?: string;
phase?: string;
args?: Record<string, unknown>;
detailMode?: "explain" | "raw";
}) => Promise<ProgressCallbackResult> | ProgressCallbackResult;
/** Called when a concrete work item starts, updates, or completes. */
onItemEvent?: (payload: {
itemId?: string;
toolCallId?: string;
kind?: string;
title?: string;
name?: string;
phase?: string;
status?: string;
summary?: string;
progressText?: string;
meta?: string;
commandBearing?: boolean;
approvalId?: string;
approvalSlug?: string;
suppressDurableProgress?: true;
}) => Promise<ProgressCallbackResult> | ProgressCallbackResult;
/**
* Called when the utility-model narration of the in-progress turn changes.
* Providing this callback opts the channel into progress narration; core
* only generates narration when a utility model resolves (explicit
* config or the provider-declared default; utilityModel: "" disables).
* An empty text clears narration; a retained model preamble still wins before
* the channel falls back to raw tool progress.
*/
onNarrationUpdate?: (payload: {
text: string;
}) => Promise<void> | void;
/** Channel-owned final and queued-turn boundaries for the current narrator. */
onProgressNarratorLifecycle?: (lifecycle: {
beginTurn: () => void;
stopTurn: () => void;
}) => void;
/** False while utility-model narration has no visible progress draft. */
isProgressDraftVisible?: () => boolean;
/**
* Omit exec/bash command text from narration model input, mirroring the
* channel's `streaming.progress.commandText: "status"` display policy so
* narration never receives more command detail than the draft shows.
*/
narrationHideCommandText?: boolean;
/** In progress mode, classify Claude pre-tool text; true also renders it as commentary. */
commentaryProgressEnabled?: boolean;
/** Bridge typed preambles to a channel-owned progress headline without commentary. */
progressPreambleEnabled?: boolean;
/** Deliver durable reasoning payloads to channels that own a separate reasoning lane. */
reasoningPayloadsEnabled?: boolean;
/** Deliver durable commentary (💬) payloads to channels that own a separate commentary lane. */
commentaryPayloadsEnabled?: boolean;
/** Optional turn-frozen commentary owner; visibility is live by default.
* With the static opt-in and this callback, core freezes, evaluates once, and snapshots. */
shouldDeliverCommentaryPayloads?: () => boolean;
/** Called when the agent emits a structured plan update. */
onPlanUpdate?: (payload: {
phase?: string;
title?: string;
explanation?: string;
steps?: AgentPlanStep[];
source?: string;
}) => Promise<ProgressCallbackResult> | ProgressCallbackResult;
/** Called when an approval becomes pending or resolves. */
onApprovalEvent?: (payload: {
phase?: string;
kind?: string;
status?: string;
title?: string;
itemId?: string;
toolCallId?: string;
approvalId?: string;
approvalSlug?: string;
command?: string;
host?: string;
reason?: string;
scope?: "turn" | "session";
message?: string;
}) => Promise<ProgressCallbackResult> | ProgressCallbackResult;
/** Called when command output streams or completes. */
onCommandOutput?: (payload: {
itemId?: string;
phase?: string;
title?: string;
toolCallId?: string;
name?: string;
output?: string;
status?: string;
exitCode?: number | null;
durationMs?: number;
cwd?: string;
}) => Promise<ProgressCallbackResult> | ProgressCallbackResult;
/** Called when a patch completes with a file summary. */
onPatchSummary?: (payload: {
itemId?: string;
phase?: string;
title?: string;
toolCallId?: string;
name?: string;
added?: string[];
modified?: string[];
deleted?: string[];
summary?: string;
}) => Promise<ProgressCallbackResult> | ProgressCallbackResult;
/** Called when context auto-compaction starts (allows UX feedback during the pause). */
onCompactionStart?: () => Promise<ProgressCallbackResult> | ProgressCallbackResult;
/** Called when context auto-compaction ends; omitted outcome means completed for legacy callers. */
onCompactionEnd?: (payload?: {
completed: boolean;
}) => Promise<ProgressCallbackResult> | ProgressCallbackResult;
/** Called when the actual model is selected (including after fallback).
* Use this to get model/provider/thinkLevel for responsePrefix template interpolation. */
onModelSelected?: (ctx: ModelSelectedContext) => void;
/**
* Controls whether normal assistant replies are automatically delivered to
* the source conversation. `message_tool_only` prefers message-tool visible
* delivery and keeps normal final text, block output, and preview output
* private unless dispatch explicitly marks a source reply as deliverable.
*/
sourceReplyDeliveryMode?: SourceReplyDeliveryMode;
/** Enables task-suggestion tools only when the initiating surface can action Gateway events. */
taskSuggestionDeliveryMode?: TaskSuggestionDeliveryMode;
/** Starts delivery tracking when this turn later drains as a queued followup. */
queuedDeliveryCorrelations?: QueuedReplyDeliveryCorrelation[];
/** Called after a queued followup owns the reply lane, before its model run starts. */
onQueuedFollowupAdmitted?: () => Promise<void> | void;
/** Called after an admitted queued followup finishes, including failed attempts. */
onQueuedFollowupSettled?: () => Promise<void> | void;
/** Allow channel-owned progress UI while final/source reply delivery remains message-tool-only. */
allowProgressCallbacksWhenSourceDeliverySuppressed?: boolean;
/** Called when a suppressed source reply mode observes visible delivery through another path. */
onObservedReplyDelivery?: () => Promise<void> | void;
/** Emit tool result summaries for channel-owned progress UI even when verbose is off. */
forceToolResultProgress?: boolean;
disableBlockStreaming?: boolean;
/** Timeout for block reply delivery (ms). */
blockReplyTimeoutMs?: number;
/** If provided, only load these skills for this session (empty = no skills). */
skillFilter?: string[];
/** Mutable ref to track if a reply was sent (for Slack "first" threading mode). */
hasRepliedRef?: {
value: boolean;
};
/** Override agent timeout in seconds (0 = no timeout). Threads through to resolveAgentTimeoutMs. */
timeoutOverrideSeconds?: number;
};
//#endregion
//#region src/auto-reply/templating.d.ts
/** Valid message channels for routing. */
type OriginatingChannelType = string & {
readonly __originatingChannelBrand?: never;
};
type MentionSource = "explicit_bot" | "subteam" | "mention_pattern" | "implicit_thread" | "command_bypass" | "none";
type InboundSourceModality = "text" | "voice" | "audio" | "image" | "video" | "document";
type StickerContextMetadata = {
cachedDescription?: string;
emoji?: string;
setName?: string;
description?: string;
fileId?: string;
fileUniqueId?: string;
uniqueFileId?: string;
isAnimated?: boolean;
isVideo?: boolean;
} & Record<string, unknown>;
type ChannelStructuredContextEntry = {
label: string;
source?: string;
type?: string;
payload: unknown;
/** Internal exact-id hints for canonical transcript/live-cache deduplication. */
sessionTranscriptDedupeMessageIds?: string[];
/** Internal visible-text hints for legacy assistant rows without transcript ids. */
sessionTranscriptAssistantTextDedupeKeys?: string[];
};
type SessionTranscriptContext = {
chatWindow?: boolean;
historyLimit: number;
beforeTimestampMs?: number;
minTimestampMs?: number;
senderLabels?: {
assistant: string;
user: string;
};
};
/** @deprecated Use ChannelStructuredContextEntry. Removal: after 2026-09-08 (see sdk-untrusted-context-identifier-aliases). */
type UntrustedStructuredContextEntry = ChannelStructuredContextEntry;
/** Structured supplemental facts projected into prompt context by inbound finalization. */
type SupplementalContextFacts = {
quote?: {
id?: string;
fullId?: string;
body?: string;
sender?: string;
senderAllowed?: boolean;
isExternal?: boolean;
isQuote?: boolean;
};
forwarded?: {
from?: string;
fromType?: string;
fromId?: string;
date?: number;
senderAllowed?: boolean;
};
thread?: {
id?: string;
starterBody?: string;
historyBody?: string;
label?: string;
parentSessionKey?: string;
modelParentSessionKey?: string;
senderAllowed?: boolean;
};
channelStructuredContext?: ChannelStructuredContextEntry[];
/** @deprecated Use channelStructuredContext. Removal: after 2026-09-08 (see sdk-untrusted-context-identifier-aliases). */
untrustedContext?: ChannelStructuredContextEntry[];
groupSystemPrompt?: string;
/** Prompt-like group metadata from user-controlled sources; never enters the system prompt. */
untrustedGroupSystemPrompt?: string;
};
/** Canonical normalized inbound text populated once by `finalizeInboundContext`. */
type CanonicalInboundText = {
/** Clean text used for command and directive parsing. */
commandText: string;
/** Prompt-facing text used for the agent turn. */
agentText: string;
/** Normalized visible/raw inbound text before command-specific projection. */
rawText: string;
};
/** Raw inbound message context accepted from channels before finalization. */
type MsgContext = Partial<CanonicalInboundText> & {
Body?: string;
InboundEventKind?: InboundEventKind;
/**
* Agent prompt body (may include envelope/history/context). Prefer this for prompt shaping.
* Should use real newlines (`\n`), not escaped `\\n`.
*/
BodyForAgent?: string;
/**
* Recent chat history for context (untrusted user content). Prefer passing this
* as structured context blocks in the user prompt rather than rendering plaintext envelopes.
*/
InboundHistory?: HistoryEntry[];
/** Internal facts used to merge canonical transcript turns before dispatch. */
SessionTranscriptContext?: SessionTranscriptContext;
/**
* @deprecated Use CommandBody.
*
* Raw message body without structural context (history, sender labels).
* Legacy alias for CommandBody. Falls back to Body if not set.
*/
RawBody?: string;
/**
* Prefer for command detection; RawBody is treated as legacy alias.
*/
CommandBody?: string;
/**
* Command parsing body. Prefer this over CommandBody/RawBody when set.
* Should be the "clean" text (no history/sender context).
*/
BodyForCommands?: string;
CommandArgs?: CommandArgs;
From?: string;
To?: string;
SessionKey?: string;
/**
* Resolved agent scope for canonical session keys that do not encode the agent
* id, such as selected-agent global sessions.
*/
AgentId?: string;
/** Effective routed DM scope, including binding overrides. */
DmScope?: DmScope;
/**
* Session-like key used for runtime policy (sandbox/tool policy) when the
* conversation key intentionally remains broader, such as a main-session DM.
*/
RuntimePolicySessionKey?: string;
/** Provider account id (multi-account). */
AccountId?: string;
ParentSessionKey?: string;
/**
* Session key used only for inheriting session-scoped model/provider
* overrides. Unlike ParentSessionKey, this must not trigger transcript
* forking or parent-session lifecycle behavior.
*/
ModelParentSessionKey?: string;
MessageSid?: string;
/** Provider-specific full message id when MessageSid is a shortened alias. */
MessageSidFull?: string;
MessageSids?: string[];
MessageSidFirst?: string;
MessageSidLast?: string;
AmbientTranscriptWatermarkKey?: string;
AmbientTranscriptBody?: string;
AmbientTranscriptMessageId?: string;
AmbientTranscriptTimestampMs?: number;
AmbientTranscriptPreviousMessageId?: string;
AmbientTranscriptPreviousTimestampMs?: number;
/** Per-turn reply-threading overrides. */
ReplyThreading?: ReplyThreadingPolicy;
/** Effective channel reply mode prepared for this turn. */
ReplyToMode?: ReplyToMode;
ReplyToId?: string;
/**
* Root message id for thread reconstruction (used by Feishu for root_id).
* When a message is part of a thread, this is the id of the first message.
*/
RootMessageId?: string;
/** Provider-specific full reply-to id when ReplyToId is a shortened alias. */
ReplyToIdFull?: string;
ReplyToBody?: string;
ReplyToQuoteText?: string;
ReplyToSender?: string;
ReplyChain?: Array<{
messageId?: string;
threadId?: string;
sender?: string;
senderId?: string;
senderUsername?: string;
timestamp?: number;
body?: string;
isQuote?: boolean;
mediaType?: string;
mediaPath?: string;
mediaRef?: string;
replyToId?: string;
forwardedFrom?: string;
forwardedFromId?: string;
forwardedFromUsername?: string;
forwardedDate?: number;
}>;
ReplyToIsQuote?: boolean;
/** Forward origin from the reply target (when reply_to_message is a forwarded message). */
ReplyToForwardedFrom?: string;
ReplyToForwardedFromType?: string;
ReplyToForwardedFromId?: string;
ReplyToForwardedFromUsername?: string;
ReplyToForwardedFromTitle?: string;
ReplyToForwardedDate?: number;
ForwardedFrom?: string;
ForwardedFromType?: string;
ForwardedFromId?: string;
ForwardedFromUsername?: string;
ForwardedFromTitle?: string;
ForwardedFromSignature?: string;
ForwardedFromChatType?: string;
ForwardedFromMessageId?: number;
ForwardedDate?: number;
ThreadStarterBody?: string;
/** Full thread history when starting a new thread session. */
ThreadHistoryBody?: string;
IsFirstThreadTurn?: boolean;
ThreadLabel?: string;
/** @deprecated Use `media?.[0]?.path`. */
MediaPath?: string;
/** @deprecated Use `media?.[0]?.url`. */
MediaUrl?: string;
/** @deprecated Use `media?.[0]?.contentType` or `.kind`. */
MediaType?: string;
/** @deprecated Derive the directory from `media?.[0]?.path` at the consuming boundary. */
MediaDir?: string;
/** @deprecated Use `media?.map((entry) => entry.path)`. */
MediaPaths?: string[];
/** @deprecated Use `media?.map((entry) => entry.url)`. */
MediaUrls?: string[];
/** @deprecated Use `media?.map((entry) => entry.contentType ?? entry.kind)`. */
MediaTypes?: string[];
/** Ordered current-turn media facts; array position is attachment identity. */
media?: MediaFact[];
/** Original message modality before transcription or other media normalization. */
SourceModality?: InboundSourceModality;
/** @deprecated Use each media fact's `workspaceDir`. */
MediaWorkspaceDir?: string;
/** Attachment indexes whose audio was already transcribed before media understanding runs. */
/** @deprecated Use each media fact's `transcribed` field. */
MediaTranscribedIndexes?: number[];
/**
* Marker: skip downstream stageSandboxMedia. chat.send RPC sets this so
* staging runs synchronously before respond() and surfaces 5xx to the
* client; any later failure only reaches the broadcast channel.
*/
/** @deprecated Use each media fact's `workspaceDir` or `staged` proof. */
MediaStaged?: boolean;
/** Telegram sticker metadata (emoji, set name, file IDs, cached description). */
Sticker?: StickerContextMetadata;
/** True when current-turn sticker media is present in structured facts. */
StickerMediaIncluded?: boolean;
/** Skip automatic understanding for the current sticker because its cached description is used. */
SkipStickerMediaUnderstanding?: boolean;
OutputDir?: string;
OutputBase?: string;
/** Remote host for SCP when media lives on a different machine (e.g., openclaw@192.168.64.3). */
MediaRemoteHost?: string;
Transcript?: string;
MediaUnderstanding?: MediaUnderstandingOutput[];
MediaUnderstandingDecisions?: MediaUnderstandingDecision[];
LinkUnderstanding?: string[];
Prompt?: string;
MaxChars?: number;
ChatType?: string;
/** Trusted channel-configured policy for this admitted conversation turn. */
ConversationToolPolicy?: GroupToolPolicyConfig;
/** Human label for envelope headers (conversation label, not sender). */
ConversationLabel?: string;
GroupSubject?: string;
/** Human label for channel-like group conversations (e.g. #general, #support). */
GroupChannel?: string;
GroupSpace?: string;
/** Trusted provider role ids for the sender in this group turn. */
MemberRoleIds?: string[];
GroupMembers?: string;
GroupSystemPrompt?: string;
/**
* Canonical inbound supplemental facts for new channel code. `finalizeInboundContext`
* projects these to the existing flat reply/forward/thread/group prompt fields.
*/
SupplementalContext?: SupplementalContextFacts;
/** Channel-provided metadata that must not be treated as system instructions. */
ChannelPromptContext?: string[];
/** @deprecated Use ChannelPromptContext. Removal: after 2026-09-08 (see sdk-untrusted-context-identifier-aliases). */
UntrustedContext?: string[];
/** Structured channel metadata rendered by prompt assembly as fenced JSON. */
ChannelStructuredContext?: ChannelStructuredContextEntry[];
/** @deprecated Use ChannelStructuredContext. Removal: after 2026-09-08 (see sdk-untrusted-context-identifier-aliases). */
UntrustedStructuredContext?: UntrustedStructuredContextEntry[];
/** System-attached provenance for the current inbound message. */
InputProvenance?: InputProvenance;
/** Internal wake cause, independent of transport, transcript provenance, and execution authority. */
InternalTurnSource?: "heartbeat" | "cron" | "exec";
/** Explicit owner allowlist overrides (trusted, configuration-derived). */
OwnerAllowFrom?: Array<string | number>;
SenderName?: string;
SenderId?: string;
/** Trusted in-process creation provenance; never populated from channel payloads. */
SessionCreation?: {
skillLibrarySelections?: SkillLibrarySelection[];
via: SessionCreatedVia;
actor?: SessionCreatedActor;
sandbox?: "required";
};
SenderUsername?: string;
SenderTag?: string;
SenderE164?: string;
SenderIsBot?: boolean;
/** Channel-ingress fact: sender is the operator's own account (from-me). */
SenderIsSelf?: boolean;
Timestamp?: number;
LocationLat?: number;
LocationLon?: number;
LocationAccuracy?: number;
LocationName?: string;
LocationAddress?: string;
LocationSource?: string;
LocationIsLive?: boolean;
LocationLivePeriodSeconds?: number;
LocationCaption?: string;
/** Stable identity of the provider update that carried this message. */
ProviderUpdateId?: string;
/** Provider update kind, for example `message` or `edited_message`. */
ProviderUpdateKind?: string;
/** Provider-native timestamp for the original message. */
ProviderMessageTimestamp?: number;
/** Provider-native timestamp for an edited message update. */
ProviderEditTimestamp?: number;
/** Provider label. */
Provider?: string;
/** Provider surface label. Prefer this over `Provider` when available. */
Surface?: string;
/** Platform bot username when command mentions should be normalized. */
BotUsername?: string;
WasMentioned?: boolean;
/** Effective channel-owned mention policy before any plugin-binding bypass. */
GroupRequireMention?: boolean;
/** True when this turn explicitly mentioned the current bot target. */
ExplicitlyMentionedBot?: boolean;
/** Provider-native explicit user mention ids present on this turn. */
MentionedUserIds?: string[];
/** Provider-native explicit user-group/subteam mention ids present on this turn. */
MentionedSubteamIds?: string[];
/** Provider-native implicit mention wake reasons present on this turn. */
ImplicitMentionKinds?: string[];
/** Provider-native source that caused the current mention decision. */
MentionSource?: MentionSource;
CommandAuthorized?: boolean;
CommandTurn?: CommandTurnContext;
CommandSource?: "text" | "native";
CommandInterpretationSuppressed?: boolean;
CommandTargetSessionKey?: string;
/**
* Internal flag: command handling prepared trailing prompt text for ACP dispatch.
* Used for `/new <prompt>` and `/reset <prompt>` on ACP-bound sessions.
*/
AcpDispatchTailAfterReset?: boolean;
/** Gateway client scopes when the message originates from the gateway. */
GatewayClientScopes?: string[];
/** Gateway client capabilities when the message originates from the gateway. */
GatewayClientCaps?: string[];
/** Run-scoped plugin tool bindings; never rendered into prompt text. */
GatewayRunToolBindings?: Readonly<Record<string, unknown>>;
/** Gateway device id allowed to review approvals initiated by this turn. */
ApprovalReviewerDeviceId?: string;
/** Thread identifier (Telegram topic id or Matrix thread event id). */
MessageThreadId?: string | number;
/** Provider-native thread target for reply delivery without making the session thread-scoped. */
TransportThreadId?: string | number;
/** Platform-native channel/conversation id (e.g. Slack DM channel "D…" id). */
NativeChannelId?: string;
/** Channel-owned local conversation image reference; never rendered into prompt text. */
ConversationAvatar?: string;
/** Channel-owned metadata exposed to plugin hook context, not prompt text. */
ChannelContext?: PluginHookChannelContext;
/** Provider-native chat/conversation id used by channel plugins that expose `chat_id`. */
ChatId?: string;
/** Stable provider-native direct-peer id when a DM room/user mapping must survive later writes. */
NativeDirectUserId?: string;
/** Telegram forum supergroup marker. */
IsForum?: boolean;
/** Human-readable Telegram forum topic name (cached from service messages). */
TopicName?: string;
/** Warning: DM has topics enabled but this message is not in a topic. */
TopicRequiredButMissing?: boolean;
/**
* Originating channel for reply routing.
* When set, replies should be routed back to this provider
* instead of using lastChannel from the session.
*/
OriginatingChannel?: OriginatingChannelType;
/**
* Originating destination for reply routing.
* The chat/channel/user ID where the reply should be sent.
*/
OriginatingTo?: string;
/**
* True when the current turn intentionally requested external delivery to
* OriginatingChannel/OriginatingTo, rather than inheriting stale session route metadata.
*/
ExplicitDeliverRoute?: boolean;
/**
* Internal proof that the channel ingress owner admitted this sender/event.
* Correlation interceptors must fail closed when this proof is absent.
*/
InboundAccessAuthorized?: boolean;
/** Internal marker that channel ingress authoritatively observed route-context facts. */
ConversationRouteContextObserved?: boolean;
/** Canonical peer used by route selection; delivery targets may use a different namespace. */
ConversationRoutePeerId?: string;
/**
* Internal flag for channels that emit message_received through a channel-specific
* privacy gate before entering the shared reply dispatcher.
*/
SuppressMessageReceivedHooks?: boolean;
/**
* Provider-specific parent conversation id for threaded contexts.
* For Discord threads, this is the parent channel id.
*/
ThreadParentId?: string;
/**
* Messages from hooks to be included in the response.
* Used for hook confirmation messages like "Session context saved to memory".
*/
HookMessages?: string[];
};
type FinalizedMsgContext = Omit<MsgContext, "CommandAuthorized"> & {
/**
* Always set by finalizeInboundContext().
* Default-deny: missing/undefined becomes false.
*/
CommandAuthorized: boolean;
/**
* Populated by finalizeInboundContext(); optional for public SDK
* compatibility with existing plugin-constructed finalized contexts.
*/
CommandTurn?: CommandTurnContext;
};
type RuntimeMediaContextKey = "MediaPath" | "MediaUrl" | "MediaType" | "MediaDir" | "MediaPaths" | "MediaUrls" | "MediaTypes" | "MediaWorkspaceDir" | "MediaTranscribedIndexes" | "MediaStaged";
/** Internal inbound context; legacy media fields exist only on the shipped SDK adapter. */
type RuntimeMsgContext = Omit<MsgContext, RuntimeMediaContextKey>;
type FinalizedRuntimeMsgContext = Omit<RuntimeMsgContext, "CommandAuthorized" | keyof CanonicalInboundText> & CanonicalInboundText & {
CommandAuthorized: boolean;
CommandTurn?: CommandTurnContext;
};
type NonTemplateContextKey = "ConversationAvatar";
type TemplateContext = Omit<RuntimeMsgContext, NonTemplateContextKey> & {
BodyStripped?: string;
SessionId?: string;
IsNewSession?: string;
/** Local path for the attachment currently being processed. */
AttachmentPath?: string;
/** Original URL/reference for the attachment currently being processed. */
AttachmentUrl?: string;
/** MIME content type for the attachment currently being processed. */
AttachmentContentType?: string;
/** Directory containing AttachmentPath. */
AttachmentDir?: string;
/** Stable zero-based source fact index for the attachment currently being processed. */
AttachmentIndex?: number;
/** @deprecated Use AttachmentPath. */
MediaPath?: string;
/** @deprecated Use AttachmentUrl. */
MediaUrl?: string;
/** @deprecated Use AttachmentContentType. */
MediaType?: string;
/** @deprecated Use AttachmentDir. */
MediaDir?: string;
};
//#endregion
//#region src/media/load-options.d.ts
/** Host callback used to read an already-authorized outbound media file. */
type OutboundMediaReadFile = (filePath: string) => Promise<Buffer>;
/** Host-provided file access used when a runtime can read outbound media from local disk. */
type OutboundMediaAccess = {
localRoots?: readonly string[];
readFile?: OutboundMediaReadFile;
/** Agent workspace directory for resolving relative media paths. */
workspaceDir?: string;
};
//#endregion
//#region src/channels/message-access/identifier-authentication.d.ts
/** Ordered strength of one identifier-authentication claim. */
type IdentifierAuthentication = "verified" | "asserted" | "unverified" | "mutable";
//#endregion
//#region src/infra/outbound/send-deps.d.ts
/**
* Dynamic bag of per-channel send functions, keyed by channel ID.
* Each outbound adapter resolves its own function from this record and
* falls back to a direct import when the key is absent.
*/
type OutboundSendDeps = {
[channelId: string]: unknown;
};
//#endregion
//#region src/polls.d.ts
type PollInput = {
question: string;
options: string[];
maxSelections?: number;
/**
* Poll duration in seconds.
* Channel-specific limits apply in each owning plugin.
*/
durationSeconds?: number;
/**
* Poll duration in hours.
* Used by channels that model duration in hours.
*/
durationHours?: number;
};
//#endregion
//#region src/channels/message/types.d.ts
type OutboundReplyFacts = Readonly<{
source: "explicit";
replyToId: string;
}> | Readonly<{
source: "implicit";
replyToId: string;
mode: "first" | "all";
}>;
/** Capability names a channel must advertise before core can rely on durable final delivery. */
declare const durableFinalDeliveryCapabilities: readonly ["text", "media", "poll", "payload", "silent", "replyTo", "thread", "nativeQuote", "messageSendingHooks", "batch", "reconcileUnknownSend", "afterSendSuccess", "afterCommit"];
/** Durable final delivery capability key understood by message-channel adapters. */
type DurableFinalDeliveryCapability = (typeof durableFinalDeliveryCapabilities)[number];
/** Capability map used by adapters to declare which final-send guarantees they support. */
type DurableFinalDeliveryRequirementMap = Partial<Record<DurableFinalDeliveryCapability, boolean>>;
/** Raw platform result shape normalized into a message receipt. */
type MessageReceiptSourceResult = {
/** Provider-confirmed intentional omission before dispatch, never an ambiguous send. */
outcome?: "not_sent";
channel?: string;
messageId?: string;
target?: {
kind: "chat" | "channel" | "room" | "conversation";
id: string;
};
chatId?: string;
channelId?: string;
roomId?: string;
conversationId?: string;
toJid?: string;
pollId?: string;
timestamp?: number;
meta?: Record<string, unknown>;
};
/** Logical part kind for multi-part rendered messages. */
type MessageReceiptPartKind = "text" | "media" | "voice" | "poll" | "card" | "preview" | "unknown";
/** One platform message produced by a logical outbound send. */
type MessageReceiptPart = {
platformMessageId: string;
kind: MessageReceiptPartKind;
index: number;
threadId?: string;
replyToId?: string;
raw?: MessageReceiptSourceResult;
};
/** Normalized receipt for all platform messages that make up a logical send. */
type MessageReceipt = {
primaryPlatformMessageId?: string;
platformMessageIds: string[];
parts: MessageReceiptPart[];
threadId?: string;
replyToId?: string;
editToken?: string;
deleteToken?: string;
sentAt: number;
raw?: readonly MessageReceiptSourceResult[];
};
/** Render-plan item category used before adapter-specific send execution. */
type RenderedMessageBatchPlanKind = "text" | "media" | "voice" | "presentation" | "interactive" | "channelData" | "empty";
/** Render plan for a single reply payload after text/media/presentation splitting. */
type RenderedMessageBatchPlanItem = {
index: number;
kinds: readonly RenderedMessageBatchPlanKind[];
text?: string;
mediaUrls: readonly string[];
audioAsVoice?: boolean;
presentationBlockCount?: number;
hasInteractive?: boolean;
hasChannelData?: boolean;
};
/** Aggregate render plan for a batch of reply payloads. */
type RenderedMessageBatchPlan = {
payloadCount: number;
textCount: number;
mediaCount: number;
voiceCount: number;
presentationCount: number;
interactiveCount: number;
channelDataCount: number;
items: readonly RenderedMessageBatchPlanItem[];
};
/** Common text-send context shared by text, media, payload, and poll adapter calls. */
type ChannelMessageSendTextContext<TConfig = OpenClawConfig> = {
cfg: TConfig;
to: string;
text: string;
accountId?: string | null;
deps?: OutboundSendDeps;
replyToId?: string | null;
replyToIdSource?: "explicit" | "implicit";
replyToMode?: ReplyToMode;
threadId?: string | number | null;
silent?: boolean;
signal?: AbortSignal;
gatewayClientScopes?: readonly string[];
/** @internal Opaque durable intent id for exact provider-side send reconciliation. */
deliveryQueueId?: string;
/** @internal Stable platform-send index within one durable payload. */
deliveryPartIndex?: number;
/** @internal Exact platform-send count within one durable payload. */
deliveryPartCount?: number;
/** @internal Channel-valid id reserved before a correlated conversation turn is sent. */
preparedMessageId?: string;
/** @internal Refresh durable timing before recipient-visible or finalizing platform I/O. */
onPlatformSendDispatch?: () => Promise<void>;
/** @internal Synchronously fence custody after refresh and immediately before provider I/O. */
assertDirectAdapterHandoff?: () => void;
/** @internal Report each completed platform sub-send before another fallible step. */
onDeliveryResult?: (result: ChannelMessageSendResult) => Promise<void> | void;
};
/** Media send context with validated access hooks and media presentation hints. */
type ChannelMessageSendMediaContext<TConfig = OpenClawConfig> = ChannelMessageSendTextContext<TConfig> & {
mediaUrl: string;
mediaAccess?: OutboundMediaAccess;
mediaLocalRoots?: readonly string[];
mediaReadFile?: (filePath: string) => Promise<Buffer>;
audioAsVoice?: boolean;
gifPlayback?: boolean;
forceDocument?: boolean;
};
/** Rich reply payload send context used when adapters can consume structured payloads. */
type ChannelMessageSendPayloadContext<TConfig = OpenClawConfig> = ChannelMessageSendTextContext<TConfig> & {
payload: ReplyPayload;
mediaUrl?: string;
mediaAccess?: OutboundMediaAccess;
mediaLocalRoots?: readonly string[];
mediaReadFile?: (filePath: string) => Promise<Buffer>;
audioAsVoice?: boolean;
gifPlayback?: boolean;
forceDocument?: boolean;
};
/** Poll send context; thread ids stay string-like because poll APIs do not accept numeric ids. */
type ChannelMessageSendPollContext<TConfig = OpenClawConfig> = Omit<ChannelMessageSendTextContext<TConfig>, "text" | "threadId"> & {
poll: PollInput;
threadId?: string | null;
isAnonymous?: boolean;
};
/** Adapter send result normalized to a receipt plus optional legacy message id. */
type ChannelMessageSendResult = {
outcome?: MessageReceiptSourceResult["outcome"];
receipt: MessageReceipt;
messageId?: string;
target?: MessageReceiptSourceResult["target"];
};
/** Concrete send shapes an adapter can reconcile after an unknown platform outcome. */
declare const unknownSendReconciliationKinds: readonly ["text", "media", "payload", "poll", "batch"];
type UnknownSendReconciliationKind = (typeof unknownSendReconciliationKinds)[number];
/** Send-attempt context tagged with the adapter method core is about to call. */
type ChannelMessageSendAttemptContext<TConfig = OpenClawConfig> = (ChannelMessageSendTextContext<TConfig> & {
kind: "text";
}) | (ChannelMessageSendMediaContext<TConfig> & {
kind: "media";
}) | (ChannelMessageSendPayloadContext<TConfig> & {
kind: "payload";
}) | (ChannelMessageSendPollContext<TConfig> & {
kind: "poll";
});
/** Lifecycle context emitted after an adapter send succeeds but before commit finishes. */
type ChannelMessageSendSuccessContext<TConfig = OpenClawConfig, TSendResult extends ChannelMessageSendResult = ChannelMessageSendResult> = ChannelMessageSendAttemptContext<TConfig> & {
result: TSendResult;
attemptToken?: unknown;
};
/** Lifecycle context emitted after an adapter send throws or rejects. */
type ChannelMessageSendFailureContext<TConfig = OpenClawConfig> = ChannelMessageSendAttemptContext<TConfig> & {
error: unknown;
attemptToken?: unknown;
};
/** Lifecycle context emitted when a successful send is being durably committed. */
type ChannelMessageSendCommitContext<TConfig = OpenClawConfig, TSendResult extends ChannelMessageSendResult = ChannelMessageSendResult> = ChannelMessageSendSuccessContext<TConfig, TSendResult>;
/** Durable queue context used to reconcile a send whose platform state is unknown. */
type ChannelMessageUnknownSendContext<TConfig = OpenClawConfig> = {
cfg: TConfig;
queueId: string;
channel: string;
to: string;
accountId?: string | null;
enqueuedAt: number;
retryCount: number;
platformSendStartedAt?: number;
/** Canonical reply target persisted after hooks and before platform I/O. */
effectiveReplyToId?: string | null;
payloads: readonly ReplyPayload[];
renderedBatchPlan?: RenderedMessageBatchPlan;
replyToId?: string | null;
replyToMode?: ReplyToMode;
threadId?: string | number | null;
silent?: boolean;
};
/** Adapter verdict for whether an unknown queued send reached the platform. */
type ChannelMessageUnknownSendReconciliationResult = {
status: "sent";
receipt: MessageReceipt;
messageId?: string;
} | {
status: "not_sent";
} | {
status: "unresolved";
error?: string;
retryable?: boolean;
};
/** Provider decision made before core persists or replays a deferred delivery. */
type ChannelMessageDeferredDeliveryAdmissionResult = {
status: "allowed";
} | {
status: "permanent_rejection";
reason: string;
};
/** Minimal context available at deferred-delivery admission boundaries. */
type ChannelMessageDeferredDeliveryAdmissionContext<TConfig = OpenClawConfig> = {
cfg: TConfig;
channel: string;
to: string;
accountId?: string | null;
phase: "live" | "recovery";
};
/** Optional hooks around adapter send attempts, platform success/failure, and commit. */
type ChannelMessageSendLifecycleAdapter<TConfig = OpenClawConfig, TSendResult extends ChannelMessageSendResult = ChannelMessageSendResult> = {
beforeSendAttempt?: (ctx: ChannelMessageSendAttemptContext<TConfig>) => unknown;
afterSendSuccess?: (ctx: ChannelMessageSendSuccessContext<TConfig, TSendResult>) => Promise<void> | void;
afterSendFailure?: (ctx: ChannelMessageSendFailureContext<TConfig>) => Promise<void> | void;
afterCommit?: (ctx: ChannelMessageSendCommitContext<TConfig, TSendResult>) => Promise<void> | void;
};
/** Adapter methods a message channel can implement for outbound text/media/payload/poll sends. */
type ChannelMessageSendAdapter<TConfig = OpenClawConfig, TSendResult extends ChannelMessageSendResult = ChannelMessageSendResult> = {
text?: (ctx: ChannelMessageSendTextContext<TConfig>) => Promise<TSendResult>;
media?: (ctx: ChannelMessageSendMediaContext<TConfig>) => Promise<TSendResult>;
payload?: (ctx: ChannelMessageSendPayloadContext<TConfig>) => Promise<TSendResult>;
poll?: (ctx: ChannelMessageSendPollContext<TConfig>) => Promise<TSendResult>;
lifecycle?: ChannelMessageSendLifecycleAdapter<TConfig, TSendResult>;
};
/** Durable final-delivery extension for queue reconciliation and capability declaration. */
type ChannelMessageDurableFinalAdapter = {
capabilities?: DurableFinalDeliveryRequirementMap;
/** Opt into provider reconciliation for ordinary single-payload queued sends. */
automaticUnknownSendReconciliation?: boolean;
/**
* Synchronous provider admission before a durable intent is created or replayed.
* Providers must not perform I/O from this hook.
*/
admitDeferredDelivery?: (ctx: ChannelMessageDeferredDeliveryAdmissionContext) => ChannelMessageDeferredDeliveryAdmissionResult;
/** Send shapes for which reconciliation can prove the complete durable intent. */
reconcileUnknownSendKinds?: Partial<Record<UnknownSendReconciliationKind, boolean>>;
reconcileUnknownSend?: (ctx: ChannelMessageUnknownSendContext) => Promise<ChannelMessageUnknownSendReconciliationResult | null> | ChannelMessageUnknownSendReconciliationResult | null;
/** Cleanup after core authoritatively retires an ambiguous send as failed. */
afterUnknownSendTerminal?: (ctx: ChannelMessageUnknownSendContext) => Promise<void> | void;
};
/** Live-message feature key declared by adapters that support preview or streaming behavior. */
type ChannelMessageLiveCapability = "draftPreview" | "previewFinalization" | "progressUpdates" | "nativeStreaming" | "quietFinalization";
/** Capability keys for turning a preview into a final platform message. */
declare const livePreviewFinalizerCapabilities: readonly ["finalEdit", "normalFallback", "discardPending", "previewReceipt", "retainOnAmbiguousFailure"];
/** Finalizer capability key understood by live-message adapters. */
type LivePreviewFinalizerCapability = (typeof livePreviewFinalizerCapabilities)[number];
/** Capability map for preview finalization behavior. */
type LivePreviewFinalizerCapabilityMap = Partial<Record<LivePreviewFinalizerCapability, boolean>>;
/** Adapter shape for finalizing live previews. */
type ChannelMessageLiveFinalizerAdapterShape = {
capabilities?: LivePreviewFinalizerCapabilityMap;
};
/** Adapter shape for live preview and streaming message features. */
type ChannelMessageLiveAdapterShape = {
capabilities?: Partial<Record<ChannelMessageLiveCapability, boolean>>;
finalizer?: ChannelMessageLiveFinalizerAdapterShape;
};
/** Receive acknowledgement timing policy for durable inbound message records. */
type ChannelMessageReceiveAckPolicy = "after_receive_record" | "after_agent_dispatch" | "after_durable_send" | "manual";
/** Adapter receive shape for default and supported inbound acknowledgement policies. */
type ChannelMessageReceiveAdapterShape = {
defaultAckPolicy?: ChannelMessageReceiveAckPolicy;
supportedAckPolicies?: readonly ChannelMessageReceiveAckPolicy[];
};
/** Full message adapter shape composed from send, durable-final, live, and receive facets. */
type ChannelMessageAdapterShape<TConfig = OpenClawConfig, TSendResult extends ChannelMessageSendResult = ChannelMessageSendResult> = {
id?: string;
durableFinal?: ChannelMessageDurableFinalAdapter;
send?: ChannelMessageSendAdapter<TConfig, TSendResult>;
live?: ChannelMessageLiveAdapterShape;
receive?: ChannelMessageReceiveAdapterShape;
};
//#endregion
//#region src/channels/plugins/conversation-read-origin.d.ts
/**
* Server-owned origin for one tool or message-action invocation.
*
* Missing and unknown values must remain delegated; callers must never derive
* this from model arguments, provider parameters, config, or persisted state.
*/
type ConversationReadInvocationOrigin = "delegated" | "direct-operator";
//#endregion
//#region src/channels/plugins/message-capabilities.d.ts
/**
* Channel message capabilities advertised through plugin discovery hooks.
*/
declare const CHANNEL_MESSAGE_CAPABILITIES: readonly ["presentation", "delivery-pin"];
/**
* Message capability union derived from the canonical capability list.
*/
type ChannelMessageCapability = (typeof CHANNEL_MESSAGE_CAPABILITIES)[number];
//#endregion
//#region src/channels/plugins/legacy-state-migration.types.d.ts
type ChannelLegacyStateMigrationPlan = {
kind: "copy" | "move";
label: string;
sourcePath: string;
targetPath: string;
} | {
kind: "plugin-state-import";
label: string;
sourcePath: string;
targetPath: string;
pluginId: string;
namespace: string;
maxEntries: number;
defaultTtlMs?: number;
scopeKey: string;
stateDir?: string;
cleanupSource?: "rename" | "remove";
cleanupWhenEmpty?: boolean;
/** Deletes a non-file legacy source (e.g. plugin-state rows) once all entries are covered. */
removeSource?: () => void | Promise<void>;
preview?: string;
shouldReplaceExistingEntry?: (params: {
key: string;
existingValue: unknown;
incomingValue: unknown;
}) => boolean | Promise<boolean>;
/**
* `timestamp` (epoch ms) and `ttlMs` order entries newest-first when capacity forces a
* partial import; `timestamp` is also persisted as the migrated row's creation time so
* cap eviction keeps treating imported rows as old as their legacy source.
*/
readEntries: () => Array<{
key: string;
value: unknown;
ttlMs?: number;
timestamp?: number;
}> | Promise<Array<{
key: string;
value: unknown;
ttlMs?: number;
timestamp?: number;
}>>;
};
//#endregion
//#region src/channels/plugins/setup-input.d.ts
type ChannelSetupEnvelope = {
name?: string;
token?: string;
tokenFile?: string;
useEnv?: boolean;
defaultTo?: string;
allowFrom?: string[];
};
/**
* Compatibility fields with known published readers in the 2026-07-22 registry sweep.
* Each field is deleted as soon as no published plugin reads it; no version boundary is needed.
*/
type DeprecatedChannelSetupFields = {
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
privateKey?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
secret?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
botToken?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
appToken?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
signingSecret?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
mode?: "socket" | "http" | "relay";
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
cliPath?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
authDir?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
httpUrl?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
httpPort?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
webhookPath?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
webhookUrl?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
userId?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
accessToken?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
password?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
deviceName?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
url?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
baseUrl?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
code?: string;
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
groupChannels?: string[];
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
dmAllowlist?: string[];
/** @deprecated Declare this field in the owning plugin's setup input type: https://docs.openclaw.ai/plugins/sdk-setup#channel-owned-setup-input-fields. Removed once no published plugin reads it. */
autoDiscoverChannels?: boolean;
};
/** Generic setup envelope used by CLI, onboarding, and channel-owned setup adapters. */
type ChannelSetupInput = ChannelSetupEnvelope & DeprecatedChannelSetupFields;
//#endregion
//#region src/channels/plugins/types.core.d.ts
type ChannelExposure = {
configured?: boolean;
setup?: boolean;
docs?: boolean;
};
type ChannelOutboundTargetMode = "explicit" | "implicit" | "heartbeat";
/** Agent tool registered by a channel plugin. */
type ChannelAgentTool = AgentTool;
/** Lazy agent-tool factory used when tool availability depends on config. */
type ChannelAgentToolFactory = (params: {
cfg?: OpenClawConfig;
}) => ChannelAgentTool[];
/**
* Discovery-time inputs passed to channel action adapters when the core is
* asking what an agent should be allowed to see. This is intentionally
* smaller than execution context: it carries routing/account scope, but no
* tool params or runtime handles.
*/
type ChannelMessageActionDiscoveryContext = {
cfg: OpenClawConfig;
chatType?: ChatType | null;
currentChannelId?: string | null;
currentChannelProvider?: string | null;
currentThreadTs?: string | null;
currentMessageId?: string | number | null;
accountId?: string | null;
sessionKey?: string | null;
sessionId?: string | null;
agentId?: string | null;
requesterSenderId?: string | null;
senderIsOwner?: boolean;
};
/**
* Plugin-owned schema fragments for the shared `message` tool.
* `current-channel` means expose the fields only when that provider is the
* active runtime channel. `all-configured` keeps the fields visible even while
* another configured channel is active, which is useful for cross-channel
* sends from cron or isolated agents.
*/
type ChannelMessageToolSchemaContribution = {
properties: Record<string, TSchema>;
/**
* Actions whose validation depends on this schema fragment. Cross-channel
* discovery can hide only these actions when the fragment is current-channel
* scoped. Omit to keep the legacy conservative behavior.
*/
actions?: readonly ChannelMessageActionName[] | null;
visibility?: "current-channel" | "all-configured";
};
type ChannelMessageToolMediaSourceParams = readonly string[] | Partial<Record<ChannelMessageActionName, readonly string[]>>;
type ChannelMessageToolDiscovery = {
actions?: readonly ChannelMessageActionName[] | null;
capabilities?: readonly ChannelMessageCapability[] | null;
schema?: ChannelMessageToolSchemaContribution | ChannelMessageToolSchemaContribution[] | null;
/**
* Plugin-owned message-tool params that carry media sources.
* Core uses this to derive sandbox path normalization and host media-access
* hints without hardcoding plugin-specific param names. Prefer scoping keys
* by action so unrelated actions do not inherit another action's media args.
*/
mediaSourceParams?: ChannelMessageToolMediaSourceParams | null;
};
type ChannelStatusIssue = {
channel: ChannelId$1;
accountId: string;
kind: "intent" | "permissions" | "config" | "auth" | "runtime";
message: string;
fix?: string;
};
type ChannelAccountState = "linked" | "not linked" | "configured" | "not configured" | "enabled" | "disabled";
type ChannelHeartbeatDeps = {
webAuthExists?: () => Promise<boolean>;
hasActiveWebListener?: (accountId?: string) => boolean;
};
/** User-facing metadata used in docs, pickers, and setup surfaces. */
type ChannelMeta = {
id: ChannelId$1;
label: string;
selectionLabel: string;
docsPath: string;
docsLabel?: string;
blurb: string;
order?: number;
aliases?: readonly string[];
selectionDocsPrefix?: string;
selectionDocsOmitLabel?: boolean;
selectionExtras?: readonly string[];
detailLabel?: string;
systemImage?: string;
markdownCapable?: boolean;
exposure?: ChannelExposure;
quickstartAllowFrom?: boolean;
forceAccountBinding?: boolean;
preferSessionLookupForAnnounceTarget?: boolean;
preferOver?: readonly string[];
};
/** Snapshot row returned by channel status and lifecycle surfaces. */
type ChannelAccountSnapshot = {
accountId: string;
name?: string;
enabled?: boolean;
configured?: boolean;
statusState?: string;
linked?: boolean;
running?: boolean;
connected?: boolean;
restartPending?: boolean;
reconnectAttempts?: number;
lastConnectedAt?: number | null;
lastDisconnect?: string | {
at: number;
status?: number;
error?: string;
loggedOut?: boolean;
} | null;
lastMessageAt?: number | null;
lastEventAt?: number | null;
lastTransportActivityAt?: number | null;
stateReason?: string;
lastError?: string | null;
/**
* Legacy channel-authored health label; channel plugins should publish `lifecycle` instead.
* Core-derived policy writes remain supported. There is no removal date; removal awaits
* external plugin adoption.
*/
healthState?: string;
/**
* Recorded account lifecycle, independent of inferred transport health.
* Optional so channels that never publish lifecycle remain unaffected.
*/
lifecycle?: "starting" | "ready" | "recovering" | "blocked" | "stopped";
/**
* Inbound admission, which is a different failure domain from `connected`.
* Optional-`true` on purpose: there is no `false` to mistake for "unknown",
* so the 20+ channels that never report ingress at all stay unaffected.
*/
ingressUnavailable?: true;
terminalDisconnect?: boolean;
lastStartAt?: number | null;
lastStopAt?: number | null;
lastInboundAt?: number | null;
lastOutboundAt?: number | null;
busy?: boolean;
activeRuns?: number;
lastRunActivityAt?: number | null;
activeRunStartedAt?: number | null;
mode?: string;
dmPolicy?: string;
allowFrom?: string[];
tokenSource?: string;
botTokenSource?: string;
appTokenSource?: string;
userTokenSource?: string;
signingSecretSource?: string;
tokenStatus?: string;
botTokenStatus?: string;
appTokenStatus?: string;
signingSecretStatus?: string;
userTokenStatus?: string;
apiCredentialStatus?: "available" | "configured_unavailable" | "missing";
identity?: string;
credentialSource?: string;
secretSource?: string;
audienceType?: string;
audience?: string;
webhookPath?: string;
webhookUrl?: string;
baseUrl?: string;
allowUnmentionedGroups?: boolean;
cliPath?: string | null;
dbPath?: string | null;
port?: number | null;
probe?: unknown;
lastProbeAt?: number | null;
audit?: unknown;
application?: unknown;
bot?: unknown;
publicKey?: string | null;
profile?: unknown;
channelAccessToken?: string;
channelSecret?: string;
};
type ChannelLogSink = {
info: (msg: string) => void;
warn: (msg: string) => void;
error: (msg: string) => void;
debug?: (msg: string) => void;
};
type ChannelGroupContext = {
cfg: OpenClawConfig;
groupId?: string | null;
/** Human label for channel-like group conversations (e.g. #general). */
groupChannel?: string | null;
groupSpace?: string | null;
accountId?: string | null;
/** Trusted host instruction to ignore toolsBySender for non-ingress work. */
senderPolicyMode?: "always" | "never";
senderId?: string | null;
senderName?: string | null;
senderUsername?: string | null;
senderE164?: string | null;
};
/** TTS voice delivery behavior advertised by a channel plugin. */
/**
* Container tokens (file-extension shape, no leading dot) that the host
* TTS pipeline knows how to pre-transcode synthesized audio into.
* Channels that benefit from a specific container — currently only
* iMessage, which needs Apple's native voice-memo CAF descriptor — name
* one here. Adding a new entry requires extending the host transcoder
* recipe table in lockstep so a typed declaration cannot silently no-op.
*/
type PreferredAudioFileFormat = "caf";
type ChannelTtsVoiceDeliveryCapabilities = {
synthesisTarget: "audio-file" | "voice-note";
transcodesAudio?: boolean;
audioFileFormats?: readonly string[];
/** Voice notes can carry the final reply text as a visible caption. */
captionedFinalText?: boolean;
/**
* Optional preferred audio container the channel wants for voice-memo
* delivery. When set and the host can transcode (e.g. `afconvert` on
* macOS), the TTS pipeline pre-encodes synthesized audio to this format
* before handing it to the channel. Useful for channels (such as
* iMessage) whose downstream attempts its own container conversion
* that races against the upload write and fails.
*/
preferAudioFileFormat?: PreferredAudioFileFormat;
};
/** Static capability flags advertised by a channel plugin. */
type ChannelCapabilities = {
chatTypes: Array<ChatType | "thread">;
polls?: boolean;
reactions?: boolean;
edit?: boolean;
unsend?: boolean;
reply?: boolean;
effects?: boolean;
groupManagement?: boolean;
threads?: boolean;
media?: boolean;
tts?: {
voice?: ChannelTtsVoiceDeliveryCapabilities;
};
nativeCommands?: boolean;
blockStreaming?: boolean;
};
type ChannelSecurityDmPolicy = {
policy: string;
allowFrom?: Array<string | number> | null;
policyPath?: string;
allowFromPath: string;
approveHint: string;
normalizeEntry?: (raw: string) => string;
classifyEntryAuthentication?: (raw: string) => IdentifierAuthentication | undefined;
};
type ChannelSecurityContext<ResolvedAccount = unknown> = {
cfg: OpenClawConfig;
accountId?: string | null;
account: ResolvedAccount;
};
type ChannelMentionAdapter = {
stripRegexes?: (params: {
ctx: MsgContext;
cfg: OpenClawConfig | undefined;
agentId?: string;
}) => RegExp[];
stripPatterns?: (params: {
ctx: MsgContext;
cfg: OpenClawConfig | undefined;
agentId?: string;
}) => string[];
stripMentions?: (params: {
text: string;
ctx: MsgContext;
cfg: OpenClawConfig | undefined;
agentId?: string;
}) => string;
};
type ChannelStreamingAdapter = {
blockStreamingCoalesceDefaults?: {
minChars: number;
idleMs: number;
};
};
type ChannelCrossContextPresentationFactory = (params: {
originLabel: string;
message: string;
cfg: OpenClawConfig;
accountId?: string | null;
}) => MessagePresentation;
type ChannelReplyTransport = {
replyToId?: string | null;
threadId?: string | number | null;
};
type ChannelFocusedBindingContext = {
conversationId: string;
parentConversationId?: string;
placement: "current" | "child";
labelNoun: string;
};
type ChannelOutboundSessionRoute = {
sessionKey: string;
baseSessionKey: string;
/** Route authority for explicit recipient session selection. */
recipientSessionExact?: boolean | "direct-alias" | "delivery-identity";
peer: {
kind: ChatType;
id: string;
};
chatType: "direct" | "group" | "channel";
from: string;
to: string;
threadId?: string | number;
};
type ChannelThreadingAdapter = {
/**
* Where the transport keeps thread identity.
* "address" (default): the thread is part of the routing address (own channel id, topic id
* in the target tuple), fully known before send.
* "message": thread identity lives on a message (e.g. Slack thread_ts) — replying to a
* message enters its thread, and routes can discover a session-scoping thread only after
* target lookup.
*/
threadAddressing?: "address" | "message";
matchesToolContextTarget?: (params: {
target: string;
toolContext: ChannelThreadingToolContext;
}) => boolean;
resolveReplyToMode?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
chatType?: string | null;
}) => "off" | "first" | "all" | "batched";
/**
* When replyToMode is "off", allow explicit reply tags/directives to keep replyToId.
*
* Default in shared reply flow: true for known providers; per-channel opt-out supported.
*/
allowExplicitReplyTagsWhenOff?: boolean;
/**
* @deprecated Use allowExplicitReplyTagsWhenOff.
*
* Deprecated alias for allowExplicitReplyTagsWhenOff.
* Kept for compatibility with older plugin surfaces.
*/
allowTagsWhenOff?: boolean;
buildToolContext?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
context: ChannelThreadingContext;
hasRepliedRef?: {
value: boolean;
};
}) => ChannelThreadingToolContext | undefined;
resolveAutoThreadId?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
to: string;
toolContext?: ChannelThreadingToolContext;
replyToId?: string | null;
}) => string | undefined;
resolveCurrentChannelId?: (params: {
to: string;
threadId?: string | number | null;
}) => string | undefined;
resolveReplyTransport?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
threadId?: string | number | null;
replyToId?: string | null;
/** True when replyToId came from an explicit payload target or reply tag. */
replyToIsExplicit?: boolean;
/** Existing payload intent to reply to the current conversation, not an arbitrary target. */
replyToCurrent?: boolean;
replyDelivery?: ReplyDeliveryContext;
}) => ChannelReplyTransport | null;
resolveFocusedBinding?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
context: ChannelThreadingContext;
}) => ChannelFocusedBindingContext | null;
};
type ChannelThreadingContext = {
Channel?: string;
From?: string;
To?: string;
ChatType?: string;
CurrentMessageId?: string | number;
/** Effective channel reply mode prepared for this turn. */
ReplyToMode?: MsgContext["ReplyToMode"];
ReplyToId?: string;
ReplyToIdFull?: string;
ThreadLabel?: string;
MessageThreadId?: string | number;
TransportThreadId?: string | number;
/** Platform-native channel/conversation id (e.g. Slack DM channel "D…" id). */
NativeChannelId?: string;
};
type ChannelThreadingToolContext = {
currentChannelId?: string;
/** Trusted normalized conversation kind for the active inbound turn. */
currentChatType?: ChatType;
/** Routable messaging target when it differs from the platform-native channel id. */
currentMessagingTarget?: string;
currentGraphChannelId?: string;
currentChannelProvider?: ChannelId$1;
currentThreadTs?: string;
currentMessageId?: string | number;
replyToMode?: "off" | "first" | "all" | "batched";
hasRepliedRef?: {
value: boolean;
};
/** True when posting at the parent conversation root would leak a thread-originated reply. */
sameChannelThreadRequired?: boolean;
/**
* When true, skip cross-context decoration (e.g., "[from X]" prefix).
* Use this for direct tool invocations where the agent is composing a new message,
* not forwarding/relaying a message from another conversation.
*/
skipCrossContextDecoration?: boolean;
};
/** Channel-owned messaging helpers for target parsing, routing, and payload shaping. */
type ChannelMessagingAdapter = {
/**
* Provider prefixes accepted in explicit targets, including aliases not used
* as channel-selection aliases. Core uses these to reject cross-channel
* targets before plugin-specific normalization.
*/
targetPrefixes?: readonly string[];
/** Re-resolve the current owner when channel behavior exceeds generic bindings. */
resolveConversationRouteOwner?: (params: {
cfg: OpenClawConfig;
accountId: string;
conversation: {
kind: "direct" | "group" | "channel";
peerId: string;
/** Canonical delivery target when it differs from the routing peer. */
target?: string;
threadId?: string;
nativeChannelId?: string;
context?: {
parentPeerId?: string;
guildId?: string;
teamId?: string;
memberRoleIds?: string[];
};
};
}) => {
kind: "agent";
agentId: string;
} | {
kind: "plugin";
pluginId: string;
fallbackAgentId: string;
} | {
kind: "unavailable";
} | null | undefined;
/** DM targets rebuilt from session keys require an explicit `user:` kind prefix. */
directTargetStyle?: "user-prefixed";
/** Equality rule for ids carried by prefixed outbound targets. */
targetIdComparison?: "case-sensitive" | "lowercase";
/** Bare numeric conversation/topic shorthand is valid for this channel. */
numericTopicShorthand?: true;
normalizeTarget?: (raw: string) => string | undefined;
defaultMarkdownTableMode?: MarkdownTableMode$1;
normalizeExplicitSessionKey?: (params: {
sessionKey: string;
ctx: MsgContext;
}) => string | undefined;
deriveLegacySessionChatType?: (sessionKey: string) => "direct" | "group" | "channel" | undefined;
isLegacyGroupSessionKey?: (key: string) => boolean;
canonicalizeLegacySessionKey?: (params: {
key: string;
agentId: string;
}) => string | null | undefined;
resolveLegacyGroupSessionKey?: (ctx: MsgContext) => {
key: string;
channel: string;
id: string;
chatType: "group" | "channel";
} | null;
resolveInboundAttachmentRoots?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => string[];
resolveRemoteInboundAttachmentRoots?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => string[];
/**
* Bundled plugins that need inbound conversation resolution before runtime
* bootstrap can mirror it through a top-level `thread-binding-api.ts` surface.
*/
resolveInboundConversation?: (params: {
from?: string;
to?: string;
conversationId?: string;
threadId?: string | number;
threadParentId?: string | number;
isGroup: boolean;
}) => {
conversationId?: string;
parentConversationId?: string;
} | null;
resolveDeliveryTarget?: (params: {
conversationId: string;
parentConversationId?: string;
}) => {
to?: string;
threadId?: string;
} | null;
/**
* Canonical plugin-owned session conversation grammar.
* Use this when the provider encodes thread or scoped-conversation semantics
* inside `rawId` (for example Telegram topics or Feishu sender scopes).
* Return `baseConversationId` and `parentConversationCandidates` here when
* you can so parsing and inheritance stay in one place.
* `parentConversationCandidates`, when present, should be ordered from the
* narrowest parent to the broadest/base conversation.
* Bundled plugins that need the same grammar before runtime bootstrap can
* mirror this contract through a top-level `session-key-api.ts` surface.
*/
resolveSessionConversation?: (params: {
kind: "group" | "channel";
rawId: string;
}) => {
id: string;
threadId?: string | null;
baseConversationId?: string | null;
parentConversationCandidates?: string[];
} | null;
/**
* @deprecated Return parentConversationCandidates from resolveSessionConversation.
*
* Legacy compatibility hook for parent fallbacks when a plugin does not need
* to customize `id` or `threadId`. Core only uses this when
* `resolveSessionConversation(...)` does not return
* `parentConversationCandidates`.
*/
resolveParentConversationCandidates?: (params: {
kind: "group" | "channel";
rawId: string;
}) => string[] | null;
resolveSessionTarget?: (params: {
kind: "group" | "channel";
id: string;
threadId?: string | null;
}) => string | undefined;
/**
* Lightweight chat-type inference used before directory lookup so plugins can
* steer peer-vs-group resolution without reimplementing host search flow.
*/
inferTargetChatType?: (params: {
to: string;
}) => ChatType | undefined;
/**
* Preserve the session thread/topic id for heartbeat replies when that thread
* is part of the destination identity, not a transient reply thread.
*/
preserveHeartbeatThreadIdForGroupRoute?: boolean;
buildCrossContextPresentation?: ChannelCrossContextPresentationFactory;
transformReplyPayload?: (params: {
payload: ReplyPayload;
cfg: OpenClawConfig;
accountId?: string | null;
}) => ReplyPayload | null;
hasStructuredReplyPayload?: (params: {
payload: ReplyPayload;
}) => boolean;
targetResolver?: {
looksLikeId?: (raw: string, normalized?: string) => boolean;
hint?: string;
/** Bare words that are command/session references for this channel, not literal destinations. */
reservedLiterals?: readonly string[];
/**
* Plugin-owned fallback for explicit/native targets or post-directory-miss
* resolution. This should complement directory lookup, not duplicate it.
*/
resolveTarget?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
input: string;
normalized: string;
preferredKind?: ChannelDirectoryEntryKind | "channel";
}) => Promise<{
to: string;
kind: ChannelDirectoryEntryKind | "channel";
display?: string;
source?: "normalized" | "directory";
} | null>;
};
formatTargetDisplay?: (params: {
target: string;
display?: string;
kind?: ChannelDirectoryEntryKind;
}) => string;
/**
* Provider-specific session-route builder used after target resolution.
* Keep session-key orchestration in core and channel-native routing rules here.
* Set `recipientSessionExact` to true only when the target maps unambiguously
* to the same canonical session that inbound delivery uses. `direct-alias`
* may be used when only the direct chat kind is authoritative.
* `delivery-identity` requires a stable outbound-only recipient identity and
* a provider-keyed session that stays isolated from the agent main session.
*/
resolveOutboundSessionRoute?: (params: {
cfg: OpenClawConfig;
agentId: string;
accountId?: string | null;
target: string;
currentSessionKey?: string;
resolvedTarget?: {
to: string;
kind: ChannelDirectoryEntryKind | "channel";
display?: string;
source: "normalized" | "directory";
};
replyToId?: string | null;
threadId?: string | number | null;
}) => ChannelOutboundSessionRoute | Promise<ChannelOutboundSessionRoute | null> | null;
};
type ChannelAgentPromptAdapter = {
messageToolHints?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => string[];
messageToolCapabilities?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => string[] | undefined;
inboundFormattingHints?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => {
text_markup: string;
rules: string[];
} | undefined;
reactionGuidance?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => {
level: "minimal" | "extensive";
channelLabel?: string;
} | undefined;
};
type ChannelDirectoryEntryKind = "user" | "group" | "channel";
type ChannelDirectoryEntry = {
kind: ChannelDirectoryEntryKind;
id: string;
name?: string;
handle?: string;
avatarUrl?: string;
rank?: number;
raw?: unknown;
};
type ChannelMessageActionName = ChannelMessageActionName$1;
/** Execution context passed to channel-owned actions on the shared `message` tool. */
type ChannelMessageActionContext = {
channel: ChannelId$1;
action: ChannelMessageActionName;
cfg: OpenClawConfig;
params: Record<string, unknown>;
reply?: OutboundReplyFacts;
mediaAccess?: OutboundMediaAccess;
mediaLocalRoots?: readonly string[];
mediaReadFile?: (filePath: string) => Promise<Buffer>;
accountId?: string | null;
/** Trusted originating account id paired with requesterSenderId. */
requesterAccountId?: string | null;
/**
* Trusted sender id from inbound context. This is server-injected and must
* never be sourced from tool/model-controlled params.
*/
requesterSenderId?: string | null;
/** Trusted owner identity bit from command/channel-action auth. */
senderIsOwner?: boolean;
/**
* Server-owned origin for this operation. Missing values are delegated.
* Plugins must use it only for conversation-read visibility policy.
*/
conversationReadOrigin?: ConversationReadInvocationOrigin;
sessionKey?: string | null;
sessionId?: string | null;
inboundEventKind?: InboundEventKind;
agentId?: string | null;
gateway?: {
url?: string;
token?: string;
timeoutMs?: number;
clientName: GatewayClientName;
clientDisplayName?: string;
mode: GatewayClientMode;
};
toolContext?: ChannelThreadingToolContext;
dryRun?: boolean;
gatewayClientScopes?: readonly string[];
/**
* Server-owned fact: this caller receives proven-not-sent failures and resends
* them. Plugins forward it into durable sends so recovery does not replay too.
*/
deliveryRetryOwner?: "caller";
};
type ChannelToolSend = {
to: string;
accountId?: string | null;
threadId?: string | null;
/** True when the native provider send may inherit the active conversation thread. */
threadImplicit?: boolean;
threadSuppressed?: boolean;
};
type ChannelMessagePreparedSendPayloadContext = {
ctx: ChannelMessageActionContext;
to: string;
payload: ReplyPayload;
replyToId?: string | null;
/** Preserve caller intent when plugins translate reply ids into durable payloads. */
replyToIdSource?: "explicit" | "implicit";
threadId?: string | number | null;
};
/** Channel-owned action surface for the shared `message` tool. */
type ChannelMessageActionAdapter = {
/**
* Unified discovery surface for the shared `message` tool.
* This returns the scoped actions,
* capabilities, schema fragments, and any plugin-owned media-source params
* together so they cannot drift.
*/
describeMessageTool: (params: ChannelMessageActionDiscoveryContext) => ChannelMessageToolDiscovery | null | undefined;
/** Delegate conversation-read authorization to this adapter for bundled registrations only. */
providerOwnedReadGates?: true | readonly ChannelMessageActionName[];
supportsAction?: (params: {
action: ChannelMessageActionName;
}) => boolean;
resolveExecutionMode?: (params: {
action: ChannelMessageActionName;
}) => "local" | "gateway";
resolveCliActionRequest?: (params: {
action: ChannelMessageActionName;
args: Record<string, unknown>;
}) => {
action: ChannelMessageActionName;
args: Record<string, unknown>;
};
messageActionTargetAliases?: Partial<Record<ChannelMessageActionName, {
aliases: string[];
/** Alias fields that identify the destination conversation, not an existing message. */
deliveryTargetAliases?: string[];
/** Convert typed owner fields such as chatId into the canonical shared target shape. */
resolveDeliveryTarget?: (params: {
args: Record<string, unknown>;
}) => string | undefined;
/**
* Prove that provider-native aliases name the trusted current conversation.
* Core consults this only for host-owned bundled registrations.
*/
matchesCurrentConversation?: (params: {
args: Record<string, unknown>;
accountId: string;
toolContext: ChannelThreadingToolContext;
}) => boolean;
}>>;
requiresTrustedRequesterSender?: (params: {
action: ChannelMessageActionName;
toolContext?: ChannelThreadingToolContext;
}) => boolean;
/** Return true when a provider-native tool invocation has a visible or destructive side effect. */
isToolDeliveryAction?: (params: {
args: Record<string, unknown>;
}) => boolean;
extractToolSend?: (params: {
args: Record<string, unknown>;
}) => ChannelToolSend | null;
/** Recover the actual resolved send route from a successful action result. */
extractToolSendResult?: (params: {
result: unknown;
send: ChannelToolSend;
}) => ChannelToolSend | null;
/**
* Translate generic `message(action=send)` arguments into the payload core
* should persist, retry, recover, and ack. Return null to keep the legacy
* plugin-owned action path for sends that cannot be represented durably.
*/
prepareSendPayload?: (params: ChannelMessagePreparedSendPayloadContext) => ReplyPayload | null | undefined | Promise<ReplyPayload | null | undefined>;
/**
* Prefer this for channel-specific poll semantics or extra poll parameters.
* Core only parses the shared poll model when falling back to `outbound.sendPoll`.
*/
handleAction?: (ctx: ChannelMessageActionContext) => Promise<AgentToolResult<unknown>>;
};
type ChannelPollResult = Pick<MessageReceiptSourceResult, "messageId" | "toJid" | "channelId" | "conversationId" | "pollId"> & {
messageId: string;
receipt?: MessageReceipt;
};
/** Shared poll input after core has normalized the common poll model. */
type ChannelPollContext = Pick<ChannelMessageSendPollContext, "cfg" | "to" | "poll" | "accountId" | "threadId" | "silent" | "isAnonymous" | "gatewayClientScopes" | "onPlatformSendDispatch" | "assertDirectAdapterHandoff"> & {
content?: string;
/** Trusted originating turn context for channel-owned delivery correlation. */
sessionKey?: string;
inboundEventKind?: InboundEventKind;
};
//#endregion
//#region src/config/legacy.shared.d.ts
type LegacyConfigRule = {
path: string[];
message: string;
match?: (value: unknown, root: Record<string, unknown>) => boolean;
requireSourceLiteral?: boolean;
};
//#endregion
//#region src/channels/plugins/approval-native.types.d.ts
/**
* Native channel surface that can receive approval prompts.
*/
type ChannelApprovalNativeSurface = "origin" | "approver-dm";
/**
* Native channel destination for an approval prompt.
*/
type ChannelApprovalNativeTarget = {
to: string;
threadId?: string | number | null;
};
/**
* Preferred native delivery surface for approval prompts.
*/
type ChannelApprovalNativeDeliveryPreference = ChannelApprovalNativeSurface | "both";
/**
* Approval request shapes supported by native channel approval delivery.
*/
type ChannelApprovalNativeRequest = ExecApprovalRequest | PluginApprovalRequest$1 | SystemAgentApprovalRequest;
/**
* Capabilities returned by native channel approval delivery inspection.
*/
type ChannelApprovalNativeDeliveryCapabilities = {
enabled: boolean;
preferredSurface: ChannelApprovalNativeDeliveryPreference;
supportsOriginSurface: boolean;
supportsApproverDmSurface: boolean;
notifyOriginWhenDmOnly?: boolean;
};
/**
* Adapter implemented by channel plugins that support native approval delivery.
*/
type ChannelApprovalNativeAdapter = {
describeDeliveryCapabilities: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
approvalKind: ChannelApprovalKind;
request: ChannelApprovalNativeRequest;
}) => ChannelApprovalNativeDeliveryCapabilities;
resolveOriginTarget?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
approvalKind: ChannelApprovalKind;
request: ChannelApprovalNativeRequest;
}) => ChannelApprovalNativeTarget | null | Promise<ChannelApprovalNativeTarget | null>;
resolveApproverDmTargets?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
approvalKind: ChannelApprovalKind;
request: ChannelApprovalNativeRequest;
}) => ChannelApprovalNativeTarget[] | Promise<ChannelApprovalNativeTarget[]>;
};
//#endregion
//#region src/infra/approval-native-delivery.d.ts
/** One native approval delivery target selected by the channel adapter plan. */
type ChannelApprovalNativePlannedTarget = {
surface: ChannelApprovalNativeSurface;
target: ChannelApprovalNativeTarget;
reason: "preferred" | "fallback";
};
//#endregion
//#region src/infra/approval-native-runtime-types.d.ts
/** Prepared delivery target plus the stable key used to avoid duplicate native messages. */
type PreparedChannelNativeApprovalTarget<TPreparedTarget> = {
dedupeKey: string;
target: TPreparedTarget;
};
//#endregion
//#region src/infra/approval-view-model.types.d.ts
type ApprovalPhase = "pending" | "resolved" | "expired";
/** Button or command action shown with a pending approval prompt. */
type ApprovalActionView = {
kind?: "command" | "decision";
decision: ExecApprovalDecision;
label: string;
style: NonNullable<MessagePresentationButton["style"]>;
action?: MessagePresentationAction;
/** Copyable command fallback for non-interactive surfaces. */
command: string;
};
/** Label/value metadata row rendered with an approval prompt. */
type ApprovalMetadataView = {
label: string;
value: string;
};
type ApprovalViewBase = {
approvalId: string;
approvalKind: ChannelApprovalKind;
phase: ApprovalPhase;
title: string;
description?: string | null;
metadata: ApprovalMetadataView[];
};
/** Shared presentation fields for exec approval views across all phases. */
type ExecApprovalViewBase = ApprovalViewBase & {
approvalKind: "exec";
ask?: string | null;
agentId?: string | null;
warningText?: string | null;
commandAnalysis?: CommandExplanationSummary | null;
commandText: string;
commandPreview?: string | null;
cwd?: string | null;
envKeys?: readonly string[];
host?: string | null;
nodeId?: string | null;
scope?: ApprovalScope | null;
sessionKey?: string | null;
};
/** Pending exec approval view, including executable reply actions. */
type ExecApprovalPendingView = ExecApprovalViewBase & {
phase: "pending";
actions: ApprovalActionView[];
expiresAtMs: number;
};
/** Resolved exec approval view with the recorded decision. */
type ExecApprovalResolvedView = ExecApprovalViewBase & {
phase: "resolved";
decision: ExecApprovalDecision;
resolvedBy?: string | null;
};
/** Expired exec approval view without reply actions. */
type ExecApprovalExpiredView = ExecApprovalViewBase & {
phase: "expired";
};
/** Shared presentation fields for plugin approval views across all phases. */
type PluginApprovalViewBase = ApprovalViewBase & {
approvalKind: "plugin";
agentId?: string | null;
pluginId?: string | null;
scope?: ApprovalScope | null;
toolName?: string | null;
severity: "info" | "warning" | "critical";
};
/** Pending plugin approval view, including executable reply actions. */
type PluginApprovalPendingView = PluginApprovalViewBase & {
phase: "pending";
actions: ApprovalActionView[];
expiresAtMs: number;
};
/** Resolved plugin approval view with the recorded decision. */
type PluginApprovalResolvedView = PluginApprovalViewBase & {
phase: "resolved";
decision: ExecApprovalDecision;
resolvedBy?: string | null;
};
/** Expired plugin approval view without reply actions. */
type PluginApprovalExpiredView = PluginApprovalViewBase & {
phase: "expired";
};
/** Shared presentation fields for OpenClaw system change approvals. */
type SystemAgentApprovalViewBase = ApprovalViewBase & {
approvalKind: "system-agent";
agentId?: string | null;
scope?: null;
commandText: string;
commandPreview?: string | null;
ask?: string | null;
cwd?: string | null;
envKeys?: readonly string[];
host?: string | null;
nodeId?: string | null;
sessionKey?: string | null;
operationSummary: string;
};
/** Pending system change approval view, including executable reply actions. */
type SystemAgentApprovalPendingView = SystemAgentApprovalViewBase & {
phase: "pending";
actions: ApprovalActionView[];
expiresAtMs: number;
};
/** Resolved system change approval view with the recorded decision. */
type SystemAgentApprovalResolvedView = SystemAgentApprovalViewBase & {
phase: "resolved";
decision: ExecApprovalDecision;
resolvedBy?: string | null;
applicationStatus?: SystemAgentApprovalApplicationStatus;
terminalStatus?: "expired" | "cancelled";
};
/** Expired system change approval view without reply actions. */
type SystemAgentApprovalExpiredView = SystemAgentApprovalViewBase & {
phase: "expired";
};
/** Any pending approval view that still accepts a user decision. */
type PendingApprovalView = ExecApprovalPendingView | PluginApprovalPendingView | SystemAgentApprovalPendingView;
/** Any approval view after a decision was recorded. */
type ResolvedApprovalView = ExecApprovalResolvedView | PluginApprovalResolvedView | SystemAgentApprovalResolvedView;
/** Any approval view after it can no longer be acted on. */
type ExpiredApprovalView = ExecApprovalExpiredView | PluginApprovalExpiredView | SystemAgentApprovalExpiredView;
//#endregion
//#region src/infra/approval-handler-runtime-types.d.ts
/** Backward-compatible approval request accepted by public plugin callbacks. */
type ApprovalRequest = ApprovalRequestInput;
/** Union of approval resolution events a native approval handler can finalize. */
type ApprovalResolved = ExecApprovalResolved | PluginApprovalResolved | SystemAgentApprovalResolved;
/** Shared context passed to channel-native approval hooks. */
type ChannelApprovalCapabilityHandlerContext = {
cfg: OpenClawConfig;
accountId?: string | null;
gatewayUrl?: string;
context?: unknown;
};
/** Result instruction for updating, deleting, clearing, or leaving a delivered approval entry. */
type ChannelApprovalNativeFinalAction<TPayload> = {
kind: "update";
payload: TPayload;
} | {
kind: "delete";
} | {
kind: "clear-actions";
} | {
kind: "leave";
};
/** Availability gate for deciding whether a channel-native approval runtime can handle work. */
type ChannelApprovalNativeAvailabilityAdapter = {
isConfigured: (params: ChannelApprovalCapabilityHandlerContext) => boolean;
shouldHandle: (params: ChannelApprovalCapabilityHandlerContext & {
request: ApprovalRequest;
/** Payload-derived owner; channel adapters must not infer ownership from the id. */
approvalKind: ChannelApprovalKind;
}) => boolean;
};
/** Builds channel-native payloads for pending, resolved, and expired approval views. */
type ChannelApprovalNativePresentationAdapter<TPendingPayload = unknown, TFinalPayload = unknown> = {
buildPendingPayload: (params: ChannelApprovalCapabilityHandlerContext & {
request: ApprovalRequest;
approvalKind: ChannelApprovalKind;
nowMs: number;
view: PendingApprovalView;
}) => TPendingPayload | Promise<TPendingPayload>;
buildResolvedResult: (params: ChannelApprovalCapabilityHandlerContext & {
request: ApprovalRequest;
resolved: ApprovalResolved;
view: ResolvedApprovalView;
entry: unknown;
}) => ChannelApprovalNativeFinalAction<TFinalPayload> | Promise<ChannelApprovalNativeFinalAction<TFinalPayload>>;
buildExpiredResult: (params: ChannelApprovalCapabilityHandlerContext & {
request: ApprovalRequest;
view: ExpiredApprovalView;
entry: unknown;
}) => ChannelApprovalNativeFinalAction<TFinalPayload> | Promise<ChannelApprovalNativeFinalAction<TFinalPayload>>;
};
type ChannelApprovalNativeTransportAdapterForView<TPreparedTarget = unknown, TPendingEntry = unknown, TPendingPayload = unknown, TFinalPayload = unknown, TPendingView extends PendingApprovalView = PendingApprovalView> = {
prepareTarget: (params: ChannelApprovalCapabilityHandlerContext & {
plannedTarget: ChannelApprovalNativePlannedTarget;
request: ApprovalRequest;
approvalKind: ChannelApprovalKind;
view: TPendingView;
pendingPayload: TPendingPayload;
}) => PreparedChannelNativeApprovalTarget<TPreparedTarget> | null | Promise<PreparedChannelNativeApprovalTarget<TPreparedTarget> | null>;
deliverPending: (params: ChannelApprovalCapabilityHandlerContext & {
plannedTarget: ChannelApprovalNativePlannedTarget;
preparedTarget: TPreparedTarget;
request: ApprovalRequest;
approvalKind: ChannelApprovalKind;
view: TPendingView;
pendingPayload: TPendingPayload;
}) => TPendingEntry | null | Promise<TPendingEntry | null>;
updateEntry?: (params: ChannelApprovalCapabilityHandlerContext & {
entry: TPendingEntry;
request: ApprovalRequest;
approvalKind: ChannelApprovalKind;
payload: TFinalPayload;
phase: "resolved" | "expired";
}) => Promise<void>;
deleteEntry?: (params: ChannelApprovalCapabilityHandlerContext & {
entry: TPendingEntry;
phase: "resolved" | "expired";
}) => Promise<void>;
};
/** Transport hooks for preparing, delivering, updating, and deleting native approval entries. */
type ChannelApprovalNativeTransportAdapter<TPreparedTarget = unknown, TPendingEntry = unknown, TPendingPayload = unknown, TFinalPayload = unknown> = ChannelApprovalNativeTransportAdapterForView<TPreparedTarget, TPendingEntry, TPendingPayload, TFinalPayload>;
type ChannelApprovalNativeInteractionAdapterForView<TPendingEntry = unknown, TBinding = unknown, TPendingPayload = unknown, TPendingView extends PendingApprovalView = PendingApprovalView> = {
bindPending?: (params: ChannelApprovalCapabilityHandlerContext & {
entry: TPendingEntry;
request: ApprovalRequest;
approvalKind: ChannelApprovalKind;
view: TPendingView;
pendingPayload: TPendingPayload;
}) => TBinding | null | Promise<TBinding | null>;
unbindPending?: (params: ChannelApprovalCapabilityHandlerContext & {
entry: TPendingEntry;
binding: TBinding;
request: ApprovalRequest;
approvalKind: ChannelApprovalKind;
}) => Promise<void> | void;
clearPendingActions?: (params: ChannelApprovalCapabilityHandlerContext & {
entry: TPendingEntry;
phase: "resolved" | "expired";
}) => Promise<void>;
cancelDelivered?: (params: ChannelApprovalCapabilityHandlerContext & {
entry: TPendingEntry;
request: ApprovalRequest;
approvalKind: ChannelApprovalKind;
}) => Promise<void> | void;
};
/** Optional hooks for binding and clearing interactive approval controls. */
type ChannelApprovalNativeInteractionAdapter<TPendingEntry = unknown, TBinding = unknown> = ChannelApprovalNativeInteractionAdapterForView<TPendingEntry, TBinding>;
type ChannelApprovalNativeObserveAdapterForView<TPreparedTarget = unknown, TPendingPayload = unknown, TPendingEntry = unknown, TPendingView extends PendingApprovalView = PendingApprovalView> = {
onDeliveryError?: (params: ChannelApprovalCapabilityHandlerContext & {
error: unknown;
plannedTarget: ChannelApprovalNativePlannedTarget;
request: ApprovalRequest;
approvalKind: ChannelApprovalKind;
view: TPendingView;
pendingPayload: TPendingPayload;
}) => void;
onDuplicateSkipped?: (params: ChannelApprovalCapabilityHandlerContext & {
plannedTarget: ChannelApprovalNativePlannedTarget;
preparedTarget: PreparedChannelNativeApprovalTarget<TPreparedTarget>;
request: ApprovalRequest;
approvalKind: ChannelApprovalKind;
view: TPendingView;
pendingPayload: TPendingPayload;
}) => void;
onDelivered?: (params: ChannelApprovalCapabilityHandlerContext & {
plannedTarget: ChannelApprovalNativePlannedTarget;
preparedTarget: PreparedChannelNativeApprovalTarget<TPreparedTarget>;
request: ApprovalRequest;
approvalKind: ChannelApprovalKind;
view: TPendingView;
pendingPayload: TPendingPayload;
entry: TPendingEntry;
}) => void;
/** Runs after every terminal entry for one approval has been finalized. */
onFinalized?: (params: ChannelApprovalCapabilityHandlerContext & {
request: ApprovalRequest;
approvalKind: ChannelApprovalKind;
phase: "resolved" | "expired";
}) => void;
};
/** Optional observer hooks for delivery errors, duplicates, and successful deliveries. */
type ChannelApprovalNativeObserveAdapter<TPreparedTarget = unknown, TPendingPayload = unknown, TPendingEntry = unknown> = ChannelApprovalNativeObserveAdapterForView<TPreparedTarget, TPendingPayload, TPendingEntry>;
/** Runtime adapter consumed by core after a plugin's strongly typed spec has been erased. */
type ChannelApprovalNativeRuntimeAdapter<TPendingPayload = unknown, TPreparedTarget = unknown, TPendingEntry = unknown, TBinding = unknown, TFinalPayload = unknown> = {
eventKinds?: readonly ChannelApprovalKind[];
/**
* Trusted legacy ownership override retained for compatibility.
* @deprecated Omit this so core derives approval ownership from the request payload.
*/
resolveApprovalKind?: (request: ApprovalRequest) => ChannelApprovalKind;
availability: ChannelApprovalNativeAvailabilityAdapter;
presentation: ChannelApprovalNativePresentationAdapter<TPendingPayload, TFinalPayload>;
transport: ChannelApprovalNativeTransportAdapter<TPreparedTarget, TPendingEntry, TPendingPayload, TFinalPayload>;
interactions?: ChannelApprovalNativeInteractionAdapter<TPendingEntry, TBinding>;
observe?: ChannelApprovalNativeObserveAdapter;
};
//#endregion
//#region src/routing/resolve-route.d.ts
type RoutePeer = {
kind: ChatType;
id: string;
};
type ResolveAgentRouteInput = {
cfg: OpenClawConfig;
channel: string;
/** Known owner when no configured binding matches this route. */
defaultAgentId?: string;
accountId?: string | null;
peer?: RoutePeer | null;
dmScope?: DmScope;
groupScope?: GroupScope;
/** Parent peer for threads — used for binding inheritance when peer doesn't match directly. */
parentPeer?: RoutePeer | null;
guildId?: string | null;
teamId?: string | null;
/** Discord member role IDs — used for role-based agent routing. */
memberRoleIds?: string[];
};
type ResolvedAgentRoute = {
agentId: string;
channel: string;
accountId: string;
/** Effective direct-message scope after a matching binding override. */
dmScope?: DmScope;
groupScope?: GroupScope;
/** Internal session key used for persistence + concurrency. */
sessionKey: string;
/** Convenience alias for direct-chat collapse. */
mainSessionKey: string;
/** Which session should receive inbound last-route updates. */
lastRoutePolicy: "main" | "session";
/** Match description for debugging/logging. */
matchedBy: "binding.peer" | "binding.peer.parent" | "binding.peer.wildcard" | "binding.guild+roles" | "binding.guild" | "binding.team" | "binding.account" | "binding.channel" | "default";
};
declare function buildAgentSessionKey(params: {
agentId: string;
mainKey?: string;
channel: string;
accountId?: string | null;
peer?: RoutePeer | null;
/** DM session scope. */
dmScope?: DmScope;
groupScope?: GroupScope;
identityLinks?: Record<string, string[]>;
}): string;
declare function resolveAgentRoute(input: ResolveAgentRouteInput): ResolvedAgentRoute;
//#endregion
//#region src/runtime.d.ts
type RuntimeExitOptions = {
/** Route ANSI terminal-reset bytes away from structured stdout when needed. */
resetStream?: NodeJS.WriteStream;
};
type RuntimeEnv = {
log: (...args: unknown[]) => void;
error: (...args: unknown[]) => void;
/**
* Exit the process after restoring terminal state.
* Pass `resetStream` to route the ANSI reset sequence to a specific
* stream (e.g. stderr) when structured output on stdout must stay clean.
*/
exit: (code: number, opts?: RuntimeExitOptions) => void;
};
//#endregion
//#region packages/model-catalog-core/src/model-catalog-types.d.ts
/** Supported API protocols for model catalog entries. */
declare const MODEL_CATALOG_APIS: readonly ["openai-completions", "openai-responses", "openai-chatgpt-responses", "anthropic-messages", "google-generative-ai", "google-vertex", "github-copilot", "bedrock-converse-stream", "ollama", "azure-openai-responses"];
/** API protocol for a model catalog entry. */
type ModelCatalogApi = (typeof MODEL_CATALOG_APIS)[number];
/** Supported model thinking/reasoning wire formats. */
declare const MODEL_CATALOG_THINKING_FORMATS: readonly ["openai", "openrouter", "deepseek", "together", "qwen", "qwen-chat-template", "zai"];
/** Thinking/reasoning wire format for model compatibility. */
type ModelCatalogThinkingFormat = (typeof MODEL_CATALOG_THINKING_FORMATS)[number];
/** Compatibility flags and provider-specific routing metadata for one model. */
type ModelCatalogCompatConfig = {
supportsStore?: boolean;
supportsDeveloperRole?: boolean;
supportsReasoningEffort?: boolean;
/** Whether the model accepts the temperature parameter (GPT-5.6 family rejects it). */
supportsTemperature?: boolean;
/** Whether the provider honors top-level `instructions` on Responses requests. */
supportsInstructions?: boolean;
supportsUsageInStreaming?: boolean;
supportsStrictMode?: boolean;
supportsJsonSchemaResponseFormat?: boolean;
maxTokensField?: "max_completion_tokens" | "max_tokens";
requiresToolResultName?: boolean;
requiresAssistantAfterToolResult?: boolean;
requiresThinkingAsText?: boolean;
requiresReasoningContentOnAssistantMessages?: boolean;
openRouterRouting?: ModelCatalogOpenRouterRouting;
vercelGatewayRouting?: ModelCatalogVercelGatewayRouting;
zaiToolStream?: boolean;
cacheControlFormat?: "anthropic";
sendSessionAffinityHeaders?: boolean;
sendSessionIdHeader?: boolean;
supportsEagerToolInputStreaming?: boolean;
supportsLongCacheRetention?: boolean;
supportsPromptCacheKey?: boolean;
supportsTools?: boolean;
/** Code-mode tier consumed by `tools.codeMode.enabled: "auto"`; absent means "capable". */
codeMode?: "preferred" | "capable";
requiresStringContent?: boolean;
strictMessageKeys?: boolean;
toolSchemaProfile?: string;
unsupportedToolSchemaKeywords?: string[];
toolCallArgumentsEncoding?: string;
requiresOpenAiAnthropicToolPayload?: boolean;
thinkingFormat?: ModelCatalogThinkingFormat;
supportedReasoningEfforts?: string[];
reasoningEffortMap?: Record<string, string>;
visibleReasoningDetailTypes?: string[];
};
/** OpenRouter routing preferences copied into request metadata. */
type ModelCatalogOpenRouterRouting = {
allow_fallbacks?: boolean;
require_parameters?: boolean;
data_collection?: "deny" | "allow";
zdr?: boolean;
enforce_distillable_text?: boolean;
order?: string[];
only?: string[];
ignore?: string[];
quantizations?: string[];
sort?: string | {
by?: string;
partition?: string | null;
};
max_price?: {
prompt?: number | string;
completion?: number | string;
image?: number | string;
audio?: number | string;
request?: number | string;
};
preferred_min_throughput?: number | {
p50?: number;
p75?: number;
p90?: number;
p99?: number;
};
preferred_max_latency?: number | {
p50?: number;
p75?: number;
p90?: number;
p99?: number;
};
};
/** Vercel AI Gateway routing preferences. */
type ModelCatalogVercelGatewayRouting = {
only?: string[];
order?: string[];
};
/** Image input limits for a model. */
type ModelCatalogImageInputConfig = {
maxBytes?: number;
maxPixels?: number;
maxSidePx?: number;
preferredSidePx?: number;
tokenMode?: "tile" | "detail" | "provider";
};
/** Media input limits for a model. */
type ModelCatalogMediaInputConfig = {
image?: ModelCatalogImageInputConfig;
};
/** Supported input modality for a model. */
type ModelCatalogInput = "text" | "image" | "document";
/** Model-level thinking settings carried by provider catalog metadata. */
declare const MODEL_CATALOG_THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
type ModelCatalogThinkingLevel = (typeof MODEL_CATALOG_THINKING_LEVELS)[number];
type ModelCatalogThinkingLevelMap = Partial<Record<ModelCatalogThinkingLevel, string | null>>;
/** Discovery lifecycle for a provider catalog. */
type ModelCatalogDiscovery = "static" | "refreshable" | "runtime";
/** Availability state for a model. */
type ModelCatalogStatus = "available" | "preview" | "deprecated" | "disabled";
/** Unified catalog kind across text and generated media models. */
type UnifiedModelCatalogKind = "text" | "voice" | "image_generation" | "video_generation" | "music_generation";
/** Source for unified model catalog entries. */
type UnifiedModelCatalogSource = "manifest" | "provider-index" | "static" | "live" | "cache" | "configured" | "runtime-refresh";
/** Unified model catalog entry for provider/model pickers. */
type UnifiedModelCatalogEntry<TCapabilities = unknown> = {
kind: UnifiedModelCatalogKind;
provider: string;
model: string;
label?: string;
source: UnifiedModelCatalogSource;
default?: boolean;
configured?: boolean;
capabilities?: TCapabilities;
modes?: readonly string[];
authEnvVars?: readonly string[];
docsPath?: string;
fetchedAt?: number;
expiresAt?: number;
warnings?: readonly string[];
};
/** Tiered token cost row. */
type ModelCatalogTieredCost = {
input: number;
output: number;
cacheRead: number;
cacheWrite: number;
range: [number, number] | [number];
};
/** Token cost metadata for one model. */
type ModelCatalogCost = {
input?: number;
output?: number;
cacheRead?: number;
cacheWrite?: number;
tieredPricing?: ModelCatalogTieredCost[];
};
/** Bounded provider-declared context-window choice for one model. */
type ModelCatalogContextWindowOption = {
id: string;
label: string;
contextWindow: number;
};
/** Provider manifest model entry. */
type ModelCatalogModel = {
id: string;
name?: string;
api?: ModelCatalogApi;
baseUrl?: string;
headers?: Record<string, string>;
input?: ModelCatalogInput[];
reasoning?: boolean;
contextWindow?: number;
contextWindows?: ModelCatalogContextWindowOption[];
contextWindowDefault?: string;
contextTokens?: number;
maxTokens?: number;
thinkingLevelMap?: ModelCatalogThinkingLevelMap;
cost?: ModelCatalogCost;
compat?: ModelCatalogCompatConfig;
/**
* Provider/model ref of the same upstream model in another bundled catalog,
* for vendors reachable through several provider ids under different model
* ids. Authoring metadata only: normalization drops it, and the shared-model
* contract test uses it to keep `compat` capability tiers from drifting apart.
*/
upstreamModel?: string;
mediaInput?: ModelCatalogMediaInputConfig;
status?: ModelCatalogStatus;
statusReason?: string;
replaces?: string[];
replacedBy?: string;
tags?: string[];
};
/** Provider manifest catalog entry. */
type ModelCatalogProvider = {
baseUrl?: string;
api?: ModelCatalogApi;
headers?: Record<string, string>;
/** Provider-recommended primary model id. */
defaultModel?: string;
/** Provider-recommended small model id for short internal utility tasks. */
defaultUtilityModel?: string;
models: ModelCatalogModel[];
};
/** Provider alias entry. */
type ModelCatalogAlias = {
provider: string;
api?: ModelCatalogApi;
baseUrl?: string;
};
/** Suppression rule for hiding a provider/model under matching config. */
type ModelCatalogSuppression = {
provider: string;
model: string;
reason?: string;
when?: {
baseUrlHosts?: string[];
providerConfigApiIn?: string[];
};
};
/** Raw model catalog manifest shape. */
type ModelCatalog = {
/** Publication-time opt-in: owned OpenClaw provider id -> models.dev provider id. */
modelsDev?: Record<string, string>;
providers?: Record<string, ModelCatalogProvider>;
aliases?: Record<string, ModelCatalogAlias>;
suppressions?: ModelCatalogSuppression[];
discovery?: Record<string, ModelCatalogDiscovery>;
runtimeAugment?: boolean;
};
//#endregion
//#region packages/model-catalog-core/src/model-catalog-pricing.d.ts
declare const MODEL_PRICING_SOURCES: readonly [{
readonly id: "openCode";
readonly label: "OpenCode";
readonly url: "https://models.opencode.ai/api.json";
readonly authoritative: true;
}, {
readonly id: "venice";
readonly label: "Venice";
readonly url: "https://api.venice.ai/api/v1/models";
readonly authoritative: true;
}, {
readonly id: "chutes";
readonly label: "Chutes";
readonly url: "https://llm.chutes.ai/v1/models";
readonly authoritative: true;
}, {
readonly id: "cerebras";
readonly label: "Cerebras";
readonly url: "https://api.cerebras.ai/public/v1/models";
readonly authoritative: true;
}, {
readonly id: "deepinfra";
readonly label: "DeepInfra";
readonly url: "https://api.deepinfra.com/models/list";
readonly authoritative: true;
}, {
readonly id: "openRouter";
readonly label: "OpenRouter";
readonly url: "https://openrouter.ai/api/v1/models";
readonly authoritative: false;
}, {
readonly id: "liteLLM";
readonly label: "LiteLLM";
readonly url: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
readonly authoritative: false;
}];
type ModelPricingSourceId = (typeof MODEL_PRICING_SOURCES)[number]["id"];
type ModelPricingSource = {
provider?: string;
passthroughProviderModel?: boolean;
modelIdTransforms?: "version-dots"[];
};
type ModelPricingProvider = {
external?: boolean;
} & Partial<Record<ModelPricingSourceId, ModelPricingSource | false>>;
//#endregion
//#region src/shared/config-ui-hints-types.d.ts
type ConfigUiPresentation = "phone-number";
//#endregion
//#region src/shared/json-schema.types.d.ts
/** TypeBox schema value widened for generic JSON-schema object transforms. */
type JsonSchemaObject = TSchema & Record<string, unknown>;
//#endregion
//#region src/channels/plugins/types.config.d.ts
/** Optional UI metadata for a JSON Schema property. */
type ChannelConfigUiHint = {
label?: string;
help?: string;
tags?: string[];
advanced?: boolean;
sensitive?: boolean;
placeholder?: string;
presentation?: ConfigUiPresentation;
itemTemplate?: unknown;
};
/** Normalized validation issue emitted by a channel runtime parser. */
type ChannelConfigRuntimeIssue = {
path?: Array<string | number>;
message?: string;
code?: string;
} & Record<string, unknown>;
/** Minimal safeParse result shape accepted from channel-owned validators. */
type ChannelConfigRuntimeParseResult = {
success: true;
data: unknown;
} | {
success: false;
issues: ChannelConfigRuntimeIssue[];
};
/** Runtime validator contract paired with the JSON Schema config surface. */
type ChannelConfigRuntimeSchema = {
safeParse: (value: unknown) => ChannelConfigRuntimeParseResult;
};
/** Complete channel config schema description exposed to host tooling. */
type ChannelConfigSchema = {
schema: JsonSchemaObject;
uiHints?: Record<string, ChannelConfigUiHint>;
runtime?: ChannelConfigRuntimeSchema;
};
//#endregion
//#region src/plugins/doctor-session-route-state-owner-types.d.ts
type DoctorSessionRouteStateOwner = {
id: string;
label: string;
providerIds?: readonly string[];
runtimeIds?: readonly string[];
cliSessionKeys?: readonly string[];
authProfilePrefixes?: readonly string[];
};
//#endregion
//#region src/plugins/manifest-command-aliases.d.ts
type PluginManifestCommandAliasKind = "runtime-slash";
/** One command alias declared by a plugin manifest. */
type PluginManifestCommandAlias = {
/** Command-like name users may put in plugin config by mistake. */
name: string;
/** Command family, used for targeted diagnostics. */
kind?: PluginManifestCommandAliasKind;
/** Optional root CLI command that handles related CLI operations. */
cliCommand?: string;
};
//#endregion
//#region src/plugins/plugin-kind.types.d.ts
/** Plugin kind labels for non-provider plugin capability groups. */
type PluginKind = "memory" | "context-engine";
//#endregion
//#region src/plugins/manifest-types.d.ts
/** UI hint metadata for plugin config schema fields. */
type PluginConfigUiHint = {
label?: string;
help?: string;
tags?: string[];
advanced?: boolean;
sensitive?: boolean;
placeholder?: string;
presentation?: ConfigUiPresentation;
};
/** Top-level plugin manifest format. */
type PluginFormat = "openclaw" | "bundle";
/** Supported external bundle manifest formats. */
type PluginBundleFormat = "agent" | "codex" | "claude" | "cursor";
/**
* Closed classification codes for plugin diagnostics. Health surfaces branch
* on these instead of matching freeform diagnostic message text.
*/
type PluginDiagnosticCode = "backup-resource-declaration-invalid" | "channel-setup-failure" | "dashboard-declaration-invalid" | "plugin-verification" | "workspace-scope-omitted";
/** Diagnostic emitted while discovering or validating plugins. */
type PluginDiagnostic = {
level: "warn" | "error";
message: string;
pluginId?: string;
source?: string;
code?: PluginDiagnosticCode;
};
type PluginManifestChannelConfig = {
schema: JsonSchemaObject;
uiHints?: Record<string, PluginConfigUiHint>;
runtime?: ChannelConfigRuntimeSchema;
label?: string;
description?: string;
preferOver?: string[];
commands?: PluginManifestChannelCommandDefaults;
};
type PluginManifestChannelCommandDefaults = {
nativeCommandsAutoEnabled?: boolean;
nativeSkillsAutoEnabled?: boolean;
};
type PluginManifestModelSupport = {
/**
* Cheap manifest-owned model-id prefixes for transparent provider activation
* from shorthand model refs such as `gpt-5.4` or `claude-sonnet-4.6`.
*/
modelPrefixes?: string[];
/**
* Regex sources matched against the raw model id after profile suffixes are
* stripped. Use this when simple prefixes are not expressive enough.
*/
modelPatterns?: string[];
};
type PluginManifestModelCatalog = ModelCatalog;
type PluginManifestModelPricing = {
providers?: Record<string, ModelPricingProvider>;
};
type PluginManifestModelIdPrefixRule = {
modelPrefix: string;
prefix: string;
};
type PluginManifestModelIdNormalizationProvider = {
aliases?: Record<string, string>;
stripPrefixes?: string[];
prefixWhenBare?: string;
prefixWhenBareAfterAliasStartsWith?: PluginManifestModelIdPrefixRule[];
};
type PluginManifestModelIdNormalization = {
providers?: Record<string, PluginManifestModelIdNormalizationProvider>;
};
type PluginManifestProviderEndpoint = {
/**
* Core endpoint class this plugin-owned endpoint should map to. Core must
* already know the class; manifests own host/baseUrl matching metadata.
*/
endpointClass: string;
/** Hostnames that should resolve to this endpoint class. */
hosts?: string[];
/** Host suffixes that should resolve to this endpoint class. */
hostSuffixes?: string[];
/** Exact normalized base URLs that should resolve to this endpoint class. */
baseUrls?: string[];
/** Static Google Vertex region metadata for exact global hosts. */
googleVertexRegion?: string;
/** Host suffix whose prefix should be exposed as the Google Vertex region. */
googleVertexRegionHostSuffix?: string;
};
type PluginManifestProviderRequestProvider = {
family?: string;
compatibilityFamily?: "moonshot";
openAICompletions?: {
supportsStreamingUsage?: boolean;
};
};
type PluginManifestProviderRequest = {
providers?: Record<string, PluginManifestProviderRequestProvider>;
};
type PluginManifestSecretProviderIntegration = {
providerAlias?: string;
displayName?: string;
description?: string;
source: "exec";
command: "${node}";
args?: string[];
timeoutMs?: number;
noOutputTimeoutMs?: number;
maxOutputBytes?: number;
jsonOnly?: boolean;
env?: Record<string, string>;
passEnv?: string[];
};
type PluginManifestActivationCapability = "provider" | "channel" | "tool" | "hook";
type PluginManifestActivation = {
/**
* Explicit Gateway startup activation. Set true when the plugin must be
* imported during Gateway startup; set false when narrower activation
* triggers should load it on demand.
*/
onStartup?: boolean;
/**
* Provider ids that should include this plugin in activation/load plans.
* This is planner metadata only; runtime behavior still comes from register().
*/
onProviders?: string[];
/** Agent harness runtime ids that should include this plugin in activation/load plans. */
onAgentHarnesses?: string[];
/** Command ids that should include this plugin in activation/load plans. */
onCommands?: string[];
/** Channel ids that should include this plugin in activation/load plans. */
onChannels?: string[];
/** Route kinds that should include this plugin in activation/load plans. */
onRoutes?: string[];
/** Root-relative config paths that should include this plugin in startup/load plans. */
onConfigPaths?: string[];
/** Broad capability hints for activation/load plans. Prefer narrower ownership metadata. */
onCapabilities?: PluginManifestActivationCapability[];
};
/** Root CLI command metadata available before plugin code is imported. */
type PluginManifestCliCommand = {
name: string;
description: string;
hasSubcommands: boolean;
};
type PluginManifestDefaultPlatform = NodeJS.Platform;
type PluginManifestSetupProvider = {
/** Provider id surfaced during setup/onboarding. */
id: string;
/** Setup/auth methods that this provider supports. */
authMethods?: string[];
/** Environment variables that can satisfy setup without runtime loading. */
envVars?: string[];
/**
* Cheap local evidence that a provider can authenticate without loading
* runtime code. Evidence checks must not read secrets, shell out, or call
* provider APIs.
*/
authEvidence?: PluginManifestSetupProviderAuthEvidence[];
};
type PluginManifestSetupProviderAuthEvidence = {
/** Generic local file evidence gated by required environment metadata. */
type: "local-file-with-env";
/** Optional env var containing an explicit credential file path. */
fileEnvVar?: string;
/** Optional fallback credential file paths. Supports `${HOME}` and `${APPDATA}`. */
fallbackPaths?: string[];
/** At least one of these env vars must be non-empty when provided. */
requiresAnyEnv?: string[];
/** Every env var listed here must be non-empty when provided. */
requiresAllEnv?: string[];
/** Non-secret marker returned when this evidence is present. */
credentialMarker: string;
/** Human-readable auth source label. */
source?: string;
};
type PluginManifestSetup = {
/** Cheap provider setup metadata exposed before runtime loads. */
providers?: PluginManifestSetupProvider[];
/** Setup-time backend ids available without full runtime activation. */
cliBackends?: string[];
/** Config migration ids owned by this plugin's setup surface. */
configMigrations?: string[];
/**
* Whether setup still needs plugin runtime execution after descriptor lookup.
* Explicit false disables setup runtime; omission preserves the legacy fallback.
*/
requiresRuntime?: boolean;
};
type PluginManifestDoctorContract = {
configRepair?: boolean;
resolveSessionStoreAgentIds?: boolean;
/**
* @deprecated Declare static ownership in top-level sessionRouteStateOwners instead.
* Removal plan: remove the module fallback in OpenClaw 2027.1 after external plugins migrate.
*/
sessionRouteStateOwners?: boolean;
stateMigrations?: boolean;
};
type PluginManifestQaRunner = {
/** Subcommand mounted beneath `openclaw qa`, for example `matrix`. */
commandName: string;
/** Optional user-facing help text for fallback host stubs. */
description?: string;
};
type PluginManifestDashboardDataBinding = {
/** Plugin-local id. Widget grants receive the plugin-id prefix. */
id: string;
/** Read-scoped Gateway method registered by this plugin. */
method: string;
description: string;
};
type PluginManifestDashboardActionVerb = {
/** Plugin-local id. Widget grants receive the plugin-id prefix. */
id: string;
/** Write-scoped Gateway method registered by this plugin. */
method: string;
description: string;
/** Optional JSON Schema for the action params object. */
paramShape?: JsonSchemaObject;
};
type PluginManifestDashboard = {
dataBindings?: PluginManifestDashboardDataBinding[];
actionVerbs?: PluginManifestDashboardActionVerb[];
};
/** Built browser assets activated by the trusted native Control UI host. */
type PluginManifestControlUi = {
/** JavaScript entry in a dedicated dist subdirectory, relative to the plugin root. */
entry: string;
/** Stylesheets in the same asset directory, loaded before activation. */
styles?: string[];
};
type PluginManifestMcpServer = Record<string, unknown>;
type PluginManifestConfigLiteral = string | number | boolean | null;
type PluginManifestDangerousConfigFlag = {
/**
* Dot-separated config path relative to `plugins.entries.<id>.config`.
* Supports `*` wildcards for map/array segments.
*/
path: string;
/** Exact literal that marks this config value as dangerous. */
equals: PluginManifestConfigLiteral;
};
type PluginManifestSecretInputPath = {
/**
* Dot-separated config path relative to `plugins.entries.<id>.config`.
* Supports `*` wildcards for map/array segments.
*/
path: string;
/** Expected resolved type for SecretRef materialization. */
expected?: "string";
/** Runtime owner kind used to isolate this surface when resolution fails. */
ownerKind?: "capability" | "route";
};
type PluginManifestSecretInputContracts = {
/**
* Override bundled-plugin default enablement when deciding whether this
* SecretRef surface is active. Use this when the plugin is bundled but the
* surface should stay inactive until explicitly enabled in config.
*/
bundledDefaultEnabled?: boolean;
paths: PluginManifestSecretInputPath[];
};
type PluginManifestConfigContracts = {
/**
* Root-relative config paths that indicate this plugin's setup-time
* compatibility migrations might apply. Use this to keep generic runtime
* config reads from loading every plugin setup surface when the config does
* not reference the plugin at all.
*/
compatibilityMigrationPaths?: string[];
/**
* Root-relative compatibility paths that this plugin can service during
* runtime before plugin code fully activates. Use this for legacy surfaces
* that should cheaply narrow bundled candidate sets without importing every
* compatible plugin runtime.
*/
compatibilityRuntimePaths?: string[];
dangerousFlags?: PluginManifestDangerousConfigFlag[];
secretInputs?: PluginManifestSecretInputContracts;
};
type PluginManifestCatalog = {
featured?: boolean;
order?: number;
};
/** Declarative backup ownership rooted at host-managed state or each configured agent. */
type PluginManifestBackupResource = {
disposition: "include" | "regenerable";
scope: "state" | "agent";
relativePath: string;
};
type PluginManifest = {
id: string;
configSchema: JsonSchemaObject;
/** Static backup inclusion/exclusion declarations; resolved without loading plugin runtime. */
backupResources?: PluginManifestBackupResource[];
/** Plugin ids that must also be installed for this plugin to have effect. */
requiresPlugins?: string[];
enabledByDefault?: boolean;
enabledByDefaultOnPlatforms?: PluginManifestDefaultPlatform[];
/** Legacy plugin ids that should normalize to this plugin id. */
legacyPluginIds?: string[];
/** Provider ids that should auto-enable this plugin when referenced in auth/config/models. */
autoEnableWhenConfiguredProviders?: string[];
kind?: PluginKind | PluginKind[];
channels?: string[];
providers?: string[];
/**
* Optional lightweight module that exports provider plugin metadata for
* auth/catalog discovery. It should not import the full plugin runtime.
*/
providerCatalogEntry?: string;
/** Lightweight capability descriptor collections; omitted families retain register() discovery. */
capabilityCatalogEntry?: string;
/**
* Cheap model-family ownership metadata used before plugin runtime loads.
* Use this for shorthand model refs that omit an explicit provider prefix.
*/
modelSupport?: PluginManifestModelSupport;
/**
* Declarative model catalog metadata used by future read-only listing,
* onboarding, and model picker surfaces before provider runtime loads.
*/
modelCatalog?: PluginManifestModelCatalog;
/** Manifest-owned external pricing lookup policy for provider refs. */
modelPricing?: PluginManifestModelPricing;
/** Manifest-owned model-id normalization used before provider runtime loads. */
modelIdNormalization?: PluginManifestModelIdNormalization;
/** Cheap provider endpoint metadata used before provider runtime loads. */
providerEndpoints?: PluginManifestProviderEndpoint[];
/** Cheap provider request metadata used before provider runtime loads. */
providerRequest?: PluginManifestProviderRequest;
/** Declarative SecretRef provider presets owned by this plugin. */
secretProviderIntegrations?: Record<string, PluginManifestSecretProviderIntegration>;
/** Cheap startup activation lookup for plugin-owned CLI inference backends. */
cliBackends?: string[];
/**
* Provider or CLI backend refs whose plugin-owned synthetic auth hook should
* be probed during cold model discovery before the runtime registry exists.
*/
syntheticAuthRefs?: string[];
/**
* Bundled-plugin-owned placeholder API key values that represent non-secret
* local, OAuth, or ambient credential state.
*/
nonSecretAuthMarkers?: string[];
/**
* Plugin-owned command aliases that should resolve to this plugin during
* config diagnostics before runtime loads.
*/
commandAliases?: PluginManifestCommandAlias[];
/** Root commands advertised by help and activation planning before runtime loads. */
cliCommands?: PluginManifestCliCommand[];
/** Usage/billing credentials excluded from inference auth but included in secret scrubbing. */
providerUsageAuthEnvVars?: Record<string, string[]>;
/** Provider ids that should reuse another provider id for auth lookup. */
providerAuthAliases?: Record<string, string>;
/**
* Cheap onboarding/auth-choice metadata used by config validation, CLI help,
* and non-runtime auth-choice routing before provider runtime loads.
*/
providerAuthChoices?: PluginManifestProviderAuthChoice[];
/** Cheap activation planner metadata exposed before plugin runtime loads. */
activation?: PluginManifestActivation;
/** Cheap setup/onboarding metadata exposed before plugin runtime loads. */
setup?: PluginManifestSetup;
/** Doctor contract surfaces available without loading the plugin artifact. */
doctorContract?: PluginManifestDoctorContract;
/** Whether the plugin public API registers structured health checks. */
doctorHealthChecks?: boolean;
/** Static ownership metadata for doctor session-route state repairs. */
sessionRouteStateOwners?: DoctorSessionRouteStateOwner[];
/** Cheap QA runner metadata exposed before plugin runtime loads. */
qaRunners?: PluginManifestQaRunner[];
/** Widget data and action capabilities validated against runtime registrations. */
dashboard?: PluginManifestDashboard;
controlUi?: PluginManifestControlUi;
/** Static MCP servers contributed while this plugin is enabled. */
mcpServers?: Record<string, PluginManifestMcpServer>;
skills?: string[];
name?: string;
description?: string;
/** Optional presentation hints for plugin catalog surfaces. */
catalog?: PluginManifestCatalog;
version?: string;
uiHints?: Record<string, PluginConfigUiHint>;
/**
* Static capability ownership snapshot used for manifest-driven discovery,
* compat wiring, and contract coverage without importing plugin runtime.
*/
contracts?: PluginManifestContracts;
/** Cheap media-understanding provider defaults without importing plugin runtime. */
mediaUnderstandingProviderMetadata?: Record<string, PluginManifestMediaUnderstandingProviderMetadata>;
/** Cheap image-generation provider auth metadata without importing plugin runtime. */
imageGenerationProviderMetadata?: Record<string, PluginManifestCapabilityProviderMetadata>;
/** Cheap video-generation provider auth metadata without importing plugin runtime. */
videoGenerationProviderMetadata?: Record<string, PluginManifestCapabilityProviderMetadata>;
/** Cheap music-generation provider auth metadata without importing plugin runtime. */
musicGenerationProviderMetadata?: Record<string, PluginManifestCapabilityProviderMetadata>;
/** Cheap plugin-tool availability metadata without importing plugin runtime. */
toolMetadata?: Record<string, PluginManifestToolMetadata>;
/** Manifest-owned config behavior consumed by generic core helpers. */
configContracts?: PluginManifestConfigContracts;
channelConfigs?: Record<string, PluginManifestChannelConfig>;
};
type PluginManifestContracts = {
embeddedExtensionFactories?: string[];
agentToolResultMiddleware?: string[];
trustedToolPolicies?: string[];
/**
* Provider ids whose external auth profile hook can contribute runtime-only
* credentials. Declaring this lets auth-store overlays load only the owning
* plugin instead of every provider plugin.
*/
externalAuthProviders?: string[];
embeddingProviders?: string[];
speechProviders?: string[];
realtimeTranscriptionProviders?: string[];
realtimeVoiceProviders?: string[];
mediaUnderstandingProviders?: string[];
transcriptSourceProviders?: string[];
documentExtractors?: string[];
imageGenerationProviders?: string[];
videoGenerationProviders?: string[];
musicGenerationProviders?: string[];
webContentExtractors?: string[];
webFetchProviders?: string[];
webSearchProviders?: string[];
workerProviders?: string[];
/** Provider ids whose plugin owns usage auth and snapshot hooks. */
usageProviders?: string[];
migrationProviders?: string[];
gatewayMethodDispatch?: string[];
tools?: string[];
};
type PluginManifestMediaUnderstandingCapability = "image" | "audio" | "video";
type PluginManifestMediaUnderstandingProviderMetadata = {
capabilities?: PluginManifestMediaUnderstandingCapability[];
defaultModels?: Partial<Record<PluginManifestMediaUnderstandingCapability, string>>;
autoPriority?: Partial<Record<PluginManifestMediaUnderstandingCapability, number>>;
nativeDocumentInputs?: Array<"pdf">;
documentModels?: Partial<Record<"pdf", {
textExtraction?: string;
image?: string | false;
}>>;
};
type PluginManifestProviderBaseUrlGuard = {
provider: string;
defaultBaseUrl?: string;
allowedBaseUrls: string[];
};
type PluginManifestCapabilityProviderAuthSignal = {
provider: string;
providerBaseUrl?: PluginManifestProviderBaseUrlGuard;
};
type PluginManifestCapabilityProviderModeConfigSignal = {
path?: string;
default?: string;
allowed?: string[];
disallowed?: string[];
};
type PluginManifestCapabilityProviderConfigSignal = {
rootPath: string;
overlayPath?: string;
overlayMapPath?: string;
required?: string[];
requiredAny?: string[];
mode?: PluginManifestCapabilityProviderModeConfigSignal;
};
type PluginManifestCapabilityProviderMetadata = {
aliases?: string[];
authProviders?: string[];
authSignals?: PluginManifestCapabilityProviderAuthSignal[];
configSignals?: PluginManifestCapabilityProviderConfigSignal[];
referenceAudioInputs?: boolean;
};
type PluginManifestToolMetadata = PluginManifestCapabilityProviderMetadata & {
optional?: boolean;
/** Built-in tool profiles that expose this plugin tool by default. */
profiles?: PluginManifestToolProfile[];
/** Tool execution is safe to repeat after an incomplete model turn. */
replaySafe?: boolean;
/** Tool execution can change durable state and failed attempts must remain visible. */
sideEffecting?: boolean;
};
type PluginManifestToolProfile = "minimal" | "coding" | "messaging" | "full";
type PluginManifestProviderAuthChoice = {
/** Provider id owned by this manifest entry. */
provider: string;
/** Provider auth method id that this choice should dispatch to. */
method: string;
/** Stable auth-choice id used by onboarding and other CLI auth flows. */
choiceId: string;
/** Optional user-facing choice label/hint for grouped onboarding UI. */
choiceLabel?: string;
choiceHint?: string;
/** Optional HTTPS artwork URL for native and web onboarding surfaces. */
icon?: string;
/** Optional HTTPS product or installation URL for onboarding surfaces. */
website?: string;
/** Lower values sort earlier in interactive assistant pickers. */
assistantPriority?: number;
/** Keep the choice out of interactive assistant pickers while preserving manual CLI support. */
assistantVisibility?: "visible" | "manual-only";
/** Legacy choice ids that should point users at this replacement choice. */
deprecatedChoiceIds?: string[];
/** Optional grouping metadata for auth-choice pickers. */
groupId?: string;
groupLabel?: string;
groupHint?: string;
/**
* Surface this group in the featured tier of the interactive onboarding
* picker. Featured groups appear before the "More…" entry.
*/
onboardingFeatured?: boolean;
/** Optional CLI flag metadata for one-flag auth flows such as API keys. */
optionKey?: string;
cliFlag?: string;
cliOption?: string;
cliDescription?: string;
/** One pasted secret plus provider defaults is sufficient for app-guided setup. */
appGuidedSecret?: boolean;
/** Interactive method stages one inline credential without host login imports or persistence. */
personalAccount?: boolean;
/** Short provider-owned command label for starting app-guided setup. */
appGuidedActionLabel?: string;
/** Provider-owned interactive login that native setup clients can render generically. */
appGuidedAuth?: "oauth" | "device-code";
/**
* Interactive onboarding surfaces where this auth choice should appear.
* Defaults to `["text-inference"]` when omitted.
*/
onboardingScopes?: PluginManifestOnboardingScope[];
/** Provider runtime can discover and prepare an already-installed local model. */
appGuidedDiscovery?: boolean;
};
type PluginManifestOnboardingScope = "text-inference" | "image-generation" | "music-generation";
//#endregion
//#region src/channels/plugins/setup-adapter.types.d.ts
type ChannelSetupAdapter<Input extends {
name?: string;
} = ChannelSetupInput> = {
/** Keep root config as an independent identity when the host adds named accounts. */
configPromotion?: "preserve-root";
resolveAccountId?: (params: {
cfg: OpenClawConfig;
accountId?: string;
input?: Input;
}) => string;
prepareAccountConfigInput?: (params: {
cfg: OpenClawConfig;
accountId: string;
input: Input;
runtime: RuntimeEnv;
}) => Promise<Input> | Input;
resolveBindingAccountId?: (params: {
cfg: OpenClawConfig;
agentId: string;
accountId?: string;
}) => string | undefined;
applyAccountName?: (params: {
cfg: OpenClawConfig;
accountId: string;
name?: string;
}) => OpenClawConfig;
applyAccountConfig: (params: {
cfg: OpenClawConfig;
accountId: string;
input: Input;
}) => OpenClawConfig;
afterAccountConfigWritten?: (params: {
previousCfg: OpenClawConfig;
cfg: OpenClawConfig;
accountId: string;
input: Input;
runtime: RuntimeEnv;
}) => Promise<void> | void;
validateInput?: (params: {
cfg: OpenClawConfig;
accountId: string;
input: Input;
}) => string | null;
singleAccountKeysToMove?: readonly string[];
namedAccountPromotionKeys?: readonly string[];
resolveSingleAccountPromotionTarget?: (params: {
channel: Record<string, unknown>;
}) => string | undefined;
};
//#endregion
//#region src/channels/plugins/setup-contract.d.ts
type ChannelSetupCliOption = {
flags: string;
negatedFlags?: string;
description: string;
defaultValue?: boolean | string;
};
type ChannelSetupStringField = {
kind: "string";
sensitive?: boolean;
cli: ChannelSetupCliOption;
};
type ChannelSetupBooleanField = {
kind: "boolean";
cli: ChannelSetupCliOption;
envVars?: readonly string[];
envVarMode?: "all" | "any";
};
type ChannelSetupIntegerField = {
kind: "integer";
cli: ChannelSetupCliOption;
};
type ChannelSetupStringListField = {
kind: "string-list";
sensitive?: boolean;
cli: ChannelSetupCliOption;
};
type ChannelSetupChoiceField<Choices extends readonly string[] = readonly string[]> = {
kind: "choice";
choices: Choices;
cli: ChannelSetupCliOption;
};
type ChannelSetupField = ChannelSetupStringField | ChannelSetupBooleanField | ChannelSetupIntegerField | ChannelSetupStringListField | ChannelSetupChoiceField;
type ChannelSetupFieldMetadataFor<Field extends ChannelSetupField> = Field extends ChannelSetupField ? Field & {
key: string;
} : never;
type ChannelSetupFieldMetadata = ChannelSetupFieldMetadataFor<ChannelSetupField>;
type ChannelSetupMetadata = {
fields: readonly ChannelSetupFieldMetadata[];
};
type ChannelSetupParseResult = {
ok: true;
value: unknown;
} | {
ok: false;
error: string;
};
type ChannelOwnedSetupAdapterShape<Input extends {
name?: string;
}> = ChannelSetupAdapter<Input>;
type ChannelOwnedSetupContract = {
kind: "channel-owned";
configPromotion?: ChannelSetupAdapter["configPromotion"];
metadata: ChannelSetupMetadata;
parseInput: (input: unknown) => ChannelSetupParseResult;
resolveAccountId?: (params: {
cfg: OpenClawConfig;
accountId?: string;
input?: unknown;
}) => string;
prepareAccountConfigInput?: (params: {
cfg: OpenClawConfig;
accountId: string;
input: unknown;
runtime: RuntimeEnv;
}) => Promise<object> | object;
resolveBindingAccountId?: ChannelOwnedSetupAdapterShape<{
name?: string;
}>["resolveBindingAccountId"];
applyAccountName?: ChannelOwnedSetupAdapterShape<{
name?: string;
}>["applyAccountName"];
applyAccountConfig: (params: {
cfg: OpenClawConfig;
accountId: string;
input: unknown;
}) => OpenClawConfig;
afterAccountConfigWritten?: (params: {
previousCfg: OpenClawConfig;
cfg: OpenClawConfig;
accountId: string;
input: unknown;
runtime: RuntimeEnv;
}) => Promise<void> | void;
validateInput?: (params: {
cfg: OpenClawConfig;
accountId: string;
input: unknown;
}) => string | null;
singleAccountKeysToMove?: readonly string[];
namedAccountPromotionKeys?: readonly string[];
resolveSingleAccountPromotionTarget?: ChannelOwnedSetupAdapterShape<{
name?: string;
}>["resolveSingleAccountPromotionTarget"];
};
//#endregion
//#region src/compat/legacy-names.d.ts
declare const MANIFEST_KEY: "openclaw";
//#endregion
//#region src/plugins/package-manifest.types.d.ts
/** package.json OpenClaw metadata used for plugin setup and catalog discovery. */
type PluginPackageChannelApprovalFlag = "native";
type PluginPackageChannel = {
id?: string;
label?: string;
selectionLabel?: string;
detailLabel?: string;
docsPath?: string;
docsLabel?: string;
blurb?: string;
order?: number;
aliases?: readonly string[];
preferOver?: readonly string[];
systemImage?: string;
selectionDocsPrefix?: string;
selectionDocsOmitLabel?: boolean;
selectionExtras?: readonly string[];
markdownCapable?: boolean;
/** Closed manifest flags for approval behavior available before the channel runtime loads. */
approvalFlags?: readonly PluginPackageChannelApprovalFlag[];
exposure?: {
configured?: boolean;
setup?: boolean;
docs?: boolean;
};
quickstartAllowFrom?: boolean;
forceAccountBinding?: boolean;
preferSessionLookupForAnnounceTarget?: boolean;
commands?: PluginManifestChannelCommandDefaults;
configuredState?: {
specifier?: string;
exportName?: string;
env?: {
allOf?: readonly string[];
anyOf?: readonly string[];
};
};
persistedAuthState?: {
specifier?: string;
exportName?: string;
};
doctorCapabilities?: PluginPackageChannelDoctorCapabilities;
/** Typed, serializable setup fields available before plugin runtime load. */
setup?: ChannelSetupMetadata;
/** @deprecated Use setup.fields. */
cliAddOptions?: readonly PluginPackageChannelCliOption[];
};
type PluginPackageChannelDoctorCapabilities = {
dmAllowFromMode?: "topOnly" | "topOrNested" | "nestedOnly";
/** Whether dmPolicy="open" requires an explicit "*" in allowFrom. Defaults to true. */
openDmRequiresAllowFromWildcard?: boolean;
groupModel?: "sender" | "route" | "hybrid";
groupAllowFromFallbackToAllowFrom?: boolean;
warnOnEmptyGroupSenderAllowlist?: boolean;
};
type PluginPackageChannelCliOption = {
flags: string;
negatedFlags?: string;
description: string;
defaultValue?: boolean | string;
valueType?: "int" | "list";
};
type PluginPackageInstall = {
clawhubSpec?: string;
npmSpec?: string;
localPath?: string;
defaultChoice?: "clawhub" | "npm" | "local";
minHostVersion?: string;
expectedIntegrity?: string;
allowInvalidConfigRecovery?: boolean;
requiredPlatformPackages?: string[];
};
type OpenClawPackageSetupFeatures = {
configPromotion?: boolean | "preserve-root";
/**
* @deprecated Declare doctorContract.stateMigrations in openclaw.plugin.json instead.
* Removal plan: remove the setup-entry adapter after the 2027.1 external-plugin migration window.
*/
legacyStateMigrations?: boolean;
legacySessionSurfaces?: boolean;
};
type OpenClawPackageCompat = {
pluginApi?: string;
minGatewayVersion?: string;
};
type OpenClawPackageBuild = {
bundledDist?: boolean;
openclawVersion?: string;
pluginSdkVersion?: string;
};
type OpenClawPackageManifest = {
extensions?: string[];
runtimeExtensions?: string[];
setupEntry?: string;
runtimeSetupEntry?: string;
controlUi?: string;
setupFeatures?: OpenClawPackageSetupFeatures;
plugin?: {
id?: string;
label?: string;
};
channel?: PluginPackageChannel;
compat?: OpenClawPackageCompat;
install?: PluginPackageInstall;
build?: OpenClawPackageBuild;
};
type ManifestKey = typeof MANIFEST_KEY;
type PackageManifest = {
name?: string;
version?: string;
description?: string;
dependencies?: Record<string, string>;
optionalDependencies?: Record<string, string>;
} & Partial<Record<ManifestKey, OpenClawPackageManifest>>;
//#endregion
//#region src/plugins/plugin-origin.types.d.ts
/** Origin class for plugin discovery and runtime trust decisions. */
type PluginOrigin$1 = "bundled" | "global" | "workspace" | "config";
//#endregion
//#region src/plugins/status-dependencies-core.d.ts
/** Dependency name-to-version map from a plugin package manifest. */
type PluginDependencySpecMap = Record<string, string>;
/** Installation status for one plugin dependency. */
type PluginDependencyEntry = {
name: string;
spec: string;
installed: boolean;
optional: boolean;
resolvedPath?: string;
};
/** Aggregate installation status for required and optional plugin dependencies. */
type PluginDependencyStatus = {
hasDependencies: boolean;
installed: boolean;
requiredInstalled: boolean;
optionalInstalled: boolean;
missing: string[];
missingOptional: string[];
dependencies: PluginDependencyEntry[];
optionalDependencies: PluginDependencyEntry[];
};
//#endregion
//#region src/plugins/discovery.types.d.ts
/** One potential plugin root discovered before manifest validation and registry normalization. */
type PluginCandidate = {
idHint: string;
/** Discovery-owned identity for one entry in a multi-entry package pack. */
effectivePluginId?: string;
diagnosticIdHint?: string;
source: string;
setupSource?: string;
rootDir: string;
origin: PluginOrigin$1;
/** Retains explicit load-path precedence when physical aliases merge their provenance. */
configSelected?: true;
/** An intentional source overlay must not execute its packaged peer. */
sourcePreferred?: true;
format?: PluginFormat;
bundleFormat?: PluginBundleFormat;
workspaceDir?: string;
packageName?: string;
packageVersion?: string;
packageDescription?: string;
packageDir?: string;
packageManifest?: OpenClawPackageManifest;
packageDependencies?: PluginDependencySpecMap;
packageOptionalDependencies?: PluginDependencySpecMap;
bundledManifestId?: string;
bundledManifest?: PluginManifest;
bundledManifestPath?: string;
requiredPluginIds?: string[];
requiredPluginSource?: string;
rawPackageManifest?: PackageManifest;
};
/** Discovery candidates plus warnings/errors emitted while scanning roots. */
type PluginDiscoveryResult = {
candidates: PluginCandidate[];
diagnostics: PluginDiagnostic[];
};
//#endregion
//#region src/plugins/plugin-trust.d.ts
/** Captured beside the trust decision; consumers never rediscover installation facts. */
type PluginTrust = {
reason: "bundled" | "trusted-official" | "record-missing" | "owner-ambiguous" | "origin-path" | "install-path-mismatch" | "provenance-missing" | "provenance-invalid";
registryPath: string | null;
origin: PluginOrigin$1 | "unknown";
installSource?: PluginInstallRecord["source"];
installSpec?: string;
};
//#endregion
//#region src/plugins/manifest-registry.types.d.ts
type PluginManifestRecord = {
id: string;
/** Process-local source selection, never persisted in the installed index. */
sourcePreferred?: true;
backupResources?: PluginManifestBackupResource[];
name?: string;
description?: string;
catalog?: PluginManifestCatalog;
iconPath?: string;
version?: string;
packageName?: string;
packageVersion?: string;
packageDescription?: string;
enabledByDefault?: boolean;
enabledByDefaultOnPlatforms?: string[];
autoEnableWhenConfiguredProviders?: string[];
legacyPluginIds?: string[];
format?: PluginFormat;
bundleFormat?: PluginBundleFormat;
bundleCapabilities?: string[];
kind?: PluginKind | PluginKind[];
channels: string[];
providers: string[];
providerDiscoverySource?: string;
/** Undefined is undeclared; null retains a rejected declaration without enabling full-entry fallback. */
capabilityCatalogSource?: string | null;
modelSupport?: PluginManifestModelSupport;
modelCatalog?: PluginManifestModelCatalog;
modelPricing?: PluginManifestModelPricing;
modelIdNormalization?: PluginManifestModelIdNormalization;
providerEndpoints?: PluginManifestProviderEndpoint[];
providerRequest?: PluginManifestProviderRequest;
secretProviderIntegrations?: Record<string, PluginManifestSecretProviderIntegration>;
cliBackends: string[];
syntheticAuthRefs?: string[];
nonSecretAuthMarkers?: string[];
commandAliases?: PluginManifestCommandAlias[];
cliCommands?: PluginManifest["cliCommands"];
providerUsageAuthEnvVars?: Record<string, string[]>;
providerAuthAliases?: Record<string, string>;
providerAuthChoices?: PluginManifest["providerAuthChoices"];
activation?: PluginManifestActivation;
setup?: PluginManifestSetup;
doctorContract?: PluginManifestDoctorContract;
doctorHealthChecks?: boolean;
sessionRouteStateOwners?: DoctorSessionRouteStateOwner[];
packageManifest?: OpenClawPackageManifest;
packageDependencies?: PluginDependencySpecMap;
packageOptionalDependencies?: PluginDependencySpecMap;
packageChannel?: PluginPackageChannel;
packageInstall?: PluginPackageInstall;
trustedOfficialInstall?: boolean;
trust?: PluginTrust;
qaRunners?: PluginManifestQaRunner[];
dashboard?: PluginManifestDashboard;
controlUi?: PluginManifestControlUi;
mcpServers?: Record<string, PluginManifestMcpServer>;
skills: string[];
settingsFiles?: string[];
hooks: string[];
origin: PluginOrigin$1;
workspaceDir?: string;
rootDir: string;
source: string;
setupSource?: string;
manifestPath: string;
schemaCacheKey?: string;
configSchema?: Record<string, unknown>;
configUiHints?: Record<string, PluginConfigUiHint>;
contracts?: PluginManifestContracts;
mediaUnderstandingProviderMetadata?: Record<string, PluginManifestMediaUnderstandingProviderMetadata>;
imageGenerationProviderMetadata?: Record<string, PluginManifestCapabilityProviderMetadata>;
videoGenerationProviderMetadata?: Record<string, PluginManifestCapabilityProviderMetadata>;
musicGenerationProviderMetadata?: Record<string, PluginManifestCapabilityProviderMetadata>;
toolMetadata?: Record<string, PluginManifestToolMetadata>;
configContracts?: PluginManifestConfigContracts;
channelConfigs?: Record<string, PluginManifestChannelConfig>;
channelCatalogMeta?: {
id: string;
label?: string;
blurb?: string;
preferOver?: readonly string[];
commands?: PluginManifestChannelCommandDefaults;
};
};
type PluginManifestRegistry = {
plugins: PluginManifestRecord[];
diagnostics: PluginDiagnostic[];
};
//#endregion
//#region src/secrets/resolve-types.d.ts
/** Shared per-runtime cache for resolved SecretRefs and file provider payloads. */
type SecretRefResolveCache = {
/** In-flight or completed resolution promise keyed by `secretRefKey(ref)`. */
resolvedByRefKey?: Map<string, Promise<unknown>>;
/** In-flight or completed parsed file-provider payload keyed by provider alias. */
filePayloadByProvider?: Map<string, Promise<unknown>>;
};
//#endregion
//#region src/secrets/runtime-degraded-state.d.ts
type SecretOwnerKind = "account" | "capability" | "gateway" | "provider" | "route" | "unknown";
type SecretAssignmentDisposition = "fail-closed" | "isolate";
//#endregion
//#region src/secrets/runtime-shared.d.ts
type SecretResolverWarningCode = "SECRETS_REF_OVERRIDES_PLAINTEXT" | "SECRETS_REF_IGNORED_INACTIVE_SURFACE" | "SECRETS_OWNER_UNAVAILABLE" | "WEB_SEARCH_PROVIDER_INVALID_AUTODETECT" | "WEB_SEARCH_AUTODETECT_SELECTED" | "WEB_SEARCH_KEY_UNRESOLVED_FALLBACK_USED" | "WEB_SEARCH_KEY_UNRESOLVED_NO_FALLBACK" | "WEB_FETCH_PROVIDER_INVALID_AUTODETECT" | "WEB_FETCH_AUTODETECT_SELECTED" | "WEB_FETCH_PROVIDER_KEY_UNRESOLVED_FALLBACK_USED" | "WEB_FETCH_PROVIDER_KEY_UNRESOLVED_NO_FALLBACK";
type SecretResolverWarning = {
code: SecretResolverWarningCode;
path: string;
message: string;
};
type SecretAssignment = {
ref: SecretRef;
path: string;
expected: "string" | "string-or-object";
ownerKind: SecretOwnerKind;
ownerId: string;
requiredForGateway: boolean;
disposition: SecretAssignmentDisposition;
/** Digest of the complete owner config captured before secret materialization. */
ownerContractDigest?: string;
apply: (value: unknown) => void;
/** Applies the canonical unavailable state when this owner must start cold. */
applyUnavailable?: () => void;
};
type ResolverContext = {
sourceConfig: OpenClawConfig;
env: NodeJS.ProcessEnv;
cache: SecretRefResolveCache;
manifestRegistry?: Pick<PluginManifestRegistry, "plugins">;
warnings: SecretResolverWarning[];
warningKeys: Set<string>;
assignments: SecretAssignment[];
};
type SecretDefaults = NonNullable<OpenClawConfig["secrets"]>["defaults"];
//#endregion
//#region src/secrets/target-registry-types.d.ts
/** Config document that owns a registered secret-bearing target. */
type SecretTargetConfigFile = "openclaw.json" | "auth-profile-store";
/** Storage shape used by a target: inline SecretInput or a sibling `*Ref` field. */
type SecretTargetShape = "secret_input" | "sibling_ref";
/** Resolved value shape accepted by runtime and apply validation. */
type SecretTargetExpected = "string" | "string-or-object";
/** Auth profile families that have separate secret target coverage. */
type AuthProfileType = "api_key" | "token";
/**
* Registry metadata for one configurable secret-bearing value.
*/
type SecretTargetRegistryEntry = {
/** Stable id used by plans, audits, docs, and targeted discovery filters. */
id: string;
/** Plan/configure target family; aliases keep CLI-facing names additive. */
targetType: string;
targetTypeAliases?: string[];
/** Config document where the value is discovered or rewritten. */
configFile: SecretTargetConfigFile;
/** Dot-path pattern for the secret-bearing value; `*` captures path segments. */
pathPattern: string;
/** Structured pattern segments preserve literal plugin IDs containing dots. */
pathPatternSegments?: string[];
/** Optional sibling SecretRef path materialized from the same captures as `pathPattern`. */
refPathPattern?: string;
/** Whether the registered value stores a SecretInput directly or via a sibling ref field. */
secretShape: SecretTargetShape;
/** Runtime value shape accepted after SecretRef resolution. */
expectedResolvedValue: SecretTargetExpected;
/** Enables `openclaw secrets apply` targeting for this entry. */
includeInPlan: boolean;
/** Enables interactive/non-interactive configure candidate generation. */
includeInConfigure: boolean;
/** Enables plaintext/unresolved-ref audit scanning. */
includeInAudit: boolean;
/** Captured path segment that names the owning provider, when applicable. */
providerIdPathSegmentIndex?: number;
/** Captured path segment that names the owning account/profile, when applicable. */
accountIdPathSegmentIndex?: number;
/** Auth-profile family for auth-profiles.json entries. */
authProfileType?: AuthProfileType;
/** Enables provider-shadowing diagnostics for provider-auth surfaces with fallback order. */
trackProviderShadowing?: boolean;
};
//#endregion
//#region src/security/audit.types.d.ts
/** Severity levels emitted by security audit checks. */
type SecurityAuditSeverity = "info" | "warn" | "critical";
/** One actionable or informational security audit finding. */
type SecurityAuditFinding = {
checkId: string;
severity: SecurityAuditSeverity;
title: string;
detail: string;
remediation?: string;
};
//#endregion
//#region src/channels/plugins/channel-runtime-surface.types.d.ts
/**
* Channel runtime context registry types.
*
* Defines the public plugin SDK surface for channel runtime context registration and watches.
*/
type ChannelRuntimeContextKey = {
channelId: string;
accountId?: string | null;
capability: string;
};
type ChannelRuntimeContextEvent = {
type: "registered" | "unregistered";
key: {
channelId: string;
accountId?: string;
capability: string;
};
context?: unknown;
};
type ChannelRuntimeContextRegistry = {
register: (params: ChannelRuntimeContextKey & {
context: unknown;
abortSignal?: AbortSignal;
}) => {
dispose: () => void;
};
get: <T = unknown>(params: ChannelRuntimeContextKey) => T | undefined;
watch: (params: {
channelId?: string;
accountId?: string | null;
capability?: string;
onEvent: (event: ChannelRuntimeContextEvent) => void;
}) => () => void;
};
/**
* Minimal channel-runtime surface exported through the public plugin SDK.
*
* Gateway startup supplies the full plugin channel runtime, but external callers
* may still type context-only helpers against this compatibility surface.
*/
type ChannelRuntimeSurface = {
runtimeContexts: ChannelRuntimeContextRegistry;
[key: string]: unknown;
};
//#endregion
//#region src/channels/plugins/config-write-policy-shared.d.ts
/**
* Channel/account scope used to evaluate config write policy.
*/
type ConfigWriteScopeLike<TChannelId extends string = string> = {
channelId?: TChannelId | null;
accountId?: string | null;
};
/**
* Target affected by a config write command.
*/
type ConfigWriteTargetLike<TChannelId extends string = string> = {
kind: "global";
} | {
kind: "channel";
scope: {
channelId: TChannelId;
};
} | {
kind: "account";
scope: {
channelId: TChannelId;
accountId: string;
};
} | {
kind: "ambiguous";
scopes: ConfigWriteScopeLike<TChannelId>[];
};
//#endregion
//#region src/channels/plugins/config-writes.d.ts
/**
* Target affected by a channel config write.
*/
type ConfigWriteTarget = ConfigWriteTargetLike;
//#endregion
//#region src/infra/outbound/deliver-types.d.ts
/** Channel send result or explicit non-outcome normalized for delivery accounting. */
type OutboundDeliveryResult = {
outcome?: MessageReceiptSourceResult["outcome"];
channel: ChannelId$1;
messageId: string;
target?: {
kind: "chat" | "channel" | "room" | "conversation";
id: string;
};
timestamp?: number;
toJid?: string;
pollId?: string;
receipt?: MessageReceipt;
meta?: Record<string, unknown>;
};
/** Reason a payload was intentionally not sent after normalization or hooks. */
type OutboundPayloadDeliverySuppressionReason = "cancelled_by_message_sending_hook" | "cancelled_by_reply_payload_sending_hook" | "empty_after_message_sending_hook" | "empty_after_reply_payload_sending_hook" | "no_visible_payload" | "adapter_returned_no_send" | "adapter_returned_no_identity";
/** Delivery phase where a failure occurred. */
type OutboundDeliveryFailureStage = "platform_send" | "queue" | "unknown";
type OutboundPayloadDeliveryKind = "text" | "media" | "other";
/** Per-payload delivery status emitted to callers and channel send summaries. */
type OutboundPayloadDeliveryOutcome = {
index: number;
status: "sent";
results: OutboundDeliveryResult[];
/** Effective post-hook, post-render payload kind. */
deliveryKind?: OutboundPayloadDeliveryKind;
} | {
index: number;
status: "suppressed";
reason: OutboundPayloadDeliverySuppressionReason;
hookEffect?: {
cancelReason?: string;
metadata?: Record<string, unknown>;
};
} | {
index: number;
status: "failed";
error: unknown;
sentBeforeError: boolean;
stage: OutboundDeliveryFailureStage;
/** Identified platform sends from this payload before its terminal failure. */
results?: OutboundDeliveryResult[];
/** Effective post-hook, post-render payload kind when platform delivery began. */
deliveryKind?: OutboundPayloadDeliveryKind;
};
//#endregion
//#region src/auto-reply/chunk.d.ts
type TextChunkProvider = ChannelId$1;
/**
* Chunking mode for outbound messages:
* - "length": Split only when exceeding textChunkLimit (default)
* - "newline": Prefer breaking on "soft" boundaries. Historically this split on every
* newline; now it only breaks on paragraph boundaries (blank lines) unless the text
* exceeds the length limit.
*/
type ChunkMode = "length" | "newline";
declare function resolveTextChunkLimit(cfg: OpenClawConfig | undefined, provider?: TextChunkProvider, accountId?: string | null, opts?: {
fallbackLimit?: number;
}): number;
declare function resolveChunkMode(cfg: OpenClawConfig | undefined, provider?: TextChunkProvider, accountId?: string | null): ChunkMode;
/**
* Split text on newlines, trimming line whitespace.
* Blank lines are folded into the next non-empty line as leading "\n" prefixes.
* Leading and trailing blank lines are capped to the available UTF-16 space.
* Long lines can be split by length (default) or kept intact via splitLongLines:false.
*/
declare function chunkByNewline(text: string, maxLineLength: number, opts?: {
splitLongLines?: boolean;
trimLines?: boolean;
isSafeBreak?: (index: number) => boolean;
}): string[];
/**
* Unified chunking function that dispatches based on mode.
*/
declare function chunkTextWithMode(text: string, limit: number, mode: ChunkMode): string[];
declare function chunkMarkdownTextWithMode(text: string, limit: number, mode: ChunkMode): string[];
declare function chunkText(text: string, limit: number): string[];
declare function chunkMarkdownText(text: string, limit: number): string[];
//#endregion
//#region src/infra/outbound/formatting.d.ts
/**
* Formatting and chunking hints carried through outbound delivery planning.
*/
type OutboundDeliveryFormattingOptions = {
textLimit?: number;
maxLinesPerMessage?: number;
tableMode?: MarkdownTableMode$1;
chunkMode?: ChunkMode;
parseMode?: "HTML";
};
//#endregion
//#region src/infra/outbound/identity-types.d.ts
/** Agent identity metadata that outbound channels can render with a message. */
type OutboundIdentity = {
name?: string;
avatarUrl?: string;
emoji?: string;
theme?: string;
};
//#endregion
//#region src/channels/plugins/outbound.types.d.ts
type ChannelOutboundContext = {
cfg: OpenClawConfig;
to: string;
text: string;
mediaUrl?: string;
audioAsVoice?: boolean;
mediaAccess?: OutboundMediaAccess;
mediaLocalRoots?: readonly string[];
mediaReadFile?: (filePath: string) => Promise<Buffer>;
gifPlayback?: boolean;
/** Send image, GIF, or video as document to avoid channel compression. */
forceDocument?: boolean;
replyToId?: string | null;
replyToIdSource?: "explicit" | "implicit";
replyToMode?: ReplyToMode;
formatting?: OutboundDeliveryFormattingOptions;
threadId?: string | number | null;
accountId?: string | null;
identity?: OutboundIdentity;
deps?: OutboundSendDeps;
silent?: boolean;
gatewayClientScopes?: readonly string[];
/** @internal Opaque durable intent id for exact provider-side send reconciliation. */
deliveryQueueId?: string;
/** @internal Stable platform-send index within one durable payload. */
deliveryPartIndex?: number;
/** @internal Exact platform-send count within one durable payload. */
deliveryPartCount?: number;
/** @internal Channel-valid id reserved before a correlated conversation turn is sent. */
preparedMessageId?: string;
/** @internal Refresh durable timing before recipient-visible or finalizing platform I/O. */
onPlatformSendDispatch?: () => Promise<void>;
/** @internal Synchronously fence custody after refresh and immediately before provider I/O. */
assertDirectAdapterHandoff?: () => void;
/** @internal Report each completed platform sub-send before starting another fallible step. */
onDeliveryResult?: (result: OutboundDeliveryResult) => Promise<void> | void;
};
type ChannelOutboundPayloadContext = ChannelOutboundContext & {
payload: ReplyPayload;
};
type ChannelPresentationCapabilities = {
/** Whether the channel accepts structured presentation payloads at all. */
supported?: boolean;
/** Whether the channel can render button action blocks natively. */
buttons?: boolean;
/** Whether the channel can render select/menu blocks natively. */
selects?: boolean;
/** Whether the channel can render low-emphasis context blocks natively. */
context?: boolean;
/** Whether the channel can render divider blocks natively. */
divider?: boolean;
/** Whether the channel can render chart blocks natively. */
charts?: boolean;
/** Whether the channel can render table blocks natively. */
tables?: boolean;
/** Per-channel limits used to adapt portable presentation blocks before rendering. */
limits?: {
actions?: {
/** Maximum total button/select actions in one message. */
maxActions?: number;
/** Maximum buttons per rendered action row. */
maxActionsPerRow?: number;
/** Maximum action rows in one message. */
maxRows?: number;
/** Maximum user-visible button label length. */
maxLabelLength?: number;
/** Maximum callback/action value size in UTF-8 bytes. */
maxValueBytes?: number;
/** Whether action styles such as primary or danger are preserved. */
supportsStyles?: boolean;
/** Whether disabled button state is preserved. */
supportsDisabled?: boolean;
/** Whether priority/layout hints affect native rendering. */
supportsLayoutHints?: boolean;
};
selects?: {
/** Maximum options in one select/menu block. */
maxOptions?: number;
/** Maximum user-visible option label length. */
maxLabelLength?: number;
/** Maximum option callback value size in UTF-8 bytes. */
maxValueBytes?: number;
};
text?: {
/** Maximum text length for title, text, and context blocks. */
maxLength?: number;
/** Unit used by maxLength. Defaults to Unicode code points. */
encoding?: "characters" | "utf8-bytes" | "utf16-units";
/** Markdown dialect understood by rendered text blocks. */
markdownDialect?: "plain" | "markdown" | "html" | "slack-mrkdwn" | "discord-markdown";
/** Whether the channel can edit presentation text in-place. */
supportsEdit?: boolean;
};
};
};
type ChannelDeliveryCapabilities = {
pin?: boolean;
durableFinal?: {
text?: boolean;
media?: boolean;
poll?: boolean;
payload?: boolean;
silent?: boolean;
replyTo?: boolean;
thread?: boolean;
nativeQuote?: boolean;
messageSendingHooks?: boolean;
batch?: boolean;
reconcileUnknownSend?: boolean;
afterSendSuccess?: boolean;
afterCommit?: boolean;
};
};
type ChannelOutboundPayloadHint = {
kind: "approval-pending";
approvalKind: ChannelApprovalKind;
nativeRouteActive?: boolean;
} | {
kind: "approval-resolved";
approvalKind: ChannelApprovalKind;
};
type ChannelOutboundTargetRef = {
channel: string;
to: string;
accountId?: string | null;
threadId?: string | number | null;
};
type ChannelOutboundFormattedContext = ChannelOutboundContext & {
abortSignal?: AbortSignal;
};
type ChannelOutboundChunkContext = {
formatting?: OutboundDeliveryFormattingOptions;
};
type ChannelOutboundNormalizePayloadParams = {
payload: ReplyPayload;
cfg: OpenClawConfig;
accountId?: string | null;
};
type ChannelOutboundNormalizePayloadBatchParams = {
payloads: readonly {
index: number;
payload: ReplyPayload;
}[];
cfg: OpenClawConfig;
accountId?: string | null;
};
type ChannelOutboundAdapter = {
deliveryMode: "direct" | "gateway" | "hybrid";
chunker?: ((text: string, limit: number, ctx?: ChannelOutboundChunkContext) => string[]) | null;
chunkerMode?: "text" | "markdown";
chunkedTextFormatting?: OutboundDeliveryFormattingOptions;
/** Lift remote Markdown image syntax in text into outbound media attachments. */
extractMarkdownImages?: boolean;
/** Preserve model-authored Markdown details blocks for a native channel renderer. */
preserveMarkdownDetails?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => boolean;
textChunkLimit?: number;
/**
* Reserve the exact provider id used by the next single-message send.
* Presence opts the channel into conversations_turn reply correlation.
*/
prepareConversationTurnMessageId?: (params: {
cfg: OpenClawConfig;
to: string;
text: string;
accountId?: string | null;
threadId?: string | number | null;
}) => string;
sanitizeText?: (params: {
text: string;
payload: ReplyPayload;
cfg?: OpenClawConfig;
accountId?: string;
}) => string;
pollMaxOptions?: number;
supportsPollDurationSeconds?: boolean;
supportsAnonymousPolls?: boolean;
normalizePayload?: (params: ChannelOutboundNormalizePayloadParams) => ReplyPayload | null;
/** Normalize an ordered batch in place. Return one entry per input; null suppresses that send. */
normalizePayloadBatch?: (params: ChannelOutboundNormalizePayloadBatchParams) => ReadonlyArray<ReplyPayload | null>;
sendTextOnlyErrorPayloads?: boolean;
shouldSkipPlainTextSanitization?: (params: {
payload: ReplyPayload;
}) => boolean;
resolveEffectiveTextChunkLimit?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
fallbackLimit?: number;
formatting?: OutboundDeliveryFormattingOptions;
}) => number | undefined;
shouldSuppressLocalPayloadPrompt?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
payload: ReplyPayload;
hint?: ChannelOutboundPayloadHint;
}) => boolean;
beforeDeliverPayload?: (params: {
cfg: OpenClawConfig;
target: ChannelOutboundTargetRef;
payload: ReplyPayload;
hint?: ChannelOutboundPayloadHint;
}) => Promise<void> | void;
afterDeliverPayload?: (params: {
cfg: OpenClawConfig;
target: ChannelOutboundTargetRef;
payload: ReplyPayload;
results: readonly OutboundDeliveryResult[];
}) => Promise<void> | void;
/** Adopt a provider-created thread for later payloads in the same durable batch. */
adoptTargetFromDelivery?: (params: {
cfg: OpenClawConfig;
target: ChannelOutboundTargetRef;
result: OutboundDeliveryResult;
}) => {
threadId: string | number;
} | null | undefined;
/** Channel-advertised presentation features and limits used by core adaptation. */
presentationCapabilities?: ChannelPresentationCapabilities;
/**
* Account- and formatting-aware capability resolution; takes precedence over
* the static declaration. Formatting is the delivery's outbound formatting
* options, so capabilities that only apply to one text funnel (for example
* rich tables on the markdown path) can turn off for HTML-mode sends.
*/
resolvePresentationCapabilities?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
formatting?: OutboundDeliveryFormattingOptions;
}) => ChannelPresentationCapabilities;
deliveryCapabilities?: ChannelDeliveryCapabilities;
/** Render an adapted portable presentation into channel-native payload data. */
renderPresentation?: (params: {
payload: ReplyPayload;
presentation: MessagePresentation;
/** Normalized original for readable fallbacks; native rendering uses presentation. */
sourcePresentation?: MessagePresentation;
ctx: ChannelOutboundPayloadContext;
}) => Promise<ReplyPayload | null> | ReplyPayload | null;
pinDeliveredMessage?: (params: {
cfg: OpenClawConfig;
target: ChannelOutboundTargetRef;
messageId: string;
pin: ReplyPayloadDeliveryPin;
gatewayClientScopes?: readonly string[];
}) => Promise<void> | void;
/**
* @deprecated Use shouldTreatDeliveredTextAsVisible instead.
*/
shouldTreatRoutedTextAsVisible?: (params: {
kind: "tool" | "block" | "final";
text?: string;
}) => boolean;
shouldTreatDeliveredTextAsVisible?: (params: {
kind: "tool" | "block" | "final";
text?: string;
}) => boolean;
preferFinalAssistantVisibleText?: boolean;
targetsMatchForReplySuppression?: (params: {
originTarget: string;
targetKey: string;
targetThreadId?: string;
}) => boolean;
resolveTarget?: (params: {
cfg?: OpenClawConfig;
to?: string;
allowFrom?: string[];
accountId?: string | null;
mode?: ChannelOutboundTargetMode;
}) => {
ok: true;
to: string;
} | {
ok: false;
error: Error;
};
sendPayload?: (ctx: ChannelOutboundPayloadContext) => Promise<OutboundDeliveryResult>;
sendFormattedText?: (ctx: ChannelOutboundFormattedContext) => Promise<OutboundDeliveryResult[]>;
sendFormattedMedia?: (ctx: ChannelOutboundFormattedContext & {
mediaUrl: string;
}) => Promise<OutboundDeliveryResult>;
sendText?: (ctx: ChannelOutboundContext) => Promise<OutboundDeliveryResult>;
sendMedia?: (ctx: ChannelOutboundContext) => Promise<OutboundDeliveryResult>;
sendPoll?: (ctx: ChannelPollContext) => Promise<ChannelPollResult>;
};
//#endregion
//#region src/channels/plugins/pairing.types.d.ts
/**
* Channel pairing hooks used by setup and allowlist approval flows.
*/
type ChannelPairingAdapter = {
idLabel: string;
normalizeAllowEntry?: (entry: string) => string;
/** Derive the persisted approval entry from the locally issued request. */
resolveApprovalStoreEntry?: (request: {
id: string;
meta?: Record<string, string>;
}) => string | null | undefined;
notifyApproval?: (params: {
cfg: OpenClawConfig;
id: string;
accountId?: string;
meta?: Record<string, string>;
runtime?: RuntimeEnv;
}) => Promise<void>;
};
//#endregion
//#region src/channels/plugins/types.adapters.d.ts
type ConfiguredBindingRule = AgentBinding;
type ChannelActionAvailabilityState = {
kind: "enabled";
} | {
kind: "disabled";
} | {
kind: "unsupported";
};
type ChannelApprovalForwardTarget = {
channel: string;
to: string;
accountId?: string | null;
threadId?: string | number | null;
source?: "session" | "target";
};
type ChannelCapabilitiesDisplayTone = "default" | "muted" | "success" | "warn" | "error";
type ChannelCapabilitiesDisplayLine = {
text: string;
tone?: ChannelCapabilitiesDisplayTone;
};
type ChannelCapabilitiesDiagnostics = {
lines?: ChannelCapabilitiesDisplayLine[];
details?: Record<string, unknown>;
};
type ChannelAdapterCallback<T extends (...args: never[]) => unknown> = T;
type ChannelAccountLinkState = "linked" | "not-linked" | "unknown";
type ChannelConfigAdapter<ResolvedAccount> = {
listAccountIds: (cfg: OpenClawConfig) => string[];
resolveAccount: (cfg: OpenClawConfig, accountId?: string | null) => ResolvedAccount;
inspectAccount?: (cfg: OpenClawConfig, accountId?: string | null) => unknown;
defaultAccountId?: (cfg: OpenClawConfig) => string;
setAccountEnabled?: (params: {
cfg: OpenClawConfig;
accountId: string;
enabled: boolean;
}) => OpenClawConfig;
deleteAccount?: (params: {
cfg: OpenClawConfig;
accountId: string;
}) => OpenClawConfig;
isEnabled?: ChannelAdapterCallback<(account: ResolvedAccount, cfg: OpenClawConfig) => boolean>;
disabledReason?: ChannelAdapterCallback<(account: ResolvedAccount, cfg: OpenClawConfig) => string>;
isConfigured?: ChannelAdapterCallback<(account: ResolvedAccount, cfg: OpenClawConfig) => boolean | Promise<boolean>>;
isLinked?: ChannelAdapterCallback<(account: ResolvedAccount, cfg: OpenClawConfig) => ChannelAccountLinkState | Promise<ChannelAccountLinkState>>;
unconfiguredReason?: ChannelAdapterCallback<(account: ResolvedAccount, cfg: OpenClawConfig) => string>;
unlinkedReason?: ChannelAdapterCallback<(account: ResolvedAccount, cfg: OpenClawConfig) => string>;
describeAccount?: ChannelAdapterCallback<(account: ResolvedAccount, cfg: OpenClawConfig) => ChannelAccountSnapshot>;
resolveAllowFrom?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => Array<string | number> | undefined;
formatAllowFrom?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
allowFrom: Array<string | number>;
}) => string[];
hasConfiguredState?: (params: {
cfg: OpenClawConfig;
env?: NodeJS.ProcessEnv;
}) => boolean;
hasPersistedAuthState?: (params: {
cfg: OpenClawConfig;
env?: NodeJS.ProcessEnv;
}) => boolean;
resolveDefaultTo?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => string | undefined;
};
type ChannelSecretsAdapter = {
secretTargetRegistryEntries?: readonly SecretTargetRegistryEntry[];
unsupportedSecretRefSurfacePatterns?: readonly string[];
collectUnsupportedSecretRefConfigCandidates?: (raw: unknown) => Array<{
path: string;
value: unknown;
}>;
collectRuntimeConfigAssignments?: (params: {
config: OpenClawConfig;
defaults: SecretDefaults | undefined;
context: ResolverContext;
}) => void;
};
type ChannelGroupAdapter = {
resolveRequireMention?: (params: ChannelGroupContext) => boolean | undefined;
resolveToolPolicy?: (params: ChannelGroupContext) => GroupToolPolicyConfig | undefined;
};
type ChannelStatusAdapter<ResolvedAccount, Probe = unknown, Audit = unknown> = {
defaultRuntime?: ChannelAccountSnapshot;
buildChannelSummary?: ChannelAdapterCallback<(params: {
account: ResolvedAccount;
cfg: OpenClawConfig;
defaultAccountId: string;
snapshot: ChannelAccountSnapshot;
}) => Record<string, unknown> | Promise<Record<string, unknown>>>;
probeAccount?: ChannelAdapterCallback<(params: {
account: ResolvedAccount;
timeoutMs: number;
cfg: OpenClawConfig;
}) => Promise<Probe>>;
formatCapabilitiesProbe?: ChannelAdapterCallback<(params: {
probe: Probe;
}) => ChannelCapabilitiesDisplayLine[]>;
auditAccount?: ChannelAdapterCallback<(params: {
account: ResolvedAccount;
timeoutMs: number;
cfg: OpenClawConfig;
probe?: Probe;
}) => Promise<Audit>>;
buildCapabilitiesDiagnostics?: ChannelAdapterCallback<(params: {
account: ResolvedAccount;
timeoutMs: number;
cfg: OpenClawConfig;
probe?: Probe;
audit?: Audit;
target?: string;
}) => Promise<ChannelCapabilitiesDiagnostics | undefined>>;
buildAccountSnapshot?: ChannelAdapterCallback<(params: {
account: ResolvedAccount;
cfg: OpenClawConfig;
runtime?: ChannelAccountSnapshot;
probe?: Probe;
audit?: Audit;
}) => ChannelAccountSnapshot | Promise<ChannelAccountSnapshot>>;
logSelfId?: ChannelAdapterCallback<(params: {
account: ResolvedAccount;
cfg: OpenClawConfig;
runtime: RuntimeEnv;
includeChannelPrefix?: boolean;
}) => void>;
resolveAccountState?: ChannelAdapterCallback<(params: {
account: ResolvedAccount;
cfg: OpenClawConfig;
configured: boolean;
enabled: boolean;
}) => ChannelAccountState>;
collectStatusIssues?: (accounts: ChannelAccountSnapshot[]) => ChannelStatusIssue[];
};
type ChannelGatewayContext<ResolvedAccount = unknown> = {
cfg: OpenClawConfig;
accountId: string;
account: ResolvedAccount;
runtime: RuntimeEnv;
abortSignal: AbortSignal;
log?: ChannelLogSink;
getStatus: () => ChannelAccountSnapshot;
setStatus: (next: ChannelAccountSnapshot) => void;
/** Clear cached outbound directory lookups after the channel accepts newer directory data. */
invalidateDirectoryCache?: () => void;
/**
* Optional channel runtime helpers for external channel plugins.
*
* This field provides the canonical channel runtime helpers for channel
* dispatch, routing, session, reply, and startup context work.
*
* ## Available Features
*
* - **reply**: AI response dispatching, formatting, and delivery
* - **routing**: Agent route resolution and matching
* - **text**: Text chunking, markdown processing, and control command detection
* - **session**: Session management and metadata tracking
* - **media**: Remote media fetching and buffer saving
* - **commands**: Command authorization and control command handling
* - **groups**: Group policy resolution and mention requirements
* - **pairing**: Channel pairing and allow-from management
*
* ## Use Cases
*
* Channel plugins that need:
* - AI-powered response generation and delivery
* - Advanced text processing and formatting
* - Session tracking and management
* - Agent routing and policy resolution
*
* ## Example
*
* ```typescript
* const emailGatewayAdapter: ChannelGatewayAdapter<EmailAccount> = {
* startAccount: async (ctx) => {
* // Check availability (for backward compatibility)
* if (!ctx.channelRuntime) {
* ctx.log?.warn?.("channelRuntime not available - skipping AI features");
* return;
* }
*
* // Use AI dispatch
* await ctx.channelRuntime.reply.dispatchReplyWithBufferedBlockDispatcher({
* ctx: { ... },
* cfg: ctx.cfg,
* dispatcherOptions: {
* deliver: async (payload) => {
* // Send reply via email
* },
* },
* });
* },
* };
* ```
*
* ## Backward Compatibility
*
* - This field is **optional** - channels that don't need it can ignore it
* - Gateway startup passes a full `createPluginRuntime().channel` surface
* when a runtime resolver is configured
* - External plugins should check for undefined before using
*
* @since Plugin SDK 2026.2.19
* @see {@link https://docs.openclaw.ai/plugins/building-plugins | Plugin SDK documentation}
*/
channelRuntime?: ChannelRuntimeSurface;
};
type ChannelLogoutResult = {
cleared: boolean;
loggedOut?: boolean;
[key: string]: unknown;
};
type ChannelLoginWithQrStartResult = {
qrDataUrl?: string;
message: string;
connected?: boolean;
sessionKey?: string;
};
type ChannelLoginWithQrWaitResult = {
connected: boolean;
message: string;
qrDataUrl?: string;
};
type ChannelLogoutContext<ResolvedAccount = unknown> = {
cfg: OpenClawConfig;
accountId: string;
account: ResolvedAccount;
runtime: RuntimeEnv;
log?: ChannelLogSink;
};
type ChannelGatewayAdapter<ResolvedAccount = unknown> = {
startAccount?: (ctx: ChannelGatewayContext<ResolvedAccount>) => Promise<unknown>;
stopAccount?: (ctx: ChannelGatewayContext<ResolvedAccount>) => Promise<void>;
/** Keep gateway auth bypass resolution mirrored through a lightweight top-level `gateway-auth-api.ts` artifact. */
resolveGatewayAuthBypassPaths?: (params: {
cfg: OpenClawConfig;
}) => string[];
loginWithQrStart?: (params: {
accountId?: string;
force?: boolean;
timeoutMs?: number;
verbose?: boolean;
}) => Promise<ChannelLoginWithQrStartResult>;
loginWithQrWait?: (params: {
accountId?: string;
sessionKey?: string;
timeoutMs?: number;
currentQrDataUrl?: string;
}) => Promise<ChannelLoginWithQrWaitResult>;
logoutAccount?: (ctx: ChannelLogoutContext<ResolvedAccount>) => Promise<ChannelLogoutResult>;
};
type ChannelAuthAdapter = {
login?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
runtime: RuntimeEnv;
verbose?: boolean;
channelInput?: string | null;
}) => Promise<void>;
};
type ChannelHeartbeatAdapter = {
checkReady?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
deps?: ChannelHeartbeatDeps;
}) => Promise<{
ok: boolean;
reason: string;
}>;
sendTyping?: (params: {
cfg: OpenClawConfig;
to: string;
accountId?: string | null;
threadId?: string | number | null;
deps?: ChannelHeartbeatDeps;
}) => Promise<void> | void;
clearTyping?: (params: {
cfg: OpenClawConfig;
to: string;
accountId?: string | null;
threadId?: string | number | null;
deps?: ChannelHeartbeatDeps;
}) => Promise<void> | void;
};
type ChannelDirectorySelfParams = {
cfg: OpenClawConfig;
accountId?: string | null;
runtime: RuntimeEnv;
};
type ChannelDirectoryListParams = {
cfg: OpenClawConfig;
accountId?: string | null;
query?: string | null;
limit?: number | null;
runtime: RuntimeEnv;
};
type ChannelDirectoryListGroupMembersParams = {
cfg: OpenClawConfig;
accountId?: string | null;
groupId: string;
limit?: number | null;
runtime: RuntimeEnv;
};
type ChannelDirectoryAdapter = {
self?: (params: ChannelDirectorySelfParams) => Promise<ChannelDirectoryEntry | null>;
listPeers?: (params: ChannelDirectoryListParams) => Promise<ChannelDirectoryEntry[]>;
listPeersLive?: (params: ChannelDirectoryListParams) => Promise<ChannelDirectoryEntry[]>;
listGroups?: (params: ChannelDirectoryListParams) => Promise<ChannelDirectoryEntry[]>;
listGroupsLive?: (params: ChannelDirectoryListParams) => Promise<ChannelDirectoryEntry[]>;
listGroupMembers?: (params: ChannelDirectoryListGroupMembersParams) => Promise<ChannelDirectoryEntry[]>;
};
type ChannelResolveKind = "user" | "group";
type ChannelResolveResult = {
input: string;
resolved: boolean;
id?: string;
name?: string;
note?: string;
};
type ChannelResolverAdapter = {
resolveTargets: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
inputs: string[];
kind: ChannelResolveKind;
runtime: RuntimeEnv;
}) => Promise<ChannelResolveResult[]>;
};
type ChannelElevatedAdapter = {
allowFromFallback?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => Array<string | number> | undefined;
};
type ChannelCommandAdapter = {
enforceOwnerForCommands?: boolean;
skipWhenConfigEmpty?: boolean;
nativeCommandsAutoEnabled?: boolean;
nativeSkillsAutoEnabled?: boolean;
preferSenderE164ForCommands?: boolean;
resolveNativeCommandName?: (params: {
commandKey: string;
defaultName: string;
}) => string | undefined;
buildCommandsListChannelData?: (params: {
currentPage: number;
totalPages: number;
agentId?: string;
}) => ReplyPayload["channelData"] | null;
buildModelsMenuChannelData?: (params: {
providers: Array<{
id: string;
count: number;
}>;
}) => ReplyPayload["channelData"] | null;
buildModelsProviderChannelData?: (params: {
providers: Array<{
id: string;
count: number;
}>;
}) => ReplyPayload["channelData"] | null;
buildModelsAddProviderChannelData?: (params: {
providers: Array<{
id: string;
}>;
}) => ReplyPayload["channelData"] | null;
buildModelsListChannelData?: (params: {
provider: string;
models: readonly string[];
currentModel?: string;
currentPage: number;
totalPages: number;
pageSize?: number;
modelNames?: ReadonlyMap<string, string>;
}) => ReplyPayload["channelData"] | null;
buildModelBrowseChannelData?: () => ReplyPayload["channelData"] | null;
};
type ChannelDoctorConfigMutation = {
config: OpenClawConfig;
changes: string[];
warnings?: string[];
};
type ChannelDoctorSequenceResult = {
changeNotes: string[];
warningNotes: string[];
};
type ChannelDoctorEmptyAllowlistAccountContext = {
account: Record<string, unknown>;
channelName: string;
dmPolicy?: string;
effectiveAllowFrom?: Array<string | number>;
parent?: Record<string, unknown>;
prefix: string;
};
type ChannelDoctorAdapter = {
dmAllowFromMode?: "topOnly" | "topOrNested" | "nestedOnly";
groupModel?: "sender" | "route" | "hybrid";
groupAllowFromFallbackToAllowFrom?: boolean;
warnOnEmptyGroupSenderAllowlist?: boolean;
legacyConfigRules?: LegacyConfigRule[];
normalizeCompatibilityConfig?: (params: {
cfg: OpenClawConfig;
}) => ChannelDoctorConfigMutation;
collectPreviewWarnings?: (params: {
cfg: OpenClawConfig;
doctorFixCommand: string;
env?: NodeJS.ProcessEnv;
}) => string[] | Promise<string[]>;
collectMutableAllowlistWarnings?: (params: {
cfg: OpenClawConfig;
}) => string[] | Promise<string[]>;
repairConfig?: (params: {
cfg: OpenClawConfig;
doctorFixCommand: string;
env?: NodeJS.ProcessEnv;
}) => ChannelDoctorConfigMutation | Promise<ChannelDoctorConfigMutation>;
runConfigSequence?: (params: {
cfg: OpenClawConfig;
env: NodeJS.ProcessEnv;
shouldRepair: boolean;
}) => ChannelDoctorSequenceResult | Promise<ChannelDoctorSequenceResult>;
cleanStaleConfig?: (params: {
cfg: OpenClawConfig;
}) => ChannelDoctorConfigMutation | Promise<ChannelDoctorConfigMutation>;
collectEmptyAllowlistExtraWarnings?: (params: ChannelDoctorEmptyAllowlistAccountContext) => string[];
shouldSkipDefaultEmptyGroupAllowlistWarning?: (params: ChannelDoctorEmptyAllowlistAccountContext) => boolean;
};
type ChannelLifecycleAdapter = {
onAccountConfigChanged?: (params: {
prevCfg: OpenClawConfig;
nextCfg: OpenClawConfig;
accountId: string;
runtime: RuntimeEnv;
}) => Promise<void> | void;
onAccountRemoved?: (params: {
prevCfg: OpenClawConfig;
accountId: string;
runtime: RuntimeEnv;
}) => Promise<void> | void;
runStartupMaintenance?: (params: {
cfg: OpenClawConfig;
env?: NodeJS.ProcessEnv;
log: {
info?: (message: string) => void;
warn?: (message: string) => void;
};
trigger?: string;
logPrefix?: string;
}) => Promise<void> | void;
/**
* @deprecated Export stateMigrations from the plugin doctor contract instead.
* Removal plan: remove the lifecycle adapter after the 2027.1 external-plugin migration window.
*/
detectLegacyStateMigrations?: (params: {
cfg: OpenClawConfig;
env: NodeJS.ProcessEnv;
stateDir: string;
oauthDir: string;
}) => ChannelLegacyStateMigrationPlan[] | Promise<ChannelLegacyStateMigrationPlan[]>;
};
type ChannelApprovalDeliveryAdapter = {
hasConfiguredDmRoute?: (params: {
cfg: OpenClawConfig;
}) => boolean;
shouldSuppressForwardingFallback?: (params: {
cfg: OpenClawConfig;
approvalKind: ChannelApprovalKind;
target: ChannelApprovalForwardTarget;
request: ExecApprovalRequest | PluginApprovalRequest$1 | SystemAgentApprovalRequest;
}) => boolean;
};
type ChannelApproveCommandBehavior = {
kind: "allow";
} | {
kind: "ignore";
} | {
kind: "reply";
text: string;
};
type ChannelApprovalRenderAdapter = {
exec?: {
buildPendingPayload?: (params: {
cfg: OpenClawConfig;
request: ExecApprovalRequest;
target: ChannelApprovalForwardTarget;
nowMs: number;
}) => ReplyPayload | null;
buildResolvedPayload?: (params: {
cfg: OpenClawConfig;
resolved: ExecApprovalResolved;
target: ChannelApprovalForwardTarget;
}) => ReplyPayload | null;
};
plugin?: {
buildPendingPayload?: (params: {
cfg: OpenClawConfig;
request: PluginApprovalRequest$1;
target: ChannelApprovalForwardTarget;
nowMs: number;
}) => ReplyPayload | null;
buildResolvedPayload?: (params: {
cfg: OpenClawConfig;
resolved: PluginApprovalResolved;
target: ChannelApprovalForwardTarget;
}) => ReplyPayload | null;
};
};
type ChannelApprovalAdapter = {
delivery?: ChannelApprovalDeliveryAdapter;
nativeRuntime?: ChannelApprovalNativeRuntimeAdapter;
render?: ChannelApprovalRenderAdapter;
native?: ChannelApprovalNativeAdapter;
describeExecApprovalSetup?: (params: {
channel: string;
channelLabel: string;
accountId?: string;
}) => string | null | undefined;
describePluginApprovalSetup?: (params: {
channel: string;
channelLabel: string;
accountId?: string;
}) => string | null | undefined;
};
type ChannelApprovalCapability = ChannelApprovalAdapter & {
authorizeActorAction?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
senderId?: string | null;
action: "approve";
approvalKind: ChannelApprovalKind;
}) => {
authorized: boolean;
reason?: string;
};
getActionAvailabilityState?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
action: "approve";
approvalKind?: ChannelApprovalKind;
}) => ChannelActionAvailabilityState;
/** Exec-native client availability for the initiating surface; distinct from same-chat auth. */
getExecInitiatingSurfaceState?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
action: "approve";
}) => ChannelActionAvailabilityState;
resolveApproveCommandBehavior?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
senderId?: string | null;
approvalKind: ChannelApprovalKind;
}) => ChannelApproveCommandBehavior | undefined;
};
type ChannelAllowlistAdapter = {
applyConfigEdit?: (params: {
cfg: OpenClawConfig;
parsedConfig: Record<string, unknown>;
accountId?: string | null;
scope: "dm" | "group";
action: "add" | "remove";
entry: string;
}) => {
kind: "ok";
changed: boolean;
pathLabel: string;
writeTarget: ConfigWriteTarget;
} | {
kind: "invalid-entry";
} | Promise<{
kind: "ok";
changed: boolean;
pathLabel: string;
writeTarget: ConfigWriteTarget;
} | {
kind: "invalid-entry";
}> | null;
readConfig?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => {
dmAllowFrom?: Array<string | number>;
groupAllowFrom?: Array<string | number>;
dmPolicy?: string;
groupPolicy?: string;
groupOverrides?: Array<{
label: string;
entries: Array<string | number>;
}>;
} | Promise<{
dmAllowFrom?: Array<string | number>;
groupAllowFrom?: Array<string | number>;
dmPolicy?: string;
groupPolicy?: string;
groupOverrides?: Array<{
label: string;
entries: Array<string | number>;
}>;
}>;
resolveNames?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
scope: "dm" | "group";
entries: string[];
}) => Array<{
input: string;
resolved: boolean;
name?: string | null;
}> | Promise<Array<{
input: string;
resolved: boolean;
name?: string | null;
}>>;
supportsScope?: (params: {
scope: "dm" | "group" | "all";
}) => boolean;
};
type ChannelConfiguredBindingConversationRef = {
conversationId: string;
parentConversationId?: string;
};
type ChannelConfiguredBindingMatch = ChannelConfiguredBindingConversationRef & {
matchPriority?: number;
};
type ChannelCommandConversationContext = {
accountId: string;
threadId?: string;
threadParentId?: string;
senderId?: string;
sessionKey?: string;
parentSessionKey?: string;
from?: string;
chatType?: string;
originatingTo?: string;
commandTo?: string;
fallbackTo?: string;
};
type ChannelConfiguredBindingProvider = {
selfParentConversationByDefault?: boolean;
compileConfiguredBinding: (params: {
binding: ConfiguredBindingRule;
conversationId: string;
}) => ChannelConfiguredBindingConversationRef | null;
matchInboundConversation: (params: {
binding: ConfiguredBindingRule;
compiledBinding: ChannelConfiguredBindingConversationRef;
conversationId: string;
parentConversationId?: string;
}) => ChannelConfiguredBindingMatch | null;
resolveCommandConversation?: (params: ChannelCommandConversationContext) => ChannelConfiguredBindingConversationRef | null;
};
type ChannelConversationBindingSupport = {
supportsCurrentConversationBinding?: boolean;
isCurrentConversationBindingSupported?: (params: {
accountId: string;
}) => boolean;
/** Declares that live bindings come from a channel-registered adapter, never generic storage. */
bindingStore?: "adapter";
/**
* Preferred placement when a command is started from a top-level conversation
* without an existing native thread id.
*
* - `current`: bind/spawn in the current conversation
* - `child`: create a child thread/conversation first
*/
defaultTopLevelPlacement?: "current" | "child";
resolveConversationRef?: (params: {
accountId?: string | null;
conversationId: string;
parentConversationId?: string;
threadId?: string | number | null;
}) => {
conversationId: string;
parentConversationId?: string;
} | null;
buildBoundReplyPayload?: (params: {
operation: "acp-spawn";
placement: "current" | "child";
conversation: {
channel: string;
accountId?: string | null;
conversationId: string;
parentConversationId?: string;
};
}) => Pick<ReplyPayload, "channelData" | "delivery" | "presentation"> | null | Promise<Pick<ReplyPayload, "channelData" | "delivery" | "presentation"> | null>;
buildModelOverrideParentCandidates?: (params: {
parentConversationId?: string | null;
}) => string[] | null | undefined;
shouldStripThreadFromAnnounceOrigin?: (params: {
requester: {
channel?: string;
to?: string;
threadId?: string | number;
};
entry: {
channel?: string;
to?: string;
threadId?: string | number;
};
}) => boolean;
setIdleTimeoutBySessionKey?: (params: {
targetSessionKey: string;
accountId?: string | null;
idleTimeoutMs: number;
}) => Array<{
boundAt: number;
lastActivityAt: number;
idleTimeoutMs?: number;
maxAgeMs?: number;
}>;
setMaxAgeBySessionKey?: (params: {
targetSessionKey: string;
accountId?: string | null;
maxAgeMs: number;
}) => Array<{
boundAt: number;
lastActivityAt: number;
idleTimeoutMs?: number;
maxAgeMs?: number;
}>;
createManager?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => {
stop: () => void | Promise<void>;
} | Promise<{
stop: () => void | Promise<void>;
}>;
};
type ChannelSecurityDmRouteContext<ResolvedAccount> = ChannelSecurityContext<ResolvedAccount> & {
accountId: string;
principalId?: string;
};
type ChannelSecurityAdapter<ResolvedAccount = unknown> = {
applyConfigFixes?: (params: {
cfg: OpenClawConfig;
env: NodeJS.ProcessEnv;
}) => ChannelDoctorConfigMutation | Promise<ChannelDoctorConfigMutation>;
resolveDmPolicy?: ChannelAdapterCallback<(ctx: ChannelSecurityContext<ResolvedAccount>) => ChannelSecurityDmPolicy | null>;
dmRouting?: {
resolveDmScope?: (ctx: ChannelSecurityDmRouteContext<ResolvedAccount>) => DmScope | undefined;
resolveDmRoute?: (ctx: ChannelSecurityDmRouteContext<ResolvedAccount> & {
route: ResolvedAgentRoute;
}) => {
kind: "core" | "isolated";
} | {
sessionKey: string;
} | undefined;
};
collectWarnings?: ChannelAdapterCallback<(ctx: ChannelSecurityContext<ResolvedAccount>) => Promise<Array<string | SecurityAuditFinding>> | Array<string | SecurityAuditFinding>>;
collectAuditFindings?: ChannelAdapterCallback<(ctx: ChannelSecurityContext<ResolvedAccount> & {
sourceConfig: OpenClawConfig;
orderedAccountIds: string[];
hasExplicitAccountPath: boolean;
}) => Promise<SecurityAuditFinding[]> | SecurityAuditFinding[]>;
};
//#endregion
//#region src/wizard/prompts.d.ts
type WizardSelectOption<T = string> = {
value: T;
label: string;
hint?: string;
};
type WizardPromptNavigation = {
canGoBack?: boolean;
canGoForward?: boolean;
};
type WizardSelectParams<T = string> = {
message: string;
options: Array<WizardSelectOption<T>>;
initialValue?: T;
searchable?: boolean;
navigation?: WizardPromptNavigation;
};
type WizardMultiSelectParams<T = string> = {
message: string;
options: Array<WizardSelectOption<T>>;
initialValues?: T[];
searchable?: boolean;
navigation?: WizardPromptNavigation;
};
type WizardTextParams = {
message: string;
initialValue?: string;
placeholder?: string;
validate?: (value: string) => string | undefined;
signal?: AbortSignal;
sensitive?: boolean;
navigation?: WizardPromptNavigation;
};
type WizardConfirmParams = {
message: string;
initialValue?: boolean;
layout?: "inline" | "vertical";
navigation?: WizardPromptNavigation;
};
type WizardProgress = {
update: (message: string) => void;
stop: (message?: string) => void;
};
type WizardDeviceCodeParams = {
title: string;
code: string;
expiresInMinutes?: number;
message?: string;
};
type WizardPrompter = {
/** End a hosted flow after a required choice is declined. */
cancel?: (message: string) => never;
intro: (title: string) => Promise<void>;
outro: (message: string) => Promise<void>;
note: (message: string, title?: string) => Promise<void>;
/** Present a browser device code as structured UI when the client supports it. */
deviceCode?: (params: WizardDeviceCodeParams) => Promise<void>;
plain?: (message: string) => Promise<void>;
select: <T>(params: WizardSelectParams<T>) => Promise<T>;
multiselect: <T>(params: WizardMultiSelectParams<T>) => Promise<T[]>;
text: (params: WizardTextParams) => Promise<string>;
confirm: (params: WizardConfirmParams) => Promise<boolean>;
progress: (label: string) => WizardProgress;
/** Queue an explicit browser destination for the next interactive client step. */
openUrl?: (url: string) => Promise<void>;
disableBackNavigation?: () => void;
};
//#endregion
//#region src/channels/plugins/setup-group-access.d.ts
/**
* Group access policy selected during channel setup.
*/
type ChannelAccessPolicy = "allowlist" | "open" | "disabled";
//#endregion
//#region src/channels/plugins/setup-wizard-types.d.ts
type ChannelSetupPlugin = {
id: ChannelId$1;
meta: ChannelMeta;
capabilities: ChannelCapabilities;
config: ChannelConfigAdapter<unknown>;
setupContract?: ChannelOwnedSetupContract;
setup?: ChannelSetupAdapter;
setupWizard?: ChannelSetupWizard | ChannelSetupWizardAdapter;
};
/** Status block shown before users select channels during setup. */
type ChannelSetupWizardStatus = {
configuredLabel: string;
unconfiguredLabel: string;
configuredHint?: string;
unconfiguredHint?: string;
configuredScore?: number;
unconfiguredScore?: number;
resolveConfigured: (params: {
cfg: OpenClawConfig;
accountId?: string;
}) => boolean | Promise<boolean>;
resolveStatusLines?: (params: {
cfg: OpenClawConfig;
accountId?: string;
configured: boolean;
}) => string[] | Promise<string[]>;
resolveSelectionHint?: (params: {
cfg: OpenClawConfig;
accountId?: string;
configured: boolean;
}) => string | undefined | Promise<string | undefined>;
resolveQuickstartScore?: (params: {
cfg: OpenClawConfig;
accountId?: string;
configured: boolean;
}) => number | undefined | Promise<number | undefined>;
};
/** Snapshot of one credential before prompting or reusing existing config. */
type ChannelSetupWizardCredentialState = {
accountConfigured: boolean;
hasConfiguredValue: boolean;
resolvedValue?: string;
envValue?: string;
};
type ChannelSetupWizardCredentialValues = Partial<Record<string, string>>;
/** Optional explanatory note shown when its owning step is reached. */
type ChannelSetupWizardNote = {
title: string;
lines: string[];
shouldShow?: (params: {
cfg: OpenClawConfig;
accountId: string;
credentialValues: ChannelSetupWizardCredentialValues;
}) => boolean | Promise<boolean>;
};
/** Lets a wizard configure an account entirely from existing environment. */
type ChannelSetupWizardEnvShortcut = {
prompt: string;
preferredEnvVar?: string;
isAvailable: (params: {
cfg: OpenClawConfig;
accountId: string;
}) => boolean;
apply: (params: {
cfg: OpenClawConfig;
accountId: string;
}) => OpenClawConfig | Promise<OpenClawConfig>;
};
/** Declarative secret/input step for a channel account credential. */
type ChannelSetupWizardCredential = {
/** Plugin-owned key written into the runtime setup input. */
inputKey: string;
providerHint: string;
credentialLabel: string;
preferredEnvVar?: string;
helpTitle?: string;
helpLines?: string[];
envPrompt: string;
keepPrompt: string;
inputPrompt: string;
allowEnv?: (params: {
cfg: OpenClawConfig;
accountId: string;
}) => boolean;
inspect: (params: {
cfg: OpenClawConfig;
accountId: string;
}) => ChannelSetupWizardCredentialState;
shouldPrompt?: (params: {
cfg: OpenClawConfig;
accountId: string;
credentialValues: ChannelSetupWizardCredentialValues;
currentValue?: string;
state: ChannelSetupWizardCredentialState;
}) => boolean | Promise<boolean>;
applyUseEnv?: (params: {
cfg: OpenClawConfig;
accountId: string;
}) => OpenClawConfig | Promise<OpenClawConfig>;
applySet?: (params: {
cfg: OpenClawConfig;
accountId: string;
credentialValues: ChannelSetupWizardCredentialValues;
value: unknown;
resolvedValue: string;
}) => OpenClawConfig | Promise<OpenClawConfig>;
};
/** Declarative text step that can depend on resolved credentials. */
type ChannelSetupWizardTextInput = {
/** Plugin-owned key written into the runtime setup input. */
inputKey: string;
message: string;
placeholder?: string;
/** Mask input and keep any configured value server-side. */
sensitive?: boolean;
required?: boolean;
applyEmptyValue?: boolean;
helpTitle?: string;
helpLines?: string[];
confirmCurrentValue?: boolean;
keepPrompt?: string | ((value: string) => string);
currentValue?: (params: {
cfg: OpenClawConfig;
accountId: string;
credentialValues: ChannelSetupWizardCredentialValues;
}) => string | undefined | Promise<string | undefined>;
initialValue?: (params: {
cfg: OpenClawConfig;
accountId: string;
credentialValues: ChannelSetupWizardCredentialValues;
}) => string | undefined | Promise<string | undefined>;
shouldPrompt?: (params: {
cfg: OpenClawConfig;
accountId: string;
credentialValues: ChannelSetupWizardCredentialValues;
currentValue?: string;
}) => boolean | Promise<boolean>;
applyCurrentValue?: boolean;
validate?: (params: {
value: string;
cfg: OpenClawConfig;
accountId: string;
credentialValues: ChannelSetupWizardCredentialValues;
}) => string | undefined;
normalizeValue?: (params: {
value: string;
cfg: OpenClawConfig;
accountId: string;
credentialValues: ChannelSetupWizardCredentialValues;
}) => string;
applySet?: (params: {
cfg: OpenClawConfig;
accountId: string;
value: string;
}) => OpenClawConfig | Promise<OpenClawConfig>;
};
type ChannelSetupWizardAllowFromEntry = {
input: string;
resolved: boolean;
id: string | null;
};
/** Channel-specific resolver for user-entered allowlist targets. */
type ChannelSetupWizardAllowFrom = {
helpTitle?: string;
helpLines?: string[];
credentialInputKey?: string;
message: string;
placeholder: string;
invalidWithoutCredentialNote: string;
parseInputs?: (raw: string) => string[];
parseId: (raw: string) => string | null;
resolveEntries: (params: {
cfg: OpenClawConfig;
accountId: string;
credentialValues: ChannelSetupWizardCredentialValues;
entries: string[];
}) => Promise<ChannelSetupWizardAllowFromEntry[]>;
apply: (params: {
cfg: OpenClawConfig;
accountId: string;
allowFrom: string[];
}) => OpenClawConfig | Promise<OpenClawConfig>;
};
/** Declarative group/DM access policy step used by interactive setup. */
type ChannelSetupWizardGroupAccess = {
label: string;
placeholder: string;
helpTitle?: string;
helpLines?: string[];
skipAllowlistEntries?: boolean;
currentPolicy: (params: {
cfg: OpenClawConfig;
accountId: string;
}) => ChannelAccessPolicy;
currentEntries: (params: {
cfg: OpenClawConfig;
accountId: string;
}) => string[];
updatePrompt: (params: {
cfg: OpenClawConfig;
accountId: string;
}) => boolean;
setPolicy: (params: {
cfg: OpenClawConfig;
accountId: string;
policy: ChannelAccessPolicy;
}) => OpenClawConfig;
resolveAllowlist?: (params: {
cfg: OpenClawConfig;
accountId: string;
credentialValues: ChannelSetupWizardCredentialValues;
entries: string[];
prompter: Pick<WizardPrompter, "note">;
}) => Promise<unknown>;
applyAllowlist?: (params: {
cfg: OpenClawConfig;
accountId: string;
resolved: unknown;
}) => OpenClawConfig;
};
/** Optional pre-step hook for deriving helper config or credential values. */
type ChannelSetupWizardPrepare = (params: {
cfg: OpenClawConfig;
accountId: string;
credentialValues: ChannelSetupWizardCredentialValues;
runtime: ChannelSetupConfigureContext["runtime"];
prompter: WizardPrompter;
options?: ChannelSetupConfigureContext["options"];
}) => {
cfg?: OpenClawConfig;
credentialValues?: ChannelSetupWizardCredentialValues;
} | void | Promise<{
cfg?: OpenClawConfig;
credentialValues?: ChannelSetupWizardCredentialValues;
} | void>;
/** Optional post-step hook for final validation, writes, or post prompts. */
type ChannelSetupWizardFinalize = (params: {
cfg: OpenClawConfig;
accountId: string;
credentialValues: ChannelSetupWizardCredentialValues;
runtime: ChannelSetupConfigureContext["runtime"];
prompter: WizardPrompter;
options?: ChannelSetupConfigureContext["options"];
forceAllowFrom: boolean;
}) => {
cfg?: OpenClawConfig;
credentialValues?: ChannelSetupWizardCredentialValues;
} | void | Promise<{
cfg?: OpenClawConfig;
credentialValues?: ChannelSetupWizardCredentialValues;
} | void>;
/** Full declarative setup wizard consumed by the generic setup adapter. */
type ChannelSetupWizard = {
channel: string;
status: ChannelSetupWizardStatus;
introNote?: ChannelSetupWizardNote;
envShortcut?: ChannelSetupWizardEnvShortcut;
resolveAccountIdForConfigure?: (params: {
cfg: OpenClawConfig;
prompter: WizardPrompter;
options?: ChannelSetupConfigureContext["options"];
accountOverride?: string;
shouldPromptAccountIds: boolean;
listAccountIds: ChannelSetupPlugin["config"]["listAccountIds"];
defaultAccountId: string;
}) => string | Promise<string>;
resolveShouldPromptAccountIds?: (params: {
cfg: OpenClawConfig;
options?: ChannelSetupConfigureContext["options"];
shouldPromptAccountIds: boolean;
}) => boolean;
prepare?: ChannelSetupWizardPrepare;
stepOrder?: "credentials-first" | "text-first";
credentials: ChannelSetupWizardCredential[];
textInputs?: ChannelSetupWizardTextInput[];
finalize?: ChannelSetupWizardFinalize;
completionNote?: ChannelSetupWizardNote;
dmPolicy?: ChannelSetupDmPolicy;
allowFrom?: ChannelSetupWizardAllowFrom;
groupAccess?: ChannelSetupWizardGroupAccess;
disable?: (cfg: OpenClawConfig) => OpenClawConfig;
onAccountRecorded?: ChannelSetupWizardAdapter["onAccountRecorded"];
};
/** Runtime options for selecting and configuring one or more channels. */
type SetupChannelsOptions = {
/** Workspace already selected by the caller, used for trusted plugin discovery. */
workspaceDir?: string;
allowDisable?: boolean;
allowIMessageInstall?: boolean;
allowSignalInstall?: boolean;
/** Revalidate host authority immediately before an installer or other durable effect. */
beforePersistentEffect?: () => Promise<void>;
onSelection?: (selection: ChannelId$1[]) => void;
onPostWriteHook?: (hook: ChannelOnboardingPostWriteHook) => void;
accountIds?: Partial<Record<ChannelId$1, string>>;
onAccountId?: (channel: ChannelId$1, accountId: string) => void;
onResolvedPlugin?: (channel: ChannelId$1, plugin: ChannelSetupPlugin) => void;
promptAccountIds?: boolean;
forceAllowFromChannels?: ChannelId$1[];
deferStatusUntilSelection?: boolean;
/**
* The controlling client finishes device linking itself after config is
* written (e.g. Control UI renders the WhatsApp QR via web.login.*), so
* setup surfaces must skip terminal-interactive login/link prompts.
*/
deferDeviceLinkToClient?: boolean;
skipStatusNote?: boolean;
skipDmPolicyPrompt?: boolean;
skipConfirm?: boolean;
quickstartDefaults?: boolean;
initialSelection?: ChannelId$1[];
/** Finish after the explicitly targeted channel is configured or paused. */
finishAfterInitialSelection?: boolean;
secretInputMode?: "plaintext" | "ref";
};
type ChannelSetupStatus = {
channel: ChannelId$1;
configured: boolean;
statusLines: string[];
selectionHint?: string;
quickstartScore?: number;
};
/** Shared context for status checks before channel selection. */
type ChannelSetupStatusContext = {
cfg: OpenClawConfig;
options?: SetupChannelsOptions;
accountOverrides: Partial<Record<ChannelId$1, string>>;
};
/** Shared context for applying setup changes for a selected channel. */
type ChannelSetupConfigureContext = {
cfg: OpenClawConfig;
runtime: RuntimeEnv;
prompter: WizardPrompter;
options?: SetupChannelsOptions;
accountOverrides: Partial<Record<ChannelId$1, string>>;
shouldPromptAccountIds: boolean;
forceAllowFrom: boolean;
};
/** Context passed after setup has written config to disk. */
type ChannelOnboardingPostWriteContext = {
previousCfg: OpenClawConfig;
cfg: OpenClawConfig;
accountId: string;
runtime: RuntimeEnv;
};
/** Deferred hook for channel work that must run after config persistence. */
type ChannelOnboardingPostWriteHook = {
channel: ChannelId$1;
accountId: string;
run: (ctx: {
cfg: OpenClawConfig;
runtime: RuntimeEnv;
}) => Promise<void> | void;
};
type ChannelSetupResult = {
cfg: OpenClawConfig;
accountId?: string;
completion?: "configured";
} | {
cfg: OpenClawConfig;
/** Paused setup is persisted without configured-account hooks or routing. */
completion: "paused";
accountId?: never;
};
type ChannelSetupConfiguredResult = ChannelSetupResult | "skip";
type ChannelSetupInteractiveContext = ChannelSetupConfigureContext & {
configured: boolean;
label: string;
};
/** Optional direct-message policy contract exposed by setup adapters. */
type ChannelSetupDmPolicy = {
label: string;
channel: ChannelId$1;
policyKey: string;
allowFromKey: string;
resolveConfigKeys?: (cfg: OpenClawConfig, accountId?: string) => {
policyKey: string;
allowFromKey: string;
};
getCurrent: (cfg: OpenClawConfig, accountId?: string) => DmPolicy;
setPolicy: (cfg: OpenClawConfig, policy: DmPolicy, accountId?: string) => OpenClawConfig;
promptAllowFrom?: (params: {
cfg: OpenClawConfig;
prompter: WizardPrompter;
accountId?: string;
}) => Promise<OpenClawConfig>;
};
/** Imperative adapter consumed by onboarding and setup flows. */
type ChannelSetupWizardAdapter = {
channel: ChannelId$1;
getStatus: (ctx: ChannelSetupStatusContext) => Promise<ChannelSetupStatus>;
configure: (ctx: ChannelSetupConfigureContext) => Promise<ChannelSetupResult>;
configureInteractive?: (ctx: ChannelSetupInteractiveContext) => Promise<ChannelSetupConfiguredResult>;
configureWhenConfigured?: (ctx: ChannelSetupInteractiveContext) => Promise<ChannelSetupConfiguredResult>;
afterConfigWritten?: (ctx: ChannelOnboardingPostWriteContext) => Promise<void> | void;
dmPolicy?: ChannelSetupDmPolicy;
onAccountRecorded?: (accountId: string, options?: SetupChannelsOptions) => void;
disable?: (cfg: OpenClawConfig) => OpenClawConfig;
};
//#endregion
//#region src/channels/plugins/types.plugin.d.ts
/** Full capability contract for a native channel plugin. */
type ChannelPluginSetupWizard = ChannelSetupWizard | ChannelSetupWizardAdapter;
type ChannelGatewayMethodDescriptor = {
name: string;
scope?: OperatorScope;
description?: string;
};
type ChannelPlugin$3<ResolvedAccount = any, Probe = unknown, Audit = unknown> = {
id: ChannelId$1;
meta: ChannelMeta;
capabilities: ChannelCapabilities;
defaults?: {
queue?: {
debounceMs?: number;
};
};
reload?: {
configPrefixes: string[];
noopPrefixes?: string[];
/**
* Opt into restarting only the changed non-default named account.
* Set only when sibling account resolution and lifecycle state are isolated and
* account stop fully settles owned work. Shared, default, removed, or unresolved
* account changes still restart the whole channel.
*/
accountScopedRestart?: boolean;
};
setupWizard?: ChannelPluginSetupWizard;
config: ChannelConfigAdapter<ResolvedAccount>;
configSchema?: ChannelConfigSchema;
/** Channel-owned typed setup contract. Preferred over the legacy shared input adapter. */
setupContract?: ChannelOwnedSetupContract;
/** @deprecated Use setupContract for new plugins. */
setup?: ChannelSetupAdapter;
pairing?: ChannelPairingAdapter;
security?: ChannelSecurityAdapter<ResolvedAccount>;
groups?: ChannelGroupAdapter;
mentions?: ChannelMentionAdapter;
outbound?: ChannelOutboundAdapter;
status?: ChannelStatusAdapter<ResolvedAccount, Probe, Audit>;
gatewayMethods?: string[];
gatewayMethodDescriptors?: ChannelGatewayMethodDescriptor[];
gateway?: ChannelGatewayAdapter<ResolvedAccount>;
auth?: ChannelAuthAdapter;
approvalCapability?: ChannelApprovalCapability;
elevated?: ChannelElevatedAdapter;
commands?: ChannelCommandAdapter;
lifecycle?: ChannelLifecycleAdapter;
secrets?: ChannelSecretsAdapter;
allowlist?: ChannelAllowlistAdapter;
doctor?: ChannelDoctorAdapter;
bindings?: ChannelConfiguredBindingProvider;
conversationBindings?: ChannelConversationBindingSupport;
streaming?: ChannelStreamingAdapter;
threading?: ChannelThreadingAdapter;
message?: ChannelMessageAdapterShape;
messaging?: ChannelMessagingAdapter;
agentPrompt?: ChannelAgentPromptAdapter;
directory?: ChannelDirectoryAdapter;
resolver?: ChannelResolverAdapter;
actions?: ChannelMessageActionAdapter;
heartbeat?: ChannelHeartbeatAdapter;
agentTools?: ChannelAgentToolFactory | ChannelAgentTool[];
};
//#endregion
//#region src/infra/outbound/session-binding.types.d.ts
/**
* Runtime destination a conversation binding points at.
*/
type BindingTargetKind = "subagent" | "session";
/**
* Lifecycle state for a registered session binding.
*/
type BindingStatus = "active" | "ending" | "ended";
/**
* Channel/account/conversation tuple used to resolve a bound delivery route.
*/
type ConversationRef = {
channel: string;
accountId: string;
conversationId: string;
parentConversationId?: string;
};
/**
* Persistable record that connects one conversation to one target session.
*/
type SessionBindingRecord = {
bindingId: string;
targetSessionKey: string;
targetKind: BindingTargetKind;
conversation: ConversationRef;
status: BindingStatus;
boundAt: number;
expiresAt?: number;
metadata?: Record<string, unknown>;
};
//#endregion
//#region src/infra/delivery-queue-sqlite.types.d.ts
type DeliveryQueueCompletionRetention = "permanent" | Readonly<{
idPrefix: string;
maxAgeMs: number;
maxEntries: number;
}>;
//#endregion
//#region src/logging/levels.d.ts
declare const ALLOWED_LOG_LEVELS: readonly ["silent", "fatal", "error", "warn", "info", "debug", "trace"];
type LogLevel = (typeof ALLOWED_LOG_LEVELS)[number];
//#endregion
//#region src/logging/subsystem.d.ts
type SubsystemLogger$1 = {
subsystem: string;
isEnabled: (level: LogLevel, target?: "any" | "console" | "file") => boolean;
trace: (message: string, meta?: Record<string, unknown>) => void;
debug: (message: string, meta?: Record<string, unknown>) => void;
info: (message: string, meta?: Record<string, unknown>) => void;
warn: (message: string, meta?: Record<string, unknown>) => void;
error: (message: string, meta?: Record<string, unknown>) => void;
fatal: (message: string, meta?: Record<string, unknown>) => void;
raw: (message: string) => void;
child: (name: string) => SubsystemLogger$1;
};
declare function createSubsystemLogger(subsystem: string): SubsystemLogger$1;
//#endregion
//#region src/infra/outbound/delivery-completion.d.ts
/** Serializable owner callback for a durable queue entry. */
type DurableDeliveryCompletion = {
kind: "conversation";
agentId: string;
operationId: string;
storePath?: string;
/** Present on Gateway-owned conversation intents created with route authorization. */
routeFingerprint?: string;
} | {
kind: "pending-final";
deliveryId: string;
intentId: string;
sessionId: string;
sessionKey: string;
storePath: string;
sessionWriterDeliveryAuthority?: SessionWriterDeliveryAuthority;
};
//#endregion
//#region src/auto-reply/reply/reply-dispatcher.types.d.ts
type ReplyDispatchKind = "tool" | "block" | "final";
type ReplyDispatchSettledCounts = {
delivered: number;
deliveredNotVisible: number;
cancelled: number;
failedBeforeSend: number;
failedAfterSend: number;
};
type ReplyDispatchReceipt = {
counts: Record<ReplyDispatchKind, ReplyDispatchSettledCounts>;
anyVisibleDelivered: boolean;
};
type ReplyFollowupAdmissionBarrierTimeoutPolicy = {
/** Absolute failsafe for owner activity that never settles. */
maxTimeoutMs: number;
/** Extend by another default settle interval while bounded owner work remains active. */
shouldExtend: () => boolean;
};
type ReplyDispatchRuntimeInfo = {
kind: ReplyDispatchKind;
assistantMessageIndex?: number;
/** @internal Claim direct-send custody immediately before recipient-visible platform I/O. */
onPlatformSendDispatch?: () => Promise<void>;
/** @internal Synchronously fence custody after claiming it and before provider I/O. */
assertPlatformSendAuthorized?: () => void;
/** @internal Bind this delivery's host-owned completion to a transformed payload. */
bindPendingFinalDelivery?: <T extends ReplyPayload>(payload: T) => T;
};
type ReplyDispatchBeforeDeliver = (payload: ReplyPayload, info: ReplyDispatchRuntimeInfo) => Promise<ReplyPayload | null> | ReplyPayload | null;
/** An owner-declared settlement budget for one before-delivery callback. */
type ReplyDispatchBeforeDeliverOptions = {
/** Positive finite per-callback deadline in milliseconds; omit for the dispatcher default. */
timeoutMs?: number;
};
type ReplyDispatcher = {
sendToolResult: (payload: ReplyPayload) => boolean;
sendBlockReply: (payload: ReplyPayload) => boolean;
sendFinalReply: (payload: ReplyPayload) => boolean;
appendBeforeDeliver?: (hook: ReplyDispatchBeforeDeliver, options?: ReplyDispatchBeforeDeliverOptions) => void;
supportsSettledReceipt?: true;
waitForIdle: () => Promise<void | ReplyDispatchReceipt>;
/** @deprecated Remove in the next Plugin SDK major; retains admission-time counts. */
getQueuedCounts: () => Record<ReplyDispatchKind, number>;
/** @deprecated Remove in the next Plugin SDK major; derived from settled receipts. */
getCancelledCounts?: () => Record<ReplyDispatchKind, number>;
/** @deprecated Remove in the next Plugin SDK major; derived from settled receipts. */
getFailedCounts: () => Record<ReplyDispatchKind, number>;
markComplete: () => void;
/** Owner-declared deadline for holding queued follow-ups behind all queued deliveries. */
resolveFollowupAdmissionBarrierTimeoutPolicy?: () => ReplyFollowupAdmissionBarrierTimeoutPolicy | undefined;
};
//#endregion
//#region src/config/sessions/transcript-assistant-delivery.d.ts
/** Turn-owned display preparation; source text precedes transcript-only hook rewrites. */
type PrepareAssistantTranscriptMessage = (message: AssistantMessage, sourceText: string | undefined) => AssistantMessage;
//#endregion
//#region src/infra/diagnostic-trace-context.d.ts
type DiagnosticTraceContext = {
/** W3C trace id, 32 lowercase hex chars. */
readonly traceId: string;
/** Current span id, 16 lowercase hex chars. */
readonly spanId?: string;
/** Parent span id, 16 lowercase hex chars. */
readonly parentSpanId?: string;
/** W3C trace flags, 2 lowercase hex chars. Defaults to sampled. */
readonly traceFlags?: string;
};
//#endregion
//#region src/plugins/hook-before-agent-start.types.d.ts
type PluginHookBeforeModelResolveAttachment = {
kind: "image" | "video" | "audio" | "document" | "other";
mimeType?: string;
};
type PluginHookBeforeModelResolveEvent = {
/** User prompt for this run. No session messages are available yet in this phase. */
prompt: string;
/** Attachment metadata for file-aware model routing. */
attachments?: PluginHookBeforeModelResolveAttachment[];
};
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. "local-provider" */
providerOverride?: string;
};
type PluginHookBeforePromptBuildEvent = {
prompt: string;
/** Session messages prepared for this run. */
messages: unknown[];
};
type PluginHookBeforePromptBuildResult = {
systemPrompt?: string;
prependContext?: string;
appendContext?: string;
/**
* Narrows the tools submitted to the model for this turn.
* An empty array disables optional tools; omitted leaves the existing tool policy unchanged.
*/
toolsAllow?: 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;
};
//#endregion
//#region src/plugins/hook-before-tool-call-result.d.ts
declare const PluginApprovalResolutions: {
readonly ALLOW_ONCE: "allow-once";
readonly ALLOW_ALWAYS: "allow-always";
readonly DENY: "deny";
readonly TIMEOUT: "timeout";
readonly CANCELLED: "cancelled";
};
type PluginApprovalResolution = (typeof PluginApprovalResolutions)[keyof typeof PluginApprovalResolutions];
type PluginHookBeforeToolCallResult = {
params?: Record<string, unknown>;
block?: boolean;
blockReason?: string;
requireApproval?: {
title: string;
description: string;
scope?: ApprovalScope;
severity?: "info" | "warning" | "critical";
timeoutMs?: number;
/**
* @deprecated Unresolved approvals always deny; retained for plugin API
* compatibility. The field will be removed after one deprecation release train.
*/
timeoutBehavior?: "allow" | "deny";
/** Override timeout text and return the timeout as a blocked tool result. */
timeoutReason?: string;
allowedDecisions?: Array<"allow-once" | "allow-always" | "deny">;
pluginId?: string;
onResolution?: (decision: PluginApprovalResolution) => Promise<void> | void;
};
};
//#endregion
//#region src/plugins/hook-decision-types.d.ts
/** Content is fine. Proceed normally. */
type HookDecisionPass = {
outcome: "pass";
};
/**
* Content is blocked. `reason` is internal plugin-local detail; core must not log,
* persist, broadcast, or expose it verbatim. `message` is user-facing detail.
*/
type HookDecisionBlock = {
outcome: "block";
/** Internal plugin-local reason. Do not log, persist, broadcast, or expose verbatim. */
reason: string;
/** Optional user-facing detail included in the block response envelope. */
message?: string;
/** Plugin-defined category for analytics (e.g. "violence", "pii", "cost_limit"). */
category?: string;
/** Opaque metadata for the plugin's own use. Core does not interpret it. */
metadata?: Record<string, unknown>;
};
/** Outcomes valid for input gates (before_agent_run). */
type InputGateDecision = HookDecisionPass | HookDecisionBlock;
//#endregion
//#region src/hooks/message-hook-media.d.ts
/** Stable media fact exposed to message-hook consumers. */
type MessageHookMediaFact = {
path?: string;
url?: string;
contentType?: string;
kind?: MediaFact["kind"];
transcribed?: boolean;
messageId?: string;
workspaceDir?: string;
};
//#endregion
//#region src/plugins/conversation-binding.types.d.ts
/** Plugin-supplied context for requesting a channel conversation binding. */
type PluginConversationBindingRequestParams = {
summary?: string;
detachHint?: string;
data?: Record<string, unknown>;
};
/** Maintainer/user decision recorded for a plugin conversation binding request. */
type PluginConversationBindingResolutionDecision = "allow-once" | "allow-always" | "deny";
/** Stored binding between a plugin and an external channel conversation. */
type PluginConversationBinding = {
bindingId: string;
pluginId: string;
pluginName?: string;
pluginRoot: string;
channel: string;
accountId: string;
conversationId: string;
parentConversationId?: string;
threadId?: string | number;
boundAt: number;
summary?: string;
detachHint?: string;
data?: Record<string, unknown>;
};
/** Result returned when a plugin asks to bind to a conversation. */
type PluginConversationBindingRequestResult = {
status: "bound";
binding: PluginConversationBinding;
} | {
status: "pending";
approvalId: string;
reply: ReplyPayload;
} | {
status: "error";
message: string;
};
/** Event emitted after a pending conversation binding request is resolved. */
type PluginConversationBindingResolvedEvent$1 = {
status: "approved" | "denied";
binding?: PluginConversationBinding;
decision: PluginConversationBindingResolutionDecision;
request: {
summary?: string;
detachHint?: string;
data?: Record<string, unknown>;
requestedBySenderId?: string;
conversation: {
channel: string;
accountId: string;
conversationId: string;
parentConversationId?: string;
threadId?: string | number;
};
};
};
//#endregion
//#region src/plugins/hook-message.types.d.ts
/** Ordered media fact exposed by inbound message hooks. */
type PluginHookMediaFact = MessageHookMediaFact;
/** Channel-neutral geographic fix carried by an inbound provider update. */
type PluginHookLocation = {
latitude: number;
longitude: number;
accuracy?: number;
name?: string;
address?: string;
source?: "pin" | "place" | "live";
isLive?: boolean;
livePeriodSeconds?: number;
caption?: string;
};
/** Stable provider update identity for transport-level correlation and deduplication. */
type PluginHookProviderUpdate = {
id: string;
kind: string;
messageId?: string;
messageTimestamp?: number;
editedTimestamp?: number;
};
/** Provider metadata plus deprecated media aliases retained during the SDK migration window. */
type PluginHookInboundMessageMetadata = Record<string, unknown> & {
/** @deprecated Use the first `event.media` fact with a defined `path`. */
mediaPath?: string;
/** @deprecated Use the first `event.media` fact's `url ?? path`. */
mediaUrl?: string;
/** @deprecated Use the first `event.media` fact's `contentType ?? kind`. */
mediaType?: string;
/** @deprecated Collect defined `path` values from `event.media` in order. */
mediaPaths?: string[];
/** @deprecated Collect each defined `url ?? path` from `event.media` in order. */
mediaUrls?: string[];
/** @deprecated Collect each defined `contentType ?? kind` from `event.media` in order. */
mediaTypes?: string[];
/** @deprecated Use the first `event.originalMedia` fact with a defined `path`. */
originalMediaPath?: string;
/** @deprecated Use the first `event.originalMedia` fact's `url ?? path`. */
originalMediaUrl?: string;
/** @deprecated Use the first `event.originalMedia` fact's `contentType ?? kind`. */
originalMediaType?: string;
/** @deprecated Collect defined `path` values from `event.originalMedia` in order. */
originalMediaPaths?: string[];
/** @deprecated Collect each defined `url ?? path` from `event.originalMedia` in order. */
originalMediaUrls?: string[];
/** @deprecated Collect each defined `contentType ?? kind` from `event.originalMedia` in order. */
originalMediaTypes?: string[];
/** @deprecated Use `event.mediaStagingPending`. */
mediaStagingPending?: boolean;
};
type PluginHookMessageContext = {
channelId: string;
accountId?: string;
conversationId?: string;
/**
* Canonical session key for this conversation — the same value the agent
* runtime sees as `params.sessionKey` for the run that produced the
* outbound payload, and the same value `agent_end`/`llm_input`/`llm_output`
* fire with. Plugins correlating per-turn state across `agent_end` and
* `message_sending` rely on this equality.
*
* For inbound message hooks (`inbound_claim` etc.), this is the canonical
* session for the inbound conversation as resolved by `resolveSessionKey`
* / `deriveInboundMessageHookContext`.
*
* For outbound delivery hooks (`message_sending` and `message_sent`),
* this mirrors `OutboundSessionContext.key` from the dispatch path when
* delivery has a session attached. When the outbound path has no
* resolvable session (e.g. internal smoke runs without
* `OutboundSessionContext`), this field is omitted; plugins must treat
* it as optional.
*/
sessionKey?: string;
/**
* Per-turn run identifier (UUID), unique to one end-to-end agent turn:
* stable across all LLM-call iterations, retry attempts (compaction,
* empty-response, planning-only, etc.), and multi-payload reply chunks
* within that turn; distinct for each new inbound user message and for
* each cron/heartbeat/followup-triggered run.
*
* Generated once in `agent-runner-execution.ts`/`followup-runner.ts` via
* `crypto.randomUUID()`. Currently populated for inbound message hooks
* (`inbound_claim`, `message_received`) and for agent-runtime hooks that
* already receive the run id (e.g. `agent_end`, `llm_input`, `llm_output`).
* It is **not yet** plumbed through the outbound delivery path, so
* plugins observing `message_sending` / `message_sent` should not rely
* on `runId` to correlate against `agent_end`; use `sessionKey` for
* outbound→inbound correlation today (with the caveat that it cannot
* disambiguate concurrent turns in the same session).
*/
runId?: string;
messageId?: string;
senderId?: string;
replyToId?: string;
replyToIdFull?: string;
replyToBody?: string;
replyToSender?: string;
replyToIsQuote?: boolean;
trace?: DiagnosticTraceContext;
traceId?: string;
spanId?: string;
parentSpanId?: string;
callDepth?: number;
};
type PluginHookInboundClaimContext = PluginHookMessageContext & {
/** Resolved owner for session scopes whose canonical key does not encode an agent id. */
agentId?: string;
parentConversationId?: string;
senderId?: string;
messageId?: string;
pluginBinding?: PluginConversationBinding;
};
type PluginHookInboundClaimEvent = {
content: string;
body?: string;
bodyForAgent?: string;
transcript?: string;
timestamp?: number;
channel: string;
accountId?: string;
conversationId?: string;
parentConversationId?: string;
senderId?: string;
senderName?: string;
senderUsername?: string;
replyToId?: string;
replyToIdFull?: string;
replyToBody?: string;
replyToSender?: string;
replyToIsQuote?: boolean;
threadId?: string | number;
messageId?: string;
sessionKey?: string;
runId?: string;
trace?: DiagnosticTraceContext;
traceId?: string;
spanId?: string;
parentSpanId?: string;
isGroup: boolean;
commandAuthorized?: boolean;
senderIsOwner?: boolean;
wasMentioned?: boolean;
location?: PluginHookLocation;
providerUpdate?: PluginHookProviderUpdate;
/** Staged, locally usable attachments in stable source order. */
media?: PluginHookMediaFact[];
/** Original attachment facts when local staging has not completed yet. */
originalMedia?: PluginHookMediaFact[];
/** True when `originalMedia` is present but `media` is intentionally withheld pending staging. */
mediaStagingPending?: boolean;
metadata?: PluginHookInboundMessageMetadata;
};
type PluginHookMessageReceivedEvent = {
from: string;
content: string;
timestamp?: number;
threadId?: string | number;
messageId?: string;
senderId?: string;
replyToId?: string;
replyToIdFull?: string;
replyToBody?: string;
replyToSender?: string;
replyToIsQuote?: boolean;
sessionKey?: string;
runId?: string;
trace?: DiagnosticTraceContext;
traceId?: string;
spanId?: string;
parentSpanId?: string;
location?: PluginHookLocation;
providerUpdate?: PluginHookProviderUpdate;
/** Staged, locally usable attachments in stable source order. */
media?: PluginHookMediaFact[];
/** Original attachment facts when local staging has not completed yet. */
originalMedia?: PluginHookMediaFact[];
/** True when `originalMedia` is present but `media` is intentionally withheld pending staging. */
mediaStagingPending?: boolean;
metadata?: PluginHookInboundMessageMetadata;
};
type PluginHookMessageSendingEvent = {
to: string;
content: string;
replyToId?: string | number;
threadId?: string | number;
metadata?: Record<string, unknown>;
};
type PluginHookMessageSendingResult = {
content?: string;
cancel?: boolean;
cancelReason?: string;
metadata?: Record<string, unknown>;
};
type PluginHookMessageSentEvent = {
to: string;
content: string;
success: boolean;
messageId?: string;
sessionKey?: string;
runId?: string;
trace?: DiagnosticTraceContext;
traceId?: string;
spanId?: string;
parentSpanId?: string;
error?: string;
};
//#endregion
//#region src/plugins/hook-skill.types.d.ts
type PluginHookSkillProposalKind = "create" | "update";
type PluginHookSkillBundleFile = {
path: string;
content: string;
encoding: "utf8" | "base64";
sha256: string;
sizeBytes: number;
};
type PluginHookSkillBundleSnapshot = {
skillMd: PluginHookSkillBundleFile;
files: PluginHookSkillBundleFile[];
treeSha256: string;
};
type PluginHookSkillProposalEvaluateEvent = {
/** Caller-supplied correlation metadata; not authenticated identity or authorization proof. */
correlationId?: string;
proposal: {
id: string;
kind: PluginHookSkillProposalKind;
revision: string;
revisionSha256: string;
targetCurrentSha256?: string;
};
skill: {
name: string;
skillKey: string;
description: string;
source?: string;
};
candidate: PluginHookSkillBundleSnapshot;
baseline?: PluginHookSkillBundleSnapshot;
reason: "created" | "revised" | "manual" | "apply";
};
type PluginHookSkillEvaluationFinding = {
ruleId: string;
severity: "info" | "warn" | "critical";
message: string;
file?: string;
line?: number;
};
type PluginHookSkillProposalEvaluateResult = {
summary?: string;
findings?: PluginHookSkillEvaluationFinding[];
metrics?: Record<string, string | number | boolean>;
/** Version of the underlying evaluator or ruleset, separate from the plugin package. */
evaluatorVersion?: string;
/** Bounded evaluator mode label such as `static`, `llm`, or `baseline-comparison`. */
mode?: string;
decision?: "pass" | "revise" | "block";
decisionReason?: string;
};
type PluginHookSkillProposalEvaluationAttribution = {
evaluatorId: string;
pluginId: string;
pluginVersion?: string;
};
type PluginHookSkillProposalEvaluationOutcome = (PluginHookSkillProposalEvaluationAttribution & {
status: "completed";
result: PluginHookSkillProposalEvaluateResult;
}) | (PluginHookSkillProposalEvaluationAttribution & {
status: "skipped";
}) | (PluginHookSkillProposalEvaluationAttribution & {
status: "error";
error: string;
});
type PluginHookSkillArtifact = {
name: string;
skillKey: string;
description?: string;
skillFile: string;
skillDir: string;
source: string;
revision: {
declaredVersion?: string;
contentSha256: string;
treeSha256: string;
sourceVersion?: string;
};
};
type PluginHookSkillChangedEvent = {
action: "created" | "updated" | "removed";
source: "workshop" | "clawhub" | "source-install" | "upload";
occurredAt: string;
before?: PluginHookSkillArtifact;
after?: PluginHookSkillArtifact;
proposal?: {
id: string;
revision: string;
revisionSha256: string;
};
};
type PluginHookSkillProposalChangedEvent = {
eventId: string;
sequence: number;
action: "created" | "revised" | "evaluation_completed" | "applied" | "rejected" | "quarantined" | "stale";
occurredAt: string;
correlationId?: string;
proposal: {
id: string;
kind: PluginHookSkillProposalKind;
status: "pending" | "applied" | "rejected" | "quarantined" | "stale";
revision: string;
revisionSha256: string;
skillName: string;
skillKey: string;
skillFile: string;
source?: string;
};
evaluations?: readonly PluginHookSkillProposalEvaluationOutcome[];
};
type PluginHookSkillContext = {
workspaceDir: string;
agentId?: string;
};
//#endregion
//#region src/plugins/host-hook-json.d.ts
/** JSON primitive values accepted across plugin host-hook boundaries. */
type PluginJsonPrimitive = string | number | boolean | null;
/** Bounded JSON value shape accepted from plugin hooks. */
type PluginJsonValue = PluginJsonPrimitive | PluginJsonValue[] | {
[key: string]: PluginJsonValue;
};
//#endregion
//#region src/plugins/host-hook-turn-types.d.ts
/** Placement for context injected into the next agent turn. */
type PluginNextTurnInjectionPlacement = "prepend_context" | "append_context";
/** Plugin request to inject text into the next turn for a session. */
type PluginNextTurnInjection = {
sessionKey: string;
/** Selected owner when the session key is unscoped, such as global. */
agentId?: string;
text: string;
idempotencyKey?: string;
placement?: PluginNextTurnInjectionPlacement;
ttlMs?: number;
metadata?: PluginJsonValue;
};
/** Stored next-turn injection after session/plugin metadata is attached. */
type PluginNextTurnInjectionRecord = Omit<PluginNextTurnInjection, "sessionKey" | "agentId"> & {
id: string;
pluginId: string;
pluginName?: string;
createdAt: number;
placement: PluginNextTurnInjectionPlacement;
};
/** Result returned after enqueueing a next-turn injection. */
type PluginNextTurnInjectionEnqueueResult = {
enqueued: boolean;
id: string;
sessionKey: string;
};
/** Event passed to plugins before an agent turn is prepared. */
type PluginAgentTurnPrepareEvent = {
prompt: string;
messages: unknown[];
queuedInjections: PluginNextTurnInjectionRecord[];
};
/** Plugin contribution to prepend or append context for a prepared agent turn. */
type PluginAgentTurnPrepareResult = {
prependContext?: string;
appendContext?: string;
};
/** Event passed to plugins that contribute heartbeat prompt context. */
type PluginHeartbeatPromptContributionEvent = {
sessionKey?: string;
agentId?: string;
heartbeatName?: string;
};
/** Plugin contribution to heartbeat prompt context. */
type PluginHeartbeatPromptContributionResult = {
prependContext?: string;
appendContext?: string;
};
//#endregion
//#region src/plugins/hook-types.d.ts
type PluginHookName = "before_model_resolve" | "agent_turn_prepare" | "before_prompt_build" | "before_agent_reply" | "model_call_started" | "model_call_ended" | "llm_input" | "llm_output" | "before_agent_finalize" | "agent_end" | "before_compaction" | "after_compaction" | "before_reset" | "inbound_claim" | "channel_pairing_requested" | "message_received" | "message_sending" | "reply_payload_sending" | "message_sent" | "before_tool_call" | "after_tool_call" | "tool_result_persist" | "before_message_write" | "session_start" | "session_end" | "subagent_delivery_target" | "subagent_spawned" | "subagent_progress" | "subagent_ended" | "gateway_start" | "gateway_stop" | "heartbeat_prompt_contribution" | "cron_reconciled" | "cron_changed" | "skill_proposal_evaluate" | "skill_proposal_changed" | "skill_changed" | "before_dispatch" | "reply_dispatch" | "before_install" | "before_agent_run" | "resolve_exec_env";
type PluginHookChannelPairingRequestedEvent = {
/** Channel that created the pending pairing request. */
channel: string;
/** Provider account ID for multi-account channel setups. */
accountId?: string;
/** Channel-scoped sender ID awaiting operator approval. */
senderId: string;
/** Short-lived code accepted by `openclaw pairing approve`. */
code: string;
/** Sender-supplied channel metadata for operator notification/audit. Treat as untrusted. */
metadata?: Record<string, string | undefined>;
};
type PluginHookChannelPairingContext = {
channelId: string;
accountId?: string;
senderId: string;
};
declare const PLUGIN_HOOK_AGENT_TRIGGERS: readonly ["cron", "heartbeat", "user"];
type PluginHookAgentTrigger = (typeof PLUGIN_HOOK_AGENT_TRIGGERS)[number];
type PluginHookReplyDispatchKind = "agent" | "acp";
type PluginToolMatcher = readonly [string, ...string[]];
type PluginHookRegistrationOptions<K extends PluginHookName> = {
priority?: number;
registrationId?: string;
timeoutMs?: number;
} & (K extends "before_agent_reply" ? {
/** Host-enforced turn triggers that may invoke this reply hook. */
eligibleTriggers?: readonly [PluginHookAgentTrigger, ...PluginHookAgentTrigger[]];
} : {
eligibleTriggers?: never;
}) & (K extends "reply_dispatch" ? {
/** Host-enforced dispatch paths that may invoke this hook; unknown paths remain eligible. */
eligibleDispatchKinds?: readonly [PluginHookReplyDispatchKind, ...PluginHookReplyDispatchKind[]];
} : {
eligibleDispatchKinds?: never;
}) & (K extends "before_tool_call" | "after_tool_call" ? {
matcher?: PluginToolMatcher;
} : {
matcher?: never;
}) & (K extends "before_prompt_build" ? {
/** Run only after the host has finalized the turn's policy-filtered tool surface. */
requiresToolAuthority?: true;
} : {
requiresToolAuthority?: never;
});
type PluginHookToolAuthority = {
/** Opaque host fingerprint for the exact turn, route, policy, and active tool surface. */
readonly fingerprint: string;
/** Checks whether the finalized turn surface contains this exact tool. */
allows(toolName: string): boolean;
/** Rejects retained or timed-out capabilities after the host dispatch closes. */
assertActive(): void;
};
type PluginHookAgentContext = {
runId?: string;
jobId?: string;
trace?: DiagnosticTraceContext;
agentId?: string;
sessionKey?: string;
sessionId?: string;
workspaceDir?: string;
/** Run-prepared repository identities; empty when the turn is outside a repository. */
activeProjectKeys?: string[];
modelProviderId?: string;
modelId?: string;
messageProvider?: string;
/** Channel/plugin id for channel-originated runs, e.g. `discord`. */
channel?: string;
/** Channel account used by the agent when multiple accounts are configured. */
accountId?: string;
/** Conversation target id for channel-originated runs. Mirrors `channelId` for compatibility. */
chatId?: string;
/** Sender identity for channel-originated runs when available. */
senderId?: string;
trigger?: string;
channelId?: string;
/** Resolved effective context-token budget after model/config/agent caps. */
contextTokenBudget?: number;
/** Source that supplied the resolved context-token budget. */
contextWindowSource?: PluginHookContextWindowSource;
/** Native/configured reference window when a lower cap wins. */
contextWindowReferenceTokens?: number;
/**
* @deprecated Core does not populate cross-app sender ids. Channel plugins
* should expose channel-specific identities by augmenting `channelContext.sender`.
*/
senderExternalId?: string;
/** Channel-owned sender/chat details. Plugins may augment the nested interfaces. */
channelContext?: PluginHookChannelContext;
/** Present only for post-policy prompt enrichment hooks that requested tool authority. */
toolAuthority?: PluginHookToolAuthority;
};
type PluginHookContextWindowSource = "model" | "modelsConfig" | "agentContextTokens" | "default";
type PluginHookBeforeAgentReplyEvent = {
cleanedBody: string;
};
type PluginHookBeforeAgentReplyResult = {
handled: boolean;
reply?: ReplyPayload;
reason?: string;
};
type PluginHookLlmInputEvent = {
runId: string;
sessionId: string;
provider: string;
model: string;
systemPrompt?: string;
prompt: string;
historyMessages: unknown[];
imagesCount: number;
tools?: unknown[];
};
type PluginHookModelCallBaseEvent = {
runId: string;
callId: string;
sessionKey?: string;
sessionId?: string;
provider: string;
model: string;
api?: string;
transport?: string;
/** Resolved effective context-token budget after model/config/agent caps. */
contextTokenBudget?: number;
/** Source that supplied the resolved context-token budget. */
contextWindowSource?: PluginHookContextWindowSource;
/** Native/configured reference window when a lower cap wins. */
contextWindowReferenceTokens?: number;
};
type PluginHookModelCallStartedEvent = PluginHookModelCallBaseEvent;
type PluginHookModelCallEndedEvent = PluginHookModelCallBaseEvent & {
durationMs: number;
outcome: "completed" | "error";
errorCategory?: string;
failureKind?: "aborted" | "connection_closed" | "connection_reset" | "terminated" | "timeout";
requestPayloadBytes?: number;
responseStreamBytes?: number;
timeToFirstByteMs?: number;
upstreamRequestIdHash?: string;
};
type PluginHookLlmOutputEvent = {
runId: string;
sessionId: string;
provider: string;
model: string;
/** Resolved effective context-token budget after model/config/agent caps. */
contextTokenBudget?: number;
/** Source that supplied the resolved context-token budget. */
contextWindowSource?: PluginHookContextWindowSource;
/** Native/configured reference window when a lower cap wins. */
contextWindowReferenceTokens?: number;
/**
* Fully resolved provider/model ref used for the call.
*
* This intentionally keeps the provider prefix so operator tooling can
* distinguish e.g. openai/gpt-5.4 from codex/gpt-5.4 even when display
* names collapse to just the model id.
*/
resolvedRef?: string;
/**
* Harness/backend responsible for the model loop. Kept separate from
* `resolvedRef` so provider/model consumers keep a stable parse contract.
*/
harnessId?: string;
/** The original user prompt that produced this output. */
prompt?: string;
assistantTexts: string[];
lastAssistant?: unknown;
usage?: {
input?: number;
output?: number;
cacheRead?: number;
cacheWrite?: number;
total?: number;
};
/**
* Requested reasoning/think effort for this call (provider think level, e.g.
* "off" | "low" | "medium" | "high"). Lets a passive footer show the mode the
* user is actually running without re-deriving it.
*/
reasoningEffort?: string;
/** Whether fast mode was active for this call. */
fastMode?: boolean;
};
type PluginHookAgentEndEvent = {
runId?: string;
messages: unknown[];
success: boolean;
error?: string;
durationMs?: number;
};
type PluginHookBeforeAgentFinalizeEvent = {
runId?: string;
sessionId: string;
sessionKey?: string;
turnId?: string;
provider?: string;
model?: string;
cwd?: string;
transcriptPath?: string;
stopHookActive: boolean;
lastAssistantMessage?: string;
messages?: unknown[];
};
type PluginHookBeforeAgentFinalizeResult = {
/**
* continue: accept normal finalization.
* revise: block finalization and ask the harness for another model pass.
* finalize: force finalization even if another hook requested revision.
*/
action?: "continue" | "revise" | "finalize";
reason?: string;
retry?: {
instruction: string;
idempotencyKey?: string;
maxAttempts?: number;
};
};
type PluginHookBeforeCompactionEvent = {
messageCount: number;
compactingCount?: number;
tokenCount?: number;
messages?: unknown[];
sessionFile?: string;
};
type PluginHookBeforeResetEvent = {
sessionFile?: string;
messages?: unknown[];
reason?: string;
};
type PluginHookAfterCompactionEvent = {
messageCount: number;
tokenCount?: number;
compactedCount: number;
sessionFile?: string;
/** Physical session generation replaced by this compaction, when it rotated. */
previousSessionId?: string;
};
type PluginHookInboundClaimResult = {
handled: boolean;
reply?: ReplyPayload;
};
type PluginHookBeforeDispatchEvent = {
messageId?: string;
content: string;
body?: string;
channel?: string;
sessionKey?: string;
senderId?: string;
replyToId?: string;
replyToIdFull?: string;
replyToBody?: string;
replyToSender?: string;
replyToIsQuote?: boolean;
isGroup?: boolean;
timestamp?: number;
};
type PluginHookBeforeDispatchContext = {
messageId?: string;
channelId?: string;
accountId?: string;
conversationId?: string;
sessionKey?: string;
senderId?: string;
replyToId?: string;
replyToIdFull?: string;
replyToBody?: string;
replyToSender?: string;
replyToIsQuote?: boolean;
};
type PluginHookBeforeDispatchResult = {
handled: boolean;
text?: string;
};
type PluginHookReplyDispatchEvent = {
ctx: FinalizedMsgContext;
runId?: string;
sessionKey?: string;
toolsAllow?: string[];
images?: Array<{
data: string;
mimeType: string;
}>;
inboundAudio: boolean;
sessionTtsAuto?: TtsAutoMode;
ttsChannel?: string;
suppressUserDelivery?: boolean;
suppressReplyLifecycle?: boolean;
sourceReplyDeliveryMode?: SourceReplyDeliveryMode;
shouldRouteToOriginating: boolean;
originatingChannel?: string;
originatingTo?: string;
originatingAccountId?: string;
originatingThreadId?: string | number;
originatingChatType?: ChatType;
shouldSendToolSummaries: boolean;
shouldSendFullToolDetails: boolean;
sendPolicy: "allow" | "deny";
isTailDispatch?: boolean;
};
type PluginHookReplyDispatchContext = {
/** Host-resolved dispatch path; omitted when the caller cannot establish it. */
dispatchKind?: PluginHookReplyDispatchKind;
cfg: OpenClawConfig;
dispatcher: ReplyDispatcher;
abortSignal?: AbortSignal;
onReplyStart?: () => Promise<void> | void;
onAgentRunStart?: GetReplyOptions["onAgentRunStart"];
userTurnTranscriptRecorder?: GetReplyOptions["userTurnTranscriptRecorder"];
/** Host-owned display facts applied before the assistant transcript is published. */
prepareAssistantTranscriptMessage?: PrepareAssistantTranscriptMessage;
recordProcessed: (outcome: "completed" | "skipped" | "error", opts?: {
reason?: string;
error?: string;
}) => void;
markIdle: (reason: string) => void;
};
type PluginHookReplyDispatchResult = {
handled: boolean;
queuedFinal: boolean;
counts: Record<ReplyDispatchKind, number>;
};
/**
* Per-turn execution state for the outbound reply, available to every harness
* (embedded, CLI, Codex app-server) — sourced from the unified `runResult.meta`
* at dispatch, not from the harness-specific `llm_output` hook. Lets a plugin
* render a passive per-response footer without re-deriving run state.
*/
type PluginHookReplyUsageState = {
provider?: string;
model?: string;
/** Resolved provider/model ref actually used (keeps the provider prefix). */
resolvedRef?: string;
/** Requested reasoning/think effort (e.g. "off" | "low" | "medium" | "high"). */
reasoningEffort?: string;
fastMode?: boolean;
/** True when a model fallback was used for this turn. */
fallbackUsed?: boolean;
/** Owning agent + session for this reply. */
agentId?: string;
sessionId?: string;
/** Chat surface kind (e.g. "direct" | "group"). */
chatType?: string;
/** Credential mode the turn ran under (e.g. "oauth" | "api_key"). */
authMode?: string;
/** Session model-override source, when a non-default model was pinned. */
overrideSource?: string;
/** Provider/model ref requested for the turn (vs resolvedRef actually used). */
requested?: string;
/** Estimated cost of this turn in USD, when a cost table is configured. */
turnUsd?: number;
/** Wall-clock duration of the turn in milliseconds. */
durationMs?: number;
/** Owning agent's configured identity (name/emoji/avatar), when set. */
identity?: {
name?: string;
emoji?: string;
avatar?: string;
};
compactionCount?: number;
/** Effective context-token budget after model/config/agent caps. */
contextTokenBudget?: number;
/**
* Actual context-window occupancy at the END of the turn — the final model
* call's prompt tokens, NOT the per-turn aggregate. This is the value
* `context.used_tokens` / `context.pct_used` must use: the aggregate prompt
* total over a multi-call tool loop overstates occupancy (often beyond the
* window). Absent on harnesses that don't report it (the contract then falls
* back to the aggregate prompt total, which is correct for single-call turns).
*/
contextUsedTokens?: number;
usage?: {
input?: number;
output?: number;
cacheRead?: number;
cacheWrite?: number;
total?: number;
};
/**
* Usage from the FINAL model call of the turn only — vs `usage`, which is the
* turn aggregate summed across every tool-loop call. Lets a footer render the
* last exchange's i/o + cache instead of the whole turn. Absent on harnesses
* that don't report per-call usage.
*/
lastUsage?: {
input?: number;
output?: number;
cacheRead?: number;
cacheWrite?: number;
total?: number;
};
};
type PluginHookReplyPayloadSendingEvent = {
payload: PluginHookReplyPayload;
kind: ReplyDispatchKind;
channel?: string;
sessionKey?: string;
runId?: string;
/**
* Per-turn usage snapshot for live dispatcher delivery. Absent on durable
* delivery/replay paths, and whenever no exact run correlation is available.
*/
usageState?: PluginHookReplyUsageState;
};
type PluginHookReplyPayload = Omit<ReplyPayload, "trustedLocalMedia">;
type PluginHookReplyPayloadSendingContext = PluginHookMessageContext;
type PluginHookReplyPayloadSendingResult = {
payload?: PluginHookReplyPayload;
cancel?: boolean;
reason?: string;
};
type PluginHookToolKind = "code_mode_exec";
type PluginHookToolInputKind = "javascript" | "typescript";
/** Host-derived identity for the message requester that initiated a tool call. */
type PluginHookToolRequesterContext = {
/** Channel/plugin id, for example `discord` or `telegram`. */
readonly channel?: string;
/** Channel account used by the agent when multiple accounts are configured. */
readonly accountId?: string;
/** Channel-scoped sender id when the host received one. */
readonly senderId?: string;
/** True only when the host resolved the sender as an owner. */
readonly senderIsOwner?: boolean;
/** Provider-native role ids when the channel supplies them. */
readonly roleIds?: readonly string[];
};
type PluginHookToolContext = {
agentId?: string;
sessionKey?: string;
sessionId?: string;
runId?: string;
/** Aborts when the owning tool call is cancelled. Hook timeout expiry does not abort this signal. */
abortSignal?: AbortSignal;
trace?: DiagnosticTraceContext;
toolName: string;
/** Host-authoritative discriminator for tools that intentionally share names. */
toolKind?: PluginHookToolKind;
/** Host-authoritative input/runtime family for tools whose payloads need policy distinction. */
toolInputKind?: PluginHookToolInputKind;
toolCallId?: string;
getSessionExtension?: (namespace: string) => PluginJsonValue | undefined;
channelId?: string;
/**
* Message requester for this turn. Absent for non-message runs and harnesses
* that cannot prove requester identity. Authorization hooks should fail
* closed when a required field is absent.
*/
requester?: PluginHookToolRequesterContext;
};
type PluginHookBeforeToolCallEvent = {
toolName: string;
params: Record<string, unknown>;
/** Host-authoritative discriminator for tools that intentionally share names. */
toolKind?: PluginHookToolKind;
/** Host-authoritative input/runtime family for tools whose payloads need policy distinction. */
toolInputKind?: PluginHookToolInputKind;
runId?: string;
toolCallId?: string;
/**
* Optional best-effort destination path hints the host derived from `params`
* for well-known tool envelopes (e.g. `apply_patch`).
*
* This is a convenience hint, not an authoritative parse result: the host's
* extractor may be intentionally lenient and can return paths for malformed
* or partial envelopes. Plugins may use `derivedPaths` as a fast path, but
* should parse and validate `params` themselves when correctness or policy
* decisions depend on the exact set of affected paths. Absent for tools the
* host does not know how to derive paths for.
*/
derivedPaths?: readonly string[];
};
type PluginHookAfterToolCallEvent = {
toolName: string;
params: Record<string, unknown>;
runId?: string;
toolCallId?: string;
result?: unknown;
error?: string;
durationMs?: number;
};
type PluginHookToolResultPersistContext = {
agentId?: string;
sessionKey?: string;
toolName?: string;
toolCallId?: string;
};
type PluginHookToolResultPersistEvent = {
toolName?: string;
toolCallId?: string;
message: AgentMessage;
isSynthetic?: boolean;
};
type PluginHookToolResultPersistResult = {
message?: AgentMessage;
};
type PluginHookBeforeMessageWriteEvent = {
message: AgentMessage;
sessionKey?: string;
agentId?: string;
};
type PluginHookBeforeMessageWriteResult = {
block?: boolean;
message?: AgentMessage;
};
type PluginHookSessionContext = {
agentId?: string;
sessionId: string;
sessionKey?: string;
};
type PluginHookSessionStartEvent = {
sessionId: string;
sessionKey?: string;
resumedFrom?: string;
};
type PluginHookSessionEndReason = "new" | "reset" | "idle" | "daily" | "compaction" | "deleted" | "shutdown" | "restart" | "unknown";
type PluginHookSessionEndEvent = {
sessionId: string;
sessionKey?: string;
messageCount: number;
durationMs?: number;
reason?: PluginHookSessionEndReason;
sessionFile?: string;
transcriptArchived?: boolean;
nextSessionId?: string;
nextSessionKey?: string;
};
type PluginHookSubagentContext = {
runId?: string;
childSessionKey?: string;
requesterSessionKey?: string;
};
type PluginHookSubagentTargetKind = "subagent" | "acp";
type PluginHookSubagentRequester = {
channel?: string;
accountId?: string;
to?: string;
threadId?: string | number;
/** Native source channel/conversation id, when distinct from the routable target. */
channelId?: string | number;
/** Native source message that initiated the parent run, when available. */
messageId?: string | number;
};
type PluginHookSubagentSpawnBase = {
childSessionKey: string;
agentId: string;
label?: string;
mode: "run" | "session";
requester?: PluginHookSubagentRequester;
threadRequested: boolean;
};
type PluginHookSubagentDeliveryTargetEvent = {
childSessionKey: string;
requesterSessionKey: string;
requesterOrigin?: {
channel?: string;
accountId?: string;
to?: string;
threadId?: string | number;
};
childRunId?: string;
spawnMode?: "run" | "session";
expectsCompletionMessage: boolean;
};
/**
* @deprecated Core route projection resolves subagent delivery targets from
* `SessionBindingRecord` and channel `resolveDeliveryTarget`. This hook result
* remains for plugin compatibility during the transition.
*/
type PluginHookSubagentDeliveryTargetResult = {
origin?: {
channel?: string;
accountId?: string;
to?: string;
threadId?: string | number;
};
};
type PluginHookSubagentSpawnedEvent = PluginHookSubagentSpawnBase & {
runId: string;
/** Fully resolved provider/model ref applied to the spawned child session. */
resolvedModel?: string;
/** Provider prefix parsed from resolvedModel when the ref includes one. */
resolvedProvider?: string;
};
/** Portable channel presentation signal for one background child run. */
type PluginHookSubagentProgressEvent = {
phase: "started";
runId: string;
childSessionKey: string;
requester?: PluginHookSubagentRequester;
} | {
phase: "ended";
runId: string;
childSessionKey: string;
outcome: "ok" | "error" | "timeout" | "killed" | "unknown";
requester?: PluginHookSubagentRequester;
};
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;
};
type PluginHookGatewayContext = {
port?: number;
config?: OpenClawConfig;
workspaceDir?: string;
getCron?: () => PluginHookGatewayCronService | undefined;
};
type PluginHookCronReconciledContext = PluginHookGatewayContext & {
/** Aborts when this exact scheduler snapshot is superseded or the Gateway closes. */
abortSignal: AbortSignal;
};
type PluginHookGatewayStartEvent = {
port: number;
};
type PluginHookGatewayStopEvent = {
reason?: string;
};
type PluginHookCronReconciledEvent = {
reason: "startup" | "reload";
enabled: boolean;
};
type PluginHookGatewayCronRunStatus = "ok" | "error" | "skipped";
type PluginHookGatewayCronDeliveryStatus = "not-requested" | "delivered" | "not-delivered" | "unknown";
type PluginHookGatewayCronJobState = {
nextRunAtMs?: number;
runningAtMs?: number;
lastRunAtMs?: number;
lastRunStatus?: PluginHookGatewayCronRunStatus;
lastError?: string;
lastDurationMs?: number;
lastDelivered?: boolean;
lastDeliveryStatus?: PluginHookGatewayCronDeliveryStatus;
lastDeliveryError?: string;
deliverySuppressionReason?: string;
lastFailureNotificationDelivered?: boolean;
lastFailureNotificationDeliveryStatus?: PluginHookGatewayCronDeliveryStatus;
lastFailureNotificationDeliveryError?: string;
streamStatus?: "starting" | "running" | "restarting" | "stopped" | "disabled" | "error";
streamError?: string;
streamConsecutiveFailures?: number;
streamRestartExhausted?: boolean;
streamDroppedBatches?: number;
streamCoalescedBatches?: number;
streamLastStartedAtMs?: number;
streamLastExitAtMs?: number;
};
type PluginHookGatewayCronJob = {
id: string;
declarationKey?: string;
/** Agent id that owns this cron job. */
agentId?: string;
name?: string;
description?: string;
enabled?: boolean;
schedule?: {
kind: "cron";
expr?: string;
tz?: string;
staggerMs?: number;
} | {
kind: "at";
at?: string;
} | {
kind: "every";
everyMs?: number;
anchorMs?: number;
} | {
kind: "on-exit";
command?: string;
cwd?: string;
} | {
kind: "stream";
command?: string[];
cwd?: string;
mode?: "line" | "match";
match?: string;
batchMs?: number;
maxBatchBytes?: number;
};
sessionTarget?: string;
wakeMode?: string;
payload?: {
kind?: string;
text?: string;
};
state?: PluginHookGatewayCronJobState;
createdAtMs?: number;
updatedAtMs?: number;
};
type PluginHookCronChangedEvent = {
action: "added" | "updated" | "removed" | "started" | "finished" | "scheduled";
jobId: string;
job?: PluginHookGatewayCronJob;
/** Top-level session target for downstream routing (mirrors job.sessionTarget). */
sessionTarget?: string;
/** Agent id that owns this cron job (mirrors job.agentId). */
agentId?: string;
runAtMs?: number;
durationMs?: number;
status?: PluginHookGatewayCronRunStatus;
completionStatus?: "succeeded" | "failed" | "unknown";
error?: string;
summary?: string;
delivered?: boolean;
deliveryStatus?: PluginHookGatewayCronDeliveryStatus;
deliveryError?: string;
deliverySuppressionReason?: string;
sessionId?: string;
sessionKey?: string;
runId?: string;
nextRunAtMs?: number;
model?: string;
provider?: string;
};
type PluginHookGatewayCronCreateInput = {
declarationKey?: string;
name: string;
description: string;
enabled: boolean;
schedule: {
kind: string;
expr: string;
tz?: string;
};
sessionTarget: string;
wakeMode: string;
payload: {
kind: string;
text?: string;
};
};
type PluginHookGatewayCronUpdateInput = Partial<PluginHookGatewayCronCreateInput>;
type PluginHookGatewayCronRemoveResult = {
removed?: boolean;
};
type PluginHookGatewayCronService = {
list: (opts?: {
includeDisabled?: boolean;
}) => Promise<PluginHookGatewayCronJob[]>;
add: (input: PluginHookGatewayCronCreateInput) => Promise<unknown>;
update: (id: string, patch: PluginHookGatewayCronUpdateInput) => Promise<unknown>;
remove: (id: string) => Promise<PluginHookGatewayCronRemoveResult>;
removeStaleJobFamily: (family: {
declarationKey: string;
name: string;
ownerPluginTag: string;
}) => Promise<number>;
};
type PluginInstallTargetType = "skill" | "plugin";
type PluginInstallRequestKind = "skill-install" | "plugin-dir" | "plugin-archive" | "plugin-file" | "plugin-npm" | "plugin-git";
type PluginInstallSourcePathKind = "file" | "directory";
type PluginInstallFinding = {
ruleId: string;
severity: "info" | "warn" | "critical";
file: string;
line: number;
message: string;
};
type PluginHookBeforeInstallRequest = {
kind: PluginInstallRequestKind;
mode: "install" | "update";
requestedSpecifier?: string;
};
type PluginHookBeforeInstallBuiltinScan = {
status: "ok" | "error";
scannedFiles: number;
critical: number;
warn: number;
info: number;
findings: PluginInstallFinding[];
error?: string;
};
type PluginHookBeforeInstallSkillInstallSpec = {
id?: string;
kind: "brew" | "node" | "go" | "uv" | "download";
label?: string;
bins?: string[];
os?: string[];
formula?: string;
package?: string;
module?: string;
url?: string;
sha256?: string;
archive?: string;
extract?: boolean;
stripComponents?: number;
targetDir?: string;
};
type PluginHookBeforeInstallSkill = {
installId: string;
installSpec?: PluginHookBeforeInstallSkillInstallSpec;
};
type PluginHookBeforeInstallPlugin = {
pluginId: string;
contentType: "bundle" | "package" | "file";
packageName?: string;
manifestId?: string;
version?: string;
extensions?: string[];
};
type PluginHookBeforeInstallContext = {
targetType: PluginInstallTargetType;
requestKind: PluginInstallRequestKind;
origin?: string;
};
type PluginHookBeforeInstallEvent = {
targetType: PluginInstallTargetType;
targetName: string;
sourcePath: string;
sourcePathKind: PluginInstallSourcePathKind;
origin?: string;
request: PluginHookBeforeInstallRequest;
builtinScan: PluginHookBeforeInstallBuiltinScan;
skill?: PluginHookBeforeInstallSkill;
plugin?: PluginHookBeforeInstallPlugin;
};
type PluginHookBeforeInstallResult = {
findings?: PluginInstallFinding[];
block?: boolean;
blockReason?: string;
};
/** Event payload for the before_agent_run gate hook. */
type PluginHookBeforeAgentRunEvent = {
/** The user's message that triggered this run. */
prompt: string;
/** Loaded session history before the current prompt is submitted. */
messages: unknown[];
/** Active system prompt prepared for this run. */
systemPrompt?: string;
/** Account identity when available. */
accountId?: string;
/** Channel the message came from. */
channelId?: string;
/** Sender identity when available. */
senderId?: string;
/** Trusted sender identity bit when available. */
senderIsOwner?: boolean;
};
/** Result type for before_agent_run. Returns pass/block or void (= pass). */
type PluginHookBeforeAgentRunResult = InputGateDecision | void;
type PluginHookResolveExecEnvEvent = {
sessionKey?: string;
toolName: "exec";
host: "gateway" | "sandbox" | "node";
};
type PluginHookResolveExecEnvContext = PluginHookAgentContext;
type PluginHookHandlerMap = {
agent_turn_prepare: (event: PluginAgentTurnPrepareEvent, ctx: PluginHookAgentContext) => Promise<PluginAgentTurnPrepareResult | void> | PluginAgentTurnPrepareResult | void;
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_reply: (event: PluginHookBeforeAgentReplyEvent, ctx: PluginHookAgentContext) => Promise<PluginHookBeforeAgentReplyResult | void> | PluginHookBeforeAgentReplyResult | void;
model_call_started: (event: PluginHookModelCallStartedEvent, ctx: PluginHookAgentContext) => Promise<void> | void;
model_call_ended: (event: PluginHookModelCallEndedEvent, ctx: PluginHookAgentContext) => Promise<void> | void;
llm_input: (event: PluginHookLlmInputEvent, ctx: PluginHookAgentContext) => Promise<void> | void;
llm_output: (event: PluginHookLlmOutputEvent, ctx: PluginHookAgentContext) => Promise<void> | void;
before_agent_finalize: (event: PluginHookBeforeAgentFinalizeEvent, ctx: PluginHookAgentContext) => Promise<PluginHookBeforeAgentFinalizeResult | void> | PluginHookBeforeAgentFinalizeResult | 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;
inbound_claim: (event: PluginHookInboundClaimEvent, ctx: PluginHookInboundClaimContext) => Promise<PluginHookInboundClaimResult | void> | PluginHookInboundClaimResult | void;
channel_pairing_requested: (event: PluginHookChannelPairingRequestedEvent, ctx: PluginHookChannelPairingContext) => Promise<void> | void;
before_dispatch: (event: PluginHookBeforeDispatchEvent, ctx: PluginHookBeforeDispatchContext) => Promise<PluginHookBeforeDispatchResult | void> | PluginHookBeforeDispatchResult | void;
reply_dispatch: (event: PluginHookReplyDispatchEvent, ctx: PluginHookReplyDispatchContext) => Promise<PluginHookReplyDispatchResult | void> | PluginHookReplyDispatchResult | void;
reply_payload_sending: (event: PluginHookReplyPayloadSendingEvent, ctx: PluginHookReplyPayloadSendingContext) => Promise<PluginHookReplyPayloadSendingResult | void> | PluginHookReplyPayloadSendingResult | 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_delivery_target: (event: PluginHookSubagentDeliveryTargetEvent, ctx: PluginHookSubagentContext) => Promise<PluginHookSubagentDeliveryTargetResult | void> | PluginHookSubagentDeliveryTargetResult | void;
subagent_spawned: (event: PluginHookSubagentSpawnedEvent, ctx: PluginHookSubagentContext) => Promise<void> | void;
subagent_progress: (event: PluginHookSubagentProgressEvent, 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;
heartbeat_prompt_contribution: (event: PluginHeartbeatPromptContributionEvent, ctx: PluginHookAgentContext) => Promise<PluginHeartbeatPromptContributionResult | void> | PluginHeartbeatPromptContributionResult | void;
cron_reconciled: (event: PluginHookCronReconciledEvent, ctx: PluginHookCronReconciledContext) => Promise<void> | void;
cron_changed: (event: PluginHookCronChangedEvent, ctx: PluginHookGatewayContext) => Promise<void> | void;
skill_proposal_evaluate: (event: PluginHookSkillProposalEvaluateEvent, ctx: PluginHookSkillContext) => Promise<PluginHookSkillProposalEvaluateResult | void> | PluginHookSkillProposalEvaluateResult | void;
skill_proposal_changed: (event: PluginHookSkillProposalChangedEvent, ctx: PluginHookSkillContext) => Promise<void> | void;
skill_changed: (event: PluginHookSkillChangedEvent, ctx: PluginHookSkillContext) => Promise<void> | void;
before_install: (event: PluginHookBeforeInstallEvent, ctx: PluginHookBeforeInstallContext) => Promise<PluginHookBeforeInstallResult | void> | PluginHookBeforeInstallResult | void;
before_agent_run: (event: PluginHookBeforeAgentRunEvent, ctx: PluginHookAgentContext) => Promise<PluginHookBeforeAgentRunResult> | PluginHookBeforeAgentRunResult;
resolve_exec_env: (event: PluginHookResolveExecEnvEvent, ctx: PluginHookResolveExecEnvContext) => Promise<Record<string, string> | void> | Record<string, string> | void;
};
type PluginHookRegistration$1<K extends PluginHookName = PluginHookName> = {
pluginId: string;
registrationId?: string;
hookName: K;
handler: PluginHookHandlerMap[K];
matcher?: PluginToolMatcher;
priority?: number;
timeoutMs?: number;
eligibleTriggers?: readonly PluginHookAgentTrigger[];
eligibleDispatchKinds?: readonly PluginHookReplyDispatchKind[];
requiresToolAuthority?: true;
source: string;
};
//#endregion
//#region src/agents/sessions/session-manager-types.d.ts
interface SessionHeader {
type: "session";
version?: number;
id: string;
timestamp: string;
cwd: string;
parentSession?: string;
}
interface NewSessionOptions {
id?: string;
parentSession?: string;
}
interface SessionEntryBase {
type: string;
id: string;
parentId: string | null;
timestamp: string;
/** This row consumes the raw side cursor instead of the visible leaf. */
appendMode?: "side";
}
interface SessionMessageEntry extends SessionEntryBase {
type: "message";
message: AgentMessage;
}
interface ThinkingLevelChangeEntry extends SessionEntryBase {
type: "thinking_level_change";
thinkingLevel: string;
}
interface ModelChangeEntry extends SessionEntryBase {
type: "model_change";
provider: string;
modelId: string;
}
interface CompactionEntry<T = unknown> extends SessionEntryBase {
type: "compaction";
__openclaw?: {
runId?: string;
itemId?: string;
};
summary: string;
firstKeptEntryId: string;
tokensBefore: number;
/** Extension-specific data, such as artifact indexes or version markers. */
details?: T;
/** True for extension-generated compaction entries. */
fromHook?: boolean;
}
type ResetReason = "new" | "reset" | "idle" | "daily" | "cron-stale";
interface ResetEntry extends SessionEntryBase {
type: "reset";
reason: ResetReason;
firstKeptEntryId?: string;
}
interface BranchSummaryEntry<T = unknown> extends SessionEntryBase {
type: "branch_summary";
fromId: string;
summary: string;
/** Extension-specific data that is not sent to the model. */
details?: T;
/** True for extension-generated branch summaries. */
fromHook?: boolean;
}
/** Extension state that is persisted but excluded from model context. */
interface CustomEntry<T = unknown> extends SessionEntryBase {
type: "custom";
customType: string;
data?: T;
}
interface LabelEntry extends SessionEntryBase {
type: "label";
targetId: string;
label: string | undefined;
}
interface SessionInfoEntry extends SessionEntryBase {
type: "session_info";
name?: string;
}
/** Extension message that participates in model context. */
interface CustomMessageEntry<T = unknown> extends SessionEntryBase {
type: "custom_message";
customType: string;
content: string | (TextContent | ImageContent$1)[];
details?: T;
display: boolean;
}
type SessionEntry = SessionMessageEntry | ThinkingLevelChangeEntry | ModelChangeEntry | CompactionEntry | ResetEntry | BranchSummaryEntry | CustomEntry | CustomMessageEntry | LabelEntry | SessionInfoEntry;
type FileEntry = SessionHeader | SessionEntry;
type AppendPersistenceOptions = {
appendIntent?: "active-branch";
config?: OpenClawConfig;
idempotencyLookup?: "scan" | "scan-assistant" | "caller-checked";
invalidateSerializedPrefixCache?: boolean;
};
interface SessionTreeNode {
entry: SessionEntry;
children: SessionTreeNode[];
label?: string;
labelTimestamp?: string;
}
interface SessionContext {
messages: AgentMessage[];
thinkingLevel: string;
model: {
provider: string;
modelId: string;
} | null;
}
type PreservedOpaqueFileEntry = {
index: number;
record: unknown;
};
type SessionLeafControl = {
type: "leaf";
id: string;
parentId: string | null;
timestamp: string;
targetId: string | null;
appendParentId?: string | null;
appendMode?: "side";
};
//#endregion
//#region src/sessions/transcript-events.d.ts
/** Storage-neutral identity for the session transcript that changed. */
type SessionTranscriptUpdateTarget = {
agentId: string;
sessionId: string;
sessionKey: string;
storePath?: string;
};
type SessionTranscriptUpdateFields = {
sessionFile?: string;
target?: SessionTranscriptUpdateTarget;
sessionKey?: string;
agentId?: string;
sessionId?: string;
/** Committed lifecycle owner; internal delivery must not expose it publicly. */
lifecycleRevision?: string;
message?: unknown;
messageId?: string;
messageSeq?: number;
runId?: string;
};
/** Normalized transcript update emitted after a session transcript changes. */
type SessionTranscriptUpdate = Omit<SessionTranscriptUpdateFields, "sessionFile" | "lifecycleRevision" | "target"> & {
target: Omit<SessionTranscriptUpdateTarget, "storePath">;
};
type SessionTranscriptListener = (update: SessionTranscriptUpdate) => void;
/** Registers a listener for normalized session transcript updates. */
declare function onSessionTranscriptUpdate(listener: SessionTranscriptListener): () => void;
//#endregion
//#region src/config/sessions/store-maintenance.d.ts
type ResolvedSessionMaintenanceConfig = {
mode: SessionMaintenanceMode;
pruneAfterMs: number;
archiveDashboardAfterMs: number | null;
maxEntries: number;
modelRunPruneAfterMs: number;
preserveRecentMs?: number | null;
resetArchiveRetentionMs: number | null;
maxDiskBytes: number | null;
highWaterBytes: number | null;
};
type ResolvedSessionMaintenanceConfigInput = Omit<ResolvedSessionMaintenanceConfig, "archiveDashboardAfterMs" | "modelRunPruneAfterMs"> & Partial<Pick<ResolvedSessionMaintenanceConfig, "archiveDashboardAfterMs" | "modelRunPruneAfterMs">>;
//#endregion
//#region src/config/sessions/session-accessor.types.d.ts
/** Raw transcript record for non-message events; message records use appendTranscriptMessage. */
type TranscriptEvent = unknown;
interface SessionTranscriptRuntimeTarget {
agentId: string;
sessionId: string;
sessionKey: string;
storePath: string;
}
//#endregion
//#region src/config/sessions/session-accessor.sqlite-active-context.d.ts
type SessionTranscriptBoundedActiveContext = {
activeLeafEntryId: string | null;
opaqueParents: Map<string, string | null>;
firstKeptRanges: Map<string, {
startIndex: number;
endIndex: number;
}>;
boundaryCount: number;
events: TranscriptEvent[];
serializedBytes: number;
totalEvents: number;
truncated: boolean;
};
//#endregion
//#region src/config/sessions/session-entry-codec.d.ts
declare function parseOpaqueLeafEntry(record: unknown): {
id: string;
parentId: string | null;
targetId: string | null;
appendParentId?: string | null;
appendMode?: "side";
} | undefined;
//#endregion
//#region src/config/sessions/session-entry-navigation.d.ts
type SessionNavigationEntry = Pick<SessionEntryBase, "id" | "parentId" | "timestamp" | "appendMode"> & ({
type: "label";
targetId: string;
label?: string;
} | {
type: Exclude<SessionEntry["type"], "label">;
});
/** One navigation owner for runtime sessions and streaming transcript operations. */
declare class SessionEntryNavigation<T extends SessionNavigationEntry> {
protected byId: Map<string, T>;
protected opaqueParentsById: Map<string, string | null>;
protected logicalParentsById: Map<string, string | null>;
protected invalidLeafControlIds: Set<string>;
protected labelsById: Map<string, string>;
protected labelTimestampsById: Map<string, string>;
protected leafId: string | null;
protected appendParentId: string | null;
protected appendMode: "side" | undefined;
private latestResetId;
private resetDescendantIds;
protected clearNavigation(): void;
protected finishNavigation(): void;
protected resolveOpaqueLeafTargetId(targetId: string | null): string | null;
protected resolveOpaqueAppendParentId(parentId: string | null): string | null;
protected resolveOpaqueLeafControl(leafEntry: ReturnType<typeof parseOpaqueLeafEntry>): {
leafId: string | null;
appendParentId: string | null;
appendMode?: "side";
} | undefined;
protected appendOpaqueNavigationRecord(opaqueRecord: unknown): void;
protected appendCanonicalNavigationEntry(entry: T, hasParentId?: boolean): void;
protected resolveCanonicalParentId(parentId: string | null): string | null;
protected resolveEntryParentId(entry: T): string | null;
protected normalizeEntryParent(entry: T): T;
getBranch(fromId?: string): T[];
}
//#endregion
//#region src/agents/sessions/session-manager-core.d.ts
type SessionManagerPersistenceTarget = SessionTranscriptRuntimeTarget;
type SessionManagerBoundedContextLimits = {
maxBytes: number;
maxEvents: number;
};
type SessionManagerBoundedContext = Pick<SessionTranscriptBoundedActiveContext, "activeLeafEntryId" | "opaqueParents" | "firstKeptRanges" | "boundaryCount"> & {
limits: SessionManagerBoundedContextLimits;
};
declare class SessionManagerCore extends SessionEntryNavigation<SessionEntry> {
migrated: boolean;
protected sessionId: string;
protected cwd: string;
protected fileEntries: FileEntry[];
protected opaqueFileEntries: PreservedOpaqueFileEntry[];
private boundedFirstKeptById;
protected pendingDeliberateAppend: boolean;
protected persistenceTarget: SessionManagerPersistenceTarget | undefined;
protected persistenceHeaderPending: boolean;
protected boundedContextLimits: SessionManagerBoundedContextLimits | undefined;
protected boundedContextIncomplete: boolean;
protected persistedBoundaryCount: number | undefined;
constructor(cwd: string, persistenceTarget?: SessionManagerPersistenceTarget, loadedEntries?: FileEntry[], boundedContext?: SessionManagerBoundedContext);
setSessionTarget(target: SessionManagerPersistenceTarget): void;
/** Active-only loads can omit sibling rows even when they fit the context limits. */
protected ensureCompletePersistedHistory(): void;
protected setLoadedSessionTarget(target: SessionManagerPersistenceTarget | undefined, entries: FileEntry[], bounded?: Pick<SessionTranscriptBoundedActiveContext, "activeLeafEntryId" | "opaqueParents" | "firstKeptRanges">): void;
reloadPersistedTranscript(): void;
newSession(options?: NewSessionOptions): string | undefined;
private initializeSession;
protected buildIndex(): void;
protected normalizeEntryParent(entry: SessionEntry): SessionEntry;
private findFirstCanonicalDescendantOnBranch;
private findFirstCanonicalDescendant;
protected resolveBranchTargetId(branchFromId: string): string | null | undefined;
protected clampOpaqueFileEntryIndexes(): void;
protected createLeafControl(parentId: string | null, appendParentId?: string | null, appendMode?: "side"): SessionLeafControl;
protected rememberLeafControl(leafEntry: SessionLeafControl): void;
getAppendParentId(): string | null;
getAppendMode(): "side" | undefined;
protected getPersistedFileEntries(leafAppendParentId?: string | null, leafAppendMode?: "side"): unknown[];
getPersistedEntries(): unknown[];
clearPreservedOpaqueFileEntries(): void;
/** SQLite appends are synchronous; retained for the AgentSession contract. */
protected flushPendingPersistence(): void;
isPersisted(): boolean;
getCwd(): string;
getSessionId(): string;
getSessionTarget(): SessionManagerPersistenceTarget | undefined;
}
//#endregion
//#region src/agents/sessions/session-manager-persistence.d.ts
type PersistRecordResult = undefined | {
anchor?: TranscriptEntryAnchor;
appended: boolean;
adoptedMessageId?: string;
effectiveParentId: string | null;
};
declare class SessionManagerPersistence extends SessionManagerCore {
#private;
removeTrailingEntries(predicate: (entry: SessionEntry) => boolean, options?: {
preserveTrailing?: (entry: SessionEntry) => boolean;
}): number;
protected persistRecord(entry: unknown, options?: AppendPersistenceOptions): PersistRecordResult;
persist(entry: SessionEntry, options?: AppendPersistenceOptions): PersistRecordResult;
private persistSqliteRecord;
}
//#endregion
//#region src/agents/sessions/session-manager-entries.d.ts
declare class SessionManagerEntries extends SessionManagerPersistence {
protected appendEntry<T extends SessionEntry>(entry: T, options?: AppendPersistenceOptions): {
entry: T;
anchor?: TranscriptEntryAnchor;
appended: boolean;
};
resolveCurrentTurnEntryId(isInterruptedTail?: (entry: SessionEntry) => boolean): string | null;
appendMessage(message: Message | CustomMessage | BashExecutionMessage, options?: AppendPersistenceOptions): string;
appendMessageWithTranscriptAnchor(message: Message | CustomMessage | BashExecutionMessage, options?: AppendPersistenceOptions): {
entryId: string;
message: SessionMessageEntry["message"];
anchor?: TranscriptEntryAnchor;
appended: boolean;
};
appendThinkingLevelChange(thinkingLevel: string): string;
appendModelChange(provider: string, modelId: string): string;
appendCompaction(summary: string, firstKeptEntryId: string, tokensBefore: number, details?: unknown, fromHook?: boolean, metadata?: CompactionEntry["__openclaw"]): string;
appendResetBoundary(reason: ResetReason, firstKeptEntryId?: string): string;
appendCustomEntry(customType: string, data?: unknown): string;
appendSessionInfo(name: string): string;
getSessionName(): string | undefined;
appendCustomMessageEntry(customType: string, content: string | (TextContent | ImageContent$1)[], display: boolean, details?: unknown): string;
getLeafId(): string | null;
appendLeafControl(params: {
targetId: string | null;
appendParentId: string | null;
appendMode?: "side";
}): SessionLeafControl;
getLeafEntry(): SessionEntry | undefined;
getEntry(id: string): SessionEntry | undefined;
getChildren(parentId: string): SessionEntry[];
getLabel(id: string): string | undefined;
appendLabelChange(targetId: string, label: string | undefined): string;
buildSessionContext(): SessionContext;
getBoundaryCount(): number;
getHeader(): SessionHeader | null;
getEntries(): SessionEntry[];
getTree(): SessionTreeNode[];
branch(branchFromId: string): void;
resetLeaf(): void;
branchWithSummary(branchFromId: string | null, summary: string, details?: unknown, fromHook?: boolean): string;
}
//#endregion
//#region src/agents/sessions/session-manager-branching.d.ts
declare class SessionManagerBranching extends SessionManagerEntries {
private collectBranchedSessionPath;
createBranchedSession(leafId: string): Promise<string | undefined>;
}
//#endregion
//#region src/agents/sessions/session-manager.d.ts
declare class SessionManager extends SessionManagerBranching {
private constructor();
/** Makes pending append-oriented persistence durable without rewriting committed entries. */
flushPendingPersistence(): void;
appendMessage(message: Message | CustomMessage | BashExecutionMessage, options?: AppendPersistenceOptions): string;
appendMessageWithTranscriptAnchor(message: Message | CustomMessage | BashExecutionMessage, options?: AppendPersistenceOptions): {
entryId: string;
message: SessionMessageEntry["message"];
anchor?: TranscriptEntryAnchor;
appended: boolean;
};
static open(target: SessionTranscriptRuntimeTarget, cwdOverride?: string, contextLimits?: SessionManagerBoundedContextLimits): SessionManager;
/** Opens only the selected model-context tail while preserving the complete durable transcript. */
static openBounded(target: SessionTranscriptRuntimeTarget, options: SessionManagerBoundedContextLimits & {
cwd?: string;
onTruncated?: () => void;
}): SessionManager;
/** Detached model view: selected payloads plus lightweight ancestry, never raw replay evidence. */
static openModelContext(target: SessionTranscriptRuntimeTarget, options?: {
cwd?: string;
admission?: UserTurnTranscriptAdmissionReceipt;
}): SessionManager;
/** The same detached model view, with durable transcript scanning off the event loop. */
static openModelContextAsync(target: SessionTranscriptRuntimeTarget, options?: {
cwd?: string;
admission?: UserTurnTranscriptAdmissionReceipt;
signal?: AbortSignal;
}): Promise<SessionManager>;
private static fromModelContextEntries;
/** Synchronously consumes full-fidelity context; its iterator closes with the read snapshot. */
static readSessionContext<T>(target: SessionTranscriptRuntimeTarget, read: (messages: Iterable<AgentMessage>, header: unknown) => T, options?: {
admission?: UserTurnTranscriptAdmissionReceipt;
}): T;
/** Appends to the current transcript leaf without hydrating its history. */
static appendMessageToTranscript(target: SessionTranscriptRuntimeTarget, message: Message | CustomMessage | BashExecutionMessage, options?: Pick<AppendPersistenceOptions, "config">): string;
static inMemory(cwd?: string): SessionManager;
static fromEntries(entries: readonly unknown[], cwdOverride?: string): SessionManager;
}
type ReadonlySessionManager = Pick<SessionManager, "getCwd" | "getSessionId" | "getSessionTarget" | "getLeafId" | "getAppendParentId" | "getAppendMode" | "getLeafEntry" | "getEntry" | "getLabel" | "getBranch" | "getHeader" | "getEntries" | "getTree" | "getSessionName">;
//#endregion
//#region src/config/sessions/transcript.d.ts
type SessionTranscriptDeliveryMirror = {
kind: "channel-final";
sourceMessageId?: string;
} | {
kind: "channel-final-suppressed";
reason: "stale-foreground";
sourceMessageId?: string;
};
//#endregion
//#region src/infra/outbound/mirror.d.ts
/**
* Transcript append data emitted after an outbound send completes.
*/
type OutboundMirror = {
sessionKey: string;
agentId?: string;
text?: string;
mediaUrls?: string[];
idempotencyKey?: string;
expectedSessionId?: string;
deliveryMirror?: SessionTranscriptDeliveryMirror;
};
/**
* Delivery-layer mirror data with optional group/channel correlation metadata.
*/
type DeliveryMirror = OutboundMirror & {
/** Whether this message is being sent in a group/channel context */
isGroup?: boolean;
/** Group or channel identifier for correlation with received events */
groupId?: string;
};
//#endregion
//#region src/infra/outbound/session-context.d.ts
type OutboundSessionContext = {
/**
* Canonical session key used for internal hook dispatch.
*
* MUST equal the agent runtime's `params.sessionKey` for the run that
* produced the payload being delivered. Plugins observing both
* `agent_end`/`llm_input`/`llm_output`/`before_tool_call`/`after_tool_call`
* and `message_sending`/`message_sent` rely on this equality to correlate
* per-turn state across the agent-loop and delivery boundaries.
*
* Callers populating this field should use the same value the agent runner
* received as its sessionKey — in the chat path that is
* `targetSessionKey || ctx.SessionKey` (see
* `auto-reply/reply/get-reply.ts`). Followup, ACP, command, and cron
* delivery paths each have their own canonical value to forward; consult
* the relevant runner.
*/
key?: string;
/**
* Session key used for policy resolution when delivery differs from the
* control session. Used to look up silent-reply policy, send rate limits,
* agent-scoped channel preferences, etc., for the chat the reply is being
* delivered into. May equal `key` when there is no redirect; otherwise
* `policyKey` describes the *delivery target*'s session while `key`
* describes the *control session* whose hooks fire.
*/
policyKey?: string;
/** Explicit conversation type for policy resolution when a session key is generic. */
conversationType?: SilentReplyConversationType;
/**
* Caller-declared destination conversation kind for metadata-only audit
* projection. Never derived from session-key parsing: policy keys can name
* an acted-on session that is not the delivery destination, and a wrong
* "direct" here over-collects under audit.messages="direct".
*/
conversationKind?: "direct" | "group" | "channel";
/** Active agent id used for workspace-scoped media roots. */
agentId?: string;
/** Originating account id used for requester-scoped group policy resolution. */
requesterAccountId?: string;
/** Originating sender id used for sender-scoped outbound media policy. */
requesterSenderId?: string;
/** Originating sender display name for name-keyed sender policy matching. */
requesterSenderName?: string;
/** Originating sender username for username-keyed sender policy matching. */
requesterSenderUsername?: string;
/** Originating sender E.164 phone number for e164-keyed sender policy matching. */
requesterSenderE164?: string;
};
//#endregion
//#region src/infra/outbound/prepared-batch.d.ts
declare const PREPARED_OUTBOUND_BATCH_SCHEMA_VERSION: 1;
type PreparedOutboundAcceptedEntry = {
sourceIndex: number;
status: "accepted";
payload: ReplyPayload;
replyHookChanged: boolean;
messageHookChanged: boolean;
preparedMediaCount: number;
};
type PreparedOutboundSuppressedEntry = {
sourceIndex: number;
status: "suppressed";
reason: OutboundPayloadDeliverySuppressionReason;
hookEffect?: {
cancelReason?: string;
metadata?: Record<string, unknown>;
};
};
type PreparedOutboundBatchEntry = PreparedOutboundAcceptedEntry | PreparedOutboundSuppressedEntry;
/** Canonical post-policy payload custody persisted by the durable outbound queue. */
type PreparedOutboundBatch = {
schemaVersion: typeof PREPARED_OUTBOUND_BATCH_SCHEMA_VERSION;
sourcePayloadCount: number;
/** True only when accepted payloads already passed post-policy channel normalization. */
channelNormalized?: true;
runId?: string;
executionIdentityToken?: ExecutionIdentityAdmissionToken;
entries: PreparedOutboundBatchEntry[];
};
//#endregion
//#region src/infra/outbound/delivery-queue-types.d.ts
type QueuedRenderedMessageBatchPlan = {
payloadCount: number;
textCount: number;
mediaCount: number;
voiceCount: number;
presentationCount: number;
interactiveCount: number;
channelDataCount: number;
items: readonly RenderedMessageBatchPlanItem[];
};
type QueuedReplyPayloadSendingHook = {
kind: ReplyDispatchKind;
channel?: string;
sessionKey?: string;
runId?: string;
context: PluginHookReplyPayloadSendingContext;
};
//#endregion
//#region src/hooks/types.d.ts
type HookInstallSpec = {
id?: string;
kind: "bundled" | "npm" | "git";
label?: string;
package?: string;
repository?: string;
bins?: string[];
};
type OpenClawHookMetadata = {
always?: boolean;
hookKey?: string;
emoji?: string;
homepage?: string;
/** Events this hook handles (e.g., ["command:new", "session:start"]) */
events: string[];
/** Optional export name (default: "default") */
export?: string;
os?: string[];
requires?: {
bins?: string[];
anyBins?: string[];
env?: string[];
config?: string[];
};
install?: HookInstallSpec[];
};
type HookInvocationPolicy = {
enabled: boolean;
};
type ParsedHookFrontmatter = Record<string, string>;
type Hook = {
name: string;
description: string;
source: "openclaw-bundled" | "openclaw-managed" | "openclaw-workspace" | "openclaw-plugin";
pluginId?: string;
filePath: string;
baseDir: string;
handlerPath: string;
};
type HookEntry = {
hook: Hook;
frontmatter: ParsedHookFrontmatter;
metadata?: OpenClawHookMetadata;
invocation?: HookInvocationPolicy;
};
//#endregion
//#region src/plugins/runtime/subagent-requester-context.d.ts
type PluginSubagentRequesterContext = Readonly<{
sessionKey: string;
origin: Readonly<DeliveryContext>;
}>;
//#endregion
//#region src/infra/outbound/message-sent-hook.d.ts
type MessageSentEvent = {
success: boolean;
content: string;
error?: string;
messageId?: string;
};
//#endregion
//#region src/infra/outbound/reply-payload-parts.d.ts
/** Derived sendability facts for text/media outbound payload delivery. */
type SendableOutboundReplyParts = {
/** Raw text selected for delivery before trimming. */
text: string;
/** Text after trimming whitespace for sendability checks. */
trimmedText: string;
/** Normalized non-empty media URLs. */
mediaUrls: string[];
/** Number of normalized media URLs. */
mediaCount: number;
/** Whether trimmed text is sendable. */
hasText: boolean;
/** Whether at least one media URL is sendable. */
hasMedia: boolean;
/** Whether the payload has any sendable text or media. */
hasContent: boolean;
};
/** Normalize reply payload text/media into a trimmed, sendable shape for delivery paths. */
declare function resolveSendableOutboundReplyParts(payload: {
text?: string;
mediaUrls?: string[];
mediaUrl?: string;
}, options?: {
text?: string;
}): SendableOutboundReplyParts;
//#endregion
//#region src/infra/outbound/payloads.d.ts
/** Runtime-ready outbound payload after text/media/rich-content normalization. */
type NormalizedOutboundPayload = {
text: string;
mediaUrls: string[];
audioAsVoice?: boolean;
presentation?: MessagePresentation;
presentationTextMode?: ReplyPayload["presentationTextMode"];
delivery?: ReplyPayloadDelivery;
interactive?: LegacyInteractiveReply;
channelData?: Record<string, unknown>;
location?: ReplyPayload["location"];
/** Hook-only content for audio-only TTS payloads. Never used as channel text/caption. */
hookContent?: string;
/** Preserves the status/answer distinction through delivery hooks. */
isStatusNotice?: boolean;
};
/** JSON-safe outbound payload projection used for envelopes and diagnostics. */
type OutboundPayloadJson = {
text: string;
mediaUrl: string | null;
mediaUrls?: string[];
audioAsVoice?: boolean;
presentation?: MessagePresentation;
presentationTextMode?: ReplyPayload["presentationTextMode"];
delivery?: ReplyPayloadDelivery;
interactive?: LegacyInteractiveReply;
channelData?: Record<string, unknown>;
location?: ReplyPayload["location"];
};
/** Prepared payload entry that keeps source indexing plus reusable projections. */
type OutboundPayloadPlan = {
sourceIndex: number;
payload: ReplyPayload;
parts: ReturnType<typeof resolveSendableOutboundReplyParts>;
hasPresentation: boolean;
hasInteractive: boolean;
hasChannelData: boolean;
};
/** Projects a payload plan into JSON-safe envelope/debug payloads. */
declare function projectOutboundPayloadPlanForJson(plan: readonly OutboundPayloadPlan[]): OutboundPayloadJson[];
//#endregion
//#region src/infra/outbound/deliver-contracts.d.ts
type ConversationDeliveryAttemptAuthority = Omit<Extract<DurableDeliveryCompletion, {
kind: "conversation";
}>, "kind">;
type OutboundDeliveryQueuePolicy = "required" | "best_effort";
type OutboundDeliveryIntent = {
id: string;
channel: string;
to: string;
accountId?: string;
queuePolicy: OutboundDeliveryQueuePolicy;
};
type DurableFinalDeliveryRequirement = keyof NonNullable<ChannelDeliveryCapabilities["durableFinal"]>;
type DurableFinalDeliveryRequirements = Partial<Record<DurableFinalDeliveryRequirement, boolean>>;
type PlatformSendRoute = {
replyToId?: string | null;
threadId?: string | number | null;
};
type DeliverOutboundPayloadsCoreParams = {
cfg: OpenClawConfig;
channel: string;
to: string;
accountId?: string;
payloads: ReplyPayload[];
/** Admitted run correlation copied into the prepared durable batch. */
runId?: string;
/** @internal Exact admitted execution provenance copied into durable custody. */
executionIdentityToken?: ExecutionIdentityAdmissionToken;
/** @internal Canonical post-policy batch used by queue recovery and physical delivery. */
preparedBatch?: PreparedOutboundBatch;
reply?: OutboundReplyFacts;
formatting?: OutboundDeliveryFormattingOptions;
threadId?: string | number | null;
identity?: OutboundIdentity;
deps?: OutboundSendDeps;
mediaAccess?: OutboundMediaAccess;
gifPlayback?: boolean;
forceDocument?: boolean;
replyPayloadSendingHook?: QueuedReplyPayloadSendingHook;
abortSignal?: AbortSignal;
bestEffort?: boolean;
onError?: (err: unknown, payload: NormalizedOutboundPayload) => void;
onPayload?: (payload: NormalizedOutboundPayload) => void;
/** @internal Reports the effective payload only after an identified platform send. */
onDeliveredPayload?: (payload: NormalizedOutboundPayload) => void;
onPayloadDeliveryOutcome?: (outcome: OutboundPayloadDeliveryOutcome) => void;
/** @internal Runs after each identified platform result, before further fallible work. */
onDeliveryResult?: (result: OutboundDeliveryResult) => Promise<void> | void;
/** @internal Reports a settled native payload for post-terminal message_sent observation. */
onMessageSentEvent?: (event: MessageSentEvent, sourceIndex: number) => void;
/** @internal Persists ambiguous-send state immediately before platform I/O. */
onPlatformSendStart?: (route: PlatformSendRoute, sourceIndex?: number) => Promise<void>;
/** @internal Opaque durable intent id forwarded to provider reconciliation hooks. */
deliveryQueueId?: string;
/** @internal Stable producer id used to make queue creation idempotent across crashes. */
deliveryIntentId?: string;
/** @internal Retain the completed receipt for a producer-owned replayable intent. */
completionRetention?: DeliveryQueueCompletionRetention;
/** @internal Producer-specific durable recovery attempt budget. */
maxRetries?: number;
/** @internal Retry this producer's pending intent only when no platform send began. */
reusePendingDeliveryIntent?: boolean;
/** @internal Serializable owner state finalized after live or recovered delivery. */
deliveryCompletion?: DurableDeliveryCompletion;
/** @internal The caller resends proven-not-sent payloads itself, so recovery must not. */
deliveryRetryOwner?: "caller";
/** @internal Ephemeral route authority for a recovered attempt; never owns completion. */
conversationDeliveryAttemptAuthority?: ConversationDeliveryAttemptAuthority;
/** @internal Revalidates authority once per durable queue execution, before adapter fanout. */
onDeliveryAttempt?: () => Promise<void>;
/** @internal Channel-valid id reserved before a correlated conversation turn is sent. */
preparedMessageId?: string;
/** @internal Recheck the concrete post-hook send shape before platform I/O. */
requiredUnknownSendReconciliation?: boolean;
/** @internal Caller preflight explicitly required provider unknown-send reconciliation. */
requireUnknownSendReconciliation?: boolean;
/** @internal Revalidate caller authority before direct adapter code can run. */
onDirectAdapterHandoff?: () => Promise<void>;
/** @internal Synchronously fence authority at the final adapter invocation. */
assertDirectAdapterHandoff?: () => void;
/** @internal Refresh durable timing before recipient-visible or finalizing platform I/O. */
onPlatformSendDispatch?: () => Promise<void>;
/** Session/agent context used for hooks and media local-root scoping. */
session?: OutboundSessionContext;
mirror?: DeliveryMirror;
silent?: boolean;
gatewayClientScopes?: readonly string[];
conversationReadOrigin?: "delegated" | "direct-operator";
};
/**
* @deprecated Direct outbound delivery is compatibility/runtime substrate.
* New message lifecycle code should use `sendDurableMessageBatch` from
* `src/channels/message/send.ts` or `deliverInboundReplyWithMessageSendContext`
* from `src/channels/turn/durable-delivery.ts`. Keep direct use only for
* outbound substrate, recovery, and compatibility paths.
*/
type DeliverOutboundPayloadsParams = DeliverOutboundPayloadsCoreParams & {
replyToId?: string | null;
replyToMode?: ReplyToMode;
/** @internal Skip write-ahead queue (used by crash-recovery to avoid re-enqueueing). */
skipQueue?: boolean;
/** @internal Fence recovery ownership at the same provider boundary as live sends. */
deliveryProducerClaimId?: string;
/** @internal Keep the exact live producer claim alive during platform preparation. */
deliveryProducerLeaseRequired?: boolean;
/** @internal Recovery already ran provider admission after its pending-row re-read. */
deferredDeliveryAdmissionPassed?: true;
/** @internal State directory that owns the existing recovery queue entry. */
deliveryQueueStateDir?: string;
/** @internal Let recovery run commit hooks after it has acked the recovered queue entry. */
deferCommitHooks?: boolean;
queuePolicy?: OutboundDeliveryQueuePolicy;
renderedBatchPlan?: QueuedRenderedMessageBatchPlan;
onDeliveryIntent?: (intent: OutboundDeliveryIntent) => void;
};
//#endregion
//#region src/plugins/plugin-command-dispatch-contract.d.ts
/** Lightweight reply-option contract for prepared plugin command ownership. */
declare const PLUGIN_COMMAND_DISPATCH: unique symbol;
type PluginCommandReplyOptions = Readonly<{
[PLUGIN_COMMAND_DISPATCH]?: Readonly<{
kind: "plugin" | "non-plugin";
}>;
}>;
//#endregion
//#region src/gateway/worker-environments/placement-state.d.ts
declare const WORKER_SESSION_PLACEMENT_STATES: readonly ["local", "requested", "provisioning", "syncing", "starting", "active", "draining", "reconciling", "reclaimed", "failed"];
type WorkerSessionPlacementState = (typeof WORKER_SESSION_PLACEMENT_STATES)[number];
//#endregion
//#region src/gateway/worker-environments/placement-record.d.ts
type WorkerSessionPlacementIdentity = {
sessionId: string;
agentId: string;
sessionKey: string;
};
type WorkerPlacementExecutionMode = "worker-turn" | "remote-exec";
type WorkerSessionPlacementDispatchIdentity = WorkerSessionPlacementIdentity & {
executionMode?: WorkerPlacementExecutionMode;
};
type WorkerSessionTurnOwner = {
kind: "local";
environmentId?: string;
ownerEpoch?: number;
} | {
kind: "worker";
environmentId: string;
ownerEpoch: number;
};
type WorkerSessionTurnClaim = {
sessionId: string;
claimId: string;
runId: string;
placementGeneration: number;
owner: WorkerSessionTurnOwner;
};
type PersistedTurnClaim = {
owner: "local";
claimId: string;
runId: string;
generation: number;
ownerEpoch: null;
} | {
owner: "worker";
claimId: string;
runId: string;
generation: number;
ownerEpoch: number;
};
type WorkerWorkspaceResultConflict = {
paths: string[];
stagedResultRef: string;
totalCount?: number;
};
type PersistedLocalTurnClaim = Extract<PersistedTurnClaim, {
owner: "local";
}>;
type PlacementRecordBase<TurnClaim extends PersistedTurnClaim | null> = WorkerSessionPlacementIdentity & {
generation: number;
executionMode: WorkerPlacementExecutionMode;
turnClaim: TurnClaim;
createdAtMs: number;
updatedAtMs: number;
stateChangedAtMs: number;
/** Process-local UI projection; deliberately absent from SQLite. */
workspaceResultConflict?: WorkerWorkspaceResultConflict;
};
type UnclaimedPlacementRecordBase = PlacementRecordBase<null>;
type LocalClaimablePlacementRecordBase = PlacementRecordBase<PersistedLocalTurnClaim | null>;
type EmptyWorkerPlacementMetadata = {
environmentId: null;
activeOwnerEpoch: null;
workspaceBaseManifestRef: null;
remoteWorkspaceDir: null;
workerBundleHash: null;
lastTranscriptAckCursor: null;
lastLiveEventAckCursor: null;
recoveryError: null;
terminalReason: null;
terminalAtMs: null;
};
type ProvisioningPlacementMetadata = {
environmentId: string | null;
activeOwnerEpoch: null;
workspaceBaseManifestRef: null;
remoteWorkspaceDir: null;
workerBundleHash: null;
lastTranscriptAckCursor: null;
lastLiveEventAckCursor: null;
recoveryError: null;
terminalReason: null;
terminalAtMs: null;
};
type SyncingPlacementMetadata = {
environmentId: string;
activeOwnerEpoch: null;
workspaceBaseManifestRef: null;
remoteWorkspaceDir: null;
workerBundleHash: string;
lastTranscriptAckCursor: null;
lastLiveEventAckCursor: null;
recoveryError: null;
terminalReason: null;
terminalAtMs: null;
};
type StartingPlacementMetadata = {
environmentId: string;
activeOwnerEpoch: null;
workspaceBaseManifestRef: string;
remoteWorkspaceDir: string;
workerBundleHash: string;
lastTranscriptAckCursor: null;
lastLiveEventAckCursor: null;
recoveryError: null;
terminalReason: null;
terminalAtMs: null;
};
type OwnedWorkerPlacementMetadata = {
environmentId: string;
activeOwnerEpoch: number;
workspaceBaseManifestRef: string;
remoteWorkspaceDir: string;
workerBundleHash: string;
lastTranscriptAckCursor: number | null;
lastLiveEventAckCursor: number | null;
recoveryError: null;
terminalReason: null;
terminalAtMs: null;
};
type TerminalPlacementMetadata = {
environmentId: string | null;
activeOwnerEpoch: number | null;
workspaceBaseManifestRef: string | null;
remoteWorkspaceDir: string | null;
workerBundleHash: string | null;
lastTranscriptAckCursor: number | null;
lastLiveEventAckCursor: number | null;
terminalReason: string | null;
terminalAtMs: number | null;
};
type LocalPlacementRecord = LocalClaimablePlacementRecordBase & EmptyWorkerPlacementMetadata & {
state: "local";
};
type RequestedPlacementRecord = LocalClaimablePlacementRecordBase & EmptyWorkerPlacementMetadata & {
state: "requested";
};
type ProvisioningPlacementRecord = UnclaimedPlacementRecordBase & ProvisioningPlacementMetadata & {
state: "provisioning";
};
type SyncingPlacementRecord = UnclaimedPlacementRecordBase & SyncingPlacementMetadata & {
state: "syncing";
};
type StartingPlacementRecord = UnclaimedPlacementRecordBase & StartingPlacementMetadata & {
state: "starting";
};
type ActivePlacementRecord = PlacementRecordBase<PersistedTurnClaim | null> & OwnedWorkerPlacementMetadata & {
state: "active";
};
type DrainingPlacementRecord = PlacementRecordBase<PersistedTurnClaim | null> & OwnedWorkerPlacementMetadata & {
state: "draining";
};
type ReconcilingPlacementRecord = UnclaimedPlacementRecordBase & OwnedWorkerPlacementMetadata & {
state: "reconciling";
};
type ReclaimedPlacementRecord = UnclaimedPlacementRecordBase & Omit<OwnedWorkerPlacementMetadata, "terminalReason" | "terminalAtMs"> & TerminalPlacementMetadata & {
state: "reclaimed";
};
type FailedPlacementRecord = LocalClaimablePlacementRecordBase & TerminalPlacementMetadata & {
state: "failed";
recoveryError: string;
};
type WorkerSessionPlacementRecord = LocalPlacementRecord | RequestedPlacementRecord | ProvisioningPlacementRecord | SyncingPlacementRecord | StartingPlacementRecord | ActivePlacementRecord | DrainingPlacementRecord | ReconcilingPlacementRecord | ReclaimedPlacementRecord | FailedPlacementRecord;
type WorkerSessionPlacementTransitionPatch = {
environmentId?: string | null;
activeOwnerEpoch?: number | null;
workspaceBaseManifestRef?: string | null;
remoteWorkspaceDir?: string | null;
workerBundleHash?: string | null;
lastTranscriptAckCursor?: number | null;
lastLiveEventAckCursor?: number | null;
recoveryError?: string | null;
terminalReason?: string | null;
};
//#endregion
//#region src/gateway/worker-environments/workspace-manifest.d.ts
type WorkerWorkspaceManifestEntry = {
path: string;
type: "file";
mode: number;
size: number;
sha256: string;
} | {
path: string;
type: "symlink";
mode: number;
target: string;
};
type WorkerWorkspaceManifest = {
version: 1;
baseCommit: string | null;
entries: WorkerWorkspaceManifestEntry[];
directories?: string[];
};
type WorkerWorkspaceReconciliationJournal = {
version: 1;
temporaryNonce: string;
baseManifestRef: string;
currentManifestRef: string;
baseEntries: WorkerWorkspaceManifestEntry[];
appliedEntries: WorkerWorkspaceManifestEntry[];
baseDirectories?: string[];
appliedDirectories?: string[];
appliedManifestRef?: string;
baseTree: string;
basePackSha256: string;
basePack: Uint8Array;
};
type WorkerWorkspaceReconciliationJournalAdapter = {
load(): WorkerWorkspaceReconciliationJournal | undefined;
begin(journal: WorkerWorkspaceReconciliationJournal): void;
commit(manifestRef: string): void;
abort(): void;
};
//#endregion
//#region src/gateway/worker-environments/placement-workspace-result.d.ts
type WorkerWorkspacePendingResult = {
sessionId: string;
environmentId: string;
ownerEpoch: number;
placementGeneration: number;
claimId: string;
runId: string;
gatewayInstanceId: string;
recoveryRequestedAtMs: number | null;
workspaceAcceptedAtMs: number | null;
stagedResultRef: string | null;
};
//#endregion
//#region src/gateway/worker-environments/placement-move-intent.d.ts
type WorkerPlacementMoveTarget = SessionMoveTarget;
type WorkerPlacementMoveSource = {
generation: number;
environmentId: string;
ownerEpoch: number;
};
type WorkerPlacementMoveIntent = {
operationId: string;
sessionId: string;
source: WorkerPlacementMoveSource;
target: WorkerPlacementMoveTarget;
abandonSource: boolean;
lastError: string | null;
createdAtMs: number;
updatedAtMs: number;
};
//#endregion
//#region src/gateway/worker-environments/placement-store.d.ts
declare const RETIRABLE_PLACEMENT_STATES: readonly ["local", "requested", "reclaimed", "failed"];
type WorkerSessionPlacementRetirement = {
sessionId: string;
expectedState: (typeof RETIRABLE_PLACEMENT_STATES)[number];
expectedGeneration: number;
};
declare function createWorkerSessionPlacementStore(options?: {
database?: OpenClawStateDatabase;
now?: () => number;
}): {
getWorkspaceReconciliationPlacement(owner: {
sessionId: string;
environmentId: string;
ownerEpoch: number;
placementGeneration: number;
}): (WorkerSessionPlacementIdentity & {
generation: number;
executionMode: WorkerPlacementExecutionMode;
turnClaim: PersistedTurnClaim | null;
createdAtMs: number;
updatedAtMs: number;
stateChangedAtMs: number;
workspaceResultConflict?: WorkerWorkspaceResultConflict;
} & OwnedWorkerPlacementMetadata & {
state: "active";
}) | (WorkerSessionPlacementIdentity & {
generation: number;
executionMode: WorkerPlacementExecutionMode;
turnClaim: PersistedTurnClaim | null;
createdAtMs: number;
updatedAtMs: number;
stateChangedAtMs: number;
workspaceResultConflict?: WorkerWorkspaceResultConflict;
} & OwnedWorkerPlacementMetadata & {
state: "draining";
}) | undefined;
listWorkspaceReconciliationOwners(): {
sessionId: string;
environmentId: string;
ownerEpoch: number;
placementGeneration: number;
}[];
pruneOrphanedWorkspaceReconciliations(options: {
retainFailedOwner: (recoveryError: string) => boolean;
}): {
sessionId: string;
environmentId: string;
ownerEpoch: number;
placementGeneration: number;
}[];
loadWorkspaceReconciliation(owner: {
sessionId: string;
environmentId: string;
ownerEpoch: number;
placementGeneration: number;
}, options?: {
allowFailedOwner?: boolean;
}): WorkerWorkspaceReconciliationJournal | undefined;
beginWorkspaceReconciliation(owner: {
sessionId: string;
environmentId: string;
ownerEpoch: number;
placementGeneration: number;
}, journal: WorkerWorkspaceReconciliationJournal): void;
abortWorkspaceReconciliation(owner: {
sessionId: string;
environmentId: string;
ownerEpoch: number;
placementGeneration: number;
}, options?: {
force?: boolean;
}): void;
workspaceResultInstanceId(): string;
validateWorkspaceResultClaim(claim: WorkerSessionTurnClaim): boolean;
listPendingWorkspaceResults(): WorkerWorkspacePendingResult[];
markWorkspaceResultPending(claim: WorkerSessionTurnClaim): void;
recordStagedWorkspaceResult(claim: WorkerSessionTurnClaim, stagedResultRef: string): void;
acceptWorkspaceResult(claim: WorkerSessionTurnClaim): void;
handoffWorkspaceResultRecovery(claim: WorkerSessionTurnClaim): void;
abandonWorkspaceResult(pending: WorkerWorkspacePendingResult): void;
getPlacementMove(sessionId: string): WorkerPlacementMoveIntent | undefined;
getPlacementMoves(sessionIds: readonly string[]): ReadonlyMap<string, WorkerPlacementMoveIntent>;
listPlacementMoves(): WorkerPlacementMoveIntent[];
beginPlacementMove(input: {
sessionId: string;
source: WorkerPlacementMoveSource;
target: WorkerPlacementMoveTarget;
abandonSource?: true;
}): {
intent: WorkerPlacementMoveIntent;
placement: WorkerSessionPlacementRecord;
joined: boolean;
};
recordPlacementMoveError(input: {
operationId: string;
sessionId: string;
error: string;
}): boolean;
cancelPlacementMove(input: {
operationId: string;
sessionId: string;
}): void;
completePlacementMoveSourceToLocal(input: {
operationId: string;
sessionId: string;
expectedGeneration: number;
}): WorkerSessionPlacementRecord;
completeAbandonedPlacementMoveSourceToLocal(input: {
operationId: string;
sessionId: string;
expectedGeneration: number;
expectedRecoveryError: string;
}): WorkerSessionPlacementRecord;
completePlacementMoveToWorker(input: {
operationId: string;
sessionId: string;
expectedGeneration: number;
environmentId: string;
ownerEpoch: number;
}): WorkerSessionPlacementRecord;
authorizeWorkerTurnTools(claim: WorkerSessionTurnClaim, toolNames: readonly string[]): void;
isWorkerTurnToolAuthorized(claim: WorkerSessionTurnClaim, toolName: string): boolean;
closeWorkerTurnToolAdmission(claim: WorkerSessionTurnClaim): void;
closeWorkerTurnToolState(claim: WorkerSessionTurnClaim): Promise<void>;
beginWorkerSessionToolOperation(params: {
claim: WorkerSessionTurnClaim;
toolName: "sessions_spawn" | "sessions_send";
toolCallId: string;
requestDigest: string;
childSessionKey?: string;
}): {
kind: "execute";
operationSeed: string;
childSessionKey?: string;
} | {
kind: "in-progress";
} | {
kind: "completed";
resultJson: string;
} | {
kind: "unknown";
} | {
kind: "capacity";
} | {
kind: "conflict";
} | {
kind: "unauthorized";
};
bindWorkerSessionToolOperationChild(params: {
sourceSessionId: string;
sourceClaimId: string;
toolCallId: string;
requestDigest: string;
childSessionKey: string;
}): boolean;
completeWorkerSessionToolOperation(params: {
sourceSessionId: string;
sourceClaimId: string;
toolCallId: string;
requestDigest: string;
resultJson: string;
failed?: boolean;
}): boolean;
abandonWorkerSessionToolOperation(params: {
sourceSessionId: string;
sourceClaimId: string;
toolCallId: string;
requestDigest: string;
}): boolean;
recoverWorkerSessionToolOperationsAfterRestart(): number;
withWorkspaceExclusion: <T>(sessionId: string, run: (assertOwned: () => void) => Promise<T>) => Promise<T>;
withLocalWorkspaceReservation<T>(identity: WorkerSessionPlacementIdentity, run: (assertCurrent: () => void) => Promise<T>): Promise<T>;
claimTurn(input: WorkerSessionPlacementIdentity & {
owner: WorkerSessionTurnOwner;
claimId: string;
runId: string;
}): WorkerSessionTurnClaim;
claimReclaimWorkspaceResult(input: WorkerSessionPlacementIdentity & {
owner: WorkerSessionTurnOwner;
claimId: string;
runId: string;
}): WorkerSessionTurnClaim;
releaseTurn(claim: WorkerSessionTurnClaim): WorkerSessionPlacementRecord;
completeWorkspaceResultAndReleaseTurn(claim: WorkerSessionTurnClaim): WorkerSessionPlacementRecord;
cancelWorkspaceResultAndReleaseTurn(claim: WorkerSessionTurnClaim, options?: {
reason: "node-disconnect";
}): WorkerSessionPlacementRecord;
clearLocalTurnClaimsAfterRestart(): number;
waitForTurnClaimRelease(sessionIdInput: string, waitOptions: {
timeoutMs: number;
signal?: AbortSignal;
}): Promise<void>;
validateTurnClaim(claim: WorkerSessionTurnClaim): boolean;
updateAckCursors(input: {
claim: WorkerSessionTurnClaim;
transcript?: number;
liveEvent?: number;
workspaceResultPending?: boolean;
}): WorkerSessionPlacementRecord;
updateWorkspaceBaseManifest(input: {
claim: WorkerSessionTurnClaim;
manifestRef: string;
}): WorkerSessionPlacementRecord;
acceptIdleWorkspaceReconciliation(input: {
sessionId: string;
environmentId: string;
ownerEpoch: number;
expectedGeneration: number;
manifestRef: string;
}): WorkerSessionPlacementRecord;
failWorkspaceResultAndReleaseTurn(pending: WorkerWorkspacePendingResult, error: unknown): WorkerSessionPlacementRecord;
registerTurnClaimClosedHandler(handler: (claim: WorkerSessionTurnClaim) => void): () => void;
get(sessionId: string): WorkerSessionPlacementRecord | undefined;
getMany(sessionIds: readonly string[]): ReadonlyMap<string, WorkerSessionPlacementRecord>;
retireSessionPlacement(input: WorkerSessionPlacementRetirement): void;
recordWorkspaceResultConflict(claim: WorkerSessionTurnClaim, conflict: WorkerWorkspaceResultConflict | undefined): void;
startDispatch(input: WorkerSessionPlacementDispatchIdentity): WorkerSessionPlacementRecord;
transition(input: {
sessionId: string;
from: WorkerSessionPlacementState;
to: WorkerSessionPlacementState;
expectedGeneration: number;
patch?: WorkerSessionPlacementTransitionPatch;
}): WorkerSessionPlacementRecord;
startDrain(input: {
sessionId: string;
environmentId: string;
ownerEpoch: number;
expectedGeneration: number;
workspaceBaseManifestRef?: string;
}): WorkerSessionPlacementRecord;
startWorkspaceResultDrain(claim: WorkerSessionTurnClaim): WorkerSessionPlacementRecord;
startReconcile(input: {
sessionId: string;
environmentId: string;
ownerEpoch: number;
expectedGeneration: number;
forceLocalClaim?: true;
}): WorkerSessionPlacementRecord;
validateWorkerOwner(input: {
sessionId: string;
environmentId: string;
ownerEpoch: number;
}): boolean;
fail(input: {
sessionId: string;
recoveryError: string;
expectedGeneration?: number;
}): WorkerSessionPlacementRecord;
adoptActive(input: {
sessionId: string;
environmentId: string;
ownerEpoch: number;
expectedGeneration?: number;
}): WorkerSessionPlacementRecord;
listForReconcile(): WorkerSessionPlacementRecord[];
list(): WorkerSessionPlacementRecord[];
};
type WorkerSessionPlacementStore = ReturnType<typeof createWorkerSessionPlacementStore>;
type WorkerSessionPlacementRetirementService = Pick<WorkerSessionPlacementStore, "retireSessionPlacement">;
//#endregion
//#region src/agents/agent-runtime-id.d.ts
type EmbeddedAgentRuntime = "openclaw" | "auto" | (string & {});
//#endregion
//#region src/system-agent/operation-types.d.ts
/** Parsed OpenClaw operation before approval/execution. */
type SystemAgentOperation = {
kind: "none";
message: string;
} | {
kind: "overview";
} | {
kind: "doctor";
} | {
kind: "doctor-fix";
} | {
kind: "status";
} | {
kind: "health";
} | {
kind: "config-validate";
} | {
kind: "config-get";
path: string;
} | {
kind: "config-schema";
path?: string;
} | {
kind: "config-set";
path: string;
value: string;
} | {
kind: "config-set-ref";
path: string;
source: "env" | "file" | "exec" | "store";
id: string;
provider?: string;
} | {
kind: "setup";
workspace?: string;
model?: string;
agentName?: string;
} | SystemAgentNavigationOperation | {
kind: "channel-list";
} | {
kind: "channel-info";
channel: string;
} | {
kind: "gateway-status";
} | {
kind: "gateway-start";
} | {
kind: "gateway-stop";
} | {
kind: "gateway-restart";
} | {
kind: "agents";
} | {
kind: "models";
} | {
kind: "plugin-list";
} | {
kind: "plugin-search";
query: string;
} | {
kind: "plugin-install";
spec: string;
} | {
kind: "plugin-activate-artifact";
path: string;
sha256: string;
} | {
kind: "plugin-uninstall";
pluginId: string;
} | {
kind: "audit";
} | {
kind: "create-agent";
agentId: string;
workspace?: string;
model?: string;
requesterAgentId?: string;
} | {
kind: "set-default-model";
model: string;
agentId?: string;
};
/** Interactive actions owned by the host chat, never by delegated model turns. */
type SystemAgentNavigationOperation = {
kind: "model-setup";
workspace?: string;
} | {
kind: "model-accounts";
} | {
kind: "channel-setup";
channel: string;
} | {
kind: "skills-setup";
} | {
kind: "search-setup";
} | {
kind: "gateway-config-setup";
} | {
kind: "memory-import";
} | {
kind: "open-setup";
target: "guided" | "classic" | "channels" | "search" | "gateway";
channel?: string;
} | {
kind: "open-tui";
agentId?: string;
workspace?: string;
agentDraft?: "hatch";
};
//#endregion
//#region src/plugins/compat/registry-records.d.ts
declare const PLUGIN_COMPAT_RECORDS: readonly [...({
code: "plugin-sdk-agent-config-primitives-subpath" | "plugin-sdk-channel-logging-subpath" | "plugin-sdk-channel-secret-runtime-subpath" | "plugin-sdk-channel-streaming-subpath" | "plugin-sdk-group-access-subpath" | "plugin-sdk-matrix-subpath" | "plugin-sdk-text-runtime-subpath" | "plugin-sdk-zod-subpath";
status: "removed";
owner: "channel" | "config" | "sdk";
introduced: string;
replacement: "`openclaw/plugin-sdk/channel-config-schema`" | "`openclaw/plugin-sdk/channel-inbound` and `openclaw/plugin-sdk/channel-outbound`" | "`openclaw/plugin-sdk/channel-ingress-runtime`" | "`openclaw/plugin-sdk/channel-outbound`" | "`openclaw/plugin-sdk/channel-secret-basic-runtime` and `openclaw/plugin-sdk/channel-secret-tts-runtime`" | "`openclaw/plugin-sdk/logging-core`, `openclaw/plugin-sdk/text-chunking`, `openclaw/plugin-sdk/text-utility-runtime`, and `openclaw/plugin-sdk/string-coerce-runtime`" | "`openclaw/plugin-sdk/run-command`" | "the direct `zod` package import";
docsPath: string;
surfaces: string[];
diagnostics: string[];
tests: string[];
releaseNote: "The deprecated `agent-config-primitives` Plugin SDK subpath was removed; plugins now use maintained config-schema primitives." | "The deprecated `channel-logging` Plugin SDK subpath was removed; channel logging helpers now come from the inbound and outbound channel surfaces." | "The deprecated `channel-secret-runtime` Plugin SDK subpath was removed; plugins now use the focused basic and TTS secret-runtime subpaths." | "The deprecated `channel-streaming` Plugin SDK subpath was removed; plugins now import channel streaming helpers from `channel-outbound`." | "The deprecated `group-access` Plugin SDK subpath was removed; plugins now resolve message admission through `channel-ingress-runtime`." | "The deprecated `matrix` Plugin SDK facade was removed; command execution now uses the generic `run-command` subpath." | "The deprecated `text-runtime` Plugin SDK facade was removed; plugins now import logging, chunking, text utility, and string coercion helpers from their focused subpaths." | "The deprecated `zod` Plugin SDK re-export was removed; plugins now import `zod` directly.";
deprecated?: undefined;
warningStarts?: undefined;
removeAfter?: undefined;
removalGate?: undefined;
} | {
releaseNote?: undefined;
code: "plugin-sdk-channel-lifecycle-subpath" | "plugin-sdk-channel-message-subpath" | "plugin-sdk-channel-reply-pipeline-subpath" | "plugin-sdk-config-runtime-subpath" | "plugin-sdk-inbound-reply-dispatch-subpath" | "plugin-sdk-infra-runtime-subpath";
status: "deprecated" | "removal-pending";
owner: "channel" | "config" | "sdk";
introduced: string;
deprecated: string;
warningStarts: string;
removeAfter: "2026-10-01" | undefined;
removalGate: "next-plugin-sdk-major" | undefined;
replacement: "`api.pluginConfig`, `openclaw/plugin-sdk/config-mutation`, `openclaw/plugin-sdk/runtime-config-snapshot`, and `openclaw/plugin-sdk/config-contracts`; retain until supported external plugin migration is verified" | "`openclaw/plugin-sdk/channel-inbound` and `openclaw/plugin-sdk/channel-outbound`" | "`openclaw/plugin-sdk/channel-outbound` and `openclaw/plugin-sdk/channel-inbound`; retain until supported external plugin migration is verified" | "`openclaw/plugin-sdk/channel-outbound`; retain until supported external plugin migration is verified" | "focused subpaths including `openclaw/plugin-sdk/delivery-queue-runtime`, `openclaw/plugin-sdk/diagnostic-runtime`, `openclaw/plugin-sdk/error-runtime`, `openclaw/plugin-sdk/exec-approvals-runtime`, `openclaw/plugin-sdk/fetch-runtime`, and `openclaw/plugin-sdk/ssrf-runtime`; retain until supported external plugin migration is verified and system-event snapshot inspection and consumption have a modern public replacement";
docsPath: string;
surfaces: string[];
diagnostics: string[];
tests: string[];
} | {
status: "removal-pending";
removeAfter: "2026-09-30";
replacement: "`api.registerMediaUnderstandingProvider(...)` with provider-owned request helpers and types from `openclaw/plugin-sdk/plugin-entry`; retain the public subpath through the 2026-09-30 window while official plugin consumers migrate";
docsPath: "/plugins/architecture";
code: "plugin-sdk-media-understanding-public-demotion" | "plugin-sdk-memory-host-core-public-demotion" | "plugin-sdk-plugin-config-runtime-public-demotion" | "plugin-sdk-tool-plugin-public-demotion";
owner: "sdk";
introduced: string;
deprecated: string;
warningStarts: string;
surfaces: string[];
diagnostics: string[];
tests: string[];
} | {
status: "removal-pending";
removeAfter: "2026-09-30";
replacement: "host-prepared memory prompts via `openclaw/plugin-sdk/core` and memory capability registration through the injected plugin API; retain the facade through the 2026-09-30 window and until a focused public-artifact read seam exists";
docsPath: "/plugins/architecture-internals#context-engine-plugins";
code: "plugin-sdk-media-understanding-public-demotion" | "plugin-sdk-memory-host-core-public-demotion" | "plugin-sdk-plugin-config-runtime-public-demotion" | "plugin-sdk-tool-plugin-public-demotion";
owner: "sdk";
introduced: string;
deprecated: string;
warningStarts: string;
surfaces: string[];
diagnostics: string[];
tests: string[];
} | {
status: "removal-pending";
removeAfter: "2026-12-01";
replacement: "`api.pluginConfig`, runtime tool context config, and focused `config-contracts`, `runtime-config-snapshot`, or `config-mutation` subpaths; retain the public subpath through the 2026-12-01 window while official plugin consumers migrate";
docsPath: "/plugins/sdk-runtime";
code: "plugin-sdk-media-understanding-public-demotion" | "plugin-sdk-memory-host-core-public-demotion" | "plugin-sdk-plugin-config-runtime-public-demotion" | "plugin-sdk-tool-plugin-public-demotion";
owner: "sdk";
introduced: string;
deprecated: string;
warningStarts: string;
surfaces: string[];
diagnostics: string[];
tests: string[];
} | {
status: "deprecated";
replacement: "retain the public subpath until plugin authoring has a nonexecuting static metadata replacement for `defineToolPlugin`; `getToolPluginMetadata` currently reads metadata only from an already-executed entry";
docsPath: "/plugins/tool-plugins";
code: "plugin-sdk-media-understanding-public-demotion" | "plugin-sdk-memory-host-core-public-demotion" | "plugin-sdk-plugin-config-runtime-public-demotion" | "plugin-sdk-tool-plugin-public-demotion";
owner: "sdk";
introduced: string;
deprecated: string;
warningStarts: string;
surfaces: string[];
diagnostics: string[];
tests: string[];
})[], {
readonly code: "plugin-sdk-channel-setup-input-fields";
readonly status: "deprecated";
readonly owner: "channel";
readonly introduced: "2026-07-25";
readonly deprecated: "2026-07-25";
readonly warningStarts: "2026-07-25";
readonly removeAfter: "2026-10-01";
readonly replacement: "plugin-local setup input intersections that declare each owning channel field";
readonly docsPath: "/plugins/sdk-migration#published-channel-setup-compatibility";
readonly surfaces: readonly ["ChannelSetupInput.privateKey", "ChannelSetupInput.secret", "ChannelSetupInput.botToken", "ChannelSetupInput.appToken", "ChannelSetupInput.signingSecret", "ChannelSetupInput.mode", "ChannelSetupInput.cliPath", "ChannelSetupInput.authDir", "ChannelSetupInput.httpUrl", "ChannelSetupInput.httpPort", "ChannelSetupInput.webhookPath", "ChannelSetupInput.webhookUrl", "ChannelSetupInput.userId", "ChannelSetupInput.accessToken", "ChannelSetupInput.password", "ChannelSetupInput.deviceName", "ChannelSetupInput.url", "ChannelSetupInput.baseUrl", "ChannelSetupInput.code", "ChannelSetupInput.groupChannels", "ChannelSetupInput.dmAllowlist", "ChannelSetupInput.autoDiscoverChannels"];
readonly diagnostics: readonly ["TypeScript @deprecated annotations on the reader-backed ChannelSetupInput compatibility tier", "published-plugin artifact reader sweep required before field removal"];
readonly tests: readonly ["src/plugin-sdk/channel-setup.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "ChannelSetupInput keeps its reader-backed channel fields through the dated migration window while plugins move them into plugin-local input types.";
}, {
readonly code: "plugin-sdk-broad-runtime-barrels";
readonly status: "deprecated";
readonly owner: "sdk";
readonly introduced: "2026-07-25";
readonly deprecated: "2026-07-25";
readonly warningStarts: "2026-07-25";
readonly removeAfter: "2026-10-01";
readonly replacement: "focused plugin SDK subpaths for each runtime capability";
readonly docsPath: "/plugins/sdk-migration#compatibility-policy";
readonly surfaces: readonly ["openclaw/plugin-sdk/agent-runtime", "openclaw/plugin-sdk/agent-runtime loadModelCatalog params.useCache", "openclaw/plugin-sdk/agent-runtime loadModelCatalog params.cacheOnly", "openclaw/plugin-sdk/agent-runtime loadModelCatalog params.metadataSnapshot", "openclaw/plugin-sdk/agent-runtime loadModelCatalog", "openclaw/plugin-sdk/cli-runtime", "openclaw/plugin-sdk/conversation-runtime", "openclaw/plugin-sdk/hook-runtime", "openclaw/plugin-sdk/media-runtime", "openclaw/plugin-sdk/media-runtime buildAgentMediaPayload", "openclaw/plugin-sdk/plugin-runtime", "openclaw/plugin-sdk/security-runtime"];
readonly diagnostics: readonly ["TypeScript @deprecated annotations on broad plugin SDK barrels", "plugin boundary report compatibility inventory"];
readonly tests: readonly ["src/plugins/contracts/plugin-sdk-subpaths.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "Broad agent, CLI, conversation, hook, media, plugin, and security runtime barrels remain available while bundled and external plugins migrate to focused subpaths.";
}, {
readonly code: "plugin-sdk-provider-owned-helper-shims";
readonly status: "deprecated";
readonly owner: "provider";
readonly introduced: "2026-07-25";
readonly deprecated: "2026-07-25";
readonly warningStarts: "2026-07-25";
readonly removeAfter: "2026-10-01";
readonly replacement: "provider-local auth, model, replay, OAuth, and stream helper APIs";
readonly docsPath: "/plugins/sdk-migration#compatibility-policy";
readonly surfaces: readonly ["openclaw/plugin-sdk/provider-stream GOOGLE_THINKING_STREAM_HOOKS", "openclaw/plugin-sdk/provider-stream KILOCODE_THINKING_STREAM_HOOKS", "openclaw/plugin-sdk/provider-stream MOONSHOT_THINKING_STREAM_HOOKS", "openclaw/plugin-sdk/provider-stream MINIMAX_FAST_MODE_STREAM_HOOKS", "openclaw/plugin-sdk/provider-stream OPENAI_RESPONSES_STREAM_HOOKS", "openclaw/plugin-sdk/provider-stream OPENROUTER_THINKING_STREAM_HOOKS", "openclaw/plugin-sdk/provider-stream TOOL_STREAM_DEFAULT_ON_HOOKS", "openclaw/plugin-sdk/provider-stream-shared defaultToolStreamExtraParams", "openclaw/plugin-sdk/provider-stream-shared stripTrailingAnthropicAssistantPrefillWhenThinking", "openclaw/plugin-sdk/provider-stream-shared createAnthropicThinkingPrefillPayloadWrapper", "openclaw/plugin-sdk/provider-stream-shared OpenAICompatibleThinkingLevel", "openclaw/plugin-sdk/provider-stream-shared isOpenAICompatibleThinkingEnabled", "openclaw/plugin-sdk/provider-stream-shared DeepSeekV4ThinkingLevel", "openclaw/plugin-sdk/provider-stream-shared DeepSeekV4ReasoningEffort", "openclaw/plugin-sdk/provider-stream-shared createDeepSeekV4OpenAICompatibleThinkingWrapper", "openclaw/plugin-sdk/provider-stream-shared createThinkingOnlyFinalTextWrapper", "openclaw/plugin-sdk/provider-stream-shared createGoogleThinkingPayloadWrapper", "openclaw/plugin-sdk/provider-stream-shared createGoogleThinkingStreamWrapper", "openclaw/plugin-sdk/provider-model-shared isProxyReasoningUnsupportedModelHint", "openclaw/plugin-sdk/provider-model-shared OPENAI_COMPATIBLE_REPLAY_HOOKS", "openclaw/plugin-sdk/provider-model-shared ANTHROPIC_BY_MODEL_REPLAY_HOOKS", "openclaw/plugin-sdk/provider-model-shared NATIVE_ANTHROPIC_REPLAY_HOOKS", "openclaw/plugin-sdk/provider-model-shared PASSTHROUGH_GEMINI_REPLAY_HOOKS", "openclaw/plugin-sdk/provider-auth DEFAULT_COPILOT_API_BASE_URL", "openclaw/plugin-sdk/provider-auth deriveCopilotApiBaseUrlFromToken", "openclaw/plugin-sdk/provider-auth resolveCopilotApiToken", "openclaw/plugin-sdk/provider-auth-copilot-cache CachedCopilotToken", "openclaw/plugin-sdk/oauth-utils toFormUrlEncoded", "openclaw/plugin-sdk/oauth-utils generatePkceVerifierChallenge", "openclaw/plugin-sdk/provider-oauth-runtime OAuthProvider", "openclaw/plugin-sdk/provider-oauth-runtime OAuthProviderInfo"];
readonly diagnostics: readonly ["TypeScript @deprecated annotations naming provider-local replacements", "plugin boundary report compatibility inventory"];
readonly tests: readonly ["src/plugins/contracts/plugin-sdk-subpaths.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "Provider-specific auth, model, replay, OAuth, and stream shortcuts remain as deprecated SDK shims while providers move to their local APIs.";
}, {
readonly code: "message-presentation-legacy-bridges";
readonly status: "deprecated";
readonly owner: "channel";
readonly introduced: "2026-07-25";
readonly deprecated: "2026-07-25";
readonly warningStarts: "2026-07-25";
readonly removeAfter: "2026-10-01";
readonly replacement: "MessagePresentation values and channel presentation renderers";
readonly docsPath: "/plugins/sdk-migration#compatibility-policy";
readonly surfaces: readonly ["InteractiveReplyButton.value", "InteractiveReplyButton.url", "InteractiveReplyButton.webApp", "InteractiveReplyButton.web_app", "InteractiveReplyOption.value", "InteractiveReplyButton", "InteractiveReplyOption", "InteractiveReplyBlock", "InteractiveReply", "normalizeInteractiveReply", "hasInteractiveReplyBlocks", "presentationToInteractiveReply", "presentationToInteractiveControlsReply", "interactiveReplyToPresentation", "resolveInteractiveTextFallback", "src/auto-reply ReplyPayload.interactive", "openclaw/plugin-sdk/reply-payload ReplyPayload.interactive", "reduceInteractiveReply", "@openclaw/discord buildDiscordInteractiveComponents", "@openclaw/slack buildSlackInteractiveBlocks", "@openclaw/telegram buildTelegramInteractiveButtons"];
readonly diagnostics: readonly ["TypeScript @deprecated annotations naming MessagePresentation replacements", "plugin boundary report compatibility inventory"];
readonly tests: readonly ["src/interactive/payload.test.ts", "src/plugin-sdk/reply-payload.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "Legacy interactive reply values and channel-specific rendering bridges remain available while producers migrate to MessagePresentation.";
}, {
readonly code: "plugin-sdk-focused-compat-aliases";
readonly status: "deprecated";
readonly owner: "sdk";
readonly introduced: "2026-07-25";
readonly deprecated: "2026-07-25";
readonly warningStarts: "2026-07-25";
readonly removeAfter: "2026-10-01";
readonly replacement: "the focused replacement named by each TypeScript @deprecated annotation";
readonly docsPath: "/plugins/sdk-migration#compatibility-policy";
readonly surfaces: readonly ["openclaw/plugin-sdk/acp-runtime __testing", "openclaw/plugin-sdk/approval-reaction-runtime", "openclaw/plugin-sdk/channel-inbound BuildChannelTurnContextParams", "openclaw/plugin-sdk/channel-inbound BuiltChannelTurnContext", "openclaw/plugin-sdk/channel-inbound buildChannelTurnContext", "openclaw/plugin-sdk/channel-inbound finalizeChannelInboundContext", "openclaw/plugin-sdk/channel-inbound filterChannelTurnSupplementalContext", "openclaw/plugin-sdk/channel-send-result ChannelSendRawResult", "openclaw/plugin-sdk/command-auth", "openclaw/plugin-sdk/command-auth ResolveSenderCommandAuthorizationParams", "openclaw/plugin-sdk/command-auth resolveCommandAuthorizedFromAuthorizers", "openclaw/plugin-sdk/command-auth CommandAuthorizationRuntime", "openclaw/plugin-sdk/command-auth ResolveSenderCommandAuthorizationWithRuntimeParams", "openclaw/plugin-sdk/command-auth resolveDirectDmAuthorizationOutcome", "openclaw/plugin-sdk/command-auth resolveSenderCommandAuthorizationWithRuntime", "openclaw/plugin-sdk/command-auth resolveSenderCommandAuthorization", "openclaw/plugin-sdk/keyed-async-queue KeyedAsyncQueue.getTailMapForTesting", "openclaw/plugin-sdk/persistent-dedupe PersistentDedupeLegacyPathOptions.lockOptions", "openclaw/plugin-sdk/retry-runtime createTelegramRetryRunner", "openclaw/plugin-sdk/ssrf-policy SsrfPolicyOptions.allowPrivateNetwork", "openclaw/plugin-sdk/ssrf-policy ssrfPolicyFromAllowPrivateNetwork", "openclaw/plugin-sdk/tts-runtime TtsSynthesisStreamResult", "openclaw/plugin-sdk/tts-runtime TtsRuntimeFacade._test"];
readonly diagnostics: readonly ["TypeScript @deprecated annotations naming focused replacements", "plugin boundary report compatibility inventory"];
readonly tests: readonly ["src/plugin-sdk/channel-inbound.test.ts", "src/plugin-sdk/command-auth.test.ts", "src/plugin-sdk/ssrf-policy.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "Focused SDK compatibility aliases remain available through a dated window while callers adopt their annotated replacements.";
}, {
readonly code: "agent-harness-terminal-result-aliases";
readonly status: "deprecated";
readonly owner: "agent-runtime";
readonly introduced: "2026-07-25";
readonly deprecated: "2026-07-25";
readonly warningStarts: "2026-07-25";
readonly removeAfter: "2026-10-01";
readonly replacement: "AgentHarnessAttemptResult.terminal and AgentHarnessDeliveryDefaults.visibleReplies";
readonly docsPath: "/plugins/sdk-agent-harness";
readonly surfaces: readonly ["AgentHarnessAttemptResult.aborted", "AgentHarnessAttemptResult.externalAbort", "AgentHarnessAttemptResult.timedOut", "AgentHarnessAttemptResult.idleTimedOut", "AgentHarnessAttemptResult.timedOutDuringCompaction", "AgentHarnessAttemptResult.timedOutDuringToolExecution", "AgentHarnessAttemptResult.timedOutByRunBudget", "AgentHarnessAttemptResult.promptError", "AgentHarnessAttemptResult.promptErrorSource", "AgentHarnessDeliveryDefaults.sourceVisibleReplies"];
readonly diagnostics: readonly ["TypeScript @deprecated annotations on agent harness result and delivery defaults", "plugin boundary report compatibility inventory"];
readonly tests: readonly ["src/agents/harness/settled-turn-finalization-result.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "Agent harness result booleans and sourceVisibleReplies remain available while harnesses migrate to terminal outcomes and visibleReplies.";
}, {
readonly code: "official-plugin-export-aliases";
readonly status: "deprecated";
readonly owner: "channel";
readonly introduced: "2026-07-25";
readonly deprecated: "2026-07-25";
readonly warningStarts: "2026-07-25";
readonly removeAfter: "2026-10-01";
readonly replacement: "the canonical testing export, MessagePresentation renderers, and host-owned timeout/runtime behavior";
readonly docsPath: "/plugins/compatibility#current-compatibility-areas";
readonly surfaces: readonly ["@openclaw/google-meet __testing", "@openclaw/discord buildDiscordInteractiveComponents", "@openclaw/discord normalizeDiscordListenerTimeoutMs", "@openclaw/discord normalizeDiscordInboundWorkerTimeoutMs", "@openclaw/discord isAbortError", "@openclaw/discord runDiscordTaskWithTimeout", "@openclaw/slack buildSlackInteractiveBlocks"];
readonly diagnostics: readonly ["TypeScript @deprecated annotations on published official-plugin exports", "plugin boundary report compatibility inventory"];
readonly tests: readonly ["extensions/google-meet/index.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "Published Google Meet testing, channel presentation, and Discord timeout aliases remain available while consumers move to their canonical exports and host-owned behavior.";
}, {
readonly code: "memory-host-compatibility-aliases";
readonly status: "deprecated";
readonly owner: "sdk";
readonly introduced: "2026-07-25";
readonly deprecated: "2026-07-25";
readonly warningStarts: "2026-07-25";
readonly removeAfter: "2026-10-01";
readonly replacement: "canonical memory cache/FTS tables and getRuntimeConfig or caller-provided config";
readonly docsPath: "/plugins/sdk-migration#compatibility-policy";
readonly surfaces: readonly ["@openclaw/memory-host-sdk ensureMemoryIndexSchema.embeddingCacheTable", "@openclaw/memory-host-sdk ensureMemoryIndexSchema.ftsTable", "@openclaw/memory-host-sdk/runtime-core loadConfig", "@openclaw/memory-host-sdk/host/openclaw-runtime loadConfig"];
readonly diagnostics: readonly ["TypeScript @deprecated annotations on memory-host SDK compatibility fields", "plugin boundary report memory-host SDK summary"];
readonly tests: readonly ["packages/memory-host-sdk/src/host/memory-schema.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "Memory-host cache-table overrides and runtime config reload aliases remain available while callers migrate to canonical tables and prepared config.";
}, {
readonly code: "plugin-runtime-api-compat-aliases";
readonly status: "deprecated";
readonly owner: "plugin-execution";
readonly introduced: "2026-07-25";
readonly deprecated: "2026-07-25";
readonly warningStarts: "2026-07-25";
readonly removeAfter: "2026-10-01";
readonly replacement: "the namespaced plugin API and focused runtime methods named per surface";
readonly docsPath: "/plugins/sdk-migration#compatibility-policy";
readonly surfaces: readonly ["OpenClawPluginApi.registerSessionExtension", "OpenClawPluginApi.enqueueNextTurnInjection", "OpenClawPluginApi.registerControlUiDescriptor", "OpenClawPluginApi.registerRuntimeLifecycle", "OpenClawPluginApi.registerAgentEventSubscription", "OpenClawPluginApi.emitAgentEvent", "OpenClawPluginApi.setRunContext", "OpenClawPluginApi.getRunContext", "OpenClawPluginApi.clearRunContext", "OpenClawPluginApi.registerSessionSchedulerJob", "OpenClawPluginApi.registerSessionAction", "OpenClawPluginApi.sendSessionAttachment", "OpenClawPluginApi.scheduleSessionTurn", "OpenClawPluginApi.unscheduleSessionTurnsByTag", "PluginHookContext.senderExternalId", "PluginAttachmentChannelHints.telegram", "PluginAttachmentChannelHints.slack", "AgentPromptSurfaceKind pi_main", "PluginRuntime.channel.reply.createReplyDispatcherWithTyping", "PluginRuntime.channel.reply.resolveHumanDelayConfig", "PluginRuntime.channel.reply.dispatchReplyFromConfig", "PluginRuntime.channel.reply.finalizeInboundContext", "PluginRuntime.channel.media.fetchRemoteMedia", "PluginRuntime.channel.session.resolveStorePath", "PluginRuntime.channel.session.recordInboundSession", "PluginRuntime.channel.inbound.runPreparedReply", "PluginRuntime.system.requestHeartbeatNow"];
readonly diagnostics: readonly ["TypeScript @deprecated annotations on plugin API and runtime aliases", "plugin boundary report compatibility inventory"];
readonly tests: readonly ["src/plugins/captured-registration.test.ts", "src/plugins/runtime/index.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "Flat plugin registration and broad runtime aliases remain available while plugins migrate to namespaced APIs and focused runtime methods.";
}, {
readonly code: "plugin-provider-manifest-compat-aliases";
readonly status: "deprecated";
readonly owner: "provider";
readonly introduced: "2026-07-25";
readonly deprecated: "2026-07-25";
readonly warningStarts: "2026-07-25";
readonly removeAfter: "2026-10-01";
readonly replacement: "manifest-owned plugin kind/setup metadata and model catalog registration";
readonly docsPath: "/plugins/sdk-migration#compatibility-policy";
readonly surfaces: readonly ["DefinePluginEntryOptions.kind", "SingleProviderPluginOptions.kind", "OpenClawPluginDefinition.kind", "PluginPackageChannel.cliAddOptions", "ProviderPlugin.catalog", "ProviderPlugin.staticCatalog", "ProviderPlugin.suppressBuiltInModel", "ProviderPlugin.augmentModelCatalog", "ProviderBuiltInModelSuppressionContext"];
readonly diagnostics: readonly ["TypeScript @deprecated annotations on plugin manifest and provider catalog aliases", "plugin boundary report compatibility inventory"];
readonly tests: readonly ["src/plugins/contracts/package-manifest.contract.test.ts", "src/plugins/contracts/provider-catalog-deprecation.contract.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "Runtime plugin kind/setup metadata and provider catalog hooks remain available while plugins migrate ownership into manifests and catalog registrations.";
}, {
readonly code: "media-legacy-projection";
readonly status: "deprecated";
readonly owner: "sdk";
readonly introduced: "2026-07-24";
readonly deprecated: "2026-07-24";
readonly warningStarts: "2026-07-24";
readonly removeAfter: "2026-10-01";
readonly replacement: "ordered `MsgContext.media` / `InboundMediaFacts[]`; typed hook `media` and `originalMedia`; `Attachment*` template variables; and `openclaw/plugin-sdk/media-local-roots`";
readonly docsPath: "/plugins/sdk-migration#media-legacy-projection";
readonly surfaces: readonly ["MsgContext MediaPath/MediaUrl/MediaType and plural/staging fields", "openclaw/plugin-sdk/agent-media-payload", "ChannelInboundMediaPayload and buildChannelInboundMediaPayload", "MediaPayload and buildMediaPayload", "message hook mediaPath/mediaUrl/mediaType and plural/original metadata aliases", "MediaPath/MediaUrl/MediaType/MediaDir template variables"];
readonly diagnostics: readonly ["TypeScript @deprecated annotations naming the facts-first replacement", "plugin boundary report compatibility inventory with the approved removeAfter date", "SDK, hook, and media template migration documentation"];
readonly tests: readonly ["src/sessions/user-turn-transcript.media.test.ts", "src/hooks/message-hook-mappers.test.ts", "src/media-understanding/runner.cli-audio.test.ts", "src/plugins/compat/registry.test.ts", "src/plugins/contracts/plugin-sdk-subpaths.test.ts"];
readonly releaseNote: "Legacy parallel media projections remain available as deprecated compatibility while plugins move to ordered facts, typed hook media, Attachment templates, and the focused media-local-roots SDK.";
}, {
readonly code: "memory-read-result-statusless-success";
readonly status: "deprecated";
readonly owner: "sdk";
readonly introduced: "2026-04-28";
readonly deprecated: "2026-08-19";
readonly warningStarts: "2026-08-19";
readonly removalGate: "next-plugin-sdk-major";
readonly replacement: "`MemoryReadResult` with explicit `status: \"ok\" | \"not_found\"`";
readonly docsPath: "/plugins/sdk-migration#memory-read-missing-results";
readonly surfaces: readonly ["statusless external memory manager read results"];
readonly diagnostics: readonly ["host memory-manager acquisition adapter"];
readonly tests: readonly ["src/plugins/memory-runtime.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "External memory managers must return explicit not-found status for absence; statusless results retain legacy successful-read semantics through the next Plugin SDK major.";
}, {
readonly code: "context-engine-legacy-host-param-default";
readonly status: "removed";
readonly owner: "sdk";
readonly introduced: "2026-07-29";
readonly replacement: "`ContextEngineInfo.acceptedHostParams` for restricted projection; omitted declarations receive full host params";
readonly docsPath: "/concepts/context-engine#the-contextengine-interface";
readonly surfaces: readonly ["ContextEngineInfo.acceptedHostParams and undeclared-engine default projection"];
readonly diagnostics: readonly ["plugin compatibility registry and context engine guide"];
readonly tests: readonly ["src/context-engine/host-param-projection.test.ts"];
readonly releaseNote: "The undeclared context-engine host-parameter compatibility default was removed; engines without `acceptedHostParams` now receive all current host fields.";
}, {
readonly code: "removed-global-api-provider-publication";
readonly status: "removed";
readonly owner: "sdk";
readonly introduced: "2026-05-27";
readonly replacement: "provider plugins via `api.registerProvider(...)`; host/runtime code registers against its lifecycle-owned `ApiRegistry`";
readonly docsPath: "/plugins/sdk-migration#process-global-api-provider-publication";
readonly surfaces: readonly ["openclaw/plugin-sdk/llm registerApiProvider", "openclaw/plugin-sdk/llm unregisterApiProviders"];
readonly diagnostics: readonly ["plugin SDK compatibility registry and migration guide"];
readonly tests: readonly ["src/plugins/compat/registry.test.ts"];
readonly releaseNote: "The process-global API-provider publication facade was removed; provider plugins now publish through their lifecycle-owned registration, and host runtimes register directly on their prepared ApiRegistry.";
}, {
readonly code: "legacy-deactivate-hook-alias";
readonly status: "removed";
readonly owner: "sdk";
readonly introduced: "2026-05-16";
readonly replacement: "`gateway_stop` hook";
readonly docsPath: "/plugins/sdk-migration#deactivate-hook-alias";
readonly surfaces: readonly ["api.on(\"deactivate\", ...)", "plugin typed hook registration"];
readonly diagnostics: readonly ["plugin compatibility registry and migration guide"];
readonly tests: readonly ["src/plugins/compat/registry.test.ts"];
readonly releaseNote: "The deprecated `api.on(\"deactivate\", ...)` hook alias was removed; plugins must register cleanup with `gateway_stop`.";
}, {
readonly code: "legacy-subagent-spawning-hook";
readonly status: "removed";
readonly owner: "sdk";
readonly introduced: "2026-05-30";
readonly replacement: "`subagent_spawned` for post-launch observation; core session-binding adapters for thread routing";
readonly docsPath: "/plugins/hooks#upcoming-deprecations";
readonly surfaces: readonly ["api.on(\"subagent_spawning\", ...)", "PluginHookSubagentSpawningEvent", "PluginHookSubagentSpawningResult", "SubagentLifecycleHookRunner.runSubagentSpawning"];
readonly diagnostics: readonly ["plugin compatibility registry and migration guide"];
readonly tests: readonly ["src/plugins/compat/registry.test.ts"];
readonly releaseNote: "`api.on(\"subagent_spawning\", ...)` was removed; core now owns thread-bound subagent routing, and `subagent_spawned` remains available for observation.";
}, {
readonly code: "hook-only-plugin-shape";
readonly status: "active";
readonly owner: "sdk";
readonly introduced: "2026-04-24";
readonly replacement: "explicit capability registration";
readonly docsPath: "/plugins/sdk-migration";
readonly surfaces: readonly ["plugin shape inspection", "plugins inspect", "status diagnostics"];
readonly diagnostics: readonly ["plugin compatibility notice"];
readonly tests: readonly ["src/plugins/status.test.ts", "src/plugins/contracts/shape.contract.test.ts"];
}, {
readonly code: "deprecated-memory-embedding-provider-api";
readonly status: "removed";
readonly owner: "sdk";
readonly introduced: "2026-05-21";
readonly replacement: "`api.registerEmbeddingProvider(...)` and `contracts.embeddingProviders`";
readonly docsPath: "/plugins/sdk-migration#memory-embedding-provider-api";
readonly surfaces: readonly ["api.registerMemoryEmbeddingProvider(...)", "contracts.memoryEmbeddingProviders", "openclaw/plugin-sdk/memory-core-host-engine-embeddings registerMemoryEmbeddingProvider", "plugin compatibility registry and migration guide"];
readonly diagnostics: readonly ["plugin compatibility registry and migration guide"];
readonly tests: readonly ["src/plugins/compat/registry.test.ts"];
readonly releaseNote: "Memory-specific embedding provider registration was removed; plugins now use the generic embedding provider contract.";
}, {
readonly code: "deprecated-session-store-beta5-api";
readonly status: "deprecated";
readonly owner: "sdk";
readonly introduced: "2026-05-21";
readonly deprecated: "2026-07-12";
readonly warningStarts: "2026-07-12";
readonly removeAfter: "2026-10-12";
readonly replacement: "`getSessionEntry(...)`, `listSessionEntries(...)`, and row-level session mutations";
readonly docsPath: "/plugins/sdk-migration#removed-session-and-transcript-file-apis";
readonly surfaces: readonly ["openclaw/plugin-sdk/session-store-runtime loadSessionStore", "openclaw/plugin-sdk/session-store-runtime updateSessionStore", "openclaw/plugin-sdk/session-store-runtime resolveSessionFilePath", "openclaw/plugin-sdk/session-store-runtime resolveSessionStoreEntry", "openclaw package root loadSessionStore", "openclaw package root saveSessionStore"];
readonly diagnostics: readonly ["plugin SDK deprecation"];
readonly tests: readonly ["src/plugin-sdk/session-store-runtime.test.ts", "src/index.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "The beta.5 session-store import set and package-root whole-store aliases remain available while official plugins and package consumers migrate to row-level session access.";
}, {
readonly code: "plugin-sdk-session-agent-resolution-aliases";
readonly status: "deprecated";
readonly owner: "sdk";
readonly introduced: "2026-08-29";
readonly deprecated: "2026-08-29";
readonly warningStarts: "2026-08-29";
readonly removeAfter: "2026-11-29";
readonly replacement: "`resolveSessionAgentIdsStrict` and `resolveSessionAgentIdStrict` with an explicit agent, agent-scoped session key, prepared fallback, or persisted owner";
readonly docsPath: "/plugins/compatibility#session-agent-resolution-aliases";
readonly surfaces: readonly ["openclaw/plugin-sdk/agent-scope-runtime resolveSessionAgentIds and resolveSessionAgentId", "openclaw/plugin-sdk/agent-runtime session-agent resolver aliases", "openclaw/plugin-sdk/agent-harness-runtime session-agent resolver aliases", "openclaw/plugin-sdk/memory-core-host-runtime-core session-agent resolver alias", "openclaw/plugin-sdk/memory-host-core session-agent resolver alias"];
readonly diagnostics: readonly ["TypeScript deprecated SDK alias annotations", "plugin compatibility registry"];
readonly tests: readonly ["src/plugin-sdk/agent-scope-runtime.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "Legacy Plugin SDK session-agent resolver names preserve ambient system-agent fallback while published plugins migrate to strict owner-required aliases.";
}, {
readonly code: "removed-session-transcript-file-api";
readonly status: "removed";
readonly owner: "sdk";
readonly introduced: "2026-07-01";
readonly replacement: "session identity (`sessionKey`/`sessionId`), `SessionTranscriptUpdate.target`, and Gateway/runtime session helpers";
readonly docsPath: "/plugins/sdk-migration#removed-session-and-transcript-file-apis";
readonly surfaces: readonly ["saveSessionStore", "resolveSessionTranscriptPathInDir", "resolveAndPersistSessionFile", "readLatestAssistantTextFromSessionTranscript", "SessionTranscriptUpdate.sessionFile", "sessionFiles", "transcriptPath", "sessionFile", "plugins inspect compatibility notices"];
readonly diagnostics: readonly ["plugin compatibility notice"];
readonly tests: readonly ["src/plugins/status.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "Session/transcript file APIs were removed with the SQLite session storage flip; plugins now use session identity and Gateway/runtime session helpers.";
}, {
readonly code: "hook.before_tool_call.terminal-block-approval";
readonly status: "active";
readonly owner: "agent-runtime";
readonly introduced: "2026-04-29";
readonly docsPath: "/plugins/hooks";
readonly surfaces: readonly ["before_tool_call block result", "before_tool_call approval result"];
readonly diagnostics: readonly ["hook runner contract probe"];
readonly tests: readonly ["src/plugins/hooks.security.test.ts", "src/agents/agent-tools.before-tool-call.e2e.test.ts"];
}, {
readonly code: "hook.llm-observer.privacy-payload";
readonly status: "active";
readonly owner: "agent-runtime";
readonly introduced: "2026-04-29";
readonly docsPath: "/plugins/hooks";
readonly surfaces: readonly ["llm_input", "llm_output", "agent_end", "allowConversationAccess"];
readonly diagnostics: readonly ["conversation access hook contract probe"];
readonly tests: readonly ["src/agents/cli-runner.reliability.test.ts", "src/config/schema.help.quality.test.ts"];
}, {
readonly code: "api.capture.runtime-registrars";
readonly status: "active";
readonly owner: "plugin-execution";
readonly introduced: "2026-04-29";
readonly docsPath: "/plugins/architecture-internals";
readonly surfaces: readonly ["createCapturedPluginRegistration", "capturePluginRegistration", "OpenClawPluginApi"];
readonly diagnostics: readonly ["runtime registration capture contract probe"];
readonly tests: readonly ["src/plugins/captured-registration.test.ts"];
}, {
readonly code: "channel.runtime.envelope-config-metadata";
readonly status: "active";
readonly owner: "channel";
readonly introduced: "2026-04-29";
readonly docsPath: "/plugins/sdk-channel-plugins";
readonly surfaces: readonly ["api.registerChannel", "channel setup metadata", "channel message envelope"];
readonly diagnostics: readonly ["channel runtime contract probe"];
readonly tests: readonly ["src/plugin-sdk/channel-entry-contract.test.ts", "src/plugins/captured-registration.test.ts"];
}, {
readonly code: "whatsapp-web-inbound-flat-message-aliases";
readonly status: "removed";
readonly owner: "channel";
readonly introduced: "2026-05-30";
readonly replacement: "WhatsApp `WebInboundCallbackMessage` nested contexts: `event`, `payload`, `quote`, `group`, and `platform`";
readonly docsPath: "/plugins/compatibility";
readonly surfaces: readonly ["@openclaw/whatsapp WebInboundMessage flat fields", "WhatsApp monitorWebInbox onMessage callback", "WhatsApp monitorWebChannel listenerFactory injected messages"];
readonly diagnostics: readonly ["plugin compatibility registry and compatibility guide"];
readonly tests: readonly ["src/plugins/compat/registry.test.ts"];
readonly releaseNote: "WhatsApp WebInboundMessage flat fields were removed; callbacks now receive only nested inbound contexts.";
}, {
readonly code: "whatsapp-web-inbound-admission-top-level-fields";
readonly status: "removed";
readonly owner: "channel";
readonly introduced: "2026-06-14";
readonly replacement: "WhatsApp `WebInboundMessage.admission` fields: `conversation.id`, `accountId`, `ingress.decision`, and `conversation.kind`";
readonly docsPath: "/plugins/compatibility";
readonly surfaces: readonly ["@openclaw/whatsapp WebInboundMessage top-level admission fields", "WhatsApp monitorWebInbox onMessage callback", "WhatsApp monitorWebChannel listenerFactory injected messages"];
readonly diagnostics: readonly ["plugin compatibility registry and compatibility guide"];
readonly tests: readonly ["src/plugins/compat/registry.test.ts"];
readonly releaseNote: "WhatsApp WebInboundMessage top-level admission fields were removed; callbacks now read the canonical admission envelope.";
}, {
readonly code: "sdk-untrusted-context-identifier-aliases";
readonly status: "deprecated";
readonly owner: "sdk";
readonly introduced: "2026-07-22";
readonly deprecated: "2026-07-22";
readonly warningStarts: "2026-07-22";
readonly removeAfter: "2026-09-08";
readonly replacement: "`MsgContext.ChannelPromptContext`, `MsgContext.ChannelStructuredContext`, `ChannelStructuredContextEntry`, `SupplementalContextFacts.channelStructuredContext`, and `buildChannelMetadata`";
readonly docsPath: "/plugins/compatibility";
readonly surfaces: readonly ["openclaw/plugin-sdk reply-runtime MsgContext.UntrustedContext and UntrustedStructuredContext", "openclaw/plugin-sdk reply-runtime UntrustedStructuredContextEntry", "openclaw/plugin-sdk channel-inbound SupplementalContextFacts.untrustedContext", "openclaw/plugin-sdk security-runtime buildUntrustedChannelMetadata"];
readonly diagnostics: readonly ["TypeScript deprecated SDK alias annotations"];
readonly tests: readonly ["src/auto-reply/reply/inbound-context.test.ts"];
readonly releaseNote: "Untrusted-named prompt-context SDK identifiers remain wired as deprecated aliases of the channel-named fields while plugins migrate.";
}, {
readonly code: "bundled-channel-sdk-compat-facades";
readonly status: "active";
readonly owner: "sdk";
readonly introduced: "2026-04-28";
readonly replacement: "generic channel SDK subpaths or plugin-local `api.ts` / `runtime-api.ts` barrels for new plugins";
readonly docsPath: "/plugins/sdk-overview";
readonly surfaces: readonly ["openclaw/plugin-sdk/discord component message helpers", "openclaw/plugin-sdk/telegram-account resolveTelegramAccount"];
readonly diagnostics: readonly ["plugin SDK compatibility registry"];
readonly tests: readonly ["src/plugin-sdk/discord.test.ts", "src/plugin-sdk/telegram-account.test.ts", "src/plugins/contracts/plugin-sdk-package-contract-guardrails.test.ts"];
}, {
readonly code: "channel-explicit-target-parser";
readonly status: "removed";
readonly owner: "sdk";
readonly introduced: "2026-04-28";
readonly replacement: "`messaging.targetResolver` for target normalization and `messaging.resolveOutboundSessionRoute` for session/thread identity";
readonly docsPath: "/plugins/sdk-migration";
readonly surfaces: readonly ["ChannelMessagingAdapter.parseExplicitTarget", "openclaw/plugin-sdk/channel-route ChannelRouteExplicitTarget", "openclaw/plugin-sdk/channel-route ChannelRouteExplicitTargetParser", "openclaw/plugin-sdk/channel-route resolveChannelRouteTargetWithParser"];
readonly diagnostics: readonly ["plugin SDK compatibility warning"];
readonly tests: readonly ["src/channels/plugins/contracts/test-helpers/surface-contract-suite.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "The deprecated channel explicit-target parser was removed; plugins must normalize targets with `messaging.targetResolver` and project session identity with `messaging.resolveOutboundSessionRoute`.";
}, {
readonly code: "channel-messaging-targets-subpath";
readonly status: "removed";
readonly owner: "sdk";
readonly introduced: "2026-04-28";
readonly replacement: "`openclaw/plugin-sdk/channel-targets`";
readonly docsPath: "/plugins/sdk-migration";
readonly surfaces: readonly ["openclaw/plugin-sdk/messaging-targets"];
readonly diagnostics: readonly ["plugin SDK compatibility warning"];
readonly tests: readonly ["src/plugins/compat/registry.test.ts", "src/plugins/contracts/plugin-sdk-subpaths.test.ts"];
readonly releaseNote: "The deprecated `openclaw/plugin-sdk/messaging-targets` subpath was removed; import target helpers from `openclaw/plugin-sdk/channel-targets`.";
}, {
readonly code: "bundled-plugin-allowlist";
readonly status: "active";
readonly owner: "config";
readonly introduced: "2026-04-24";
readonly replacement: "manifest-owned plugin enablement and scoped load plans";
readonly docsPath: "/plugins/architecture";
readonly surfaces: readonly ["plugins.allow", "bundled provider startup", "plugins status"];
readonly diagnostics: readonly ["plugin status report"];
readonly tests: readonly ["src/plugins/status.test.ts", "src/plugins/config-state.test.ts"];
}, {
readonly code: "bundled-plugin-enablement";
readonly status: "active";
readonly owner: "config";
readonly introduced: "2026-04-24";
readonly replacement: "manifest-owned plugin defaults and scoped load plans";
readonly docsPath: "/plugins/architecture";
readonly surfaces: readonly ["plugins.entries", "bundled provider startup", "plugins status"];
readonly diagnostics: readonly ["plugin status report"];
readonly tests: readonly ["src/plugins/status.test.ts", "src/plugins/config-state.test.ts"];
}, {
readonly code: "activation-agent-harness-hint";
readonly status: "active";
readonly owner: "plugin-execution";
readonly introduced: "2026-04-24";
readonly replacement: "top-level `cliBackends[]` for CLI aliases and future `agentRuntime` ownership metadata";
readonly docsPath: "/plugins/manifest";
readonly surfaces: readonly ["activation.onAgentHarnesses", "activation planner"];
readonly diagnostics: readonly ["activation plan compat reason"];
readonly tests: readonly ["src/plugins/activation-planner.test.ts"];
}, {
readonly code: "activation-provider-hint";
readonly status: "active";
readonly owner: "plugin-execution";
readonly introduced: "2026-04-24";
readonly replacement: "`providers[]` manifest ownership";
readonly docsPath: "/plugins/manifest";
readonly surfaces: readonly ["activation.onProviders", "activation planner"];
readonly diagnostics: readonly ["activation plan compat reason"];
readonly tests: readonly ["src/plugins/activation-planner.test.ts"];
}, {
readonly code: "activation-channel-hint";
readonly status: "active";
readonly owner: "plugin-execution";
readonly introduced: "2026-04-24";
readonly replacement: "`channels[]` manifest ownership";
readonly docsPath: "/plugins/manifest";
readonly surfaces: readonly ["activation.onChannels", "activation planner"];
readonly diagnostics: readonly ["activation plan compat reason"];
readonly tests: readonly ["src/plugins/activation-planner.test.ts"];
}, {
readonly code: "activation-command-hint";
readonly status: "active";
readonly owner: "plugin-execution";
readonly introduced: "2026-04-24";
readonly replacement: "`commandAliases` or command contribution metadata";
readonly docsPath: "/plugins/manifest";
readonly surfaces: readonly ["activation.onCommands", "activation planner"];
readonly diagnostics: readonly ["activation plan compat reason"];
readonly tests: readonly ["src/plugins/activation-planner.test.ts"];
}, {
readonly code: "activation-route-hint";
readonly status: "active";
readonly owner: "plugin-execution";
readonly introduced: "2026-04-24";
readonly replacement: "HTTP route contribution metadata";
readonly docsPath: "/plugins/manifest";
readonly surfaces: readonly ["activation.onRoutes", "activation planner"];
readonly diagnostics: readonly ["activation plan compat reason"];
readonly tests: readonly ["src/plugins/activation-planner.test.ts"];
}, {
readonly code: "activation-config-path-hint";
readonly status: "active";
readonly owner: "plugin-execution";
readonly introduced: "2026-04-27";
readonly replacement: "manifest contribution ownership for root config surfaces";
readonly docsPath: "/plugins/manifest";
readonly surfaces: readonly ["activation.onConfigPaths", "startup plugin selection"];
readonly diagnostics: readonly ["activation plan compat reason"];
readonly tests: readonly ["src/plugins/channel-plugin-ids.test.ts"];
}, {
readonly code: "activation-capability-hint";
readonly status: "active";
readonly owner: "plugin-execution";
readonly introduced: "2026-04-24";
readonly replacement: "manifest contribution ownership";
readonly docsPath: "/plugins/manifest";
readonly surfaces: readonly ["activation.onCapabilities", "activation planner"];
readonly diagnostics: readonly ["activation plan compat reason"];
readonly tests: readonly ["src/plugins/activation-planner.test.ts"];
}, {
readonly code: "agent-harness-sdk-alias";
readonly status: "deprecated";
readonly owner: "agent-runtime";
readonly introduced: "2026-04-24";
readonly deprecated: "2026-04-25";
readonly warningStarts: "2026-04-25";
readonly replacement: "none yet; retain until a harness subpath ships and external migration is proven";
readonly docsPath: "/plugins/sdk-agent-harness";
readonly surfaces: readonly ["openclaw/plugin-sdk/agent-harness", "openclaw/plugin-sdk/agent-harness-runtime"];
readonly diagnostics: readonly ["plugin SDK compatibility warning"];
readonly tests: readonly ["src/plugins/contracts/plugin-sdk-subpaths.test.ts"];
}, {
readonly code: "embedded-pi-agent-sdk-aliases";
readonly status: "removed";
readonly owner: "agent-runtime";
readonly introduced: "2026-05-21";
readonly replacement: "`runEmbeddedAgent` and `EmbeddedAgent*` SDK/runtime names";
readonly docsPath: "/plugins/sdk-runtime";
readonly surfaces: readonly ["api.runtime.agent.runEmbeddedPiAgent", "openclaw/extension-api runEmbeddedPiAgent", "openclaw/plugin-sdk/agent-harness-runtime EmbeddedPi* aliases"];
readonly diagnostics: readonly ["plugin SDK compatibility registry"];
readonly tests: readonly ["src/plugins/runtime/index.test.ts", "src/plugins/contracts/plugin-sdk-subpaths.test.ts"];
readonly releaseNote: "The legacy `runEmbeddedPiAgent` and `EmbeddedPi*` plugin aliases were removed; plugins must use the neutral embedded-agent names.";
}, {
readonly code: "plugin-sdk-shipped-channel-setup-exports";
readonly status: "deprecated";
readonly owner: "channel";
readonly introduced: "2026-07-23";
readonly deprecated: "2026-07-23";
readonly warningStarts: "2026-07-23";
readonly replacement: "retain until supported published packages migrate to plugin-owned config schemas plus generic `openclaw/plugin-sdk/channel-config-schema` and `openclaw/plugin-sdk/setup-runtime` primitives";
readonly docsPath: "/plugins/sdk-migration#published-channel-setup-compatibility";
readonly surfaces: readonly ["openclaw/plugin-sdk/bundled-channel-config-schema SlackConfigSchema", "openclaw/plugin-sdk/bundled-channel-config-schema DiscordConfigSchema", "openclaw/plugin-sdk/bundled-channel-config-schema SignalConfigSchema", "openclaw/plugin-sdk/bundled-channel-config-schema MSTeamsConfigSchema", "openclaw/plugin-sdk/setup-runtime createLegacyCompatChannelDmPolicy", "openclaw/plugin-sdk/setup-runtime promptLegacyChannelAllowFromForAccount"];
readonly diagnostics: readonly ["repository deprecated API usage guard for core and bundled plugins; no external runtime import warning"];
readonly tests: readonly ["src/plugin-sdk/shipped-channel-compat.test.ts", "src/plugins/compat/registry.test.ts"];
readonly releaseNote: "Published OpenClaw channel packages through 2026.7.1 remain loadable while they migrate to plugin-owned config and setup helpers.";
}, {
readonly code: "generated-bundled-channel-config-fallback";
readonly status: "active";
readonly owner: "channel";
readonly introduced: "2026-04-24";
readonly replacement: "manifest registry `channelConfigs` metadata";
readonly docsPath: "/plugins/manifest";
readonly surfaces: readonly ["generated bundled channel config metadata", "channel config validation"];
readonly diagnostics: readonly ["channel config metadata fallback"];
readonly tests: readonly ["src/plugins/contracts/config-footprint-guardrails.test.ts"];
}, {
readonly code: "setup-runtime-fallback";
readonly status: "active";
readonly owner: "setup";
readonly introduced: "2026-04-24";
readonly replacement: "`setup.requiresRuntime: false` with complete setup descriptors";
readonly docsPath: "/plugins/manifest#setup-reference";
readonly surfaces: readonly ["setup-api runtime fallback", "setup.requiresRuntime omitted"];
readonly diagnostics: readonly ["setup registry runtime diagnostic"];
readonly tests: readonly ["src/plugins/setup-registry.test.ts", "src/plugins/setup-registry.runtime.test.ts"];
}];
//#endregion
//#region src/plugins/compat/registry.d.ts
type PluginCompatCode = (typeof PLUGIN_COMPAT_RECORDS)[number]["code"];
//#endregion
//#region src/infra/npm-registry-spec.d.ts
/**
* Parsed registry-only npm spec accepted by plugin install flows.
* Selectors are limited to exact versions and dist-tags; URL/git/file specs
* are rejected before they can execute on the gateway host.
*/
type ParsedRegistryNpmSpec = {
name: string;
raw: string;
selector?: string;
selectorKind: "none" | "exact-version" | "tag";
selectorIsPrerelease: boolean;
};
//#endregion
//#region src/plugins/install-source-info.types.d.ts
/** Warning emitted while describing plugin package install source metadata. */
type PluginInstallSourceWarning = "invalid-clawhub-spec" | "invalid-npm-spec" | "invalid-default-choice" | "default-choice-missing-source" | "clawhub-spec-floating" | "npm-integrity-without-source" | "npm-spec-floating" | "npm-spec-missing-integrity" | "npm-spec-package-name-mismatch";
/** Pinning state for npm plugin install metadata. */
type PluginInstallNpmPinState = "exact-with-integrity" | "exact-without-integrity" | "floating-with-integrity" | "floating-without-integrity";
/** Parsed npm install source metadata for a plugin package. */
type PluginInstallNpmSourceInfo = {
spec: string;
packageName: string;
expectedPackageName?: string;
selector?: string;
selectorKind: ParsedRegistryNpmSpec["selectorKind"];
exactVersion: boolean;
expectedIntegrity?: string;
pinState: PluginInstallNpmPinState;
};
/** Parsed local install source metadata for a plugin package. */
type PluginInstallLocalSourceInfo = {
path: string;
};
/** Parsed ClawHub install source metadata for a plugin package. */
type PluginInstallClawHubSourceInfo = {
spec: string;
packageName: string;
version?: string;
exactVersion: boolean;
};
/** Parsed plugin install sources plus validation warnings. */
type PluginInstallSourceInfo = {
defaultChoice?: PluginPackageInstall["defaultChoice"];
clawhub?: PluginInstallClawHubSourceInfo;
npm?: PluginInstallNpmSourceInfo;
local?: PluginInstallLocalSourceInfo;
warnings: readonly PluginInstallSourceWarning[];
};
//#endregion
//#region src/plugins/installed-plugin-index-hash.d.ts
/** File metadata signature used to skip unchanged installed plugin files. */
type InstalledPluginFileSignature = {
size: number;
mtimeMs: number;
ctimeMs?: number;
};
//#endregion
//#region src/plugins/installed-plugin-index-types.d.ts
/** Schema version for installed plugin index files. */
declare const INSTALLED_PLUGIN_INDEX_VERSION = 1;
declare const INSTALLED_PLUGIN_INDEX_MIGRATION_VERSION = 1;
type InstalledPluginIndexRefreshReason = "missing" | "stale-manifest" | "stale-package" | "source-changed" | "policy-changed" | "migration" | "host-contract-changed" | "compat-registry-changed" | "manual";
type InstalledPluginStartupInfo = {
sidecar: boolean;
memory: boolean;
agentHarnesses: readonly string[];
/**
* Manifest activation.onConfigPaths copied into the installed index for
* pre-manifest startup scoping. Missing on older persisted index files.
*/
configPaths?: readonly string[];
};
type InstalledPluginContributionInfo = {
channels: readonly string[];
channelConfigs: readonly string[];
providers: readonly string[];
modelCatalogProviders: readonly string[];
modelSupportPrefixes: readonly string[];
modelSupportPatterns: readonly string[];
autoEnableProviderIds: readonly string[];
commandAliases: readonly string[];
contracts: Readonly<Record<string, readonly string[]>>;
};
type InstalledPluginInstallRecordInfo = Pick<PluginInstallRecord, "source" | "spec" | "sourcePath" | "installPath" | "version" | "resolvedName" | "resolvedVersion" | "resolvedSpec" | "integrity" | "shasum" | "resolvedAt" | "installedAt" | "clawhubUrl" | "clawhubPackage" | "clawhubFamily" | "clawhubChannel" | "clawhubTrustDisposition" | "clawhubTrustScanStatus" | "clawhubTrustModerationState" | "clawhubTrustReasons" | "clawhubTrustPending" | "clawhubTrustStale" | "clawhubTrustCheckedAt" | "clawhubTrustAcknowledgedAt" | "artifactKind" | "artifactFormat" | "npmIntegrity" | "npmShasum" | "npmTarballName" | "clawpackSha256" | "clawpackSpecVersion" | "clawpackManifestSha256" | "clawpackSize" | "gitUrl" | "gitRef" | "gitCommit" | "marketplaceName" | "marketplaceSource" | "marketplacePlugin" | "acceptedSurface" | "acceptedSurfaceHash" | "acceptedSurfaceAt" | "acceptedSurfaceIntegrity">;
type InstalledPluginPackageChannelInfo = PluginPackageChannel;
/** One manifest-backed plugin entry in the generated installed plugin index. */
type InstalledPluginIndexRecord = {
pluginId: string;
packageName?: string;
packageVersion?: string;
/**
* Legacy embedded install record accepted when reading earlier index files.
* New index writes keep install records in InstalledPluginIndex.installRecords.
*/
installRecord?: InstalledPluginInstallRecordInfo;
/** Hash of the top-level installRecords entry; used to detect source-changed invalidation. */
installRecordHash?: string;
/**
* Package-authored openclaw.install metadata. This describes catalog/package
* install intent and must not be treated as the durable install record.
*/
packageInstall?: PluginInstallSourceInfo;
packageChannel?: InstalledPluginPackageChannelInfo;
packageBuild?: OpenClawPackageBuild;
manifestPath: string;
manifestHash: string;
/** Hash of the doctor-contract artifact selected by the runtime resolver. */
doctorContractHash?: string;
doctorContractFile?: InstalledPluginFileSignature;
manifestFile?: InstalledPluginFileSignature;
format?: PluginManifestRecord["format"];
bundleFormat?: PluginManifestRecord["bundleFormat"];
source?: string;
setupSource?: string;
packageJson?: {
path: string;
hash: string;
fileSignature?: InstalledPluginFileSignature;
};
rootDir: string;
origin: PluginManifestRecord["origin"];
enabled: boolean;
enabledByDefault?: boolean;
enabledByDefaultOnPlatforms?: readonly string[];
syntheticAuthRefs?: readonly string[];
startup: InstalledPluginStartupInfo;
contributions?: InstalledPluginContributionInfo;
compat: readonly PluginCompatCode[];
};
/** Full installed-index payload used by control-plane plugin registry loading. */
type InstalledPluginIndex = {
version: typeof INSTALLED_PLUGIN_INDEX_VERSION;
warning?: string;
hostContractVersion: string;
compatRegistryVersion: string;
migrationVersion: typeof INSTALLED_PLUGIN_INDEX_MIGRATION_VERSION;
policyHash: string;
generatedAtMs: number;
/** Selected workspace used to build this index. Missing for omitted and legacy scopes. */
workspaceDir?: string;
refreshReason?: InstalledPluginIndexRefreshReason;
installRecords: Readonly<Record<string, InstalledPluginInstallRecordInfo>>;
plugins: readonly InstalledPluginIndexRecord[];
diagnostics: readonly PluginDiagnostic[];
};
//#endregion
//#region src/plugins/plugin-registry-snapshot.types.d.ts
/** Source class for plugin registry snapshots used by diagnostics and cache decisions. */
type PluginRegistrySnapshotSource = "provided" | "persisted" | "derived";
type PluginRegistryDifference = {
pluginId: string;
persistedSource: string | null;
derivedSource: string | null;
};
type PluginRegistrySnapshotDiagnostic = {
level: "info" | "warn";
code: "persisted-registry-missing" | "persisted-registry-stale-policy" | "persisted-registry-stale-source";
message: string;
differences?: readonly PluginRegistryDifference[];
};
//#endregion
//#region src/plugins/plugin-metadata-snapshot.types.d.ts
type PluginProviderAuthAliasCandidate = {
plugin: PluginManifestRecord;
target: string;
/** First eligible declaration owns public map order, even if a later candidate wins. */
order: number;
};
type PluginMetadataSnapshotOwnerMaps = {
channels: ReadonlyMap<string, readonly string[]>;
channelConfigs: ReadonlyMap<string, readonly string[]>;
providers: ReadonlyMap<string, readonly string[]>;
modelCatalogProviders: ReadonlyMap<string, readonly string[]>;
cliBackends: ReadonlyMap<string, readonly string[]>;
setupProviders: ReadonlyMap<string, readonly string[]>;
commandAliases: ReadonlyMap<string, readonly string[]>;
contracts: ReadonlyMap<string, readonly string[]>;
/** Empty views must not fall through to process-current model normalization policies. */
modelIdNormalizationPolicies: ReadonlyMap<string, PluginManifestModelIdNormalizationProvider>;
providerAuthAliases?: ReadonlyMap<string, readonly PluginProviderAuthAliasCandidate[]>;
providerEndpoints?: readonly PluginManifestProviderEndpoint[];
providerRequests?: ReadonlyMap<string, PluginManifestProviderRequestProvider>;
};
type PluginMetadataSnapshotMetrics = {
registrySnapshotMs: number;
manifestRegistryMs: number;
ownerMapsMs: number;
totalMs: number;
indexPluginCount: number;
manifestPluginCount: number;
};
type PluginMetadataSnapshot = {
policyHash: string;
configFingerprint?: string;
pluginIds?: readonly string[];
registrySource?: PluginRegistrySnapshotSource;
workspaceDir?: string;
index: InstalledPluginIndex;
/** The original workspace-scoped index described by registrySource, before runtime unions. */
registryIndex: InstalledPluginIndex;
registryDiagnostics: readonly PluginRegistrySnapshotDiagnostic[];
manifestRegistry: PluginManifestRegistry;
/** Independently validated bundled owners, including packages shadowed by active plugins. */
bundledManifestRegistry?: PluginManifestRegistry;
plugins: readonly PluginManifestRecord[];
diagnostics: readonly PluginDiagnostic[];
byPluginId: ReadonlyMap<string, PluginManifestRecord>;
normalizePluginId: (pluginId: string) => string;
owners: PluginMetadataSnapshotOwnerMaps;
metrics: PluginMetadataSnapshotMetrics;
discovery?: PluginDiscoveryResult;
};
type PluginMetadataRegistryView = Pick<PluginMetadataSnapshot, "index" | "manifestRegistry" | "discovery">;
//#endregion
//#region src/config/runtime-snapshot.d.ts
type ConfigWriteAfterWrite = {
mode: "auto";
} | {
mode: "restart";
reason: string;
} | {
mode: "none";
reason: string;
};
type ConfigWriteFollowUp = {
mode: "auto";
requiresRestart: false;
} | {
mode: "none";
reason: string;
requiresRestart: false;
} | {
mode: "restart";
reason: string;
requiresRestart: true;
};
//#endregion
//#region src/config/mutation-types.d.ts
/** Selects whether a mutation starts from runtime or source config shape. */
type ConfigMutationBase = "runtime" | "source";
//#endregion
//#region src/config/mutate.d.ts
type ConfigReplaceResult = {
path: string;
previousHash: string | null;
snapshot: ConfigFileSnapshot;
nextConfig: OpenClawConfig;
persistedHash: string | null;
afterWrite: ConfigWriteAfterWrite;
followUp: ConfigWriteFollowUp;
};
//#endregion
//#region src/config/paths.d.ts
/**
* State directory for mutable data (sessions, logs, caches).
* Can be overridden via OPENCLAW_STATE_DIR.
* Default: ~/.openclaw
*/
declare function resolveStateDir(env?: NodeJS.ProcessEnv, homedir?: () => string): string;
//#endregion
//#region extensions/a2a/src/runtime.d.ts
declare const setA2aChannelRuntime: (next: PluginRuntime) => void, getA2aChannelRuntime: () => PluginRuntime;
//#endregion
//#region src/plugins/provider-auth-types.d.ts
/** Provider secret input modes: inline plaintext or external secret reference. */
type SecretInputMode = "plaintext" | "ref";
//#endregion
//#region src/commands/daemon-runtime.d.ts
type GatewayDaemonRuntime = "bun" | "node";
//#endregion
//#region src/commands/onboard-types.d.ts
type OnboardMode = "local" | "remote";
/**
* Auth choices are plugin-owned contract ids plus a few legacy aliases that
* are normalized elsewhere (for example `oauth` -> `setup-token`).
*/
type BuiltInAuthChoice =
/** @deprecated Use `setup-token`. */
"oauth" | "setup-token" | "token" | "apiKey" | "custom-api-key" | "skip";
type AuthChoice = BuiltInAuthChoice | (string & {});
type GatewayAuthChoice = "token" | "password";
type ResetScope = "config" | "config+creds+sessions" | "full";
type GatewayBind = "loopback" | "lan" | "auto" | "custom" | "tailnet";
type TailscaleMode = "off" | "serve" | "funnel";
declare const NODE_MANAGER_CHOICES: readonly ["npm", "pnpm", "bun"];
type NodeManagerChoice = (typeof NODE_MANAGER_CHOICES)[number];
declare const ONBOARD_FLOWS: readonly ["quickstart", "advanced", "manual", "import"];
type OnboardFlow = (typeof ONBOARD_FLOWS)[number];
type OnboardDynamicProviderOptions = {
/**
* Provider-specific non-interactive auth flags are plugin-owned and keyed by
* manifest `providerAuthChoices[].optionKey` values.
*/
[optionKey: string]: unknown;
};
/** Parsed options accepted by `openclaw onboard`. */
type OnboardOptions = OnboardDynamicProviderOptions & {
mode?: OnboardMode;
/** "manual" is an alias for "advanced". */
flow?: OnboardFlow;
/** Force the classic multi-step interactive wizard instead of guided setup. */
classic?: boolean;
/** Force the terminal hatch instead of the guided browser handoff. */
tui?: boolean;
workspace?: string;
/** Name for the first persisted agent; defaults to `main` in non-interactive setup. */
agentName?: string;
nonInteractive?: boolean;
/** Required for non-interactive setup; skips the interactive risk prompt when true. */
acceptRisk?: boolean;
reset?: boolean;
resetScope?: ResetScope;
authChoice?: AuthChoice;
/** Used when `authChoice=token` in non-interactive mode. */
tokenProvider?: string;
/** Used when `authChoice=token` in non-interactive mode. */
token?: string;
/** Used when `authChoice=token` in non-interactive mode. */
tokenProfileId?: string;
/** Used when `authChoice=token` in non-interactive mode. */
tokenExpiresIn?: string;
/** API key persistence mode for setup flows (default: plaintext). */
secretInputMode?: SecretInputMode;
arceeaiApiKey?: string;
cloudflareAiGatewayAccountId?: string;
cloudflareAiGatewayGatewayId?: string;
customBaseUrl?: string;
customApiKey?: string;
lmstudioApiKey?: string;
customModelId?: string;
customProviderId?: string;
customCompatibility?: "openai" | "openai-responses" | "anthropic";
customImageInput?: boolean;
gatewayPort?: number;
gatewayBind?: GatewayBind;
gatewayAuth?: GatewayAuthChoice;
gatewayToken?: string;
gatewayTokenRefEnv?: string;
gatewayPassword?: string;
tailscale?: TailscaleMode;
installDaemon?: boolean;
daemonRuntime?: GatewayDaemonRuntime;
skipChannels?: boolean;
skipSkills?: boolean;
skipBootstrap?: boolean;
skipSearch?: boolean;
skipHealth?: boolean;
skipUi?: boolean;
suppressGatewayTokenOutput?: boolean;
skipHooks?: boolean;
nodeManager?: NodeManagerChoice;
remoteUrl?: string;
remoteToken?: string;
remotePassword?: string;
importFrom?: string;
importSource?: string;
importSecrets?: boolean;
json?: boolean;
};
//#endregion
//#region src/agents/tools/common.d.ts
type AgentToolWithMeta<TParameters extends TSchema, TResult> = AgentTool<TParameters, TResult> & {
displaySummary?: string;
/** Keep this tool model-visible; hidden catalog bridges cannot preserve its result contract. */
catalogMode?: "direct-only";
/** Gateway client capabilities required before this tool can be assembled. */
requiredClientCaps?: string[];
prepareBeforeToolCallParams?: (params: unknown, ctx: {
toolCallId?: string;
hookContext?: unknown;
signal?: AbortSignal;
}) => unknown;
finalizeBeforeToolCallParams?: (params: unknown, preparedParams: unknown) => unknown;
};
type ErasedAgentToolExecute = {
execute(this: void, toolCallId: string, params: unknown, signal?: AbortSignal, onUpdate?: AgentToolUpdateCallback): Promise<AgentToolResult<unknown>>;
};
type AnyAgentTool = Omit<AgentTool, "execute"> & ErasedAgentToolExecute & {
displaySummary?: string;
/** Keep this tool model-visible; hidden catalog bridges cannot preserve its result contract. */
catalogMode?: "direct-only";
/** Gateway client capabilities required before this tool can be assembled. */
requiredClientCaps?: string[];
prepareBeforeToolCallParams?: AgentToolWithMeta<TSchema, unknown>["prepareBeforeToolCallParams"];
finalizeBeforeToolCallParams?: AgentToolWithMeta<TSchema, unknown>["finalizeBeforeToolCallParams"];
};
//#endregion
//#region src/infra/agent-events.d.ts
/** Stream name for agent events delivered to gateway listeners and plugin host hooks. */
type AgentEventStream = "lifecycle" | "tool" | "assistant" | "usage" | "error" | "item" | "plan" | "approval" | "command_output" | "patch" | "compaction" | "thinking" | (string & {});
/** Enriched event delivered to subscribers after sequencing and context stamping. */
type AgentEventPayload = {
runId: string;
seq: number;
stream: AgentEventStream;
ts: number;
data: Record<string, unknown>;
/** Internal, non-enumerable gateway lifecycle generation that owns this run. */
lifecycleGeneration?: string;
sessionKey?: string;
/**
* sessionId the run was bound to when it started. Lifecycle persistence uses
* this to reject terminal events from a pre-`sessions.reset` run that would
* otherwise clobber the rotated session row resolved by the shared sessionKey.
*/
sessionId?: string;
agentId?: string;
};
/** Subscribes to sequenced agent events; returns an unsubscribe callback. */
declare function onAgentEvent(listener: (evt: AgentEventPayload) => void): () => void;
//#endregion
//#region src/plugins/host-hooks.d.ts
/** Reason passed to plugin cleanup callbacks when host-owned state changes. */
type PluginHostCleanupReason = "disable" | "reset" | "delete" | "restart";
type PluginSessionExtensionProjectionContext = {
sessionKey: string;
sessionId?: string;
state: PluginJsonValue | undefined;
};
/** Session extension registration owned by a plugin namespace. */
type PluginSessionExtensionRegistration = {
namespace: string;
description: string;
project?: (ctx: PluginSessionExtensionProjectionContext) => PluginJsonValue | undefined;
cleanup?: (ctx: {
reason: PluginHostCleanupReason;
sessionKey?: string;
}) => void | Promise<void>;
/**
* When set, after every successful `patchSessionExtension` the projected
* value is mirrored to `SessionEntry[<slotKey>]` so non-plugin readers
* can consume the typed slot without reaching into
* `pluginExtensions[pluginId][namespace]`.
*
* The slot is a read-only mirror: writes always go through
* `patchSessionExtension`; the host overwrites the slot value on every
* subsequent patch.
*/
sessionEntrySlotKey?: string;
/**
* Optional JSON-compatible schema describing the projected slot value.
* Purely informational at this layer; clients may use it to validate the
* mirrored slot against a contract.
*/
sessionEntrySlotSchema?: PluginJsonValue;
};
type PluginToolPolicyDecision = PluginHookBeforeToolCallResult | {
allow?: boolean;
reason?: string;
};
type PluginTrustedToolPolicyRegistration = {
id: string;
description: string;
matcher?: PluginToolMatcher;
evaluate: (event: PluginHookBeforeToolCallEvent, ctx: PluginHookToolContext) => PluginToolPolicyDecision | void | Promise<PluginToolPolicyDecision | void>;
};
type PluginToolMetadataRegistration = {
toolName: string;
displayName?: string;
description?: string;
risk?: "low" | "medium" | "high";
tags?: string[];
};
type PluginControlUiTabGroup = "control" | "agent";
type PluginControlUiDescriptor = {
id: string;
/** "tab" adds a sidebar tab; "widget" advertises a trusted dashboard renderer. */
surface: "session" | "tool" | "run" | "settings" | "tab" | "widget";
label: string;
description?: string;
/** Bundled plugins may claim their matching native route as `route:<pluginId>`. */
placement?: string;
schema?: PluginJsonValue;
requiredScopes?: OperatorScope[];
/** Icon name hint for tab descriptors; unknown names fall back to a generic icon. */
icon?: string;
/**
* Gateway HTTP path (e.g. /plugins/<id>/panel) rendered in a sandboxed frame
* when the Control UI has no bundled view for this tab.
*/
path?: string;
/** Sidebar group for tab descriptors; defaults to "control". */
group?: PluginControlUiTabGroup;
/** Sort order among plugin tabs; lower renders first. */
order?: number;
};
type PluginSessionActionContext = {
pluginId: string;
actionId: string;
sessionKey?: string;
agentId?: string;
payload?: PluginJsonValue;
client?: {
connId?: string;
scopes: string[];
};
};
type PluginSessionActionResult = {
ok?: true;
result?: PluginJsonValue;
reply?: PluginJsonValue;
continueAgent?: boolean;
} | {
ok: false;
error: string;
code?: string;
details?: PluginJsonValue;
};
type PluginSessionActionRegistration = {
id: string;
description?: string;
schema?: PluginJsonValue;
requiredScopes?: OperatorScope[];
handler: (ctx: PluginSessionActionContext) => PluginSessionActionResult | void | Promise<PluginSessionActionResult | void>;
};
type PluginRuntimeLifecycleRegistration = {
id: string;
description?: string;
cleanup?: (ctx: {
reason: PluginHostCleanupReason;
sessionKey?: string;
runId?: string;
}) => void | Promise<void>;
};
type PluginAgentEventSubscriptionRegistration = {
id: string;
description?: string;
streams?: AgentEventStream[];
handle: (event: AgentEventPayload, ctx: {
getRunContext: <T extends PluginJsonValue = PluginJsonValue>(namespace: string) => T | undefined;
setRunContext: (namespace: string, value: PluginJsonValue) => void;
clearRunContext: (namespace?: string) => void;
}) => void | Promise<void>;
};
type PluginAgentEventEmitParams = {
runId: string;
stream: AgentEventStream;
data: PluginJsonValue;
sessionKey?: string;
};
type PluginAgentEventEmitResult = {
emitted: true;
stream: AgentEventStream;
} | {
emitted: false;
reason: string;
};
type PluginRunContextPatch = {
runId: string;
namespace: string;
value?: PluginJsonValue;
unset?: boolean;
};
type PluginRunContextGetParams = {
runId: string;
namespace: string;
};
type PluginSessionSchedulerJobRegistration = {
id: string;
sessionKey: string;
kind: string;
description?: string;
cleanup?: (ctx: {
reason: PluginHostCleanupReason;
sessionKey: string;
jobId: string;
}) => void | Promise<void>;
};
type PluginSessionSchedulerJobHandle = {
id: string;
pluginId: string;
sessionKey: string;
kind: string;
};
type PluginSessionAttachmentFile = {
path: string;
};
type PluginAttachmentChannelHints = {
parseMode?: "HTML";
silent?: boolean;
/** Require host detection to match this MIME before forcing document delivery. */
forceDocumentMime?: string;
threadId?: string | number;
/** @deprecated Put portable attachment hints directly on `channelHints`. */
telegram?: {
parseMode?: "HTML";
disableNotification?: boolean;
/**
* Require host-side detection to match this MIME before forcing document delivery.
* Mismatched files are rejected before the outbound adapter is called.
*/
forceDocumentMime?: string;
};
/** @deprecated Use `channelHints.threadId`. */
slack?: {
threadTs?: string;
};
};
type PluginSessionAttachmentCaptionFormat = "plain" | "html" | "markdown";
type PluginSessionAttachmentParams = {
sessionKey: string;
files: PluginSessionAttachmentFile[];
text?: string;
threadId?: string | number;
forceDocument?: boolean;
maxBytes?: number;
captionFormat?: PluginSessionAttachmentCaptionFormat;
channelHints?: PluginAttachmentChannelHints;
};
type PluginSessionAttachmentResult = {
ok: true;
channel: string;
deliveredTo: string;
count: number;
} | {
ok: false;
error: string;
};
type PluginSessionTurnScheduleCommonParams = {
sessionKey: string;
message: string;
agentId?: string;
deliveryMode?: "none" | "announce";
name?: string;
/** Optional cleanup tag. Reserved cron-name delimiters like `:` are rejected. */
tag?: string;
};
type PluginSessionTurnScheduleParams = ({
at: string | number | Date;
deleteAfterRun?: boolean;
} & PluginSessionTurnScheduleCommonParams) | ({
delayMs: number;
deleteAfterRun?: boolean;
} & PluginSessionTurnScheduleCommonParams) | ({
cron: string;
tz?: string;
deleteAfterRun?: false;
} & PluginSessionTurnScheduleCommonParams);
type PluginSessionTurnUnscheduleByTagParams = {
sessionKey: string;
tag: string;
};
type PluginSessionTurnUnscheduleByTagResult = {
removed: number;
failed: number;
};
//#endregion
//#region src/plugins/logger-types.d.ts
/** Logger passed into plugin registration, services, and CLI surfaces. */
type PluginLogger = {
debug?: (message: string) => void;
info: (message: string) => void;
warn: (message: string) => void;
error: (message: string) => void;
};
//#endregion
//#region src/plugins/provider-config-context.types.d.ts
/**
* Provider-owned config normalization for `models.providers.<id>` entries.
*
* Use this for provider-specific config cleanup that should stay with the
* plugin rather than in core config-policy tables.
*/
type ProviderNormalizeConfigContext = {
provider: string;
providerConfig: ModelProviderConfig;
};
/**
* Provider-owned env/config auth marker resolution for `models.providers`.
*
* Use this when a provider resolves auth from env vars that do not follow the
* generic API-key conventions.
*/
type ProviderResolveConfigApiKeyContext = {
provider: string;
env: NodeJS.ProcessEnv;
};
/**
* Provider-owned config-default application input.
*
* Use this when a provider needs to add global config defaults that depend on
* provider auth mode or provider-specific model families.
*/
type ProviderApplyConfigDefaultsContext = {
provider: string;
config: OpenClawConfig;
env: NodeJS.ProcessEnv;
};
//#endregion
//#region src/plugins/provider-external-auth.types.d.ts
type ProviderAuthOptionBag = {
token?: string;
tokenProvider?: string;
secretInputMode?: SecretInputMode;
[key: string]: unknown;
};
/** Context for resolving synthetic provider credentials from config. */
type ProviderResolveSyntheticAuthContext = {
config?: OpenClawConfig;
provider: string;
providerConfig?: ModelProviderConfig;
};
/** Synthetic provider credential returned by plugin auth helpers. */
type ProviderSyntheticAuthResult = {
apiKey: string;
source: string;
mode: Exclude<ModelProviderAuthMode, "aws-sdk">;
expiresAt?: number;
};
/** Context for resolving external provider auth profiles. */
type ProviderResolveExternalAuthProfilesContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
env: NodeJS.ProcessEnv;
store: AuthProfileStore;
};
/** External auth profile credential resolved for a provider. */
type ProviderExternalAuthProfile = {
profileId: string;
credential: OAuthCredential$1;
persistence?: "runtime-only" | "persisted";
};
//#endregion
//#region src/llm/stream.d.ts
declare function completeSimple<TApi extends Api>(model: Model<TApi>, context: Context, options?: SimpleStreamOptions, assertCurrent?: () => void): Promise<AssistantMessage>;
//#endregion
//#region src/plugins/provider-runtime-model.types.d.ts
/**
* Fully-resolved runtime model shape used after provider/plugin-owned
* discovery, overrides, and compat normalization.
*/
type ProviderRuntimeModel = Omit<Model, "compat"> & {
compat?: ModelCompatConfig;
contextWindows?: ModelCatalogContextWindowOption[];
contextWindowDefault?: string;
contextTokens?: number;
/** Host-resolved provenance for the top-level wire output cap. */
maxTokensSource?: "configured" | "discovered";
params?: Record<string, unknown>;
requestTimeoutMs?: number;
mediaInput?: ModelMediaInputConfig;
};
//#endregion
//#region src/plugins/provider-thinking.types.d.ts
/**
* Provider-owned thinking policy input.
*
* Used by shared `/think`, ACP controls, and directive parsing to ask a
* provider whether a model supports special reasoning UX such as adaptive,
* xhigh, max, or a binary on/off toggle.
*/
type ProviderThinkingPolicyContext = {
provider: string;
modelId: string;
};
type ProviderThinkingModelCompat = {
thinkingFormat?: string;
supportedReasoningEfforts?: readonly string[] | null;
};
/**
* Provider-owned default thinking policy input.
*
* `reasoning` is the merged catalog hint for the selected model when one is
* available. Providers can use it to keep "reasoning model => low" behavior
* without re-reading the catalog themselves.
*
* `compat` carries model-level request contract facts for the selected model
* when available. Providers can use it to expose model-specific thinking
* profiles only when the configured payload style supports them.
*/
type ProviderDefaultThinkingPolicyContext = ProviderThinkingPolicyContext & {
/** Effective agent runtime selected for this model, when known. */
agentRuntime?: string | null;
/** API adapter id from the selected catalog route, when known. */
api?: string | null;
reasoning?: boolean;
params?: Record<string, unknown>;
compat?: ProviderThinkingModelCompat | null;
};
type ProviderThinkingLevelId = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive" | "max" | "ultra";
type ProviderThinkingLevel = {
id: ProviderThinkingLevelId;
/**
* Optional display label. Use this when the stored value differs from the
* provider-facing UX, for example binary providers storing `low` but showing
* `on`.
*/
label?: string;
/**
* Relative strength used when downgrading a stored level that the selected
* model no longer supports.
*/
rank?: number;
};
type ProviderThinkingProfile = {
levels: ProviderThinkingLevel[] | ReadonlyArray<ProviderThinkingLevel>;
defaultLevel?: ProviderThinkingLevelId | null;
/**
* Some bundled providers have model-specific thinking contracts that are more
* current than cached generic catalog metadata. Keep this opt-in so
* `reasoning: false` remains authoritative for ordinary catalog entries.
*/
preserveWhenCatalogReasoningFalse?: boolean;
};
/** Prepared provider policy ownership, without the broader Gateway registry contract. */
type ProviderThinkingRegistry = {
providers: ReadonlyArray<{
provider: {
id: string;
aliases?: string[];
hookAliases?: string[];
resolveThinkingProfile?: (context: ProviderDefaultThinkingPolicyContext) => ProviderThinkingProfile | null | undefined;
};
}>;
};
//#endregion
//#region src/agents/conversation-recall.types.d.ts
type ConversationRecallContext = {
/** Private conversation that requested this bounded recall pass. */
anchorSessionKey: string;
/** Only same-agent private transcript hits may pass. */
scope: "same-agent-private";
/** Product-only recall searches sessions; advanced recall keeps configured corpora. */
corpus: "sessions" | "configured";
};
//#endregion
//#region src/agents/tool-fs-policy.types.d.ts
type PreparedSessionPermissionPolicy = Readonly<{
root: string;
mode: SessionPermissionMode;
}>;
/** Filesystem policy for agent tools that can touch local paths. */
type ToolFsPolicy = {
workspaceOnly: boolean;
root?: string;
};
//#endregion
//#region src/plugins/tool-types.d.ts
type OpenClawPluginActiveModelContext = {
provider?: string;
modelId?: string;
modelRef?: string;
};
/** Current-turn outbound delivery capability bound to the host-selected route and media policy. */
type OpenClawPluginToolDelivery = {
send: (params: {
text?: string;
mediaUrl?: string;
}) => Promise<void>;
};
/** Trusted execution context passed to plugin-owned agent tool factories. */
type OpenClawPluginToolContext = {
config?: OpenClawConfig;
/** Active runtime-resolved config snapshot when one is available. */
runtimeConfig?: OpenClawConfig;
/** Returns the latest runtime-resolved config snapshot for long-lived tool definitions. */
getRuntimeConfig?: () => OpenClawConfig | undefined;
/** Effective filesystem policy for the active tool run. */
fsPolicy?: ToolFsPolicy;
workspaceDir?: string;
agentDir?: string;
agentId?: string;
sessionKey?: string;
/** Ephemeral session UUID - regenerated on /new and /reset. Use for per-conversation isolation. */
sessionId?: string;
/** Out-of-band plugin-owned bindings attached by the current run initiator. */
toolBindings?: Readonly<Record<string, unknown>>;
/** Host-prepared repository identities for project-aware tool behavior. */
activeProjectKeys?: readonly string[];
/** Trusted runtime-only authorization for one bounded cross-conversation recall pass. */
conversationRecall?: ConversationRecallContext;
/**
* Runtime-supplied active model metadata for informational use, diagnostics,
* and plugin-owned policy decisions. This is not a security boundary against
* the local operator, installed plugin code, or a modified OpenClaw runtime.
*/
activeModel?: OpenClawPluginActiveModelContext;
browser?: {
sandboxBridgeUrl?: string;
allowHostControl?: boolean;
};
messageChannel?: string;
agentAccountId?: string;
/** Trusted provider auth availability from the active auth profile store. */
hasAuthForProvider?: (providerId: string) => boolean;
/** Resolves an API key from the active auth profile store when available. */
resolveApiKeyForProvider?: (providerId: string) => Promise<string | undefined>;
/** Trusted ambient delivery route for the active agent/session. */
deliveryContext?: DeliveryContext;
/** Host-bound current-route delivery. Retained copies fail after the owning turn closes. */
delivery?: OpenClawPluginToolDelivery;
/** Trusted platform-native conversation id for the active inbound turn. */
nativeChannelId?: string;
/** Trusted sender id from inbound context (runtime-provided, not tool args). */
requesterSenderId?: string;
/** Trusted owner bit from inbound context (runtime-provided, not tool args). */
senderIsOwner?: boolean;
/**
* Server-owned origin for this operation. Missing values are delegated.
* Plugins must use it only for conversation-read visibility policy.
*/
conversationReadOrigin?: ConversationReadInvocationOrigin;
sandboxed?: boolean;
/**
* True for explicit one-shot local CLI runs that must release plugin-owned
* process resources before the command exits.
*/
oneShotCliRun?: boolean;
};
type OpenClawPluginToolFactory$1 = (ctx: OpenClawPluginToolContext) => AnyAgentTool | AnyAgentTool[] | null | undefined;
type OpenClawPluginToolOptions = {
name?: string;
names?: string[];
optional?: boolean;
};
type OpenClawPluginHookOptions = {
entry?: HookEntry;
name?: string;
description?: string;
register?: boolean;
};
//#endregion
//#region src/plugins/types.node-host.d.ts
type OpenClawPluginNodeHostCommandAvailabilityContext = {
/** Node-local configuration used to build this host's Gateway declaration. */
config: OpenClawConfig;
/** Node-host process environment. */
env: NodeJS.ProcessEnv;
};
type OpenClawPluginNodeHostCommandIo = {
emitChunk(chunk: string): Promise<void>;
onInput(callback: (payloadJSON: string) => void): void;
/** Complete binary messages; available when the node host dispatches a duplex command. */
frames?: {
send(message: Uint8Array): Promise<void>;
onMessage(listener: (message: Uint8Array) => void | Promise<void>): () => void;
};
signal: AbortSignal;
};
type OpenClawPluginNodeWorkspace = {
workspaceDir: string;
environmentId: string;
sessionId: string;
ownerEpoch: number;
sessionKey: string;
};
type OpenClawPluginNodeHostCommandContext = {
/** Emit one node-owned event through the active Gateway connection. */
sendNodeEvent(event: string, payload: unknown): Promise<unknown>;
/** Agent session that owns this invocation, when the caller supplied one. */
sessionKey?: string;
/** Aborts when the Gateway cancels this specific node-host invocation. */
signal?: AbortSignal;
/** Prepare local exec policy; call the returned guard synchronously immediately before spawn. */
prepareExecAuthorization?: (source: "human-approved" | "session-full") => () => void;
/** Protect one exact node-owned placement workspace for this invocation's lifetime. */
acquireManagedWorkspace?: (request: OpenClawPluginNodeWorkspace) => {
workspaceDir: string;
release: () => void;
};
};
type OpenClawPluginNodeHostCommandBase = {
command: string;
cap?: string;
dangerous?: boolean;
/** Settle node-local startup before the initial capability declaration; registration stays synchronous. */
prepare?: (context: OpenClawPluginNodeHostCommandAvailabilityContext) => Promise<void> | void;
/** Return false to omit this command and capability from the node declaration. */
isAvailable?: (context: OpenClawPluginNodeHostCommandAvailabilityContext) => boolean;
/** Watch node-local availability and request a fresh Gateway declaration. */
watchAvailability?: (context: OpenClawPluginNodeHostCommandAvailabilityContext, onChange: () => void) => (() => void) | void;
/** Release command-owned state when the active Gateway connection closes. */
onDisconnect?: () => Promise<void> | void;
/** Optional Computer Use declaration published with this command's node manifest. */
computerUse?: (context: OpenClawPluginNodeHostCommandAvailabilityContext) => unknown;
agentTool?: {
name: string;
description: string;
parameters?: Record<string, unknown>;
/** Platforms where this tool is allowlisted by default; omit for explicit config only. */
defaultPlatforms?: Array<"ios" | "android" | "macos" | "windows" | "linux" | "unknown">;
mcp?: {
server: string;
tool: string;
};
};
};
type OpenClawPluginNodeHostCommand = OpenClawPluginNodeHostCommandBase & {
duplex?: boolean;
handle: (paramsJSON?: string | null, io?: OpenClawPluginNodeHostCommandIo, context?: OpenClawPluginNodeHostCommandContext) => Promise<string>;
};
//#endregion
//#region src/secrets/runtime-web-tools.types.d.ts
/** Diagnostic codes emitted while selecting runtime web search/fetch providers. */
type RuntimeWebDiagnosticCode = "WEB_SEARCH_PROVIDER_INVALID_AUTODETECT" | "WEB_SEARCH_AUTODETECT_SELECTED" | "WEB_SEARCH_KEY_UNRESOLVED_FALLBACK_USED" | "WEB_SEARCH_KEY_UNRESOLVED_NO_FALLBACK" | "WEB_FETCH_PROVIDER_INVALID_AUTODETECT" | "WEB_FETCH_AUTODETECT_SELECTED" | "WEB_FETCH_PROVIDER_KEY_UNRESOLVED_FALLBACK_USED" | "WEB_FETCH_PROVIDER_KEY_UNRESOLVED_NO_FALLBACK";
/** User-facing diagnostic attached to runtime web-tool metadata. */
type RuntimeWebDiagnostic = {
code: RuntimeWebDiagnosticCode;
message: string;
path?: string;
};
/** Runtime selection metadata for the web search tool. */
type RuntimeWebSearchMetadata = {
/** Provider explicitly configured in source config, before auto-detect fallback. */
providerConfigured?: string;
providerSource: "configured" | "auto-detect" | "none";
/** Provider that runtime calls should use after config validation and credential lookup. */
selectedProvider?: string;
/** Source that supplied the selected provider credential, or why it is unavailable. */
selectedProviderKeySource?: "config" | "secretRef" | "env" | "missing";
/** Perplexity transport chosen from provider config or runtime default. */
perplexityTransport?: "search_api" | "chat_completions";
diagnostics: RuntimeWebDiagnostic[];
};
/** Runtime selection metadata for the web fetch tool. */
type RuntimeWebFetchMetadata = {
/** Provider explicitly configured in source config, before auto-detect fallback. */
providerConfigured?: string;
providerSource: "configured" | "auto-detect" | "none";
/** Provider that runtime calls should use after config validation and credential lookup. */
selectedProvider?: string;
/** Source that supplied the selected provider credential, or why it is unavailable. */
selectedProviderKeySource?: "config" | "secretRef" | "env" | "missing";
diagnostics: RuntimeWebDiagnostic[];
};
//#endregion
//#region src/plugins/web-provider-types.d.ts
type WebSearchProviderId = string;
type WebFetchProviderId = string;
type WebSearchProviderToolDefinition = {
description: string;
parameters: TSchema;
execute: (args: Record<string, unknown>, context?: WebSearchProviderToolExecutionContext) => Promise<Record<string, unknown>>;
};
type WebFetchProviderToolDefinition = {
description: string;
parameters: TSchema;
execute: (args: Record<string, unknown>, context?: {
signal?: AbortSignal;
}) => Promise<Record<string, unknown>>;
};
type WebSearchProviderContext = {
config?: OpenClawConfig;
searchConfig?: Record<string, unknown>;
runtimeMetadata?: RuntimeWebSearchMetadata;
agentDir?: string;
};
type WebSearchProviderToolExecutionContext = {
signal?: AbortSignal;
};
type WebFetchProviderContext = {
config?: OpenClawConfig;
fetchConfig?: Record<string, unknown>;
runtimeMetadata?: RuntimeWebFetchMetadata;
};
type WebSearchCredentialResolutionSource = "config" | "secretRef" | "env" | "missing";
type WebSearchProviderConfiguredCredentialFallback = {
path: string;
value: unknown;
};
type WebFetchProviderConfiguredCredentialFallback = {
path: string;
value: unknown;
};
type WebSearchRuntimeMetadataContext = {
config?: OpenClawConfig;
searchConfig?: Record<string, unknown>;
runtimeMetadata?: RuntimeWebSearchMetadata;
resolvedCredential?: {
value?: string;
source: WebSearchCredentialResolutionSource;
fallbackEnvVar?: string;
};
};
type WebSearchProviderSetupContext = {
config: OpenClawConfig;
runtime: RuntimeEnv;
prompter: WizardPrompter;
quickstartDefaults?: boolean;
secretInputMode?: SecretInputMode;
};
type WebFetchCredentialResolutionSource = "config" | "secretRef" | "env" | "missing";
type WebFetchRuntimeMetadataContext = {
config?: OpenClawConfig;
fetchConfig?: Record<string, unknown>;
runtimeMetadata?: RuntimeWebFetchMetadata;
resolvedCredential?: {
value?: string;
source: WebFetchCredentialResolutionSource;
fallbackEnvVar?: string;
};
};
type WebSearchProviderPlugin$1 = {
id: WebSearchProviderId;
label: string;
hint: string;
onboardingScopes?: readonly "text-inference"[];
requiresCredential?: boolean;
credentialLabel?: string;
envVars: string[];
/** Optional model-provider auth profile id that can satisfy this web provider without a tool-specific API key. */
authProviderId?: string;
placeholder: string;
signupUrl: string;
docsUrl?: string;
/** Optional note shown before credential collection for provider-specific prerequisites. */
credentialNote?: string;
autoDetectOrder?: number;
credentialPath: string;
inactiveSecretPaths?: string[];
getCredentialValue: (searchConfig?: Record<string, unknown>) => unknown;
setCredentialValue: (searchConfigTarget: Record<string, unknown>, value: unknown) => void;
getConfiguredCredentialValue?: (config?: OpenClawConfig) => unknown;
setConfiguredCredentialValue?: (configTarget: OpenClawConfig, value: unknown) => void;
getConfiguredCredentialFallback?: (config?: OpenClawConfig) => WebSearchProviderConfiguredCredentialFallback | undefined;
applySelectionConfig?: (config: OpenClawConfig) => OpenClawConfig;
runSetup?: (ctx: WebSearchProviderSetupContext) => OpenClawConfig | Promise<OpenClawConfig>;
resolveRuntimeMetadata?: (ctx: WebSearchRuntimeMetadataContext) => Partial<RuntimeWebSearchMetadata> | Promise<Partial<RuntimeWebSearchMetadata>>;
createTool: (ctx: WebSearchProviderContext) => WebSearchProviderToolDefinition | null;
};
type PluginWebSearchProviderEntry = WebSearchProviderPlugin$1 & {
pluginId: string;
};
type WebFetchProviderPlugin$1 = {
id: WebFetchProviderId;
label: string;
hint: string;
requiresCredential?: boolean;
credentialLabel?: string;
envVars: string[];
placeholder: string;
signupUrl: string;
docsUrl?: string;
autoDetectOrder?: number;
credentialPath: string;
inactiveSecretPaths?: string[];
getCredentialValue: (fetchConfig?: Record<string, unknown>) => unknown;
setCredentialValue: (fetchConfigTarget: Record<string, unknown>, value: unknown) => void;
getConfiguredCredentialValue?: (config?: OpenClawConfig) => unknown;
setConfiguredCredentialValue?: (configTarget: OpenClawConfig, value: unknown) => void;
getConfiguredCredentialFallback?: (config?: OpenClawConfig) => WebFetchProviderConfiguredCredentialFallback | undefined;
applySelectionConfig?: (config: OpenClawConfig) => OpenClawConfig;
resolveRuntimeMetadata?: (ctx: WebFetchRuntimeMetadataContext) => Partial<RuntimeWebFetchMetadata> | Promise<Partial<RuntimeWebFetchMetadata>>;
createTool: (ctx: WebFetchProviderContext) => WebFetchProviderToolDefinition | null;
};
//#endregion
//#region src/plugins/types.mcp-connection.d.ts
/** Plugin-owned MCP server connection resolver contracts. */
/**
* Trusted runtime identity for per-requester MCP connection resolution.
* Only host-provided fields; plugins must not invent sender identity.
* Future trusted fields (for example cron/subagent user context) can be added additively.
*/
type McpServerConnectionResolveContext = {
/** Trusted message sender id. Required; runs without one fail closed. */
requesterSenderId: string;
/** Channel account id that received the message. */
agentAccountId?: string;
/** Message channel id (for example telegram or slack). */
messageChannel?: string;
};
/** Transport connection resolved for one requester-scoped MCP server. */
type McpServerConnectionResolved = {
url: string;
/** Per-user credentials; never logged, fingerprinted, or persisted by core. */
headers?: Record<string, string>;
};
/**
* Plugin-owned connection resolver for a statically declared MCP server.
* Server name/tool surface stay static; only the transport is requester-bound.
*/
type OpenClawPluginMcpServerConnectionResolver = {
/** Server name matching `mcp.servers` / bundle MCP declaration. */
serverName: string;
resolve: (ctx: McpServerConnectionResolveContext) => McpServerConnectionResolved | null | Promise<McpServerConnectionResolved | null>;
};
/** Registry entry for a plugin MCP server connection resolver. */
type PluginMcpServerConnectionResolverRegistration = {
pluginId: string;
pluginName?: string;
resolver: OpenClawPluginMcpServerConnectionResolver;
source: string;
rootDir?: string;
};
//#endregion
//#region packages/media-generation-core/src/normalization.d.ts
/** Primitive value types reported in media generation normalization metadata. */
type MediaNormalizationValue = string | number | boolean;
/** Requested/applied value pair plus provenance for a normalized media option. */
type MediaNormalizationEntry<TValue extends MediaNormalizationValue> = {
requested?: TValue;
applied?: TValue;
derivedFrom?: string;
supportedValues?: readonly TValue[];
};
//#endregion
//#region src/infra/net/ssrf.d.ts
type LookupFn = (hostname: string, options: {
all: true;
}) => Promise<LookupAddress[]>;
type SsrFPolicy = {
allowPrivateNetwork?: boolean;
dangerouslyAllowPrivateNetwork?: boolean;
allowRfc2544BenchmarkRange?: boolean;
/**
* Exempt addresses in `fc00::/7` (IPv6 Unique Local Address block, RFC 4193)
* from the SSRF private-IP block. Companion to
* `allowRfc2544BenchmarkRange` for fake-ip proxy stacks (sing-box, Clash,
* Surge) that resolve foreign domains to ULA addresses alongside the IPv4
* 198.18.0.0/15 range. See #74351.
*/
allowIpv6UniqueLocalRange?: boolean;
allowedHostnames?: string[];
/**
* Exact HTTP origins that may promote only the current request hostname into
* `allowedHostnames`. Evaluated per URL inside the redirect loop.
*/
allowedOrigins?: string[];
hostnameAllowlist?: string[];
/** Deny exact hosts or wildcard subdomains; "*.example.com" excludes the apex. */
blockedHostnames?: string[];
};
type PinnedHostnameOverride = {
hostname: string;
addresses: string[];
};
type PinnedDispatcherPolicy = {
mode: "direct";
connect?: Record<string, unknown>;
pinnedHostname?: PinnedHostnameOverride;
} | {
mode: "env-proxy";
connect?: Record<string, unknown>;
proxyTls?: Record<string, unknown>;
pinnedHostname?: PinnedHostnameOverride;
} | {
mode: "explicit-proxy";
proxyUrl: string;
allowPrivateProxy?: boolean;
proxyTls?: Record<string, unknown>;
pinnedHostname?: PinnedHostnameOverride;
};
//#endregion
//#region src/image-generation/types.d.ts
/** Non-empty binary image asset returned by an image-generation provider. */
type GeneratedImageAsset = {
buffer: Buffer;
mimeType: string;
fileName?: string;
revisedPrompt?: string;
metadata?: Record<string, unknown>;
};
type ImageGenerationResolution = "1K" | "2K" | "4K";
type ImageGenerationQuality = "low" | "medium" | "high" | "auto";
type ImageGenerationOutputFormat = "png" | "jpeg" | "webp";
type ImageGenerationBackground = "transparent" | "opaque" | "auto";
type ImageGenerationOpenAIBackground = ImageGenerationBackground;
type ImageGenerationOpenAIModeration = "low" | "auto";
type ImageGenerationOpenAIOptions = {
background?: ImageGenerationOpenAIBackground;
moderation?: ImageGenerationOpenAIModeration;
outputCompression?: number;
user?: string;
};
type ImageGenerationProviderOptions = Record<string, unknown> & {
openai?: ImageGenerationOpenAIOptions;
};
type ImageGenerationIgnoredOverrideKey = "size" | "aspectRatio" | "resolution" | "quality" | "outputFormat" | "background";
type ImageGenerationIgnoredOverride = {
key: ImageGenerationIgnoredOverrideKey;
value: string;
};
type ImageGenerationSourceImage = {
buffer: Buffer;
mimeType: string;
fileName?: string;
metadata?: Record<string, unknown>;
};
type ImageGenerationProviderConfiguredContext = {
cfg?: OpenClawConfig;
agentDir?: string;
};
/** Runtime request passed to an image-generation provider implementation. */
type ImageGenerationRequest = {
provider: string;
model: string;
prompt: string;
cfg: OpenClawConfig;
agentDir?: string;
authStore?: AuthProfileStore;
timeoutMs?: number;
count?: number;
size?: string;
aspectRatio?: string;
resolution?: ImageGenerationResolution;
quality?: ImageGenerationQuality;
outputFormat?: ImageGenerationOutputFormat;
background?: ImageGenerationBackground;
inputImages?: ImageGenerationSourceImage[];
providerOptions?: ImageGenerationProviderOptions;
ssrfPolicy?: SsrFPolicy;
};
type ImageGenerationResult = {
images: GeneratedImageAsset[];
model?: string;
metadata?: Record<string, unknown>;
};
type ImageGenerationModeCapabilities = {
maxCount?: number;
supportsSize?: boolean;
supportsAspectRatio?: boolean;
supportsResolution?: boolean;
};
type ImageGenerationEditCapabilities = ImageGenerationModeCapabilities & {
enabled: boolean;
maxInputImages?: number;
maxInputImagesByModel?: Readonly<Record<string, number>>;
maxInputImagesByModelPrefix?: Readonly<Record<string, number>>;
};
type ImageGenerationGeometryCapabilities = {
sizes?: string[];
sizesByModel?: Record<string, string[]>;
aspectRatios?: string[];
aspectRatiosByModel?: Record<string, string[]>;
resolutions?: ImageGenerationResolution[];
resolutionsByModel?: Record<string, ImageGenerationResolution[]>;
};
type ImageGenerationOutputCapabilities = {
qualities?: ImageGenerationQuality[];
formats?: ImageGenerationOutputFormat[];
backgrounds?: ImageGenerationBackground[];
};
type ImageGenerationNormalization = {
size?: MediaNormalizationEntry<string>;
aspectRatio?: MediaNormalizationEntry<string>;
resolution?: MediaNormalizationEntry<ImageGenerationResolution>;
};
type ImageGenerationProviderCapabilities = {
generate: ImageGenerationModeCapabilities;
edit: ImageGenerationEditCapabilities;
geometry?: ImageGenerationGeometryCapabilities;
output?: ImageGenerationOutputCapabilities;
};
type ImageGenerationProvider = {
id: string;
aliases?: string[];
label?: string;
defaultModel?: string;
/** Default provider operation timeout in milliseconds when caller/config omit timeoutMs. */
defaultTimeoutMs?: number;
models?: string[];
capabilities: ImageGenerationProviderCapabilities;
isConfigured?: (ctx: ImageGenerationProviderConfiguredContext) => boolean;
generateImage: (req: ImageGenerationRequest) => Promise<ImageGenerationResult>;
};
//#endregion
//#region src/music-generation/types.d.ts
/**
* Public music generation provider contracts.
*
* Providers implement these request/result/capability shapes so the core
* runtime can normalize prompts, options, assets, and fallback diagnostics.
*/
/** Audio output formats currently understood by music generation providers. */
type MusicGenerationOutputFormat = "mp3" | "wav";
/** Non-empty in-memory audio asset returned from a music generation provider. */
type GeneratedMusicAsset = {
buffer: Buffer;
mimeType: string;
fileName?: string;
metadata?: Record<string, unknown>;
};
/** Optional source image passed to image-conditioned music edit models. */
type MusicGenerationSourceImage = {
url?: string;
buffer?: Buffer;
mimeType?: string;
fileName?: string;
metadata?: Record<string, unknown>;
};
type MusicGenerationProviderConfiguredContext = {
cfg?: OpenClawConfig;
agentDir?: string;
};
/** Provider request after runtime fallback and override normalization. */
type MusicGenerationRequest = {
provider: string;
model: string;
prompt: string;
cfg: OpenClawConfig;
agentDir?: string;
authStore?: AuthProfileStore;
timeoutMs?: number;
lyrics?: string;
instrumental?: boolean;
durationSeconds?: number;
format?: MusicGenerationOutputFormat;
inputImages?: MusicGenerationSourceImage[];
};
/** Provider result before runtime fallback metadata is attached. */
type MusicGenerationResult = {
tracks: GeneratedMusicAsset[];
model?: string;
lyrics?: string[];
metadata?: Record<string, unknown>;
};
/** Caller override dropped because the selected provider/model does not support it. */
type MusicGenerationIgnoredOverride = {
key: "lyrics" | "instrumental" | "durationSeconds" | "format";
value: string | boolean | number;
};
/** Capability block for prompt-only music generation. */
type MusicGenerationModeCapabilities = {
maxTracks?: number;
maxDurationSeconds?: number;
supportsLyrics?: boolean;
supportsLyricsByModel?: Readonly<Record<string, boolean>>;
supportsInstrumental?: boolean;
supportsInstrumentalByModel?: Readonly<Record<string, boolean>>;
supportsDuration?: boolean;
supportsFormat?: boolean;
supportedFormats?: readonly MusicGenerationOutputFormat[];
supportedFormatsByModel?: Readonly<Record<string, readonly MusicGenerationOutputFormat[]>>;
};
/** Capability block for image-conditioned music generation. */
type MusicGenerationEditCapabilities = MusicGenerationModeCapabilities & {
enabled: boolean;
maxInputImages?: number;
};
/** Provider capability declaration, including optional mode-specific overrides. */
type MusicGenerationProviderCapabilities = MusicGenerationModeCapabilities & {
maxInputImages?: number;
generate?: MusicGenerationModeCapabilities;
edit?: MusicGenerationEditCapabilities;
};
/** Normalization metadata attached to runtime results. */
type MusicGenerationNormalization = {
durationSeconds?: MediaNormalizationEntry<number>;
};
/** Provider implementation contract consumed by the music generation runtime. */
type MusicGenerationProvider = {
id: string;
aliases?: string[];
label?: string;
defaultModel?: string;
models?: string[];
capabilities: MusicGenerationProviderCapabilities;
isConfigured?: (ctx: MusicGenerationProviderConfiguredContext) => boolean;
generateMusic: (req: MusicGenerationRequest) => Promise<MusicGenerationResult>;
};
//#endregion
//#region src/realtime-transcription/provider-types.d.ts
type RealtimeTranscriptionProviderId = string;
type RealtimeTranscriptionProviderConfig = Record<string, unknown>;
type RealtimeTranscriptionProviderResolveConfigContext = {
cfg: OpenClawConfig;
rawConfig: RealtimeTranscriptionProviderConfig;
};
type RealtimeTranscriptionProviderConfiguredContext = {
cfg?: OpenClawConfig;
providerConfig: RealtimeTranscriptionProviderConfig;
};
/** Callback hooks emitted by realtime transcription sessions. */
type RealtimeTranscriptionSessionCallbacks = {
onPartial?: (partial: string) => void;
onTranscript?: (transcript: string) => void;
onSpeechStart?: () => void;
onError?: (error: Error) => void;
};
/** Inputs passed to a provider when creating a transcription session. */
type RealtimeTranscriptionSessionCreateRequest = RealtimeTranscriptionSessionCallbacks & {
cfg?: OpenClawConfig;
providerConfig: RealtimeTranscriptionProviderConfig;
};
/** Runtime control surface for a realtime transcription session. */
type RealtimeTranscriptionSession = {
connect(): Promise<void>;
sendAudio(audio: Buffer): void;
close(): void;
isConnected(): boolean;
};
//#endregion
//#region src/talk/talk-events.d.ts
/**
* Canonical event names emitted by Talk sessions across realtime and STT/TTS flows.
*/
declare const TALK_EVENT_TYPES: readonly ["session.started", "session.ready", "session.closed", "session.error", "session.replaced", "turn.started", "turn.ended", "turn.cancelled", "capture.started", "capture.stopped", "capture.cancelled", "capture.once", "input.audio.delta", "input.audio.committed", "transcript.delta", "transcript.done", "output.text.delta", "output.text.done", "output.audio.started", "output.audio.delta", "output.audio.done", "tool.call", "tool.progress", "tool.result", "tool.error", "usage.metrics", "latency.metrics", "health.changed"];
/**
* Talk event name accepted by the event sequencer.
*/
type TalkEventType = (typeof TALK_EVENT_TYPES)[number];
/**
* High-level media mode used to group Talk session telemetry.
*/
type TalkMode = "realtime" | "stt-tts" | "transcription";
/**
* Transport family carrying Talk audio and session control.
*/
type TalkTransport = "webrtc" | "provider-websocket" | "gateway-relay" | "managed-room";
/**
* Brain mode that explains whether Talk output is agent-mediated, tool-only, or passive.
*/
type TalkBrain = "agent-consult" | "direct-tools" | "none";
//#endregion
//#region src/talk/provider-types.d.ts
type RealtimeVoiceProviderId = string;
type RealtimeVoiceRole = "user" | "assistant";
type RealtimeVoiceCloseReason = "completed" | "error";
type RealtimeVoiceAudioFormat = {
encoding: "g711_ulaw";
sampleRateHz: 8000;
channels: 1;
} | {
encoding: "pcm16";
sampleRateHz: 24000;
channels: 1;
};
type RealtimeVoiceTool = {
type: "function";
name: string;
description: string;
parameters: {
type: "object";
properties: Record<string, unknown>;
required?: string[];
};
};
type RealtimeVoiceToolCallEvent = {
itemId: string;
callId: string;
name: string;
args: unknown;
};
type RealtimeVoiceToolResultOptions = {
/**
* Submit the tool result without prompting the realtime provider to generate a new assistant
* response. Use when another channel has already delivered the user-visible answer.
*/
suppressResponse?: boolean;
willContinue?: boolean;
};
type RealtimeVoiceCloseDisposition = "abort" | "detach";
type RealtimeVoiceCloseOptions = {
/** Whether closing the transport also cancels work already accepted by the host. */
disposition?: RealtimeVoiceCloseDisposition;
};
type RealtimeVoiceBridgeEvent = {
direction: "client" | "server";
type: string;
detail?: string;
itemId?: string;
responseId?: string;
};
type RealtimeVoiceResponseError = {
code?: string;
message?: string;
type?: string;
};
type RealtimeVoiceResponseOutcomeBase = {
responseId?: string;
};
type RealtimeVoiceResponseOutcome = (RealtimeVoiceResponseOutcomeBase & {
status: "completed";
}) | (RealtimeVoiceResponseOutcomeBase & {
status: "cancelled";
reason?: string;
}) | (RealtimeVoiceResponseOutcomeBase & {
status: "failed" | "incomplete";
reason?: string;
error?: RealtimeVoiceResponseError;
message: string;
});
type RealtimeVoiceAudioClearReason = "barge-in";
type RealtimeVoiceAudioChunkMetadata = {
itemId: string;
};
type RealtimeVoicePlaybackItem = {
itemId: string;
audioEndMs: number;
};
type RealtimeVoiceBridgeCallbacks = {
onAudio: (audio: Buffer, metadata?: RealtimeVoiceAudioChunkMetadata) => void;
/** Retained native items in playback order; queued items have zero consumed duration.
* An empty snapshot is authoritative. Omit when the transport cannot measure playback.
*/
getPlaybackState?: () => readonly RealtimeVoicePlaybackItem[];
onClearAudio: (reason?: RealtimeVoiceAudioClearReason) => void;
/** Scoped acknowledgments are valid only for the provider connection that emitted the mark. */
onMark?: (markName: string, acknowledge?: () => void) => void;
onTranscript?: (role: RealtimeVoiceRole, text: string, isFinal: boolean) => void;
/** Synchronously admits native control; only consult permits task fallthrough. Respond is call-bound. */
handleDelegationInput?: (text: string, respond: (message: string) => void) => "control" | "consult";
/** Diagnostic observation; returning from this callback cannot veto an event. */
onEvent?: (event: RealtimeVoiceBridgeEvent) => void;
onResponseDone?: (outcome: RealtimeVoiceResponseOutcome) => void;
onToolCall?: (event: RealtimeVoiceToolCallEvent) => void;
onReady?: () => void;
onError?: (error: Error) => void;
onClose?: (reason: RealtimeVoiceCloseReason) => void;
};
type RealtimeVoiceProviderConfig = Record<string, unknown>;
type RealtimeVoiceProviderCapabilities = {
transports: TalkTransport[];
inputAudioFormats: RealtimeVoiceAudioFormat[];
outputAudioFormats: RealtimeVoiceAudioFormat[];
supportsBrowserSession?: boolean;
supportsBargeIn?: boolean;
/** True when provider VAD reports confirmed interruptions through onClearAudio("barge-in"). */
handlesInputAudioBargeIn?: boolean;
supportsToolCalls?: boolean;
/** True when user transcripts are reliable enough to gate responses on a leading wake name. */
supportsActivationNameGating?: boolean;
supportsVideoFrames?: boolean;
supportsSessionResumption?: boolean;
};
type RealtimeVoiceProviderResolveConfigContext = {
cfg: OpenClawConfig;
rawConfig: RealtimeVoiceProviderConfig;
};
type RealtimeVoiceProviderConfiguredContext = {
cfg?: OpenClawConfig;
/** Host-selected agent scope for provider auth readiness. */
agentId?: string;
providerConfig: RealtimeVoiceProviderConfig;
};
type RealtimeVoiceAgentConsultRunner = (params: {
prompt: string;
signal?: AbortSignal;
}) => Promise<{
text: string;
}>;
type RealtimeVoiceBridgeCreateRequest = RealtimeVoiceBridgeCallbacks & {
cfg?: OpenClawConfig;
/** Host-selected agent scope for provider auth and agent-owned bridge state. */
agentId?: string;
providerConfig: RealtimeVoiceProviderConfig;
audioFormat?: RealtimeVoiceAudioFormat;
instructions?: string;
language?: string;
autoRespondToAudio?: boolean;
interruptResponseOnInputAudio?: boolean;
tools?: RealtimeVoiceTool[];
/** Host-injected agent delegation runner for provider-owned realtime control channels. */
runAgentConsult?: RealtimeVoiceAgentConsultRunner;
};
type RealtimeVoiceBrowserSessionCreateRequest = {
cfg?: OpenClawConfig;
providerConfig: RealtimeVoiceProviderConfig;
instructions?: string;
tools?: RealtimeVoiceTool[];
model?: string;
voice?: string;
vadThreshold?: number;
silenceDurationMs?: number;
prefixPaddingMs?: number;
reasoningEffort?: string;
/** Host-injected agent delegation runner for provider-owned realtime control channels. */
runAgentConsult?: RealtimeVoiceAgentConsultRunner;
} & ({
clientControl?: undefined;
gatewayControl?: RealtimeVoiceGatewayControl;
} | {
/** Explicit ownership requires command binding; lifecycle callbacks alone do not select it. */
clientControl: {
owner: "gateway";
};
gatewayControl: RealtimeVoiceGatewayControl & Required<Pick<RealtimeVoiceGatewayControl, "bindControl">>;
});
/** Narrow host/plugin seam for Gateway-owned control of a client-owned media session. */
type RealtimeVoiceGatewayControl = Omit<RealtimeVoiceBridgeCallbacks, "onAudio" | "onClearAudio" | "onMark" | "getPlaybackState"> & {
/** Bind only supported sideband commands; client-owned media needs no audio bridge. */
bindControl?: (control: Partial<Pick<RealtimeVoiceBridge, "submitToolResult" | "sendUserMessage">>) => void;
/** @deprecated Stable 2026.8.1 SDK contract; remove only with a versioned SDK break. */
bindBridge: (bridge: RealtimeVoiceBridge) => void;
};
type RealtimeVoiceBrowserAudioContract = {
inputEncoding: "pcm16" | "g711_ulaw";
inputSampleRateHz: number;
outputEncoding: "pcm16" | "g711_ulaw";
outputSampleRateHz: number;
};
type RealtimeVoiceBrowserWebRtcSdpSession = {
provider: RealtimeVoiceProviderId;
transport: "webrtc";
clientSecret: string;
offerUrl?: string;
offerHeaders?: Record<string, string>;
offerResponseMaxBytes?: number;
model?: string;
voice?: string;
expiresAt?: number;
};
type RealtimeVoiceBrowserJsonPcmWebSocketSession = {
provider: RealtimeVoiceProviderId;
transport: "provider-websocket";
protocol: string;
clientSecret: string;
websocketUrl: string;
audio: RealtimeVoiceBrowserAudioContract;
initialMessage?: unknown;
model?: string;
voice?: string;
expiresAt?: number;
};
type RealtimeVoiceBrowserGatewayRelaySession = {
provider: RealtimeVoiceProviderId;
transport: "gateway-relay";
relaySessionId: string;
audio: RealtimeVoiceBrowserAudioContract;
model?: string;
voice?: string;
expiresAt?: number;
};
type RealtimeVoiceBrowserManagedRoomSession = {
provider: RealtimeVoiceProviderId;
transport: "managed-room";
roomUrl: string;
token?: string;
model?: string;
voice?: string;
expiresAt?: number;
};
type RealtimeVoiceBrowserSession = RealtimeVoiceBrowserWebRtcSdpSession | RealtimeVoiceBrowserJsonPcmWebSocketSession | RealtimeVoiceBrowserGatewayRelaySession | RealtimeVoiceBrowserManagedRoomSession;
type RealtimeVoiceBridge = {
supportsToolResultContinuation?: boolean;
/** False when the provider cannot accept a tool result without starting a response. */
supportsToolResultSuppression?: boolean;
/** Per-session override for provider-confirmed input-audio barge-in handling. */
handlesInputAudioBargeIn?: boolean;
connect(): Promise<void>;
sendAudio(audio: Buffer): void;
setMediaTimestamp(ts: number): void;
sendUserMessage?(text: string, options?: {
toolChoice?: {
type: "function";
name: string;
};
}): void;
triggerGreeting?(instructions?: string): void;
handleBargeIn?(options?: RealtimeVoiceBargeInOptions): void;
/**
* Returns void when submission completes synchronously, or a Promise that resolves at the
* asynchronous completion boundary exposed by the provider and rejects on submission failure.
*/
submitToolResult(callId: string, result: unknown, options?: RealtimeVoiceToolResultOptions): void | Promise<void>;
acknowledgeMark(markName?: string): void;
close(options?: RealtimeVoiceCloseOptions): void;
isConnected(): boolean;
};
type RealtimeVoiceBargeInOptions = {
/**
* The caller has already confirmed assistant audio is still playing in its output sink.
* This lets providers interrupt output even when the sink cannot provide real playback marks.
*/
audioPlaybackActive?: boolean;
/** Interrupt even when normal barge-in audio-duration guards would treat the event as echo. */
force?: boolean;
};
//#endregion
//#region src/transcripts/provider-types.d.ts
/**
* Public contracts for transcript source providers.
*
* Providers can stream live utterances, import post-hoc transcript text, expose
* status, and stop active sessions using shared session/source descriptors.
*/
/** Supported source families for transcript providers. */
type TranscriptSourceKind = "live-audio" | "live-caption" | "posthoc-transcript" | "recording-stt";
/** Provider-specific locator for a live, recorded, or imported transcript source. */
type TranscriptSourceLocator = {
providerId: string;
kind?: TranscriptSourceKind;
accountId?: string;
guildId?: string;
channelId?: string;
meetingUrl?: string;
threadTs?: string;
fileId?: string;
[key: string]: string | undefined;
};
/** Speaker/participant identity attached to an utterance. */
type TranscriptParticipant = {
id?: string;
label: string;
};
/** One captured or imported transcript utterance. */
type TranscriptUtterance = {
id?: string;
sessionId?: string;
startedAt?: string;
endedAt?: string;
speaker?: TranscriptParticipant;
text: string;
final?: boolean;
metadata?: Record<string, unknown>;
};
/** Durable transcript session metadata. */
type TranscriptSessionDescriptor = {
sessionId: string;
title?: string;
source: TranscriptSourceLocator;
startedAt: string;
stoppedAt?: string;
metadata?: Record<string, unknown>;
};
/** Request passed to providers that can start live transcript capture. */
type TranscriptStartRequest = {
cfg?: OpenClawConfig;
session: TranscriptSessionDescriptor;
abortSignal?: AbortSignal;
startupWaitMs?: number;
onUtterance: (utterance: TranscriptUtterance) => void | Promise<void>;
/**
* `active: false` permanently ends this exact capture subscription, including
* replacement or detach; transient transport disconnects must not emit it.
* Deliver final utterances first. Callback payload ids/source are descriptive;
* consumers retain their admitted session identity and ownership metadata.
*/
onStatus?: (status: TranscriptSourceStatus) => void | Promise<void>;
};
/** Request to watch whether a live source currently has human participants. */
type TranscriptOccupancyWatchRequest = {
cfg?: OpenClawConfig;
source: TranscriptSourceLocator;
abortSignal?: AbortSignal;
startupWaitMs?: number;
/** Emitted on 0 -> >0 humans, and once on subscription if already occupied. */
onOccupied: () => void;
/** Emitted on >0 -> 0 humans. Bots never count; callbacks preserve observed order. */
onEmpty: () => void;
};
type TranscriptOccupancyWatchHandle = {
stop: () => void;
};
/**
* Result from starting a transcript source provider.
*
* Providers retain cleanup ownership until they return `ok: true`. A failed or
* rejected start must release any partial capture before it settles.
*/
type TranscriptsStartResult = {
ok: true;
session: TranscriptSessionDescriptor;
} | {
ok: false;
error: string;
};
/** Request passed to providers that can stop live transcript capture. */
type TranscriptStopRequest = {
cfg?: OpenClawConfig;
sessionId: string;
source: TranscriptSourceLocator;
reason?: string;
};
/** Result from stopping a transcript source provider. */
type TranscriptsStopResult = {
ok: true;
sessionId: string;
stoppedAt?: string;
} | {
ok: false;
error: string;
};
/** Runtime status reported by transcript source providers. */
type TranscriptSourceStatus = {
sessionId?: string;
active: boolean;
message?: string;
source?: TranscriptSourceLocator;
};
/** Request passed to providers that import post-hoc transcript text. */
type TranscriptImportRequest = {
cfg?: OpenClawConfig;
session: TranscriptSessionDescriptor;
text: string;
speakerLabel?: string;
};
/** Trusted caller facts projected by core; never accepted from tool arguments. */
type TranscriptToolCaller = {
kind: "operator";
source: "channel-owner" | "local" | "scheduled";
} | {
kind: "channel";
channel: string;
accountId?: string;
senderId: string;
groupId?: string;
groupSpace?: string;
roleIds: readonly string[];
};
type TranscriptToolAction = "import" | "start" | "status" | "stop" | "summarize" | "list" | "show";
type TranscriptSourceAccessControl = {
/** Ingress channel whose trusted account owns this provider's account namespace. */
channelId: string;
/** Resolve and validate the canonical account before persistence. */
resolveAccountId: (params: {
cfg?: OpenClawConfig;
source: TranscriptSourceLocator;
}) => Result<string | undefined, string>;
/** Apply the provider's native access policy to the resolved source. */
authorize: (params: {
action: TranscriptToolAction;
caller: TranscriptToolCaller;
cfg?: OpenClawConfig;
source: TranscriptSourceLocator;
}) => Promise<Result<void, string>>;
};
/** Provider contract for transcript capture/import integrations. */
type TranscriptSourceProvider$2 = {
id: string;
aliases?: readonly string[];
/** Closed access contract for providers sharing one inbound channel namespace. */
accessControl?: TranscriptSourceAccessControl;
name: string;
sourceKinds: readonly TranscriptSourceKind[];
start?: (request: TranscriptStartRequest) => Promise<TranscriptsStartResult>;
watchOccupancy?: (request: TranscriptOccupancyWatchRequest) => Promise<Result<TranscriptOccupancyWatchHandle, string>>;
stop?: (request: TranscriptStopRequest) => Promise<TranscriptsStopResult>;
status?: (source: TranscriptSourceLocator, cfg?: OpenClawConfig) => Promise<TranscriptSourceStatus[]>;
importTranscript?: (request: TranscriptImportRequest) => Promise<TranscriptUtterance[]>;
};
//#endregion
//#region src/tts/provider-types.d.ts
/** Canonical speech provider identifier after provider registry normalization. */
type SpeechProviderId = string;
/** Output context requested from a speech provider. */
type SpeechSynthesisTarget = "audio-file" | "voice-note" | "telephony";
/** Provider-owned normalized config map. */
type SpeechProviderConfig = Record<string, unknown>;
/** Provider-owned per-request directive/persona overrides. */
type SpeechProviderOverrides = Record<string, unknown>;
/** Policy controlling which [[tts:*]] directive fields can affect synthesis. */
type SpeechModelOverridePolicy = {
enabled: boolean;
allowText: boolean;
allowProvider: boolean;
allowVoice: boolean;
allowModelId: boolean;
allowVoiceSettings: boolean;
allowNormalization: boolean;
allowSeed: boolean;
};
/** Parsed directive overrides grouped by provider. */
type TtsDirectiveOverrides = {
ttsText?: string;
provider?: SpeechProviderId;
providerOverrides?: Record<string, SpeechProviderOverrides>;
};
/** Result of parsing TTS directives from message text. */
type TtsDirectiveParseResult = {
cleanedText: string;
ttsText?: string;
hasDirective: boolean;
overrides: TtsDirectiveOverrides;
warnings: string[];
};
/** Context for checking whether a provider has enough config to synthesize. */
type SpeechProviderConfiguredContext = {
cfg?: OpenClawConfig;
providerConfig: SpeechProviderConfig;
timeoutMs: number;
};
/** Request for buffered speech synthesis. */
type SpeechSynthesisRequest = {
text: string;
cfg: OpenClawConfig;
providerConfig: SpeechProviderConfig;
target: SpeechSynthesisTarget;
providerOverrides?: SpeechProviderOverrides;
timeoutMs: number;
};
/** Buffered speech synthesis result plus file/voice-note compatibility metadata. */
type SpeechSynthesisResult = {
audioBuffer: Buffer;
outputFormat: string;
fileExtension: string;
voiceCompatible: boolean;
};
type SpeechSynthesisStreamRequest = SpeechSynthesisRequest;
/** Streaming speech synthesis result; release frees provider transport resources. */
type SpeechSynthesisStreamResult = {
audioStream: ReadableStream<Uint8Array>;
outputFormat: string;
fileExtension: string;
voiceCompatible: boolean;
release?: () => Promise<void>;
};
/** Telephony synthesis request for provider output that needs a fixed sample rate. */
type SpeechTelephonySynthesisRequest = {
text: string;
cfg: OpenClawConfig;
providerConfig: SpeechProviderConfig;
providerOverrides?: SpeechProviderOverrides;
timeoutMs: number;
};
/** Telephony synthesis result with sample-rate metadata for call transports. */
type SpeechTelephonySynthesisResult = {
audioBuffer: Buffer;
outputFormat: string;
sampleRate: number;
};
/** Provider hook input for applying persona/config before synthesis. */
type SpeechProviderPrepareSynthesisContext = {
text: string;
cfg: OpenClawConfig;
providerConfig: SpeechProviderConfig;
providerOverrides?: SpeechProviderOverrides;
persona?: ResolvedTtsPersona;
personaProviderConfig?: SpeechProviderConfig;
target: SpeechSynthesisTarget;
timeoutMs: number;
};
/** Optional provider-prepared synthesis overrides. */
type SpeechProviderPreparedSynthesis = {
text?: string;
providerConfig?: SpeechProviderConfig;
providerOverrides?: SpeechProviderOverrides;
};
/** Voice metadata returned by provider list-voices hooks. */
type SpeechVoiceOption = {
id: string;
name?: string;
category?: string;
description?: string;
locale?: string;
gender?: string;
personalities?: string[];
};
/** Provider voice-listing request with optional direct auth/URL overrides. */
type SpeechListVoicesRequest = {
cfg?: OpenClawConfig;
providerConfig?: SpeechProviderConfig;
apiKey?: string;
baseUrl?: string;
/** Core-resolved request timeout after config and provider defaults. */
timeoutMs?: number;
};
/** Provider hook input for resolving normalized config from raw OpenClaw config. */
type SpeechProviderResolveConfigContext = {
cfg: OpenClawConfig;
rawConfig: Record<string, unknown>;
timeoutMs: number;
};
/** One parsed directive key/value plus current provider override state. */
type SpeechDirectiveTokenParseContext = {
key: string;
value: string;
policy: SpeechModelOverridePolicy;
selectedProvider?: SpeechProviderId;
providerConfig?: SpeechProviderConfig;
currentOverrides?: SpeechProviderOverrides;
};
/** Provider directive parser result. */
type SpeechDirectiveTokenParseResult = {
handled: boolean;
overrides?: SpeechProviderOverrides;
warnings?: string[];
};
/** Provider hook input for resolving talk-command speech config. */
type SpeechProviderResolveTalkConfigContext = {
cfg: OpenClawConfig;
baseTtsConfig: Record<string, unknown>;
talkProviderConfig: TalkProviderConfig;
timeoutMs: number;
};
/** Provider hook input for per-call talk-command overrides. */
type SpeechProviderResolveTalkOverridesContext = {
talkProviderConfig: TalkProviderConfig;
params: Record<string, unknown>;
};
//#endregion
//#region src/video-generation/types.d.ts
/** Video asset returned by a provider after generation or transformation. */
type GeneratedVideoAsset = {
/** Non-empty raw video bytes; may accompany url as a delivery fallback. */
buffer?: Buffer;
/** Provider-hosted URL returned instead of bytes or alongside them as a delivery fallback.
* When buffer is absent, callers can forward or download without materializing the video. */
url?: string;
mimeType: string;
fileName?: string;
metadata?: Record<string, unknown>;
};
/** Resolution label accepted by video generation providers. */
type VideoGenerationResolution = "360P" | "480P" | "540P" | "720P" | "768P" | "1080P" | (string & {});
/**
* Canonical semantic role hints for reference assets (first/last frame,
* reference image/video/audio). Providers may accept additional role strings;
* the asset.role type accepts both canonical values and arbitrary strings.
*/
type VideoGenerationAssetRole = "first_frame" | "last_frame" | "reference_image" | "reference_video" | "reference_audio";
/** Source media asset supplied to image/video/audio-to-video providers. */
type VideoGenerationSourceAsset = {
url?: string;
buffer?: Buffer;
mimeType?: string;
fileName?: string;
/**
* Optional semantic role hint forwarded to the provider. Canonical values
* come from `VideoGenerationAssetRole`; plain strings are accepted for
* provider-specific extensions.
*/
role?: VideoGenerationAssetRole | (string & {});
metadata?: Record<string, unknown>;
};
/** Context passed when checking whether a video provider is configured. */
type VideoGenerationProviderConfiguredContext = {
cfg?: OpenClawConfig;
agentDir?: string;
};
/** Context passed when resolving model-specific video generation capabilities. */
type VideoGenerationModelCapabilitiesContext = {
provider: string;
model: string;
cfg: OpenClawConfig;
agentDir?: string;
authStore?: AuthProfileStore;
timeoutMs?: number;
};
/** Normalized request object passed to a selected video generation provider. */
type VideoGenerationRequest = {
provider: string;
model: string;
prompt: string;
cfg: OpenClawConfig;
agentDir?: string;
authStore?: AuthProfileStore;
timeoutMs?: number;
size?: string;
aspectRatio?: string;
resolution?: VideoGenerationResolution;
durationSeconds?: number;
audio?: boolean;
watermark?: boolean;
inputImages?: VideoGenerationSourceAsset[];
inputVideos?: VideoGenerationSourceAsset[];
/** Reference audio assets (e.g. background music) forwarded to the provider. */
inputAudios?: VideoGenerationSourceAsset[];
/** Arbitrary provider-specific parameters forwarded as-is (e.g. seed, draft, camerafixed). */
providerOptions?: Record<string, unknown>;
};
/** Provider video generation response returned to the runtime. */
type VideoGenerationResult = {
videos: GeneratedVideoAsset[];
model?: string;
metadata?: Record<string, unknown>;
};
/** Supported high-level video generation operation modes. */
type VideoGenerationMode = "generate" | "imageToVideo" | "videoToVideo";
/**
* Primitive type tag for a declared `providerOptions` key. Keep narrow —
* plugins that need richer shapes should leave them out of the typed contract
* and interpret the forwarded opaque value inside their own provider code.
*/
type VideoGenerationProviderOptionType = "number" | "boolean" | "string";
/** Capability limits and supported options for one video generation mode. */
type VideoGenerationModeCapabilities = {
maxVideos?: number;
maxInputImages?: number;
maxInputImagesByModel?: Readonly<Record<string, number>>;
maxInputVideos?: number;
maxInputVideosByModel?: Readonly<Record<string, number>>;
/** Max number of reference audio assets the provider accepts (e.g. background music, voice reference). */
maxInputAudios?: number;
maxInputAudiosByModel?: Readonly<Record<string, number>>;
maxDurationSeconds?: number;
supportedDurationSeconds?: readonly number[];
supportedDurationSecondsByModel?: Readonly<Record<string, readonly number[]>>;
sizes?: readonly string[];
aspectRatios?: readonly string[];
resolutions?: readonly VideoGenerationResolution[];
supportsSize?: boolean;
supportsAspectRatio?: boolean;
supportsResolution?: boolean;
supportsAudio?: boolean;
supportsWatermark?: boolean;
/**
* Declared typed schema for `VideoGenerationRequest.providerOptions`. Keys
* listed here are accepted and validated against the declared primitive
* type before forwarding; unknown keys or type mismatches skip the
* candidate provider at runtime so mis-typed or provider-specific options
* never silently reach the wrong provider.
*/
providerOptions?: Readonly<Record<string, VideoGenerationProviderOptionType>>;
};
/** Capability block for transform modes that may be independently enabled. */
type VideoGenerationTransformCapabilities = VideoGenerationModeCapabilities & {
enabled: boolean;
};
/** Full provider capability map including base and transform mode overrides. */
type VideoGenerationProviderCapabilities = VideoGenerationModeCapabilities & {
generate?: VideoGenerationModeCapabilities;
imageToVideo?: VideoGenerationTransformCapabilities;
videoToVideo?: VideoGenerationTransformCapabilities;
};
/** Static catalog metadata that overrides provider defaults for one video model. */
type VideoGenerationCatalogModelEntry = {
capabilities?: VideoGenerationProviderCapabilities;
modes?: readonly VideoGenerationMode[];
};
/** Video generation provider contract implemented by provider plugins. */
type VideoGenerationProvider = {
id: string;
aliases?: string[];
label?: string;
defaultModel?: string;
/** Default provider operation timeout in milliseconds when caller/config omit timeoutMs. */
defaultTimeoutMs?: number;
models?: string[];
capabilities: VideoGenerationProviderCapabilities;
catalogByModel?: Readonly<Record<string, VideoGenerationCatalogModelEntry>>;
isConfigured?: (ctx: VideoGenerationProviderConfiguredContext) => boolean;
resolveModelCapabilities?: (ctx: VideoGenerationModelCapabilitiesContext) => VideoGenerationProviderCapabilities | undefined | Promise<VideoGenerationProviderCapabilities | undefined>;
generateVideo: (req: VideoGenerationRequest) => Promise<VideoGenerationResult>;
};
type VideoGenerationIgnoredOverride = {
key: "size" | "aspectRatio" | "resolution" | "audio" | "watermark";
value: string | boolean;
};
type VideoGenerationNormalization = {
size?: MediaNormalizationEntry<string>;
aspectRatio?: MediaNormalizationEntry<string>;
resolution?: MediaNormalizationEntry<VideoGenerationResolution>;
durationSeconds?: MediaNormalizationEntry<number>;
};
//#endregion
//#region src/plugins/capability-provider.types.d.ts
/** JSON-compatible provider settings for one configured worker profile. */
type WorkerProfile = Readonly<Record<string, PluginJsonValue>>;
/** Provider-authored picker metadata for one machine class or exact machine type. */
type WorkerMachineOption = Readonly<{
id: string;
label: string;
cpu?: number;
memoryGb?: number;
default?: boolean;
}>;
/** SSH endpoint material returned by a worker provider after provisioning. */
type WorkerSshEndpoint = {
host: string;
port: number;
/**
* Up to 10 ordered unique integer ports (1..65535) after `port`; excludes the primary.
* Core rotates only for idempotent probes, content-addressed transfers, receipt/lock-guarded
* artifact installation, convergent managed-worktree mirroring, and tunnel reconnects.
* Ambiguous unguarded stateful commands fail closed and are not replayed.
*/
fallbackPorts?: readonly number[];
user: string;
/** OpenSSH public host-key line obtained from trusted provisioning output. */
hostKey: string;
/** Secret reference only; providers must never return plaintext key material. */
keyRef: SecretRef;
};
/** Resolved SSH client identity. Providers may return a local path or ephemeral material. */
type WorkerSshIdentity = {
kind: "path";
path: string;
} | {
kind: "material";
contents: string;
};
/** Durable context supplied when a worker provider resolves the identity it minted. */
type WorkerSshIdentityRequest = {
leaseId: string;
profile: WorkerProfile;
keyRef: SecretRef;
};
/** Closed set of applications installed and launchable on a provisioned worker desktop. */
type WorkerDesktopApp = {
id: "browser";
executablePath: string;
cdpPort: number;
} | {
id: "terminal";
executablePath: string;
};
/** Optional interactive desktop endpoint provisioned with the lease (warm-time capability). */
type WorkerDesktopEndpoint = {
/** Desktop service protocol on the worker loopback; "rfb" is the only phase-1 value. */
protocol: "rfb";
/** Loopback port on the worker (e.g. 5900). */
port: number;
/** Absolute on-box path to the per-lease password file; read by the owning transport, never persisted as plaintext. */
passwordFilePath?: string;
/** Closed application metadata advertised by the provider for this desktop. */
apps?: WorkerDesktopApp[];
};
/** Placement execution modes a worker provider can carry. */
type WorkerExecutionMode = "worker-turn" | "remote-exec";
type WorkerNodeBootstrapAccess = {
/** Immutable node distribution prepared by the Gateway for this provision operation. */
nodeBootstrap: {
url: string;
token: string;
sha256: string;
bytes: number;
openclawVersion: string;
enabledPluginIds: readonly string[];
tlsFingerprint?: string;
};
/** Runtime/enrollment closure, including shutdown; provision's separate signal identifies explicit Stop. */
signal?: AbortSignal;
};
/** Operation-bound immutable artifacts without a node identity or enrollment credential. */
type WorkerNodeRuntimePreparation = WorkerNodeBootstrapAccess & {
workerBundle: {
url: string;
token: string;
sha256: string;
bytes: number;
tlsFingerprint?: string;
/** Core-owned location within the installed node package, outside dist and enrollment state. */
packageRelativePath: string;
};
};
/** Replay-safe node enrollment prepared only after a provider has allocated its machine. */
type WorkerNodeEnrollment = WorkerNodeBootstrapAccess & {
openclawVersion: string;
displayName: string;
waitForDeviceId: () => Promise<string>;
} & ({
mode: "connect";
setupCode: string;
setupId: string;
} | {
mode: "resume";
deviceId: string;
});
/** Durable lease identity and endpoint returned by a successful provision operation. */
type WorkerLease = {
leaseId: string;
/** The SSH account also owns processes unrelated to this worker lease. */
sharedHost?: boolean;
desktop?: WorkerDesktopEndpoint;
} & ({
ssh: WorkerSshEndpoint;
node?: never;
} | {
node: {
deviceId: string;
};
ssh?: never;
});
/** Authoritative inspection result for an already-known worker lease. */
type WorkerLeaseStatus = {
status: "active";
/** Explicit provider fact used to reconcile leases persisted before this metadata existed. */
sharedHost?: boolean;
} | {
status: "dormant";
} | {
status: "destroyed";
} | {
status: "unknown";
};
/** Cloud-worker lifecycle capability shared by plugin and internal providers. */
type WorkerProvider$1 = {
id: string;
/** Process-stable choices available for this profile; omit the hook to hide machine selection. */
listMachineOptions?: (profile: WorkerProfile) => Promise<readonly WorkerMachineOption[]>;
/** Omission advertises no placement support; multiple modes use their canonical order. */
supportedExecutionModes?: readonly [WorkerExecutionMode] | readonly ["worker-turn", "remote-exec"];
/**
* Provision before preparing an installation when the lease transport decides whether an
* installation is needed. Defaults to false so SSH providers retain prepare-before-allocation.
*/
provisionBeforeInstallation?: boolean;
/** Provider allocates a node host through the environment-owned enrollment callback. */
requiresNodeEnrollment?: boolean;
/** Prepare a pristine project before enrollment so it can be included in a reusable image. */
supportsProjectPreparation?: (profile: WorkerProfile, machineClass?: string) => boolean;
/**
* Resolve the exact cleanup handle for this operation, even if no machine was created.
* Must not provision, start, renew, run setup, enroll, or wait for transport readiness.
* Identity is not existence/readiness proof; destroy still owns teardown confirmation.
*/
resolveAllocation: (profile: WorkerProfile, operationId: string) => Promise<{
leaseId: string;
sharedHost: boolean;
}>;
/**
* Provision or adopt the lease for this operation id.
* Repeating the same operation id must be idempotent across gateway restarts.
*/
provision: (profile: WorkerProfile, operationId: string, options?: {
/** Cancel this attempt; settle its active commands before rejecting. Cleanup proves release separately. */
signal?: AbortSignal;
executionMode?: WorkerExecutionMode;
machineClass?: string;
prepareNodeRuntime?: () => Promise<WorkerNodeRuntimePreparation>;
beginNodeEnrollment?: () => Promise<WorkerNodeEnrollment>;
project?: {
key: string;
baseCommit: string;
signal: AbortSignal;
assertCurrent: () => void;
/** Bound to this provision attempt; retained callbacks reject after it closes. */
prepare: (transport: {
runScript: (script: string, signal: AbortSignal) => Promise<string>;
upload: (localPath: string, remotePath: string, signal: AbortSignal) => Promise<void>;
}) => Promise<{
seedKey: string;
cacheHit: boolean;
}>;
};
}) => Promise<WorkerLease>;
/** Maximum core wait for one provision attempt, including provider-owned setup and cleanup. */
resolveProvisionTimeoutMs?: (profile: WorkerProfile) => number;
/**
* Throws on transient/indeterminate observation failures. `unknown` means the provider no
* longer recognizes a usable lease; core fences it and requests destroy. Only `destroyed`
* proves teardown complete and lets core skip destroy.
*/
inspect: (lease: {
leaseId: string;
profile: WorkerProfile;
}) => Promise<WorkerLeaseStatus>;
/**
* Resolves provider-owned dynamic identities. When absent, the gateway uses its generic
* SecretRef resolver; when present, failures are authoritative and never fall back.
*/
resolveSshIdentity?: (request: WorkerSshIdentityRequest) => Promise<WorkerSshIdentity>;
renew?: (leaseId: string) => Promise<void>;
/**
* Bounded cleanup for configured profiles, including when no leases remain. Core schedules
* one pass at a time without blocking allocation. Check authority before external effects
* and after awaits before persistence; settle only after all owned commands have stopped.
*/
maintain?: (context: {
profiles: readonly WorkerProfile[];
signal: AbortSignal;
assertCurrent: () => void;
}) => Promise<void>;
/** Idempotent; resolves only after the provider can prove teardown. */
destroy: (lease: {
leaseId: string;
profile: WorkerProfile;
}) => Promise<void>;
/** Maximum core wait for teardown, including provider-owned checkpointing and cleanup. */
resolveDestroyTimeoutMs?: (profile: WorkerProfile) => number;
};
/** Speech capability registered by a plugin. */
type SpeechProviderPlugin$1 = {
id: SpeechProviderId;
label: string;
aliases?: string[];
autoSelectOrder?: number;
/** Default provider operation timeout in milliseconds when caller/config omit timeoutMs. */
defaultTimeoutMs?: number;
defaultModel?: string;
models?: readonly string[];
voices?: readonly string[];
resolveConfig?: (ctx: SpeechProviderResolveConfigContext) => SpeechProviderConfig;
parseDirectiveToken?: (ctx: SpeechDirectiveTokenParseContext) => SpeechDirectiveTokenParseResult;
resolveTalkConfig?: (ctx: SpeechProviderResolveTalkConfigContext) => SpeechProviderConfig;
resolveTalkOverrides?: (ctx: SpeechProviderResolveTalkOverridesContext) => SpeechProviderConfig | undefined;
prepareSynthesis?: (ctx: SpeechProviderPrepareSynthesisContext) => SpeechProviderPreparedSynthesis | undefined | Promise<SpeechProviderPreparedSynthesis | undefined>;
isConfigured: (ctx: SpeechProviderConfiguredContext) => boolean;
synthesize: (req: SpeechSynthesisRequest) => Promise<SpeechSynthesisResult>;
streamSynthesize?: (req: SpeechSynthesisStreamRequest) => Promise<SpeechSynthesisStreamResult>;
synthesizeTelephony?: (req: SpeechTelephonySynthesisRequest) => Promise<SpeechTelephonySynthesisResult>;
listVoices?: (req: SpeechListVoicesRequest) => Promise<SpeechVoiceOption[]>;
};
/** Realtime transcription capability registered by a plugin. */
type RealtimeTranscriptionProviderPlugin$1 = {
id: RealtimeTranscriptionProviderId;
label: string;
aliases?: string[];
defaultModel?: string;
models?: readonly string[];
autoSelectOrder?: number;
resolveConfig?: (ctx: RealtimeTranscriptionProviderResolveConfigContext) => RealtimeTranscriptionProviderConfig;
isConfigured: (ctx: RealtimeTranscriptionProviderConfiguredContext) => boolean;
createSession: (req: RealtimeTranscriptionSessionCreateRequest) => RealtimeTranscriptionSession;
};
/** Transcript source capability registered by a channel or meeting plugin. */
type TranscriptSourceProvider$1 = TranscriptSourceProvider$2;
/** Realtime voice capability registered by a plugin. */
type RealtimeVoiceProviderPlugin$1 = {
id: RealtimeVoiceProviderId;
label: string;
aliases?: string[];
defaultModel?: string;
models?: readonly string[];
/** Known speaker voices for pickers; providers still accept free-form values. */
voices?: readonly string[];
autoSelectOrder?: number;
capabilities?: RealtimeVoiceProviderCapabilities;
resolveConfig?: (ctx: RealtimeVoiceProviderResolveConfigContext) => RealtimeVoiceProviderConfig;
isConfigured: (ctx: RealtimeVoiceProviderConfiguredContext) => boolean;
createBridge: (req: RealtimeVoiceBridgeCreateRequest) => RealtimeVoiceBridge;
createBrowserSession?: (req: RealtimeVoiceBrowserSessionCreateRequest) => Promise<RealtimeVoiceBrowserSession>;
};
type MediaUnderstandingProviderPlugin$1 = MediaUnderstandingProvider;
type ImageGenerationProviderPlugin$1 = ImageGenerationProvider;
type VideoGenerationProviderPlugin$1 = VideoGenerationProvider;
type MusicGenerationProviderPlugin$1 = MusicGenerationProvider;
//#endregion
//#region src/plugins/migration-provider.types.d.ts
type PluginConfigMigration = (config: OpenClawConfig) => {
config: OpenClawConfig;
changes: string[];
} | null | undefined;
type MigrationItemStatus = "planned" | "migrated" | "skipped" | "warning" | "conflict" | "error";
type MigrationItemKind = "auth" | "config" | "secret" | "memory" | "skill" | "workspace" | "session" | "file" | "archive" | "manual";
type MigrationItemAction = "copy" | "create" | "update" | "merge" | "append" | "archive" | "skip" | "manual";
type MigrationApplyPhase = "before-promotion" | "after-promotion";
/** Provider guarantee required before onboarding defers non-rollbackable effects. */
type MigrationDeferredApplyContract = {
retrySafe: true;
};
type MigrationItem = {
id: string;
kind: MigrationItemKind | (string & {});
action: MigrationItemAction | (string & {});
status: MigrationItemStatus;
source?: string;
target?: string;
message?: string;
reason?: string;
sensitive?: boolean;
/** Onboarding may defer non-rollbackable effects only for retry-safe providers. */
applyPhase?: MigrationApplyPhase;
/** Retry-safe deferred apply may report a non-mutating already-satisfied terminal result. */
deferredCompletion?: true;
/** Core-owned source revision bound by reviewed embedded migration flows. */
sourceRevision?: {
algorithm: "sha256";
digest: string;
};
details?: Record<string, unknown>;
};
type MigrationSummary = {
total: number;
planned: number;
migrated: number;
skipped: number;
conflicts: number;
errors: number;
sensitive: number;
};
type MigrationDetection = {
found: boolean;
source?: string;
label?: string;
confidence?: "low" | "medium" | "high";
message?: string;
};
type MigrationPlan = {
providerId: string;
source: string;
target?: string;
summary: MigrationSummary;
items: MigrationItem[];
warnings?: string[];
nextSteps?: string[];
metadata?: Record<string, unknown>;
};
type MigrationApplyResult = MigrationPlan & {
backupPath?: string;
reportDir?: string;
};
type MigrationProviderPreparation = {
dispose?: () => void | Promise<void>;
};
type MigrationConfigRuntime = Pick<NonNullable<PluginRuntime["config"]>, "current" | "mutateConfigFile">;
type MigrationProviderContext = {
config: OpenClawConfig;
runtime?: PluginRuntime;
/** Host-owned config mutation target for isolated embedded migration flows. */
configRuntime?: MigrationConfigRuntime;
logger: PluginLogger;
stateDir: string;
/** Explicit destination agent for embedded migration surfaces such as Control UI. */
targetAgentId?: string;
/** Optional item-kind scope used by embedded migration surfaces to avoid unrelated discovery. */
itemKinds?: readonly string[];
source?: string;
includeSecrets?: boolean;
overwrite?: boolean;
providerOptions?: Record<string, unknown>;
backupPath?: string;
reportDir?: string;
signal?: AbortSignal;
};
/** Migration source implemented by a plugin and orchestrated by `openclaw migrate`. */
type MigrationProviderPlugin$1 = {
id: string;
label: string;
description?: string;
/** Item kinds this provider can expose without requiring a full plan. */
supportedItemKinds?: readonly string[];
/** Required when this provider plans items for `after-promotion`. */
deferredApply?: MigrationDeferredApplyContract;
detect?: (ctx: MigrationProviderContext) => MigrationDetection | Promise<MigrationDetection>;
prepareApply?: (ctx: MigrationProviderContext) => MigrationProviderPreparation | Promise<MigrationProviderPreparation | undefined> | undefined;
plan: (ctx: MigrationProviderContext) => MigrationPlan | Promise<MigrationPlan>;
apply: (ctx: MigrationProviderContext, plan?: MigrationPlan) => MigrationApplyResult | Promise<MigrationApplyResult>;
};
type PluginSetupAutoEnableContext = {
config: OpenClawConfig;
env: NodeJS.ProcessEnv;
};
type PluginSetupAutoEnableProbe = (ctx: PluginSetupAutoEnableContext) => string | string[] | null | undefined;
//#endregion
//#region src/plugins/embedding-provider-types.d.ts
/** Input accepted by embedding providers, including multimodal inline-data parts. */
type EmbeddingInput = string | {
text: string;
parts?: Array<{
type: "text";
text: string;
} | {
type: "inline-data";
mimeType: string;
data: string;
}>;
};
/** Per-call options passed to embedding provider calls. */
type EmbeddingProviderCallOptions = {
signal?: AbortSignal;
inputType?: "query" | "document" | "semantic" | "classification" | "clustering";
};
/** Runtime metadata returned with a created embedding provider. */
type EmbeddingProviderRuntime = {
id: string;
cacheKeyData?: Record<string, unknown>;
/** Prior persisted model/cache identities that are equivalent to the current identity. */
indexIdentityAliases?: Array<{
model: string;
cacheKeyData: Record<string, unknown>;
}>;
inlineQueryTimeoutMs?: number;
inlineBatchTimeoutMs?: number;
};
/** Provider-owned canonical identity and exact aliases for persisted indexes. */
type EmbeddingProviderIndexIdentity = {
model: string;
cacheKeyData: Record<string, unknown>;
aliases?: Array<{
model: string;
cacheKeyData: Record<string, unknown>;
}>;
};
/** Created embedding provider instance used by memory/search callers. */
type EmbeddingProvider = {
id: string;
model: string;
dimensions?: number;
maxInputTokens?: number;
embed: (input: EmbeddingInput, options?: EmbeddingProviderCallOptions) => Promise<number[]>;
embedBatch: (inputs: EmbeddingInput[], options?: EmbeddingProviderCallOptions) => Promise<number[][]>;
close?: () => Promise<void> | void;
};
/** Options passed to embedding provider adapters when creating providers. */
type EmbeddingProviderCreateOptions = {
config: OpenClawConfig;
agentDir?: string;
provider?: string;
remote?: {
baseUrl?: string;
apiKey?: SecretInput;
headers?: Record<string, string>;
};
model: string;
inputType?: string;
queryInputType?: string;
documentInputType?: string;
local?: {
modelPath?: string;
modelCacheDir?: string;
};
dimensions?: number;
taskType?: string;
};
/** Result returned by an embedding provider adapter create call. */
type EmbeddingProviderCreateResult = {
provider: EmbeddingProvider | null;
runtime?: EmbeddingProviderRuntime;
};
/** Adapter contract registered by core or plugin embedding providers. */
type EmbeddingProviderAdapter = {
id: string;
defaultModel?: string;
transport?: "local" | "remote";
authProviderId?: string;
/** Canonical model from config only: synchronous, without auth or network access. */
normalizeModel?: (options: EmbeddingProviderCreateOptions) => string;
resolveIndexIdentity?: (options: EmbeddingProviderCreateOptions) => EmbeddingProviderIndexIdentity;
create: (options: EmbeddingProviderCreateOptions) => Promise<EmbeddingProviderCreateResult>;
formatSetupError?: (err: unknown) => string;
};
//#endregion
//#region src/plugins/gateway-events.d.ts
type OpenClawPluginGatewayEventScope = "operator.read" | "operator.write" | "operator.admin";
type OpenClawPluginSessionsChangedEvent = {
sessionKey: string;
agentId?: string;
label?: string;
displayName?: string;
reason?: string;
phase?: string;
};
type OpenClawPluginGatewayEvents = {
emit: (event: string, payload: PluginJsonValue, opts: {
scope: OpenClawPluginGatewayEventScope;
}) => void;
/**
* Native plugins can already read full session entries through the injected runtime;
* this notice only avoids polling and does not widen session access.
*/
onSessionsChanged: (handler: (event: OpenClawPluginSessionsChangedEvent) => void) => () => void;
};
//#endregion
//#region src/infra/diagnostic-event-listener-presence.d.ts
/** Process-wide listener counts used to avoid telemetry work without consumers. */
type InternalDiagnosticEventInterest<EventType extends string = string> = Readonly<{
include?: readonly EventType[];
exclude?: readonly EventType[];
}>;
//#endregion
//#region src/agents/embedded-agent-runner/execution-phase.d.ts
/**
* Ordered execution milestones reported by the embedded runner while a turn starts up.
*
* Keep labels stable: external status surfaces and diagnostics consume the formatted values.
*/
declare const EMBEDDED_AGENT_EXECUTION_PHASES: readonly ["runner_entered", "workspace", "runtime_plugins", "before_agent_reply", "model_resolution", "auth", "context_engine", "attempt_dispatch", "context_assembled", "turn_accepted", "process_spawned", "tool_execution_started", "assistant_output_started", "model_call_started"];
type EmbeddedAgentExecutionPhase = (typeof EMBEDDED_AGENT_EXECUTION_PHASES)[number];
//#endregion
//#region src/infra/diagnostic-events.d.ts
type DiagnosticSessionState = "idle" | "processing" | "waiting";
type DiagnosticBaseEvent = {
ts: number;
seq: number;
trace?: DiagnosticTraceContext;
};
/** Payload-free facts from authenticated Gateway WebSocket request owners. */
type DiagnosticGatewayRpcEvent = DiagnosticBaseEvent & {
type: "gateway.rpc";
/** Canonical core method name, or a fixed other/unknown bucket. */
method: string;
} & ({
phase: "received";
} | {
phase: "response";
outcome: "ok" | "error" | "unavailable" | "suppressed";
durationMs: number;
} | {
phase: "handler";
outcome: "returned" | "threw";
durationMs: number;
admissionMs: number;
} | {
phase: "dispatch";
outcome: "returned" | "threw" | "rejected" | "cancelled";
durationMs: number;
queueWaitMs?: number;
response: "none" | "sent" | "unavailable" | "suppressed";
});
type DiagnosticUsageEvent = DiagnosticBaseEvent & {
type: "model.usage";
sessionKey?: string;
sessionId?: string;
channel?: string;
agentId?: string;
provider?: string;
model?: string;
usage: {
input?: number;
output?: number;
cacheRead?: number;
cacheWrite?: number;
promptTokens?: number;
total?: number;
};
lastCallUsage?: {
input?: number;
output?: number;
cacheRead?: number;
cacheWrite?: number;
total?: number;
};
context?: {
limit?: number;
used?: number;
};
costUsd?: number;
durationMs?: number;
};
type DiagnosticFailoverEvent = DiagnosticBaseEvent & {
type: "model.failover";
sessionId?: string;
sessionKey?: string;
lane?: string;
fromProvider?: string;
fromModel?: string;
toProvider?: string;
toModel?: string;
reason: string;
cascadeDepth?: number;
suspended?: boolean;
};
type DiagnosticSecurityEventActor = {
kind: "operator" | "node" | "agent" | "plugin" | "channel_sender" | "system";
idHash?: string;
deviceIdHash?: string;
channel?: string;
role?: string;
scopes?: string[];
};
type DiagnosticSecurityEventTarget = {
kind: "gateway" | "device" | "node" | "tool" | "plugin" | "secret_ref" | "channel" | "config" | "session";
idHash?: string;
name?: string;
owner?: string;
};
type DiagnosticSecurityEventPolicy = {
id?: string;
decision?: "allow" | "deny" | "ask" | "auto" | "full" | "not_applicable";
reason?: string;
};
type DiagnosticSecurityEventControl = {
id?: string;
family?: "auth" | "authorization" | "approval" | "sandbox" | "secret" | "supply_chain";
};
type DiagnosticSecurityEvent = DiagnosticBaseEvent & {
type: "security.event";
eventId: string;
category: "auth" | "approval" | "tool" | "plugin" | "secret" | "channel" | "config" | "audit" | "telemetry";
action: string;
outcome: "success" | "failure" | "denied" | "error";
severity: "info" | "low" | "medium" | "high" | "critical";
actor?: DiagnosticSecurityEventActor;
target?: DiagnosticSecurityEventTarget;
policy?: DiagnosticSecurityEventPolicy;
control?: DiagnosticSecurityEventControl;
reason?: string;
attributes?: Record<string, string | number | boolean>;
};
type DiagnosticWebhookReceivedEvent = DiagnosticBaseEvent & {
type: "webhook.received";
channel: string;
updateType?: string;
chatId?: number | string;
};
type DiagnosticWebhookProcessedEvent = DiagnosticBaseEvent & {
type: "webhook.processed";
channel: string;
updateType?: string;
chatId?: number | string;
durationMs?: number;
};
type DiagnosticWebhookErrorEvent = DiagnosticBaseEvent & {
type: "webhook.error";
channel: string;
updateType?: string;
chatId?: number | string;
error: string;
};
type DiagnosticMessageQueuedEvent = DiagnosticBaseEvent & {
type: "message.queued";
sessionKey?: string;
sessionId?: string;
channel?: string;
source: string;
queueDepth?: number;
};
type DiagnosticMessageReceivedEvent = DiagnosticBaseEvent & {
type: "message.received";
sessionKey?: string;
sessionId?: string;
channel?: string;
messageId?: number | string;
chatId?: number | string;
source: string;
};
type DiagnosticMessageDispatchStartedEvent = DiagnosticBaseEvent & {
type: "message.dispatch.started";
sessionKey?: string;
sessionId?: string;
channel?: string;
source: string;
};
type DiagnosticMessageDispatchCompletedEvent = DiagnosticBaseEvent & {
type: "message.dispatch.completed";
sessionKey?: string;
sessionId?: string;
channel?: string;
source: string;
durationMs: number;
outcome: "completed" | "skipped" | "error";
reason?: string;
error?: string;
};
type DiagnosticMessageProcessedEvent = DiagnosticBaseEvent & {
type: "message.processed";
channel: string;
messageId?: number | string;
chatId?: number | string;
sessionKey?: string;
sessionId?: string;
durationMs?: number;
outcome: "completed" | "skipped" | "error";
reason?: string;
error?: string;
};
type DiagnosticMessageDeliveryKind = "text" | "media" | "edit" | "reaction" | "other";
type DiagnosticMessageDeliveryBaseEvent = DiagnosticBaseEvent & {
channel: string;
sessionKey?: string;
deliveryKind: DiagnosticMessageDeliveryKind;
};
type DiagnosticMessageDeliveryStartedEvent = DiagnosticMessageDeliveryBaseEvent & {
type: "message.delivery.started";
};
type DiagnosticMessageDeliveryCompletedEvent = DiagnosticMessageDeliveryBaseEvent & {
type: "message.delivery.completed";
durationMs: number;
resultCount: number;
};
type DiagnosticMessageDeliveryErrorEvent = DiagnosticMessageDeliveryBaseEvent & {
type: "message.delivery.error";
durationMs: number;
errorCategory: string;
};
type DiagnosticTalkEvent = DiagnosticBaseEvent & {
type: "talk.event";
sessionId?: string;
turnId?: string;
captureId?: string;
talkEventType: TalkEventType;
mode: TalkMode;
transport: TalkTransport;
brain: TalkBrain;
provider?: string;
final?: boolean;
durationMs?: number;
byteLength?: number;
};
type DiagnosticSessionStateEvent = DiagnosticBaseEvent & {
type: "session.state";
sessionKey?: string;
sessionId?: string;
prevState?: DiagnosticSessionState;
state: DiagnosticSessionState;
reason?: string;
queueDepth?: number;
};
type DiagnosticSessionActiveWorkKind = "embedded_run" | "model_call" | "tool_call";
type DiagnosticSessionAttentionClassification = "long_running" | "blocked_tool_call" | "stalled_agent_run" | "stale_session_state";
type DiagnosticSessionAttentionBaseEvent = DiagnosticBaseEvent & {
sessionKey?: string;
sessionId?: string;
state: DiagnosticSessionState;
ageMs: number;
queueDepth?: number;
reason?: string;
classification: DiagnosticSessionAttentionClassification;
activeWorkKind?: DiagnosticSessionActiveWorkKind;
lastProgressAgeMs?: number;
lastProgressReason?: string;
activeToolName?: string;
activeToolCallId?: string;
activeToolAgeMs?: number;
repeatedRequestNoProgressAgeMs?: number;
terminalProgressStale?: boolean;
};
type DiagnosticSessionLongRunningEvent = DiagnosticSessionAttentionBaseEvent & {
type: "session.long_running";
classification: "long_running";
};
type DiagnosticSessionStalledEvent = DiagnosticSessionAttentionBaseEvent & {
type: "session.stalled";
classification: "blocked_tool_call" | "stalled_agent_run";
};
type DiagnosticSessionStuckEvent = DiagnosticSessionAttentionBaseEvent & {
type: "session.stuck";
classification: "stale_session_state";
};
type DiagnosticSessionRecoveryStatus = "aborted" | "released" | "skipped" | "noop" | "failed";
type DiagnosticSessionRecoveryBaseEvent = DiagnosticBaseEvent & {
sessionKey?: string;
sessionId?: string;
state: DiagnosticSessionState;
stateGeneration?: number;
ageMs: number;
queueDepth?: number;
reason?: string;
activeWorkKind?: DiagnosticSessionActiveWorkKind;
allowActiveAbort?: boolean;
};
type DiagnosticSessionRecoveryRequestedEvent = DiagnosticSessionRecoveryBaseEvent & {
type: "session.recovery.requested";
};
type DiagnosticSessionRecoveryCompletedEvent = DiagnosticSessionRecoveryBaseEvent & {
type: "session.recovery.completed";
status: DiagnosticSessionRecoveryStatus;
action: string;
outcomeReason?: string;
released?: number;
stale?: boolean;
};
type DiagnosticSessionTurnCreatedEvent = DiagnosticBaseEvent & {
type: "session.turn.created";
runId: string;
sessionKey?: string;
sessionId?: string;
agentId?: string;
channel?: string;
trigger: "user" | "heartbeat";
};
type DiagnosticLaneEnqueueEvent = DiagnosticBaseEvent & {
type: "queue.lane.enqueue";
lane: string;
queueSize: number;
};
type DiagnosticLaneDequeueEvent = DiagnosticBaseEvent & {
type: "queue.lane.dequeue";
lane: string;
queueSize: number;
waitMs: number;
};
type DiagnosticRunAttemptEvent = DiagnosticBaseEvent & {
type: "run.attempt";
sessionKey?: string;
sessionId?: string;
runId: string;
attempt: number;
};
type DiagnosticRunProgressEvent = DiagnosticBaseEvent & {
type: "run.progress";
sessionKey?: string;
sessionId?: string;
runId?: string;
reason: string;
};
/**
* Session-correlated embedded-runner execution milestone. Emitted for every
* phase transition so external status surfaces can render turn startup
* without a control-UI subscription. `phase` is the closed
* EmbeddedAgentExecutionPhase contract (type-only import keeps this module
* runtime-independent of the agents layer).
*/
type DiagnosticRunExecutionPhaseEvent = DiagnosticBaseEvent & {
type: "run.execution_phase";
sessionKey?: string;
sessionId: string;
runId: string;
phase: EmbeddedAgentExecutionPhase;
provider?: string;
model?: string;
backend?: string;
source?: string;
tool?: string;
toolCallId?: string;
itemId?: string;
firstModelCallStarted?: boolean;
};
type DiagnosticGatewayEventLoopSampleEvent = DiagnosticBaseEvent & {
type: "gateway.event_loop.sample";
intervalMs: number;
delayMaxMs: number;
};
type DiagnosticHeartbeatEvent = DiagnosticBaseEvent & {
type: "diagnostic.heartbeat";
webhooks: {
received: number;
processed: number;
errors: number;
};
active: number;
waiting: number;
queued: number;
};
type DiagnosticLivenessWarningReason = "event_loop_delay" | "event_loop_utilization" | "cpu";
type DiagnosticPhaseDetails = Record<string, string | number | boolean>;
type DiagnosticPhaseSnapshot = {
name: string;
startedAt: number;
endedAt?: number;
durationMs?: number;
cpuUserMs?: number;
cpuSystemMs?: number;
cpuTotalMs?: number;
cpuCoreRatio?: number;
details?: DiagnosticPhaseDetails;
};
type DiagnosticLivenessWarningEvent = DiagnosticBaseEvent & {
type: "diagnostic.liveness.warning";
reasons: DiagnosticLivenessWarningReason[];
intervalMs: number;
degradedSinceMs?: number;
eventLoopDelayP99Ms?: number;
eventLoopDelayMaxMs?: number;
eventLoopUtilization?: number;
cpuUserMs?: number;
cpuSystemMs?: number;
cpuTotalMs?: number;
cpuCoreRatio?: number;
active: number;
waiting: number;
queued: number;
phase?: string;
recentPhases?: DiagnosticPhaseSnapshot[];
activeWorkLabels?: string[];
waitingWorkLabels?: string[];
queuedWorkLabels?: string[];
};
type DiagnosticPhaseCompletedEvent = DiagnosticBaseEvent & DiagnosticPhaseSnapshot & {
type: "diagnostic.phase.completed";
};
type DiagnosticToolLoopEvent = DiagnosticBaseEvent & {
type: "tool.loop";
sessionKey?: string;
sessionId?: string;
toolName: string;
level: "warning" | "critical";
action: "warn" | "block";
detector: "generic_repeat" | "argument_churn" | "unknown_tool_repeat" | "known_poll_no_progress" | "global_circuit_breaker" | "ping_pong";
count: number;
message: string;
pairedToolName?: string;
};
type DiagnosticToolParamsSummary = {
kind: "object";
} | {
kind: "array";
length: number;
} | {
kind: "string";
length: number;
} | {
kind: "number" | "boolean" | "null" | "undefined" | "other";
};
type DiagnosticToolSource = "channel" | "core" | "mcp" | "plugin";
type DiagnosticToolTerminalReason = "failed" | "cancelled" | "timed_out";
type DiagnosticToolExecutionBaseEvent = DiagnosticBaseEvent & {
runId?: string;
sessionKey?: string;
sessionId?: string;
agentId?: string;
/** Authoritative lifecycle time from the tool runtime, when it exposes one. */
sourceTimestampMs?: number;
toolName: string;
toolSource?: DiagnosticToolSource;
toolOwner?: string;
toolCallId?: string;
paramsSummary?: DiagnosticToolParamsSummary;
/** Deterministic mutation classification computed before tool execution. */
mutatingAction?: boolean;
};
type DiagnosticToolExecutionStartedEvent = DiagnosticToolExecutionBaseEvent & {
type: "tool.execution.started";
};
type DiagnosticToolExecutionCompletedEvent = DiagnosticToolExecutionBaseEvent & {
type: "tool.execution.completed";
durationMs: number;
};
type DiagnosticToolExecutionErrorEvent = DiagnosticToolExecutionBaseEvent & {
type: "tool.execution.error";
durationMs: number;
errorCategory: string;
errorCode?: string;
terminalReason?: DiagnosticToolTerminalReason;
};
type DiagnosticToolExecutionBlockedEvent = DiagnosticToolExecutionBaseEvent & {
type: "tool.execution.blocked";
deniedReason: string;
reason: string;
};
type DiagnosticSkillTelemetrySource = "bundled" | "unknown" | "workspace";
type DiagnosticSkillActivation = "command" | "read";
type DiagnosticSkillUsedEvent = DiagnosticBaseEvent & {
type: "skill.used";
runId?: string;
sessionKey?: string;
sessionId?: string;
agentId?: string;
skillName: string;
skillSource: DiagnosticSkillTelemetrySource;
activation: DiagnosticSkillActivation;
toolName?: string;
toolCallId?: string;
};
type DiagnosticExecProcessCompletedEvent = DiagnosticBaseEvent & {
type: "exec.process.completed";
sessionKey?: string;
target: "host" | "sandbox";
mode: "child" | "pty";
outcome: "completed" | "failed";
durationMs: number;
commandLength: number;
exitCode?: number;
exitSignal?: string;
timedOut?: boolean;
failureKind?: "shell-command-not-found" | "shell-not-executable" | "overall-timeout" | "no-output-timeout" | "signal" | "aborted" | "runtime-error";
};
type DiagnosticExecApprovalFollowupSuppressedEvent = DiagnosticBaseEvent & {
type: "exec.approval.followup_suppressed";
approvalId: string;
reason: "session_rebound";
phase: "direct_delivery" | "gateway_preflight";
};
type DiagnosticRunBaseEvent = DiagnosticBaseEvent & {
runId: string;
sessionKey?: string;
sessionId?: string;
provider?: string;
model?: string;
trigger?: string;
channel?: string;
};
type DiagnosticRunStartedEvent = DiagnosticRunBaseEvent & {
type: "run.started";
};
type DiagnosticRunCompletedEvent = DiagnosticRunBaseEvent & {
type: "run.completed";
durationMs: number;
outcome: "completed" | "aborted" | "blocked" | "error";
errorCategory?: string;
blockedBy?: string;
};
type DiagnosticHarnessRunPhase = "prepare" | "start" | "send" | "resolve" | "cleanup";
type DiagnosticHarnessRunOutcome = "completed" | "aborted" | "timed_out" | "error";
type DiagnosticHarnessRunBaseEvent = DiagnosticBaseEvent & {
type: "harness.run.started" | "harness.run.completed" | "harness.run.error";
runId: string;
sessionKey?: string;
sessionId?: string;
provider?: string;
model?: string;
trigger?: string;
channel?: string;
harnessId: string;
pluginId?: string;
};
type DiagnosticHarnessRunStartedEvent = DiagnosticHarnessRunBaseEvent & {
type: "harness.run.started";
};
type DiagnosticHarnessRunCompletedEvent = DiagnosticHarnessRunBaseEvent & {
type: "harness.run.completed";
durationMs: number;
outcome: DiagnosticHarnessRunOutcome;
resultClassification?: "empty" | "reasoning-only" | "planning-only";
yieldDetected?: boolean;
itemLifecycle?: {
startedCount: number;
completedCount: number;
activeCount: number;
};
};
type DiagnosticHarnessRunErrorEvent = DiagnosticHarnessRunBaseEvent & {
type: "harness.run.error";
durationMs: number;
phase: DiagnosticHarnessRunPhase;
errorCategory: string;
cleanupFailed?: boolean;
};
type DiagnosticModelCallBaseEvent = DiagnosticBaseEvent & {
type: "model.call.started" | "model.call.completed" | "model.call.error";
runId: string;
callId: string;
sessionKey?: string;
sessionId?: string;
provider: string;
model: string;
api?: string;
transport?: string;
/** Defaults to request for emitters created before turn-level CLI diagnostics. */
observationUnit?: "request" | "turn";
contextTokenBudget?: number;
contextWindowSource?: "model" | "modelsConfig" | "agentContextTokens" | "default";
contextWindowReferenceTokens?: number;
upstreamRequestIdHash?: string;
promptStats?: DiagnosticModelCallPromptStats;
};
type DiagnosticModelCallStartedEvent = DiagnosticModelCallBaseEvent & {
type: "model.call.started";
};
type DiagnosticModelCallCompletedEvent = DiagnosticModelCallBaseEvent & {
type: "model.call.completed";
durationMs: number;
requestPayloadBytes?: number;
responseStreamBytes?: number;
timeToFirstByteMs?: number;
usage?: DiagnosticModelCallUsage;
};
type DiagnosticModelCallErrorEvent = DiagnosticModelCallBaseEvent & {
type: "model.call.error";
durationMs: number;
errorCategory: string;
failureKind?: "aborted" | "connection_closed" | "connection_reset" | "terminated" | "timeout";
memory?: DiagnosticMemoryUsage;
requestPayloadBytes?: number;
responseStreamBytes?: number;
timeToFirstByteMs?: number;
usage?: DiagnosticModelCallUsage;
};
type DiagnosticModelCallPromptStats = Readonly<{
inputMessagesCount?: number;
inputMessagesChars?: number;
systemPromptChars?: number;
toolDefinitionsCount?: number;
toolDefinitionsChars?: number;
totalChars?: number;
}>;
type DiagnosticModelCallUsage = Readonly<{
input?: number;
output?: number;
cacheRead?: number;
cacheWrite?: number;
reasoningTokens?: number;
promptTokens?: number;
total?: number;
}>;
type DiagnosticContextAssembledEvent = DiagnosticBaseEvent & {
type: "context.assembled";
runId: string;
sessionKey?: string;
sessionId?: string;
provider: string;
model: string;
channel?: string;
trigger?: string;
messageCount: number;
historyTextChars: number;
historyImageBlocks: number;
maxMessageTextChars: number;
systemPromptChars: number;
promptChars: number;
promptImages: number;
contextTokenBudget?: number;
reserveTokens?: number;
};
type DiagnosticMemoryUsage = {
rssBytes: number;
heapTotalBytes: number;
heapUsedBytes: number;
externalBytes: number;
arrayBuffersBytes: number;
};
type DiagnosticMemorySampleEvent = DiagnosticBaseEvent & {
type: "diagnostic.memory.sample";
memory: DiagnosticMemoryUsage;
uptimeMs?: number;
};
type DiagnosticMemoryPressureEvent = DiagnosticBaseEvent & {
type: "diagnostic.memory.pressure";
level: "warning" | "critical";
reason: "rss_threshold" | "heap_threshold" | "rss_growth";
memory: DiagnosticMemoryUsage;
thresholdBytes?: number;
rssGrowthBytes?: number;
windowMs?: number;
};
type DiagnosticPayloadLargeEvent = DiagnosticBaseEvent & {
type: "payload.large";
surface: string;
action: "rejected" | "truncated" | "chunked";
bytes?: number;
limitBytes?: number;
count?: number;
channel?: string;
pluginId?: string;
reason?: string;
};
type DiagnosticLogRecordEvent = DiagnosticBaseEvent & {
type: "log.record";
level: string;
message: string;
loggerName?: string;
loggerParents?: string[];
attributes?: Record<string, string | number | boolean>;
code?: {
line?: number;
functionName?: string;
};
};
type DiagnosticTelemetryExporterEvent = DiagnosticBaseEvent & {
type: "telemetry.exporter";
exporter: string;
signal: "traces" | "metrics" | "logs";
status: "started" | "failure" | "dropped";
reason?: "configured" | "emit_failed" | "handler_failed" | "queue_full" | "shutdown_failed" | "start_failed" | "unsupported_protocol";
errorCategory?: string;
};
type DiagnosticAsyncQueueDroppedEvent = DiagnosticBaseEvent & {
type: "diagnostic.async_queue.dropped";
droppedEvents: number;
droppedTrustedEvents?: number;
droppedUntrustedEvents?: number;
droppedPriorityEvents?: number;
queueLength: number;
maxQueueLength: number;
drainBatchSize: number;
};
type DiagnosticEventPayload = DiagnosticGatewayRpcEvent | DiagnosticUsageEvent | DiagnosticWebhookReceivedEvent | DiagnosticWebhookProcessedEvent | DiagnosticWebhookErrorEvent | DiagnosticMessageQueuedEvent | DiagnosticMessageReceivedEvent | DiagnosticMessageDispatchStartedEvent | DiagnosticMessageDispatchCompletedEvent | DiagnosticMessageProcessedEvent | DiagnosticMessageDeliveryStartedEvent | DiagnosticMessageDeliveryCompletedEvent | DiagnosticMessageDeliveryErrorEvent | DiagnosticTalkEvent | DiagnosticSessionStateEvent | DiagnosticSessionLongRunningEvent | DiagnosticSessionStalledEvent | DiagnosticSessionStuckEvent | DiagnosticSessionRecoveryRequestedEvent | DiagnosticSessionRecoveryCompletedEvent | DiagnosticSessionTurnCreatedEvent | DiagnosticLaneEnqueueEvent | DiagnosticLaneDequeueEvent | DiagnosticRunAttemptEvent | DiagnosticRunProgressEvent | DiagnosticRunExecutionPhaseEvent | DiagnosticGatewayEventLoopSampleEvent | DiagnosticHeartbeatEvent | DiagnosticLivenessWarningEvent | DiagnosticPhaseCompletedEvent | DiagnosticToolLoopEvent | DiagnosticToolExecutionStartedEvent | DiagnosticToolExecutionCompletedEvent | DiagnosticToolExecutionErrorEvent | DiagnosticToolExecutionBlockedEvent | DiagnosticSkillUsedEvent | DiagnosticExecProcessCompletedEvent | DiagnosticExecApprovalFollowupSuppressedEvent | DiagnosticRunStartedEvent | DiagnosticRunCompletedEvent | DiagnosticHarnessRunStartedEvent | DiagnosticHarnessRunCompletedEvent | DiagnosticHarnessRunErrorEvent | DiagnosticModelCallStartedEvent | DiagnosticModelCallCompletedEvent | DiagnosticModelCallErrorEvent | DiagnosticContextAssembledEvent | DiagnosticMemorySampleEvent | DiagnosticMemoryPressureEvent | DiagnosticPayloadLargeEvent | DiagnosticLogRecordEvent | DiagnosticSecurityEvent | DiagnosticTelemetryExporterEvent | DiagnosticAsyncQueueDroppedEvent | DiagnosticFailoverEvent;
type DiagnosticNonSecurityEventPayload = Exclude<DiagnosticEventPayload, DiagnosticSecurityEvent>;
type DiagnosticEventInput = DiagnosticNonSecurityEventPayload extends (infer Event) ? Event extends DiagnosticEventPayload ? Omit<Event, "seq" | "ts"> : never : never;
type DiagnosticEventMetadata = Readonly<{
internal?: boolean;
trustedTraceContext?: boolean;
trusted: boolean;
}>;
type DiagnosticModelCallContent = Readonly<{
inputMessages?: unknown;
outputMessages?: unknown;
systemPrompt?: string;
toolDefinitions?: unknown;
}>;
type DiagnosticToolCallContent = Readonly<{
toolInput?: unknown;
toolOutput?: unknown;
}>;
type DiagnosticSkillUsagePrivateData = Readonly<{
skillFile: string;
}>;
type DiagnosticEventPrivateData = Readonly<{
/** Raw failure text for trusted diagnostics exporters; never part of the public event payload. */
errorMessage?: string;
modelContent?: DiagnosticModelCallContent;
skillUsage?: DiagnosticSkillUsagePrivateData;
toolContent?: DiagnosticToolCallContent;
}>;
//#endregion
//#region src/infra/diagnostic-trace-propagation.d.ts
type DiagnosticTracePropagationBridge$1<TEvent, TMetadata> = Readonly<{
/** Selects events that need synchronous exporter preparation. */
shouldPrepareEvent?: (event: TEvent) => boolean;
/** Prepares exporter-owned state before an outbound caller can resolve it. */
prepareEvent?: (event: TEvent, metadata: TMetadata) => void;
/** Translates a diagnostic correlation context to an exporter-owned context. */
resolveTraceContext: (traceContext: DiagnosticTraceContext) => DiagnosticTraceContext | undefined;
}>;
//#endregion
//#region src/plugins/plugin-registration.types.d.ts
type ChannelPlugin$2 = ChannelPlugin$3;
type DiagnosticTracePropagationBridge = DiagnosticTracePropagationBridge$1<DiagnosticEventPayload, DiagnosticEventMetadata>;
type PluginInteractiveHandlerResult = {
handled?: boolean;
} | void;
type PluginInteractiveRegistration<TContext = unknown, TChannel extends string = string, TResult = PluginInteractiveHandlerResult> = {
channel: TChannel;
namespace: string;
handler: (ctx: TContext) => Promise<TResult> | TResult;
};
type PluginInteractiveHandlerRegistration$1 = PluginInteractiveRegistration;
type OpenClawPluginHttpRouteAuth = "gateway" | "plugin";
type OpenClawPluginHttpRouteMatch$1 = "exact" | "prefix";
type OpenClawPluginGatewayRuntimeScopeSurface$1 = "write-default" | "trusted-operator";
type OpenClawPluginHttpRouteHandler$1 = (req: IncomingMessage, res: ServerResponse) => Promise<boolean | void> | boolean | void;
type OpenClawPluginHttpRouteUpgradeHandler = (req: IncomingMessage, socket: Duplex, head: Buffer) => Promise<boolean | void> | boolean | void;
type OpenClawPluginHttpRouteParams = {
path: string;
handler: OpenClawPluginHttpRouteHandler$1;
handleUpgrade?: OpenClawPluginHttpRouteUpgradeHandler;
auth: OpenClawPluginHttpRouteAuth;
match?: OpenClawPluginHttpRouteMatch$1;
gatewayRuntimeScopeSurface?: OpenClawPluginGatewayRuntimeScopeSurface$1;
nodeCapability?: {
surface: string;
ttlMs?: number;
};
replaceExisting?: boolean;
};
type OpenClawPluginHostedMediaResolver$1 = (mediaUrl: string) => string | null | undefined | Promise<string | null | undefined>;
type WidgetPresenterContext = Readonly<{
messageChannel?: string;
accountId?: string;
deliveryContext?: Readonly<DeliveryContext>;
nativeChannelId?: string;
currentChannelId?: string;
currentMessagingTarget?: string;
sessionKey?: string;
}>;
type WidgetPresenterDocument = Readonly<{
kind: "html";
html: string;
hostedUrl?: string;
}>;
type WidgetPresentationError = {
code: "no_eligible_node";
message: string;
} | {
code: "node_error";
message: string;
nodeId?: string;
} | {
code: "unavailable";
message: string;
} | {
code: "presentation_error";
message: string;
};
type WidgetPresentationSuccess = {
kind: "node";
nodeId: string;
nodeName?: string;
} | {
kind: "message";
receipt: MessageReceipt;
};
type WidgetPresenterBase = {
description: string;
availability: (context: WidgetPresenterContext) => Promise<Result<{
available: true;
}, WidgetPresentationError>>;
present: (params: {
document: WidgetPresenterDocument;
title: string;
context: WidgetPresenterContext;
}) => Promise<Result<WidgetPresentationSuccess, WidgetPresentationError>>;
};
type WidgetPresenter = WidgetPresenterBase & ({
target: "node_panel";
match?: never;
capabilities?: never;
} | {
target: "current_channel";
match: (context: WidgetPresenterContext) => boolean;
capabilities: Readonly<{
sourceKinds: readonly string[];
maxSourceBytes?: number;
}>;
});
type OpenClawPluginCliContext = {
/**
* Command object where this plugin should register its commands.
*
* For root CLI registrations this is the root `openclaw` program. For nested
* registrations it is the resolved parent command from `parentPath`.
*/
program: Command;
parentPath: readonly string[];
config: OpenClawConfig;
workspaceDir?: string;
logger: PluginLogger;
};
type OpenClawPluginCliRegistrar$1 = (ctx: OpenClawPluginCliContext) => void | Promise<void>;
/**
* Top-level CLI metadata for plugin-owned commands.
*
* Descriptors are the parse-time contract for lazy plugin CLI registration.
* If you want OpenClaw to keep a plugin command lazy-loaded while still
* advertising it at the root CLI level, provide descriptors that cover every
* top-level command root registered by that plugin CLI surface.
*/
type OpenClawPluginCliCommandDescriptor = {
name: string;
description: string;
hasSubcommands: boolean;
};
/** Root-command metadata that is available before a plugin registrar is activated. */
type OpenClawPluginCliRootCommandDescriptor$1 = OpenClawPluginCliCommandDescriptor & {
machineOutput?: (params: {
argv: readonly string[];
stdoutIsTTY: boolean;
}) => boolean;
};
type OpenClawPluginRootCliRegistrationOptions = {
/** Omit or pass an empty path for root commands. */
parentPath?: readonly [];
commands?: readonly string[];
descriptors?: readonly OpenClawPluginCliRootCommandDescriptor$1[];
};
/** Backward-compatible registration shape for dynamic root or nested paths. */
type OpenClawPluginLegacyCliRegistrationOptions = {
parentPath?: readonly string[];
commands?: readonly string[];
descriptors?: readonly OpenClawPluginCliCommandDescriptor[];
};
type OpenClawPluginCliRegistrationOptions = OpenClawPluginRootCliRegistrationOptions | OpenClawPluginLegacyCliRegistrationOptions;
type OpenClawPluginNodeCliFeatureOptions = {
/** Explicit node feature command names owned under `openclaw nodes`. */
commands?: string[];
/**
* Parse-time command descriptors for lazy node feature CLI registration.
*
* Descriptors are registered under `openclaw nodes`, so a descriptor named
* `"camera"` exposes `openclaw nodes camera`.
*/
descriptors?: OpenClawPluginCliCommandDescriptor[];
};
type OpenClawPluginReloadRegistration$1 = {
restartPrefixes?: string[];
hotPrefixes?: string[];
noopPrefixes?: string[];
};
type OpenClawPluginNodeInvokeTransportResult = {
ok: true;
payload?: unknown;
payloadJSON?: string | null;
} | {
ok: false;
code?: string;
message: string;
details?: Record<string, unknown>;
};
type OpenClawPluginNodeInvokeApprovalDecision = "allow-once" | "allow-always" | "deny";
type OpenClawPluginNodeInvokePolicyApprovalRuntime = {
request: (input: {
title: string;
description: string;
scope?: ApprovalScope;
severity?: "info" | "warning" | "critical";
toolName?: string;
toolCallId?: string;
agentId?: string;
sessionKey?: string;
allowedDecisions?: readonly OpenClawPluginNodeInvokeApprovalDecision[];
timeoutMs?: number;
}) => Promise<{
id?: string;
decision?: OpenClawPluginNodeInvokeApprovalDecision | null;
}>;
};
type OpenClawPluginNodeInvokePolicyContext = {
nodeId: string;
command: string;
params: unknown;
timeoutMs?: number;
idempotencyKey?: string;
config: OpenClawConfig;
pluginConfig?: Record<string, unknown>;
node?: {
nodeId: string;
displayName?: string;
platform?: string;
deviceFamily?: string;
commands?: string[];
};
client?: {
connId?: string;
scopes?: string[];
} | null;
risk?: {
level: "ordinary" | "high";
/** Stable, content-free family name; never include user or action arguments. */
family: string;
};
approvals?: OpenClawPluginNodeInvokePolicyApprovalRuntime;
/** Full covers only the selected harness's declared node commands; undefined requires a human decision. */
invokeNodeWithSessionFull?: (input: {
workspace: OpenClawPluginNodeWorkspace;
/** Called only after the host authorizes this exact admitted Full launch. */
createParams: () => unknown;
}) => Promise<OpenClawPluginNodeInvokeTransportResult | undefined>;
invokeNode: (input?: {
params?: unknown;
/** Bind an approved launch to its admitted managed workspace, when present. */
workspace?: OpenClawPluginNodeWorkspace;
timeoutMs?: number;
idempotencyKey?: string;
}) => Promise<OpenClawPluginNodeInvokeTransportResult>;
};
type OpenClawPluginNodeInvokePolicyResult = {
ok: true;
payload?: unknown;
payloadJSON?: string | null;
} | {
ok: false;
message: string;
code?: string;
details?: Record<string, unknown>;
unavailable?: boolean;
};
type OpenClawPluginNodeInvokePolicy = {
commands: string[];
/**
* Platforms where these node-handled commands should be allowlisted by default.
* Omit for commands that require explicit `gateway.nodes.commands.allow`.
*/
defaultPlatforms?: Array<"ios" | "android" | "macos" | "windows" | "linux" | "unknown">;
/**
* Dangerous policy commands are filtered out of default allowlists unless
* explicitly allowed by config.
*/
dangerous?: boolean;
/**
* Explicitly permits one approval to cover later launches on the same managed placement.
* The scope is a stable semantic capability key, never user or action arguments.
*/
standingApproval?: {
kind: "placement";
scope: string;
};
/**
* iOS foreground-restricted commands should be queued for foreground delivery
* when an iOS node reports BACKGROUND_UNAVAILABLE.
*/
foregroundRestrictedOnIos?: boolean;
/**
* Classify exact command arguments before the policy handler or node transport runs.
* Throwing rejects the invocation before dispatch.
*/
classifyRisk?: (ctx: Pick<OpenClawPluginNodeInvokePolicyContext, "command" | "params">) => NonNullable<OpenClawPluginNodeInvokePolicyContext["risk"]>;
handle: (ctx: OpenClawPluginNodeInvokePolicyContext) => Promise<OpenClawPluginNodeInvokePolicyResult> | OpenClawPluginNodeInvokePolicyResult;
};
type OpenClawPluginSecurityAuditContext = {
config: OpenClawConfig;
sourceConfig: OpenClawConfig;
env: NodeJS.ProcessEnv;
stateDir: string;
configPath: string;
};
type OpenClawPluginSecurityAuditCollector$1 = (ctx: OpenClawPluginSecurityAuditContext) => SecurityAuditFinding[] | Promise<SecurityAuditFinding[]>;
type OpenClawGatewayDiscoveryAdvertiseContext = {
machineDisplayName: string;
gatewayPort: number;
gatewayTlsEnabled: boolean;
gatewayTlsFingerprintSha256?: string;
gatewayDirectReachable: boolean;
tailnetDns?: string;
sshPort?: number;
cliPath?: string;
minimal: boolean;
};
type OpenClawGatewayDiscoveryService$1 = {
id: string;
advertise: (ctx: OpenClawGatewayDiscoveryAdvertiseContext) => void | Promise<void | {
stop?: () => void | Promise<void>;
}>;
};
/** Context passed to long-lived plugin services. */
type OpenClawPluginServiceHealth = {
reportFailure: (error: unknown) => void;
clearFailure: () => void;
};
type OpenClawPluginServiceContext = {
config: OpenClawConfig;
workspaceDir?: string;
stateDir: string;
logger: PluginLogger;
serviceHealth?: OpenClawPluginServiceHealth;
/** Gateway-owned scheduler access, revoked when this service stops. */
getCron?: () => PluginHookGatewayCronService | undefined;
gatewayEvents?: OpenClawPluginGatewayEvents;
startupTrace?: {
detail?: (name: string, metrics: ReadonlyArray<readonly [string, number | string]>) => void;
measure: <T>(name: string, run: () => T | Promise<T>) => Promise<T>;
};
internalDiagnostics?: {
emit: (event: DiagnosticEventInput, privateData?: DiagnosticEventPrivateData) => void;
onEvent: (listener: (event: DiagnosticEventPayload, metadata: DiagnosticEventMetadata, privateData: DiagnosticEventPrivateData) => void, filter?: InternalDiagnosticEventInterest<DiagnosticEventPayload["type"]>) => () => void;
registerTracePropagationBridge?: (bridge: DiagnosticTracePropagationBridge) => () => void;
};
};
/** Background service registered by a plugin during `register(api)`. */
type OpenClawPluginService$1 = {
id: string;
/** Restart this service with committed config when one of these paths changes. */
reload?: {
configPrefixes: readonly string[];
};
start: (ctx: OpenClawPluginServiceContext) => void | Promise<void>;
stop?: (ctx: OpenClawPluginServiceContext) => void | Promise<void>;
};
type OpenClawPluginChannelRegistration = {
plugin: ChannelPlugin$2;
};
/**
* Public label exposed to plugin `register(api)` calls.
*
* Keep this as a compatibility signal for plugin authors. Loader internals
* should derive explicit capability booleans from the mode instead of branching
* on raw strings throughout the code path.
*
* - `full`: live runtime activation; long-lived side effects may start.
* - `discovery`: read-only capability discovery; skip sockets/workers/clients.
* - `tool-discovery`: capability discovery for executable tools; skip channel runtime hydration.
* - `setup-only`: lightweight channel setup entry only.
* - `setup-runtime`: setup flow that also needs the runtime channel entry.
* - `cli-metadata`: CLI command metadata collection.
*/
type PluginRegistrationMode = "full" | "discovery" | "tool-discovery" | "setup-only" | "setup-runtime" | "cli-metadata";
//#endregion
//#region src/plugins/capability-catalog.types.d.ts
/** Default export of capabilityCatalogEntry. Each present family is complete, even when empty. */
type PluginCapabilityCatalog = {
speechProviders?: readonly SpeechProviderPlugin$1[];
realtimeTranscriptionProviders?: readonly RealtimeTranscriptionProviderPlugin$1[];
realtimeVoiceProviders?: readonly RealtimeVoiceProviderPlugin$1[];
};
//#endregion
//#region src/agents/failover/signal.d.ts
/** Persisted and wire-visible failover reason codes. Spellings are frozen. */
declare const FAILOVER_REASONS: readonly ["auth", "auth_permanent", "format", "rate_limit", "overloaded", "billing", "server_error", "timeout", "tls_certificate", "context_overflow", "model_not_found", "session_expired", "empty_response", "no_error_details", "unclassified", "unknown"];
type FailoverReason = (typeof FAILOVER_REASONS)[number];
//#endregion
//#region src/auto-reply/reply/normalize-reply-skip-reason.d.ts
type NormalizeReplySkipReason = "empty" | "silent" | "heartbeat" | "channel_transform";
//#endregion
//#region src/cron/runtime-authority.d.ts
type CronRuntimeAuthority = Readonly<{
version: 1;
/** Concrete harness runtime that alone may consume this opaque authority. */
runtimeId: string;
/** Runtime-owned payload discriminator; core never interprets its value. */
namespace: string;
payload: Readonly<Record<string, unknown>>;
}>;
//#endregion
//#region src/cron/types-shared.d.ts
/** Optional dynamic-cadence bounds for one cron job. */
type CronPacing = {
min?: string;
max?: string;
};
/** Shared persisted cron job envelope used by runtime and external config shapes. */
type CronJobBase<TSchedule, TSessionTarget, TWakeMode, TPayload, TDelivery, TFailureAlert> = {
id: string;
agentId?: string;
sessionKey?: string;
name: string;
description?: string;
enabled: boolean;
deleteAfterRun?: boolean;
createdAtMs: number;
updatedAtMs: number;
schedule: TSchedule;
pacing?: CronPacing;
sessionTarget: TSessionTarget;
wakeMode: TWakeMode;
payload: TPayload;
delivery?: TDelivery;
failureAlert?: TFailureAlert;
};
//#endregion
//#region src/cron/types.d.ts
/** Supported schedule forms persisted in cron job specs. */
type CronSchedule = {
kind: "at";
at: string;
} | {
kind: "every";
everyMs: number;
anchorMs?: number;
} | {
kind: "cron";
expr: string;
tz?: string;
/** Optional deterministic stagger window in milliseconds (0 keeps exact schedule). */
staggerMs?: number;
} | {
/**
* Event-driven (non-time) trigger: the job fires once when a gateway-owned
* watcher process running `command` exits. The watcher lives under the
* gateway ProcessSupervisor, NOT inside any agent turn's process tree, so
* it survives the per-turn spawn-and-kill teardown that CLI backends apply
* (#71662). On exit the job runs through the normal cron run pipeline, so
* delivery to the bound session works exactly like a scheduled main job.
* `computeNextRunAtMs` returns undefined for this kind (never time-due).
*/
kind: "on-exit";
command: string;
cwd?: string;
} | {
/** Event-driven source whose supervised argv emits payload-triggering lines. */
kind: "stream";
command: string[];
cwd?: string;
mode?: "line" | "match";
/** JavaScript regular-expression source, required when mode is "match". */
match?: string;
batchMs?: number;
maxBatchBytes?: number;
};
/** Runtime target that decides whether a job joins main, isolated, or a named session. */
type CronSessionTarget = "main" | "isolated" | "current" | `session:${string}`;
/** Wake policy for main-session jobs waiting on heartbeat/user activity. */
type CronWakeMode$1 = "next-heartbeat" | "now";
/** Messaging channel id accepted by cron delivery settings. */
type CronMessageChannel = ChannelId$1;
/** Delivery mode for job completion output. */
type CronDeliveryMode = "none" | "announce" | "webhook";
/** Completion delivery configuration for cron job output. */
type CronDelivery = {
mode: CronDeliveryMode;
channel?: CronMessageChannel;
to?: string;
/** Explicit thread/topic id for channels that support threaded delivery. */
threadId?: string | number;
/** Explicit channel account id for multi-account setups (e.g. multiple Telegram bots). */
accountId?: string;
bestEffort?: boolean;
/** Additional webhook destination used when a job must keep chat delivery. */
completionDestination?: CronCompletionDestination;
/** Separate destination for failure notifications. */
failureDestination?: CronFailureDestination;
};
/** Webhook completion destination used alongside chat delivery. */
type CronCompletionDestination = {
mode: "webhook";
to?: string;
};
/** Destination override for failed-run notifications. */
type CronFailureDestination = {
channel?: CronMessageChannel;
to?: string;
accountId?: string;
mode?: "announce" | "webhook";
};
/** Partial failure-destination update shape; null clears individual override fields. */
type CronFailureDestinationPatch = {
channel?: CronMessageChannel | null;
to?: string | null;
accountId?: string | null;
mode?: "announce" | "webhook" | null;
};
/** Partial delivery update shape; null clears optional delivery destinations or fields. */
type CronDeliveryPatch = Partial<Pick<CronDelivery, "mode" | "bestEffort">> & {
channel?: CronMessageChannel | null;
to?: string | null;
threadId?: string | number | null;
accountId?: string | null;
completionDestination?: CronCompletionDestination | null;
failureDestination?: CronFailureDestinationPatch | null;
};
/** Execution outcome, separate from delivery outcome. */
type CronRunStatus = "ok" | "error" | "skipped";
/** Delivery outcome for completion or failure-notification sends. */
type CronDeliveryStatus = "delivered" | "not-delivered" | "unknown" | "not-requested";
/** Bounded diagnostic bundle stored on the run outcome. */
type CronRunDiagnostics = NonNullable<CronRunLogEntry["diagnostics"]>;
/** Failure alert policy persisted on a cron job. */
type CronFailureAlert = {
after?: number;
channel?: CronMessageChannel;
to?: string;
cooldownMs?: number;
/** When true, consecutive skipped runs count toward the alert threshold. */
includeSkipped?: boolean;
/** Delivery mode: announce (via messaging channels) or webhook (HTTP POST). */
mode?: "announce" | "webhook";
/** Account ID for multi-account channel configurations. */
accountId?: string;
};
/** Partial failure-alert update; null clears an inherited field override. */
type CronFailureAlertPatch = { [K in keyof CronFailureAlert]?: CronFailureAlert[K] | null; };
/** Payload variants cron can execute in main-session or detached modes. */
type CronPayload = ({
kind: "systemEvent";
text: string;
} & CronPayloadToolAllow) | (CronAgentTurnPayload & CronPayloadToolAllow) | (CronCommandPayload & CronPayloadToolAllow) | (CronScriptPayload & CronPayloadToolAllow) | ({
kind: "heartbeat";
} & CronPayloadToolAllow) | ({
kind: "skillCollectionReview";
} & CronPayloadToolAllow);
/** Partial payload update shape used by cron patch/edit flows. */
type CronPayloadPatch = ({
kind: "systemEvent";
text?: string;
} & CronPayloadToolAllowPatch) | (CronAgentTurnPayloadPatch & CronPayloadToolAllowPatch) | (CronCommandPayloadPatch & CronPayloadToolAllowPatch) | (CronScriptPayloadPatch & CronPayloadToolAllowPatch) | ({
kind: "heartbeat";
} & CronPayloadToolAllowPatch) | ({
kind: "skillCollectionReview";
} & CronPayloadToolAllowPatch);
type CronPayloadToolAllow = {
/** Restricts agentTurn execution, or the trigger runtime for other payload kinds. */
toolsAllow?: string[];
/** Server-managed marker for auto-stamped defaults; explicit restrictions omit it. */
toolsAllowIsDefault?: boolean;
};
type CronPayloadToolAllowPatch = {
toolsAllow?: string[] | null;
toolsAllowIsDefault?: boolean;
};
type CronAgentTurnPayloadFields = {
message: string;
/** Optional model override (provider/model or alias). */
model?: string;
/** Optional per-job fallback models; overrides agent/global fallbacks when defined. */
fallbacks?: string[];
thinking?: string;
timeoutSeconds?: number;
allowUnsafeExternalContent?: boolean;
/** Immutable external hook provenance for async dispatch. */
externalContentSource?: HookExternalContentSource;
/** If true, run with lightweight bootstrap context. */
lightContext?: boolean;
};
type CronAgentTurnPayload = {
kind: "agentTurn";
} & CronAgentTurnPayloadFields;
type CronAgentTurnPayloadPatch = {
kind: "agentTurn";
} & Partial<Omit<CronAgentTurnPayloadFields, "model" | "fallbacks" | "toolsAllow" | "thinking">> & {
model?: string | null;
fallbacks?: string[] | null;
toolsAllow?: string[] | null;
thinking?: string | null;
};
type CronCommandPayloadFields = {
/** Explicit argv vector to execute. Use a shell wrapper argv for shell syntax. */
argv: string[];
cwd?: string;
env?: Record<string, string>;
input?: string;
timeoutSeconds?: number;
noOutputTimeoutSeconds?: number;
outputMaxBytes?: number;
};
type CronCommandPayload = {
kind: "command";
} & CronCommandPayloadFields;
type CronCommandPayloadPatch = {
kind: "command";
} & Partial<CronCommandPayloadFields>;
type CronScriptPayloadFields = {
script: string;
timeoutSeconds?: number;
toolBudget?: number;
};
type CronScriptPayload = {
kind: "script";
} & CronScriptPayloadFields;
type CronScriptPayloadPatch = {
kind: "script";
} & Partial<CronScriptPayloadFields>;
/** Mutable runtime state persisted beside the immutable cron job spec. */
type CronJobState = {
nextRunAtMs?: number;
/**
* When the current scheduling inputs took effect. Restart catch-up replays a
* missed slot only when the slot is newer than this, because slots computed
* from a freshly edited schedule never existed under the old one. Absent on
* jobs whose schedule has not changed, where every computed slot is real.
*/
scheduleActivatedAtMs?: number;
/** Exact startup catch-up slot protected from future-slot repair across restarts. */
startupCatchupAtMs?: number;
/** Exact paced completion slot protected from future-slot repair until consumed. */
pacedNextRunAtMs?: number;
/** Exact recurring slot retained across an out-of-band manual force run. */
forcePreservedNextRunAtMs?: number;
/** Durable pre-admission reservation. Cleared on restart without recording a run. */
queuedAtMs?: number;
runningAtMs?: number;
lastRunAtMs?: number;
/** Preferred execution outcome field. */
lastRunStatus?: CronRunStatus;
/** @deprecated Use lastRunStatus. */
lastStatus?: "ok" | "error" | "skipped";
lastError?: string;
lastDiagnostics?: CronRunDiagnostics;
lastDiagnosticSummary?: string;
/** Classified reason for the last error (when available). */
lastErrorReason?: FailoverReason;
lastDurationMs?: number;
/** Number of consecutive execution errors (reset on success). Used for backoff. */
consecutiveErrors?: number;
/** Durable explanation for a scheduler-owned automatic disable transition. */
autoDisabled?: {
reason: "consecutive-failures" | "schedule-errors";
atMs: number;
consecutiveErrors: number;
};
/** Number of consecutive skipped executions (reset on success or error). */
consecutiveSkipped?: number;
/** Last failure alert timestamp (ms since epoch) for cooldown gating. */
lastFailureAlertAtMs?: number;
/** Number of consecutive schedule computation errors. Auto-disables job after threshold. */
scheduleErrorCount?: number;
/** Timestamp of the last trigger script evaluation. */
lastTriggerEvalAtMs?: number;
/** Number of completed trigger script evaluations. */
triggerEvalCount?: number;
/** Timestamp of the last trigger evaluation that fired. */
lastTriggerFireAtMs?: number;
/** JSON state returned by the last trigger script evaluation. */
triggerState?: unknown;
/** Current gateway-owned stream source lifecycle state. */
streamStatus?: "starting" | "running" | "restarting" | "stopped" | "disabled" | "error";
streamError?: string;
streamConsecutiveFailures?: number;
streamRestartExhausted?: boolean;
streamSourceIdentity?: string;
streamDroppedBatches?: number;
streamCoalescedBatches?: number;
streamLastStartedAtMs?: number;
streamLastExitAtMs?: number;
/** Explicit delivery outcome, separate from execution outcome. */
lastDeliveryStatus?: CronDeliveryStatus;
/** Delivery-specific error text when available. */
lastDeliveryError?: string;
/** Intentional non-delivery reason for the last run, when recorded by the dispatcher. */
deliverySuppressionReason?: NormalizeReplySkipReason;
/** Whether the last run's output was delivered to the target channel. */
lastDelivered?: boolean;
/** Whether the last failed run's failure notification was delivered to the target channel. */
lastFailureNotificationDelivered?: boolean;
/** Delivery outcome for the last failed run's failure notification. */
lastFailureNotificationDeliveryStatus?: CronDeliveryStatus;
/** Delivery-specific error for the last failed run's failure notification. */
lastFailureNotificationDeliveryError?: string;
};
type CronTrigger = {
script: string;
once?: boolean;
};
/** Public cron job contract with spec fields and mutable run state. */
type CronJob = CronJobBase<CronSchedule, CronSessionTarget, CronWakeMode$1, CronPayload, CronDelivery, CronFailureAlert | false> & {
declarationKey?: string;
displayName?: string;
owner?: {
agentId?: string;
sessionKey?: string;
/** Authenticated account that created this scheduled authority envelope. */
accountId?: string;
};
/** Server-authored provenance for requester-scoped scheduled tool authority. */
scheduledToolPolicy?: CronScheduledToolPolicy;
trigger?: CronTrigger;
state: CronJobState;
};
/** Store-only proof omitted from public Gateway results and the CronJob wire/type contract. */
type CronToolsAllowProvenance = {
version: 1;
source: "final-executable-surface";
/** Store-private creator origin; missing legacy facts normalize to unknown. */
callerOrigin?: CronScheduledToolCallerOrigin;
};
/** Persisted row shape; public Gateway and wire contracts use CronJob. */
type CronStoredJob = CronJob & {
/** Immutable revisions inherited from the authorized creator session, never human mutation authority. */
skillLibrarySelections?: SessionEntry$1["skillLibrarySelections"];
/** Immutable creator provenance stamped by the trusted cron creation seam. */
createdActor?: SessionCreatedActor;
toolsAllowProvenance?: CronToolsAllowProvenance;
toolsAllowExecTarget?: CronToolsAllowExecTarget;
/** Exact expected pin for jobs created from a verified host-owned exec projection. */
toolsAllowExecTargetRequirement?: CronToolsAllowExecTargetRequirement;
/** Runtime-private authority omitted from public Gateway and wire contracts. */
runtimeAuthority?: CronRuntimeAuthority;
/** Authority was explicitly cleared and must be reauthorized before app reuse. */
runtimeAuthorityRecoveryRequired?: true;
};
type CronJobStateInput = Partial<Omit<CronJobState, "autoDisabled" | "scheduleActivatedAtMs" | "streamSourceIdentity">>;
/** Create input accepted by cron APIs before id/timestamps/state are assigned. */
type CronJobCreate = Omit<CronJob, "id" | "createdAtMs" | "updatedAtMs" | "state" | "scheduledToolPolicy"> & {
/** Internal callers can reserve a durable id before creation; public cron.add omits this. */
id?: string;
state?: CronJobStateInput;
};
/** Patch input accepted by cron APIs without allowing immutable identity fields. */
type CronJobPatch = Partial<Omit<CronJob, "id" | "createdAtMs" | "state" | "payload" | "delivery" | "failureAlert" | "declarationKey" | "displayName" | "owner" | "scheduledToolPolicy" | "pacing" | "trigger">> & {
displayName?: string | null;
pacing?: CronPacing | null;
trigger?: CronTrigger | null;
payload?: CronPayloadPatch;
delivery?: CronDeliveryPatch;
failureAlert?: CronFailureAlertPatch | false | null;
state?: CronJobStateInput;
};
//#endregion
//#region src/cron/service/list-page-types.d.ts
/** Enabled-state filter accepted by paginated cron listing. */
type CronJobsEnabledFilter = "all" | "enabled" | "disabled";
/** Schedule-kind filter accepted by paginated cron listing. */
type CronJobsScheduleKindFilter = "all" | "at" | "every" | "cron" | "on-exit" | "stream";
/** Last-run status filter, including jobs that have not produced a status yet. */
type CronJobsLastRunStatusFilter = "all" | CronRunStatus | "unknown";
/** Condition-trigger filter accepted by paginated cron listing. */
type CronJobsTriggerFilter = "all" | "conditional" | "unconditional";
/** Stable sort keys supported by paginated cron listing. */
type CronJobsSortBy = "nextRunAtMs" | "updatedAtMs" | "name";
/** Sort direction for paginated cron listing. */
type CronSortDir = "asc" | "desc";
/** Input contract for filtered, sorted, offset-based cron job pages. */
type CronListPageOptions = {
includeDisabled?: boolean;
limit?: number;
offset?: number;
query?: string;
enabled?: CronJobsEnabledFilter;
scheduleKind?: CronJobsScheduleKindFilter;
lastRunStatus?: CronJobsLastRunStatusFilter;
trigger?: CronJobsTriggerFilter;
sortBy?: CronJobsSortBy;
sortDir?: CronSortDir;
agentId?: string;
};
/** Offset-page result returned by cron listPage callers. */
type CronListPageResult<TJobs extends readonly CronJob[] = CronJob[]> = {
jobs: TJobs;
/** Opaque revision for the complete filtered, sorted result set. */
snapshotRevision: string;
total: number;
offset: number;
limit: number;
hasMore: boolean;
nextOffset: number | null;
};
//#endregion
//#region src/auto-reply/thinking.shared.d.ts
/** Canonical thinking level values accepted by chat commands and session state. */
type ThinkLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive" | "max" | "ultra";
type VerboseLevel = "off" | "on" | "full";
type ReasoningLevel = "off" | "on" | "stream";
/** Prepared model catalog fields reused while choosing and dispatching a queued runtime. */
type ThinkingCatalogEntry = {
provider: string;
id: string;
api?: string;
baseUrl?: string;
contextWindow?: number;
contextTokens?: number;
reasoning?: boolean;
configuredReasoning?: boolean;
/** Concrete runtime owner of thinking policy; internal and never project to clients. */
thinkingPolicyProvider?: string;
thinkingLevelMap?: ThinkingLevelMap;
input?: readonly ("text" | "image" | "audio" | "video" | "document")[];
params?: Record<string, unknown>;
compat?: {
thinkingFormat?: string;
supportedReasoningEfforts?: readonly string[] | null;
} | null;
};
//#endregion
//#region src/infra/agent-run-authority.types.d.ts
/** Exact admitted-run claim shared by the registry and its subordinate approval leases. */
type AgentRunDelegatedAuthority = Readonly<{
operationalRunInstance: Readonly<{
instanceId: string;
runId: string;
}>;
lifecycleGeneration: string;
claimId: string;
}>;
declare namespace admitted_run_context_d_exports {
export { AdmittedRunContext, OperationalRunInstanceRef, PreparedAgentRunAdmission, closeAdmittedRunDelegatedAuthority, createExecutionIdentityRecoveryAdmission, createOperationalRunInstanceRef, getAdmittedRunDelegatedAuthority, prepareAgentRunAdmission, prepareSystemAgentRunAdmission, resolveAdmittedRunActiveAssertion, resolvePreparedRunAdmission, retainAdmittedRunBeforeToolCallRecovery };
}
/** Operational lifecycle correlation. This is never identity or authorization evidence. */
type OperationalRunInstanceRef = Readonly<{
instanceId: string;
runId: string;
}>;
/** Exact context carried by one admitted execution and every retry/fallback it owns. */
type AdmittedRunContext = Readonly<{
operationalRunInstance: OperationalRunInstanceRef;
executionIdentityToken?: ExecutionIdentityAdmissionToken;
}>;
type PreparedAgentRunAdmission = Readonly<{
operationalRunInstance: OperationalRunInstanceRef;
/** Exact post-prepare owner; repeated fallback/retry returns the same object. */
admit: (runtimeKind: ExecutionIdentityAdmissionFacts["runtime"]["kind"], runtimeInstanceId?: string) => Promise<AdmittedRunContext>;
/** Idempotently closes the exact delegated approval lease, if admission occurred. */
close: () => void;
}>;
/** Reads the immutable outer-run authority without reviving a closed claim. */
declare function getAdmittedRunDelegatedAuthority(context: AdmittedRunContext): AgentRunDelegatedAuthority | undefined;
/** Captures an exact admitted-run assertion for work that may cross an await boundary. */
declare function resolveAdmittedRunActiveAssertion(context: AdmittedRunContext, signal?: AbortSignal): (() => void) | undefined;
/** Idempotently compare-releases the authority captured by this admission. */
declare function closeAdmittedRunDelegatedAuthority(context: AdmittedRunContext): boolean;
type AdmittedRunBeforeToolCallRecovery = Readonly<{
assertActive: () => void;
release: () => void;
}>;
/** Recovery-only lease for the already-created native pre-tool policy callback. */
declare function retainAdmittedRunBeforeToolCallRecovery(context: AdmittedRunContext): AdmittedRunBeforeToolCallRecovery | undefined;
type ExecutionIdentityRecoveryAdmission = Readonly<{
/** Recovery retries never manufacture replacement identity when exact evidence is absent. */
retryOnly: boolean;
consume: (runId: string) => Readonly<{
accepted: boolean;
token?: ExecutionIdentityAdmissionToken;
}>;
}>;
/** Creates a one-shot recovery admission owned by the durable recovery resolver. */
declare function createExecutionIdentityRecoveryAdmission(params: {
retryOnly: boolean;
token?: ExecutionIdentityAdmissionToken;
expectedOperationalRunId?: string;
}): ExecutionIdentityRecoveryAdmission;
declare function createOperationalRunInstanceRef(runId: string): OperationalRunInstanceRef;
/** Prepares a system-owned run without selecting its eventual execution runtime early. */
declare function prepareSystemAgentRunAdmission(cfg: OpenClawConfig, runId: string, agentId: string, boundary: string): PreparedAgentRunAdmission;
/**
* Freezes ingress facts before preparation while deferring allocation/capture until the
* authoritative runtime owner is selected immediately before execution.
*/
declare function prepareAgentRunAdmission(params: {
cfg: OpenClawConfig;
facts: Omit<ExecutionIdentityAdmissionFacts, "runtime">;
operationalRunInstance: OperationalRunInstanceRef;
recovery?: ExecutionIdentityRecoveryAdmission;
onAdmitted?: (context: AdmittedRunContext) => void | Promise<void>;
}): PreparedAgentRunAdmission;
/** Resolves a host-only continuation or validates an already-admitted internal caller. */
declare function resolvePreparedRunAdmission(params: {
runId: string;
runtimeKind: ExecutionIdentityAdmissionFacts["runtime"]["kind"];
runtimeInstanceId?: string;
admittedRunContext?: AdmittedRunContext;
preparedRunAdmission?: PreparedAgentRunAdmission;
}): Promise<AdmittedRunContext>;
//#endregion
//#region src/infra/heartbeat-wake-contracts.d.ts
type HeartbeatRunResult = {
status: "ran";
durationMs: number;
} | {
status: "skipped";
reason: string;
retryAtMs?: number;
} | {
status: "failed";
reason: string;
};
type HeartbeatWakeIntent = "scheduled" | "task" | "event" | "immediate" | "manual";
type HeartbeatWakeSource = "interval" | "manual" | "exec-event" | "notifications-event" | "cron" | "hook" | "background-task" | "background-task-blocked" | "acp-spawn" | "session-state" | "cli-watchdog" | "restart-sentinel" | "retry" | "other";
type HeartbeatWakeOverride = {
target?: string;
to?: string | undefined;
accountId?: string | undefined;
};
/** Cron-owned periodic work carried directly into a guarded heartbeat turn. */
type HeartbeatScheduledTask = {
jobId: string;
name: string;
prompt: string;
};
type HeartbeatWakeRequest = {
source: HeartbeatWakeSource;
intent: HeartbeatWakeIntent;
reason?: string;
agentId?: string;
sessionKey?: string;
heartbeat?: HeartbeatWakeOverride;
/** Persisted cron monitor cadence carried with a scheduled heartbeat tick. */
scheduledEveryMs?: number;
tasks?: readonly HeartbeatScheduledTask[];
/** Internal marker for work retained after a spacing/cooldown deferral. */
retainedWork?: boolean;
};
//#endregion
//#region src/infra/heartbeat-wake.d.ts
type HeartbeatRequestOptions = Omit<HeartbeatWakeRequest, "retainedWork"> & {
coalesceMs?: number;
};
declare const requestHeartbeat: (opts: HeartbeatRequestOptions) => void;
//#endregion
//#region src/process/command-queue.types.d.ts
/**
* Public enqueue knobs shared by command-lane callers and narrower injection
* points that should not import the full queue implementation.
*/
type CommandQueueTaskDeadline = {
kind: "bounded";
deadlineAtMs: number;
} | {
kind: "unlimited";
};
type CommandQueueEnqueueOptions = {
/** Cancels queued admission; the task owns cancellation after it starts. */
abortSignal?: AbortSignal;
/** Called only when this entry remains queued after immediate lane admission. */
onQueued?: () => void;
warnAfterMs?: number;
onWait?: (waitMs: number, queuedAhead: number) => void;
taskTimeoutMs?: number;
taskTimeoutProgressAtMs?: () => number | undefined;
/** Replaces idle timing with an owner deadline; undefined restores idle timing. */
taskTimeoutSubscribe?: (onDeadline: (deadline: CommandQueueTaskDeadline | undefined) => void) => () => void;
taskTimeoutAbortSignal?: AbortSignal;
taskTimeoutAbortGraceMs?: number;
/** Ends the task after a caller-owned timeout cleanup grace has already elapsed. */
taskTimeoutReleaseSignal?: AbortSignal;
priority?: "foreground" | "normal" | "background";
};
/** Minimal queue function contract used by code that only needs to schedule work. */
type CommandQueueEnqueueFn = <T>(task: () => Promise<T>, opts?: CommandQueueEnqueueOptions) => Promise<T>;
//#endregion
//#region src/process/gateway-work-admission.d.ts
type GatewayRootWorkAdmissionContinuationScope = {
release: () => void;
run: <T>(run: () => Promise<T>) => Promise<T>;
};
//#endregion
//#region src/cron/service/state.d.ts
/** Direct-run mode: respect due time, force execution, or run immediately while enabled. */
type CronRunMode = "due" | "force" | "if-enabled";
/** Main-session wake strategy used after enqueuing cron text. */
type CronWakeMode = "now" | "next-heartbeat";
/** Lightweight service status returned to gateway/control surfaces. */
type CronStatusSummary = {
enabled: boolean;
triggersEnabled: boolean;
/** @deprecated Alias for `sqlitePath`. */
storePath: string;
/** Storage backend identifier. */
storage: "sqlite";
/** Resolved path to the shared state SQLite database. */
sqlitePath: string;
jobs: number;
nextWakeAtMs: number | null;
};
/** Result shape for immediate or queued cron run requests. */
type CronRunResult = {
ok: true;
ran: true;
} | {
ok: true;
enqueued: true;
runId: string;
} | {
ok: true;
ran: false;
reason: "disabled";
} | {
ok: true;
ran: false;
reason: "not-due";
} | {
ok: true;
ran: false;
reason: "already-running";
} | {
ok: true;
ran: false;
reason: "invalid-spec";
} | {
ok: true;
ran: false;
reason: "stopped";
} | {
ok: false;
};
/** Remove result that distinguishes missing jobs from failed removal. */
type CronRemoveResult = {
ok: true;
removed: boolean;
} | {
ok: false;
removed: false;
};
/** Created cron job returned by service mutation calls. */
type CronDeclarativeAddResult = CronStoredJob & {
created: boolean;
updated?: boolean;
job: CronStoredJob;
};
type CronAddResult = CronStoredJob | CronDeclarativeAddResult;
/** Updated cron job returned by service mutation calls. */
type CronUpdateResult = CronJob;
/** Chronological job list returned by service read calls. */
type CronListResult = CronJob[];
/** Normalized create input accepted by the cron service. */
type CronAddInput = CronJobCreate;
/** Caller-specific declaration-key visibility and explicit enablement metadata. */
type CronAddOptions = {
/** Selected revisions captured from a validated caller session, never public input. */
skillLibrarySelections?: CronStoredJob["skillLibrarySelections"];
matchesExisting?: (job: CronJob) => boolean;
enabledExplicit?: boolean;
/** Gateway/doctor-owned heartbeat jobs require this opt-in at service creation. */
systemOwned?: boolean;
/** Trusted creator provenance persisted with new jobs; never accepted from public input. */
createdActor?: SessionCreatedActor;
/** Authenticated caller provenance stamped by the service, never public input. */
scheduledToolPolicy?: CronScheduledToolPolicy;
/** Private proof from an authenticated agent-runtime caller. */
toolsAllowProvenance?: CronToolsAllowProvenance;
/** Restrict-only exec pin from the signed creator-turn identity. */
toolsAllowExecTarget?: CronToolsAllowExecTarget;
/** Synchronous Gateway-owned liveness guard consumed immediately before mutation. */
commitGuard?: () => void;
/** One-use fresh capture; callback presence means fresh even when it returns undefined. */
captureRuntimeAuthority?: () => CronRuntimeAuthority | undefined;
};
/** Normalized patch input accepted by cron service updates. */
type CronUpdateInput = CronJobPatch;
/** Authenticated caller provenance used only when a tool policy is explicitly adopted. */
type CronUpdateOptions = {
scheduledToolPolicy?: CronScheduledToolPolicy;
toolsAllowProvenance?: CronToolsAllowProvenance;
/** Restrict-only exec pin from the signed creator-turn identity. */
toolsAllowExecTarget?: CronToolsAllowExecTarget;
/** Synchronous Gateway-owned liveness guard consumed immediately before mutation. */
commitGuard?: () => void;
/** One-use fresh capture; callback presence means fresh even when it returns undefined. */
captureRuntimeAuthority?: () => CronRuntimeAuthority | undefined;
};
type CronCommitGuardOptions = {
/** Synchronous Gateway-owned guard consumed at the mutation owner. */
commitGuard?: () => void;
};
/** Cron-store-locked guard evaluated against the current job before an update applies. */
type CronUpdatePrecondition = (job: CronJob, nowMs: number) => void | Promise<void>;
//#endregion
//#region src/cron/service-contract.d.ts
type CronWakeResult = {
ok: true;
} | {
ok: false;
reason?: "unwakeable-session-key";
};
/** Result shape for direct/queued cron runs. */
type CronServiceRunResult = CronRunResult;
type CronServiceRunOptions = {
payload?: CronPayload;
/** Internal event-source runs keep their persisted trigger on force execution. */
evaluateTrigger?: boolean;
/** Current stream batch exposed to trigger scripts as trigger.streamBatch. */
streamBatch?: string;
/** Source schedule identity checked under the cron store lock before admission. */
streamScheduleKey?: string;
/** Logical source identity; rejects retired batches under same-schedule ABA. */
streamSourceIdentity?: string;
onTriggerDisposition?: (disposition: "fired" | "dropped" | "busy" | "error") => void;
/** Synchronous caller-authority guard consumed before run reservation. */
commitGuard?: () => void;
};
/** Public cron service facade used by gateway, plugin SDK, and tests. */
interface CronServiceContract {
start(): Promise<void>;
stop(): void;
status(): Promise<CronStatusSummary>;
list(opts?: {
includeDisabled?: boolean;
}): Promise<CronListResult>;
listPage(opts?: CronListPageOptions): Promise<CronListPageResult>;
add(input: CronAddInput, opts?: CronAddOptions): Promise<CronAddResult>;
update(id: string, patch: CronUpdateInput, opts?: CronUpdateOptions): Promise<CronUpdateResult>;
updateWithPrecondition(id: string, patch: CronUpdateInput, precondition: CronUpdatePrecondition, opts?: CronUpdateOptions): Promise<CronUpdateResult>;
remove(id: string, opts?: {
systemOwned?: boolean;
} & CronCommitGuardOptions): Promise<CronRemoveResult>;
run(id: string, mode?: CronRunMode, opts?: CronServiceRunOptions): Promise<CronServiceRunResult>;
enqueueRun(id: string, mode?: CronRunMode, opts?: CronCommitGuardOptions): Promise<CronServiceRunResult>;
getJob(id: string): CronJob | undefined;
readJob(id: string): Promise<CronJob | undefined>;
getDefaultAgentId(): string | undefined;
wake(opts: {
mode: CronWakeMode;
text: string;
sessionKey?: string;
agentId?: string;
}): CronWakeResult;
}
//#endregion
//#region src/gateway/methods/descriptor.d.ts
/** Scope marker for methods that only authenticated node clients may call. */
declare const NODE_GATEWAY_METHOD_SCOPE: "node";
/** Scope marker for methods whose handler derives the required operator scope at runtime. */
declare const DYNAMIC_GATEWAY_METHOD_SCOPE: "dynamic";
/** Authorization scope attached to a gateway method descriptor. */
type GatewayMethodScope = OperatorScope | typeof NODE_GATEWAY_METHOD_SCOPE | typeof DYNAMIC_GATEWAY_METHOD_SCOPE;
/** Owner metadata used to keep core, plugin, channel, and auxiliary methods distinguishable. */
type GatewayMethodOwner = {
kind: "core";
area: string;
} | {
kind: "plugin";
pluginId: string;
} | {
kind: "channel";
channelId: string;
} | {
kind: "aux";
area: string;
};
/** Startup availability flag exposed to clients as retryable startup-unavailable errors. */
type GatewayMethodStartupAvailability = "available" | "unavailable-until-sidecars";
type GatewayMethodProfileAccess = "independent" | "required";
type GatewayMethodHandler = (opts: never) => unknown;
/** Complete metadata for one dispatchable gateway method. */
type GatewayMethodDescriptor = {
name: string;
handler: GatewayMethodHandler;
scope: GatewayMethodScope;
owner: GatewayMethodOwner;
profileAccess: GatewayMethodProfileAccess;
since?: string;
startup?: GatewayMethodStartupAvailability;
controlPlaneWrite?: boolean;
advertise?: boolean;
description?: string;
};
/** Read-only method registry view used by request dispatch and method listing. */
type GatewayMethodRegistryView = {
/** Opaque registry handle carried into request scope by the gateway composition root. */
pluginRegistry?: object;
getHandler: (name: string) => GatewayMethodHandler | undefined;
listMethods: () => string[];
listAdvertisedMethods: () => string[];
getScope: (name: string) => GatewayMethodScope | undefined;
isStartupUnavailable: (name: string) => boolean;
isControlPlaneWrite: (name: string) => boolean;
requiresAuthenticatedProfile: (name: string) => boolean;
descriptors: () => readonly GatewayMethodDescriptor[];
};
//#endregion
//#region src/wizard/session.d.ts
type WizardStep = WizardStep$1;
type WizardSessionStatus = NonNullable<WizardNextResult$1["status"]>;
type WizardNextResult = WizardNextResult$1 & {
status: WizardSessionStatus;
};
declare class WizardSession {
private runner;
private readonly abortController;
private readonly expiryTimer;
private readonly runnerPromise;
private currentStep;
private progressSteps;
private deliveredProgressStepIds;
private stepDeferred;
private cancellationLocked;
private settled;
private pendingExternalUrl;
private answerDeferred;
private status;
private error;
private configuredAccounts;
private preparedModelRef;
private modelActivation;
private activationRejection;
constructor(runner: (prompter: WizardPrompter, signal: AbortSignal, session: WizardSession) => Promise<void>, options?: {
timeoutMs?: number;
});
next(): Promise<WizardNextResult>;
/** A non-consuming view for polling clients; retired prompts are never replayed. */
getCurrentStep(): WizardStep | undefined;
private terminalResult;
/** Record what the channels flow actually configured (channels flow only). */
setConfiguredAccounts(accounts: ReadonlyArray<{
channel: string;
accountId: string;
}>): void;
/** Record the exact provider-owned model prepared by a setup flow. */
setPreparedModelRef(modelRef: string): void;
/** Record the live activation result, distinct from provider preparation. */
setModelActivation(activation: NonNullable<WizardNextResult$1["modelActivation"]>): void;
/** Only the activation owner can distinguish rejection from possibly committed failure. */
setActivationRejection(rejection: NonNullable<WizardNextResult$1["activationRejection"]>): void;
answer(stepId: string, value: unknown): Promise<string | undefined>;
cancel(): boolean;
/** The underlying mutation crossed its durable commit point and must finish. */
lockCancellation(): void;
get signal(): AbortSignal;
pushStep(step: WizardStep): void;
pushProgress(message: string): void;
private rememberDeliveredProgressStep;
queueExternalUrl(url: string): void;
consumeExternalUrl(): string | undefined;
private run;
private rejectPendingAnswers;
awaitAnswer(step: WizardStep, validate?: (value: string) => string | undefined, signal?: AbortSignal): Promise<unknown>;
private resolveStep;
getStatus(): WizardSessionStatus;
/** Whether the runner has stopped and can no longer mutate setup state. */
isSettled(): boolean;
/** Resolves after the runner can no longer mutate setup state. */
whenSettled(): Promise<void>;
getError(): string | undefined;
}
//#endregion
//#region src/gateway/session-observer-contract.d.ts
type SessionObserverEvent = {
runId: string;
seq: number;
stream: string;
ts: number;
data: Record<string, unknown>;
lifecycleGeneration?: string;
sessionKey?: string;
sessionId?: string;
agentId?: string;
};
type SessionObserverCompanionSnapshot = {
agentId: string;
runId?: string;
digest?: SessionObserverDigest;
notes: Array<{
sequence: number;
text: string;
}>;
};
type SessionObserverService = {
handleEvent: (event: SessionObserverEvent) => void;
setConnectionVisibility: (connId: string, visible: boolean) => void;
removeConnection: (connId: string) => void;
getCompanionSnapshot: (sessionKey: string, agentId?: string) => SessionObserverCompanionSnapshot;
dispose: () => void;
};
//#endregion
//#region src/gateway/session-companion.d.ts
type SessionCompanionTarget = {
sessionKey: string;
agentId: string;
};
type SessionCompanionService = {
ask: (params: {
agentId: string;
sessionKey: string;
question: string;
connId: string;
signal?: AbortSignal;
}) => Promise<SessionsCompanionAskResult>;
state: (target: SessionCompanionTarget) => SessionsCompanionStateResult;
reset: (target: SessionCompanionTarget) => void;
dispose: () => void;
};
//#endregion
//#region src/gateway/chat-queued-turns.d.ts
type QueuedChatTurnEntry = {
controller: AbortController;
sessionId: string;
sessionKey: string;
/** False once collect-mode transfers cancellation to the aggregate owner. */
abortable?: boolean;
abortListener?: () => void;
agentId?: string;
ownerConnId?: string;
ownerDeviceId?: string;
};
//#endregion
//#region src/gateway/server-methods/wizard.d.ts
type ChannelSetupWizardRunner = (opts: {
channel?: string;
onConfigured?: (accounts: Array<{
channel: string;
accountId: string;
}>) => void;
beforePersistentEffect?: () => Promise<void>;
}, runtime: RuntimeEnv, prompter: WizardPrompter) => Promise<void>;
//#endregion
//#region src/gateway/methods/registry.d.ts
type GatewayMethodRegistry = GatewayMethodRegistryView;
//#endregion
//#region src/gateway/control-ui-contract.d.ts
/** Check-run rollup for a PR head commit, chip pill + CI monitoring popover. */
type ControlUiSessionPullRequestChecks = {
state: "pending" | "passing" | "failing";
passed: number;
failed: number;
skipped: number;
/** Queued/in-progress runs plus stale conclusions GitHub invalidated. */
running: number;
};
/** One GitHub pull request whose head is the session's working branch. */
type ControlUiSessionPullRequest = {
number: number;
/**
* Author login from the list payload GitHub already returns; no extra call.
* Absent for a ghosted or deleted account. Deliberately login-only: the
* sibling GitHub-link hovercard inlines avatars server-side rather than
* hotlinking them, so a remote <img> here would leak a browser request to
* GitHub on every hover.
*/
author?: {
login: string;
};
owner: string;
repo: string;
branch: string;
title: string;
url: string;
state: "open" | "draft" | "merged" | "closed";
additions?: number;
deletions?: number;
changedFiles?: number;
/** Latest check-run rollup for the head commit; absent when no checks ran. */
checks?: ControlUiSessionPullRequestChecks;
checksUrl?: string;
};
/**
* The session's working branch, resolved from local git only so the pre-PR
* "Create PR" row keeps rendering while the GitHub quota is exhausted.
*/
type ControlUiSessionBranch = {
owner: string;
repo: string;
branch: string;
/** Working-tree diff vs the merge base with the remote default branch. */
additions?: number;
deletions?: number;
changedFiles?: number;
/**
* GitHub "open a pull request for this branch" page. Absent while the
* branch is unpushed or has nothing to compare — the row then only reports
* the session's local changed files.
*/
createUrl?: string;
};
/** Pull requests detected for a session's git branch, chip row payload. */
type ControlUiSessionPullRequests = {
pullRequests: ControlUiSessionPullRequest[];
/**
* Present when the session's non-default GitHub branch has a creatable PR
* on origin or local changed files in the working tree.
*/
branch?: ControlUiSessionBranch;
/** GitHub quota exhausted; entries may be stale until the limit resets. */
rateLimited: boolean;
};
//#endregion
//#region src/process/exec-result.d.ts
type SpawnResult = {
pid?: number;
stdout: string;
stderr: string;
stdoutTruncatedBytes?: number;
stderrTruncatedBytes?: number;
preservedStdoutLines?: string[];
preservedStderrLines?: string[];
code: number | null;
signal: NodeJS.Signals | null;
killed: boolean;
termination: "exit" | "timeout" | "no-output-timeout" | "signal";
noOutputTimedOut?: boolean;
outputLimitExceeded?: boolean;
outputErrorStream?: "stdout" | "stderr";
};
//#endregion
//#region src/process/exec-output.d.ts
type CommandOutputCaptureMode = "head" | "tail" | "discard";
type CommandOutputStream = "stdout" | "stderr";
type CommandOutputCaptureOption = CommandOutputCaptureMode | {
stdout?: CommandOutputCaptureMode;
stderr?: CommandOutputCaptureMode;
};
type CommandOutputLimitOption = boolean | {
stdout?: boolean;
stderr?: boolean;
combined?: boolean;
};
type CommandOutputErrorOption = boolean | {
stdout?: boolean;
stderr?: boolean;
};
type PreserveOutputLine = (line: string, stream: CommandOutputStream) => boolean;
//#endregion
//#region src/process/exec-runner.d.ts
type CommandOptions = {
timeoutMs?: number;
cwd?: string;
input?: string | Uint8Array;
baseEnv?: NodeJS.ProcessEnv;
env?: NodeJS.ProcessEnv;
windowsVerbatimArguments?: boolean;
noOutputTimeoutMs?: number;
signal?: AbortSignal;
maxOutputBytes?: number | {
stdout?: number;
stderr?: number;
};
maxCombinedOutputBytes?: number;
outputCapture?: CommandOutputCaptureOption;
/** Observe raw output without owning child lifecycle. Return false to stop the command. */
onOutputChunk?: (chunk: Buffer, stream: CommandOutputStream) => boolean | void;
/** Accept a successful exit when only the selected diagnostic output stream failed. */
tolerateOutputError?: {
stdout?: boolean;
stderr?: boolean;
};
/** Terminate when the selected output stream emits an error. */
terminateOnOutputError?: CommandOutputErrorOption;
terminateOnOutputLimit?: CommandOutputLimitOption;
maxPreservedOutputLines?: number;
preserveOutputLine?: PreserveOutputLine;
killProcessTree?: boolean;
/** Signal used when terminating the direct child; tree termination owns its own grace policy. */
killSignal?: NodeJS.Signals | number;
/** Grace between graceful termination and the force-kill fallback. */
killGraceMs?: number;
};
declare function runCommandWithTimeout(argv: string[], optionsOrTimeout: number | CommandOptions): Promise<SpawnResult>;
//#endregion
//#region src/gateway/control-ui-session-prs.d.ts
type ControlUiSessionPullRequestsParams = {
sessionKey: string;
agentId?: string;
refresh?: boolean;
};
//#endregion
//#region src/gateway/server-broadcast-types.d.ts
type GatewayBroadcastStateVersion = {
presence?: number;
health?: number;
};
/** Options for gateway websocket broadcasts. */
type GatewayBroadcastOpts = {
/** Agent scope for agent-relative keys such as `global`. */
agentId?: string;
dropIfSlow?: boolean;
/** Canonical subscription keys for session-scoped delivery. */
sessionKeys?: readonly string[];
/** Target recipients were selected from subscriptions at ingress. */
sessionSubscriptionVerified?: boolean;
stateVersion?: GatewayBroadcastStateVersion;
/** Private live-text ownership; omitting coalesce flushes this group's progress. */
liveText?: {
group: AbortSignal;
isCurrent?: () => boolean;
coalesce?: {
key: string;
merge: (previous: unknown, next: unknown) => unknown;
};
};
};
/** Broadcast function signature for all connected clients. */
type GatewayBroadcastFn = (event: string, payload: unknown, opts?: GatewayBroadcastOpts) => void;
/** Broadcast function signature for targeted connection ids. */
type GatewayBroadcastToConnIdsFn = (event: string, payload: unknown, connIds: ReadonlySet<string>, opts?: GatewayBroadcastOpts) => void;
//#endregion
//#region src/gateway/control-ui-session-pr-subscriptions.d.ts
type LoadSessionPullRequests = (params: ControlUiSessionPullRequestsParams) => Promise<ControlUiSessionPullRequests>;
type SubscriptionDeps = {
broadcastToConnIds: GatewayBroadcastToConnIdsFn;
isConnectionActive?: (connId: string) => boolean;
load?: LoadSessionPullRequests;
setTimer?: typeof globalThis.setTimeout;
clearTimer?: typeof globalThis.clearTimeout;
};
type ControlUiSessionPullRequestSubscriptions = {
replace: (connId: string, sessionKeys: readonly string[], refreshSessionKeys?: ReadonlySet<string>) => Promise<void>;
unsubscribe: (connId: string) => void;
pollNow: () => Promise<void>;
stop: () => Promise<void>;
};
/**
* Owns the union of connection replace-sets. Only this union drives GitHub
* refreshes, so hidden/disconnected clients cannot leave orphan polling work.
*/
declare function createControlUiSessionPullRequestSubscriptions(deps: SubscriptionDeps): ControlUiSessionPullRequestSubscriptions;
//#endregion
//#region src/gateway/agent-runtime-session-spawn-context.d.ts
type AgentRuntimeSessionSpawnContext = {
completionOwnerSessionKey?: string;
inheritedToolPolicy: {
version: 1;
allow: string[];
deny: string[];
};
};
//#endregion
//#region src/gateway/cron-creator-authority-grant.types.d.ts
type CronCreatorAuthorityGrant = Readonly<{
runId: string;
token: string;
}>;
//#endregion
//#region src/channels/threading-tool-context-internal.d.ts
/** Host-only turn correlation carried beside the plugin-facing threading contract. */
type InternalChannelThreadingToolContext = ChannelThreadingToolContext & {
currentSourceTurnId?: string;
};
//#endregion
//#region src/gateway/message-action-turn-capability.d.ts
type MessageActionRequesterIdentity = {
requesterAccountId?: string;
requesterSenderId?: string;
requesterSenderName?: string;
requesterSenderUsername?: string;
requesterSenderE164?: string;
};
type AgentRuntimeMessageActionContextBase = MessageActionRequesterIdentity & {
expiresAtMs: number;
/** Process-local owner reference revalidated before privileged Gateway use. */
turnCapability?: string;
sessionId?: string;
/** Durable session entry that owns restart-recovery receipt state. */
sourceReplySessionKey?: string;
toolContext?: InternalChannelThreadingToolContext;
};
type AgentRuntimeMessageActionContext = AgentRuntimeMessageActionContextBase & ({
sourceReplyFinal: true;
sourceReplyToolCallId: string;
} | {
sourceReplyFinal?: false;
sourceReplyToolCallId?: string;
});
//#endregion
//#region src/gateway/agent-runtime-identity-token.d.ts
type AgentRuntimeCronSelfManagementContext = {
jobId: string;
expiresAtMs: number;
};
type AgentRuntimeIdentity = {
kind: "agentRuntime";
agentId: string;
sessionKey: string;
operationalRunInstance: OperationalRunInstanceRef;
delegatedAuthority: AgentRuntimeDelegatedAuthority;
approvalOwnerPluginId?: string;
executionIdentity?: ExecutionIdentityAdmissionToken;
turnSourceChannel?: string;
/** Explicit admission fact; omission is unknown, never inferred from session routing. */
turnSourceLocal?: true;
turnSourceTo?: string;
turnSourceAccountId?: string;
turnSourceThreadId?: string | number;
messageActionContext?: AgentRuntimeMessageActionContext;
cronSelfManagementContext?: AgentRuntimeCronSelfManagementContext;
cronToolsAllowCapture?: "final-executable-surface";
cronExecToolTarget?: {
host: "gateway";
ask?: "always";
};
cronCreatorAuthorityGrant?: CronCreatorAuthorityGrant;
cronManagementGrant?: CronCreatorAuthorityGrant;
sessionSpawnContext?: AgentRuntimeSessionSpawnContext;
};
type AgentRuntimeDelegatedAuthority = AgentRunDelegatedAuthority & ({
kind: "local";
} | {
kind: "worker";
turnClaim: WorkerSessionTurnClaim;
});
type AgentRuntimeApprovalAuthorityValidator = (identity: AgentRuntimeIdentity) => boolean;
//#endregion
//#region src/gateway/github-user-identity.d.ts
type AuthenticatedGitHubIdentitySyncResult = {
profileId: string;
updatedAt: number;
};
type AuthenticatedGitHubIdentitySync = () => Promise<AuthenticatedGitHubIdentitySyncResult>;
//#endregion
//#region src/gateway/operator-role-actor.d.ts
/** Host-minted role authority; never accepted from Gateway wire params.
Leaf contract: both ws-types and server-methods/shared-types embed it in
client `internal` state, so it must not import either hub. */
type GatewayOperatorRoleActor = {
kind: "system";
} | {
kind: "operator";
profileId: string;
};
//#endregion
//#region src/gateway/server-methods/response-types.d.ts
/** Callback used by method handlers to emit one protocol response frame. */
type RespondFn = (ok: boolean, payload?: unknown, error?: ErrorShape, meta?: Record<string, unknown>) => void;
//#endregion
//#region src/gateway/plugin-node-capability.d.ts
/** Declared plugin surface that may receive scoped node capabilities. */
type PluginNodeCapabilitySurface = {
surface: string;
ttlMs?: number;
scopeKey?: string;
};
/** Client state used to authorize plugin-node surface capabilities. */
type PluginNodeCapabilityClient = {
/** Retired clients cannot back HTTP capability auth or its renewal while close is pending. */
invalidated?: boolean;
pluginSurfaceUrls?: Record<string, string>;
pluginNodeCapabilitySurfaces?: Record<string, PluginNodeCapabilitySurface>;
pluginNodeCapabilities?: Record<string, {
capability: string;
expiresAtMs: number;
}>;
};
//#endregion
//#region src/gateway/worker-environments/connection-identity.d.ts
/** Hash-only worker identity retained after admission. */
type WorkerConnectionIdentity = {
environmentId: string;
credentialHash: string;
bundleHash: string;
sessionId: string | null;
runId: string | null;
turnClaim: WorkerSessionTurnClaim | null;
ownerEpoch: number;
rpcSetVersion: number;
protocolFeatures: string[];
credentialExpiresAtMs: number;
};
//#endregion
//#region src/gateway/server/ws-types.d.ts
type GatewayWsBrowserOrigin = {
requestHost?: string;
origin?: string;
isLocalClient?: boolean;
};
type GatewayWsConnectionKind = "gateway" | "worker";
/**
* Runtime WebSocket client state tracked by the gateway server.
*/
type GatewayWsClient = PluginNodeCapabilityClient & {
socket: WebSocket;
connect: ConnectParams;
connId: string;
/** Host-owned transport retirement notification; never accepted from wire params. */
connectionSignal?: AbortSignal;
connectionKind?: GatewayWsConnectionKind;
worker?: WorkerConnectionIdentity;
isDeviceTokenAuth?: boolean;
/** Client id verified against the server-approved device pairing record. */
pairedClientId?: string;
usesSharedGatewayAuth: boolean;
sharedGatewaySessionGeneration?: string;
presenceKey?: string;
/** Connection-owned timing facts, reconciled across live peers independently of the TTL cache. */
personPresence?: {
onlineSince: number;
lastActivityAt?: number;
};
authenticatedUserId?: string;
/** Verified Tailscale provider identity; generic proxy identities must not infer this. */
authenticatedUserIsTailscaleProvider?: boolean;
authenticatedGitHubIdentitySync?: AuthenticatedGitHubIdentitySync;
authenticatedUserProfile?: {
profileId: string;
displayName: string | null;
avatarRevision: string;
hasAvatar: boolean;
updatedAt: number;
};
clientIp?: string;
/** Server-attested inputs for rechecking browser-origin policy after config publication. */
browserOrigin?: GatewayWsBrowserOrigin;
internal?: {
/** Handshake-attested direct-local transport; never accepted from wire params. */
isLocalClient?: true;
/** Authenticated Control UI admin admission; never accepted from wire params. */
controlUiAdmin?: true;
approvalRuntime?: boolean;
agentRuntimeIdentity?: AgentRuntimeIdentity;
/** Server-attested role-policy actor; never accepted from WebSocket wire params. */
operatorRoleActor?: GatewayOperatorRoleActor;
};
canvasHostUrl?: string;
canvasCapability?: string;
canvasCapabilityExpiresAtMs?: number;
invalidatedReason?: string;
};
//#endregion
//#region src/gateway/server/client-registry.d.ts
declare class GatewayClientRegistry extends Set<GatewayWsClient> {
#private;
constructor(clients?: Iterable<GatewayWsClient>);
add(client: GatewayWsClient): this;
delete(client: GatewayWsClient): boolean;
clear(): void;
getByConnectionId(connId: string): GatewayWsClient | undefined;
getByConnectionIds(connIds: ReadonlySet<string>): GatewayWsClient[];
}
//#endregion
//#region src/gateway/server/presence-events.d.ts
/**
* Presence snapshot broadcaster for gateway clients.
*/
declare function broadcastPresenceSnapshot(params: {
broadcast: GatewayBroadcastFn;
incrementPresenceVersion: () => number;
getHealthVersion: () => number;
}): number;
//#endregion
//#region src/gateway/session-viewer-presence.d.ts
type SessionViewerPresenceDeclarationsDeps = Parameters<typeof broadcastPresenceSnapshot>[0] & {
clients: GatewayClientRegistry;
};
type SessionViewerPresenceDeclarations = {
replace: (connId: string, sessionKeys: readonly string[]) => readonly string[];
unsubscribe: (connId: string) => void;
stop: () => void;
};
/** Owns one replace-set per websocket connection until empty declaration or disconnect. */
declare function createSessionViewerPresenceDeclarations(deps: SessionViewerPresenceDeclarationsDeps): SessionViewerPresenceDeclarations;
//#endregion
//#region src/process/supervisor/types.d.ts
type TerminationReason = "manual-cancel" | "overall-timeout" | "no-output-timeout" | "spawn-error" | "signal" | "exit";
//#endregion
//#region src/gateway/desktop/managed-linux.d.ts
type ManagedLinuxDesktopStatus = {
state: "not-started";
} | {
state: "starting";
display?: number;
port?: number;
} | {
state: "running";
display: number;
port: number;
} | {
state: "failed";
error: string;
display?: number;
port?: number;
};
//#endregion
//#region src/gateway/desktop/host-source.d.ts
type HostDesktopStatus = {
enabled: false;
state: "disabled";
port: number;
} | {
enabled: true;
state: "attached";
port: number;
security: string;
} | {
enabled: true;
state: "unavailable";
port: number;
security?: string;
} | {
enabled: true;
state: "managed";
managedState: ManagedLinuxDesktopStatus["state"] | "unknown";
port: number;
display?: number;
error?: string;
security?: "VncAuth";
};
type HostDesktopService = {
observe(params: {
control: boolean;
credentials?: {
username?: string;
password?: string;
};
}): Promise<{
transport: "rfb";
wsPath: string;
expiresAtMs: number;
control: boolean;
auth: "vnc-password" | "ard-account";
vncPassword?: string;
}>;
status(): Promise<HostDesktopStatus>;
};
//#endregion
//#region src/gateway/github-personal-oauth.d.ts
type PersonalGitHubAction = {
owner: string;
assertCurrent: () => void;
};
//#endregion
//#region src/config/sessions/paths.d.ts
/** Resolves fixed literal paths without an owner; derived or templated paths require agentId. */
declare function resolveSessionStorePathCore(store?: string, opts?: {
agentId?: string;
env?: NodeJS.ProcessEnv;
}): string;
//#endregion
//#region src/agents/agent-scope-config.d.ts
declare function resolveAgentWorkspaceDir(cfg: OpenClawConfig, agentId: string, env?: NodeJS.ProcessEnv): string;
declare function resolveAgentDir(cfg: OpenClawConfig, agentId: string, env?: NodeJS.ProcessEnv): string;
//#endregion
//#region src/agents/github-tool-identity.d.ts
type PreparedGitHubToolEnvironment = Readonly<{
credentialScrubEnv: Readonly<Record<string, string>>;
localIdentityEnv: Readonly<Record<string, string>>;
excludedStoreNames: readonly string[];
/** A local process must retain the host-selected profile and author identity. */
managedLocalIdentity: boolean;
}>;
//#endregion
//#region src/gateway/github-publication-coordinator-methods.d.ts
type GitHubPublicationClaimRequest = {
claim: WorkerSessionTurnClaim;
sessionKey: string;
agentId: string;
idempotencyKey: string;
title?: string;
body?: string;
assertCurrent?: () => void;
expectedPublisher?: GitHubPublicationPublisher;
};
//#endregion
//#region src/gateway/github-publication.d.ts
type GitHubPublicationCoordinator = ReturnType<typeof createGitHubPublicationCoordinator>;
declare function createGitHubPublicationCoordinator(params: {
placements: WorkerSessionPlacementStore;
}): {
requestPersonalForSession(input: SessionGitHubPublishParams, action: PersonalGitHubAction & {
sessionId: string;
sessionKey: string;
agentId: string;
}): Promise<SessionGitHubPublicationResult>;
personalStatus(action: PersonalGitHubAction, session: {
sessionKey: string;
agentId: string;
sessionId: string;
}, requestId: string): {
result: {
requestId: string;
publisher?: {
accountId: number;
login: string;
source: "agent-override" | "personal" | "system-configured" | "system-detected";
} | undefined;
effect?: {
kind: "pull_request" | "push";
status: "dispatched" | "observed";
headCommit?: string | undefined;
url?: string | undefined;
} | undefined;
status: "requested";
message: string;
} | {
requestId: string;
publisher?: {
accountId: number;
login: string;
source: "agent-override" | "personal" | "system-configured" | "system-detected";
} | undefined;
effect?: {
kind: "pull_request" | "push";
status: "dispatched" | "observed";
headCommit?: string | undefined;
url?: string | undefined;
} | undefined;
status: "publishing";
message: string;
} | {
requestId: string;
publisher?: {
accountId: number;
login: string;
source: "agent-override" | "personal" | "system-configured" | "system-detected";
} | undefined;
effect?: {
kind: "pull_request" | "push";
status: "dispatched" | "observed";
headCommit?: string | undefined;
url?: string | undefined;
} | undefined;
status: "published";
url: string;
repository: string;
branch: string;
headCommit: string;
} | {
requestId: string;
publisher?: {
accountId: number;
login: string;
source: "agent-override" | "personal" | "system-configured" | "system-detected";
} | undefined;
effect?: {
kind: "pull_request" | "push";
status: "dispatched" | "observed";
headCommit?: string | undefined;
url?: string | undefined;
} | undefined;
status: "failed";
code: "github_rejected" | "identity_changed" | "identity_unavailable" | "no_changes" | "not_git" | "not_github" | "push_rejected" | "session_changed" | "unavailable" | "workspace_changed";
message: string;
nextAction: string;
} | {
requestId: string;
publisher?: {
accountId: number;
login: string;
source: "agent-override" | "personal" | "system-configured" | "system-detected";
} | undefined;
effect?: {
kind: "pull_request" | "push";
status: "dispatched" | "observed";
headCommit?: string | undefined;
url?: string | undefined;
} | undefined;
status: "needs_confirmation";
message: string;
};
confirmation: {
requestDigest: string;
generation: string;
account: {
accountId: number;
login: string;
};
pushRepository: string;
repository: string;
branch: string;
baseBranch: string;
sourceHeadCommit: string;
sourceIndexTree: string;
workspaceTree: string;
} | null;
};
personalPending(action: PersonalGitHubAction, session: {
sessionKey: string;
agentId: string;
sessionId: string;
}): {
result: {
requestId: string;
publisher?: {
accountId: number;
login: string;
source: "agent-override" | "personal" | "system-configured" | "system-detected";
} | undefined;
effect?: {
kind: "pull_request" | "push";
status: "dispatched" | "observed";
headCommit?: string | undefined;
url?: string | undefined;
} | undefined;
status: "requested";
message: string;
} | {
requestId: string;
publisher?: {
accountId: number;
login: string;
source: "agent-override" | "personal" | "system-configured" | "system-detected";
} | undefined;
effect?: {
kind: "pull_request" | "push";
status: "dispatched" | "observed";
headCommit?: string | undefined;
url?: string | undefined;
} | undefined;
status: "publishing";
message: string;
} | {
requestId: string;
publisher?: {
accountId: number;
login: string;
source: "agent-override" | "personal" | "system-configured" | "system-detected";
} | undefined;
effect?: {
kind: "pull_request" | "push";
status: "dispatched" | "observed";
headCommit?: string | undefined;
url?: string | undefined;
} | undefined;
status: "published";
url: string;
repository: string;
branch: string;
headCommit: string;
} | {
requestId: string;
publisher?: {
accountId: number;
login: string;
source: "agent-override" | "personal" | "system-configured" | "system-detected";
} | undefined;
effect?: {
kind: "pull_request" | "push";
status: "dispatched" | "observed";
headCommit?: string | undefined;
url?: string | undefined;
} | undefined;
status: "failed";
code: "github_rejected" | "identity_changed" | "identity_unavailable" | "no_changes" | "not_git" | "not_github" | "push_rejected" | "session_changed" | "unavailable" | "workspace_changed";
message: string;
nextAction: string;
} | {
requestId: string;
publisher?: {
accountId: number;
login: string;
source: "agent-override" | "personal" | "system-configured" | "system-detected";
} | undefined;
effect?: {
kind: "pull_request" | "push";
status: "dispatched" | "observed";
headCommit?: string | undefined;
url?: string | undefined;
} | undefined;
status: "needs_confirmation";
message: string;
};
confirmation: {
requestDigest: string;
generation: string;
account: {
accountId: number;
login: string;
};
pushRepository: string;
repository: string;
branch: string;
baseBranch: string;
sourceHeadCommit: string;
sourceIndexTree: string;
workspaceTree: string;
} | null;
} | null;
confirmPersonal(input: SessionGitHubConfirmParams, action: PersonalGitHubAction & {
sessionId: string;
sessionKey: string;
agentId: string;
}): Promise<SessionGitHubPublicationResult>;
requestForSession(input: SessionGitHubPublishParams & {
agentId: string;
expectedRunId?: string;
assertCurrent?: () => void;
}): Promise<SessionGitHubPublicationResult>;
resumeSessionRequests(): Promise<void>;
processClaim(claim: WorkerSessionTurnClaim): Promise<SessionGitHubPublicationResult[]>;
deferOrphanedRequests(): void;
listUnreportedResults(): Array<{
sessionId: string;
sessionKey: string;
agentId: string;
result: SessionGitHubPublicationResult;
}>;
read(requestId: string): SessionGitHubPublicationResult | undefined;
markReported(requestId: string): void;
requestForClaim: (request: GitHubPublicationClaimRequest) => Promise<SessionGitHubPublicationResult>;
prepareClaimWorkspace: (claim: WorkerSessionTurnClaim) => Promise<void>;
deferClaimPreparation: (claim: WorkerSessionTurnClaim) => void;
};
//#endregion
//#region src/agents/github-oauth-records.d.ts
declare const scope: z.ZodEnum<{
agent: "agent";
system: "system";
}>;
type GitHubIdentityScope = z.infer<typeof scope>;
//#endregion
//#region src/gateway/github-oauth-lifecycle.d.ts
declare function createGitHubOAuthLifecycle(params: {
getConfig: () => OpenClawConfig;
getPersistedConfig?: () => OpenClawConfig;
warn: (message: string) => void;
}): {
personal: {
status: (action: PersonalGitHubAction) => Promise<PersonalGitHubStatus>;
startAuthorization(action: PersonalGitHubAction): Promise<UsersGitHubAuthorizeStartResult>;
pollAuthorization(action: PersonalGitHubAction, requestId: string): Promise<UsersGitHubAuthorizePollResult>;
cancelAuthorization(action: PersonalGitHubAction, requestId: string): boolean;
disconnect(action: PersonalGitHubAction): void;
refresh: (owner: string) => Promise<void>;
maintain(): Promise<void>;
stop(): Promise<void>;
};
startAuthorization: (input: {
scope: GitHubIdentityScope;
agentId: string;
}) => Promise<ToolsGitHubAuthorizeStartResult>;
pollAuthorization: (requestId: string) => Promise<ToolsGitHubAuthorizePollResult>;
cancelAuthorization: (requestId: string) => boolean;
status: (agentId: string, selectedScope: GitHubIdentityScope) => Promise<{
agentId: string;
selectedScope: "agent" | "system";
selected: {
scope: "agent" | "system";
configured: boolean;
identity: {
source: "agent-override" | "system-configured" | "system-detected";
credentialKind: "managed-oauth" | "managed-pat" | "native";
credentialState: "available" | "configured_unavailable" | "rate_limited" | "unavailable" | "unverified";
account: {
login: string;
} | null;
gitAuthor: {
name: string | null;
email: string | null;
};
evidence: "github-api" | "none" | "rate-limited" | "unverified";
accessExpiresAtMs: number | null;
refreshState: "available" | "expired" | "failed" | "not_applicable" | "refreshing" | "unavailable";
oauthScopes: string[];
repositoryGrants: "unknown";
} | null;
};
effective: {
source: "agent-override" | "system-configured" | "system-detected";
credentialKind: "managed-oauth" | "managed-pat" | "native";
credentialState: "available" | "configured_unavailable" | "rate_limited" | "unavailable" | "unverified";
account: {
login: string;
} | null;
gitAuthor: {
name: string | null;
email: string | null;
};
evidence: "github-api" | "none" | "rate-limited" | "unverified";
accessExpiresAtMs: number | null;
refreshState: "available" | "expired" | "failed" | "not_applicable" | "refreshing" | "unavailable";
oauthScopes: string[];
repositoryGrants: "unknown";
};
}>;
retireProfile: (profileId: string) => void;
refreshEffectiveIdentity: (agentId: string) => Promise<void>;
maintain: () => Promise<void>;
start: () => void;
stop: () => Promise<void>;
};
//#endregion
//#region src/gateway/model-account-authority.d.ts
/** In-process account authority shared by connect and selection owners; never serialized. */
type ModelAccountConnectAction = {
owner: string;
assertCurrent: () => void;
};
type UserModelAccountSelection = ModelAccountConnectAction & {
authProfileId: string;
};
//#endregion
//#region src/gateway/model-account-connect.d.ts
/** One Gateway lifetime owns sign-in steps and authority; provider methods only stage credentials. */
declare function createModelAccountConnectService(options: {
getConfig: () => OpenClawConfig;
onChanged?: () => void;
}): {
listLinks(action: ModelAccountConnectAction): UsersListAuthLinksResult;
link(action: ModelAccountConnectAction, authProfileId: string): UsersLinkAuthProfileResult;
unlink(action: ModelAccountConnectAction, provider: string): UsersUnlinkAuthProfileResult;
list(action: ModelAccountConnectAction, cursor?: string): UsersListModelAccountsResult;
catalog(action: ModelAccountConnectAction): UsersAuthConnectCatalogResult;
select(action: ModelAccountConnectAction, authProfileId: string): UsersSelectModelAccountResult;
start(action: ModelAccountConnectAction, provider: string, methodId: string): Promise<UsersAuthConnectStartResult>;
status(action: ModelAccountConnectAction, connectId: string): UsersAuthConnectStatusResult;
answer(action: ModelAccountConnectAction, connectId: string, stepId: string, value?: unknown): Promise<UsersAuthConnectStatusResult>;
cancel(action: ModelAccountConnectAction, connectId: string): UsersAuthConnectStatusResult;
supersede: (owner: string, provider: string) => void;
stop(): Promise<void>;
};
//#endregion
//#region src/infra/voicewake-routing.d.ts
type VoiceWakeRouteTarget = {
mode: "current";
agentId?: undefined;
sessionKey?: undefined;
} | {
agentId: string;
sessionKey?: undefined;
mode?: undefined;
} | {
sessionKey: string;
agentId?: undefined;
mode?: undefined;
};
type VoiceWakeRouteRule = {
trigger: string;
target: VoiceWakeRouteTarget;
};
type VoiceWakeRoutingConfig = {
version: 1;
defaultTarget: VoiceWakeRouteTarget;
routes: VoiceWakeRouteRule[];
updatedAtMs: number;
};
//#endregion
//#region src/shared/async-work-scope.d.ts
/** Outside a managed scope, the returned promise remains the caller's responsibility. */
declare function trackAsyncWork<T>(run: () => T | Promise<T>): Promise<T>;
//#endregion
//#region src/tasks/task-registry.types.d.ts
/** JSON value shape persisted with runtime-owned task detail. */
type JsonValue = null | boolean | number | string | JsonValue[] | {
[key: string]: JsonValue;
};
/** Runtime families that own task run lifecycles. */
declare const TASK_RUNTIMES: readonly ["subagent", "acp", "cron", "cli"];
declare const TASK_STATUSES: readonly ["queued", "running", "succeeded", "failed", "timed_out", "cancelled", "lost"];
type TaskRuntime = (typeof TASK_RUNTIMES)[number];
type TaskStatus = (typeof TASK_STATUSES)[number];
type TaskDeliveryStatus = "pending" | "delivered" | "session_queued" | "failed" | "dismissed" | "parent_missing" | "not_applicable";
type TaskNotifyPolicy = "done_only" | "state_changes" | "silent";
/** Semantic success detail for required-completion task outcomes. */
type TaskTerminalOutcome = "succeeded" | "blocked";
type TaskScopeKind = "session" | "system";
type TaskStatusCounts = Record<TaskStatus, number>;
type TaskRuntimeCounts = Record<TaskRuntime, number>;
type TaskRegistrySummary = {
total: number;
active: number;
terminal: number;
failures: number;
byStatus: TaskStatusCounts;
byRuntime: TaskRuntimeCounts;
warning?: string;
};
type TaskDeliveryState = {
taskId: string;
requesterOrigin?: DeliveryContext;
lastNotifiedEventAt?: number;
};
type TaskRecord = {
taskId: string;
runtime: TaskRuntime;
taskKind?: string;
sourceId?: string;
requesterSessionKey: string;
ownerKey: string;
scopeKind: TaskScopeKind;
childSessionKey?: string;
parentFlowId?: string;
parentTaskId?: string;
agentId?: string;
/** Agent store for requester transcripts whose session key is unscoped, such as `global`.
* Task authorization remains keyed by ownerKey. */
requesterAgentId?: string;
runId?: string;
label?: string;
task: string;
status: TaskStatus;
deliveryStatus: TaskDeliveryStatus;
notifyPolicy: TaskNotifyPolicy;
createdAt: number;
startedAt?: number;
endedAt?: number;
lastEventAt?: number;
cleanupAfter?: number;
/** Tool invocations observed on this run's agent-event stream. */
toolUseCount?: number;
/** Name of the most recent tool invocation observed for this run. */
lastToolName?: string;
error?: string;
progressSummary?: string;
terminalSummary?: string;
terminalOutcome?: TaskTerminalOutcome;
detail?: JsonValue;
};
//#endregion
//#region src/infra/gateway-suspend-coordinator.d.ts
/** Private identity of one live process-owning host iteration, never a wire token. */
type GatewaySuspendHandoffOwner = {
isCurrent: () => boolean;
};
//#endregion
//#region src/plugins/provider-catalog-outcome.d.ts
type ProviderCatalogOutcome = {
provider: string;
/** Auth profile tested by discovery; omission means provider-wide auth. */
profileId?: string;
/** Limits an auth rejection to catalog discovery rather than model execution. */
rejectionScope?: "catalog";
status: "ready" | "auth-rejected" | "unavailable";
};
//#endregion
//#region src/agents/model-catalog.types.d.ts
/** Input modalities a catalog entry can advertise. */
type ModelInputType = "text" | "image" | "audio" | "video" | "document";
type ModelContextWindowOption = {
id: string;
label: string;
contextWindow: number;
};
/** Normalized model metadata exposed by the agent model catalog. */
type ModelCatalogEntry = {
/** Native catalog owner, not a physical provider route or transferable readiness fact. */
nativeRuntime?: string;
id: string;
name: string;
provider: string;
/** Provider-owned strongest-first picker order; internal and never projected to clients. */
providerOrder?: number;
alias?: string;
api?: ModelApi;
/** Private transport provenance for route matching; never project directly to clients. */
baseUrl?: string;
contextWindow?: number;
contextWindows?: ModelContextWindowOption[];
contextWindowDefault?: string;
contextTokens?: number;
reasoning?: boolean;
/** Config-authored reasoning override; internal provenance, never project to clients. */
configuredReasoning?: boolean;
/** Concrete runtime owner of thinking policy; internal and never project to clients. */
thinkingPolicyProvider?: string;
/** Provider-owned effort support for this exact physical model route. */
thinkingLevelMap?: ThinkingLevelMap;
input?: ModelInputType[];
params?: Record<string, unknown>;
compat?: ModelCompatConfig;
mediaInput?: ModelMediaInputConfig;
status?: ModelCatalogStatus;
statusReason?: string;
replaces?: string[];
replacedBy?: string;
};
/** Logical catalog rows plus the physical variants used for route selection. */
type ModelCatalogSnapshot = {
entries: ModelCatalogEntry[];
routeVariants: ModelCatalogEntry[];
/** Provider-owned outcome of each live catalog request in this generation. */
providerOutcomes?: readonly ProviderCatalogOutcome[];
/** Static provider-hook rows captured alongside the full lifecycle generation. */
staticEntries?: ModelCatalogEntry[];
/**
* `false` only when this snapshot came from a degraded load (discovery threw,
* static or empty fallback). Absent/`true` means authoritative — consumers that
* destroy durable state (e.g. resetting a pinned model override) must treat only
* an explicit `false` as degraded, so unrelated hand-built snapshots stay safe.
*/
authoritative?: boolean;
};
//#endregion
//#region src/plugins/provider-catalog.types.d.ts
type ProviderCatalogOrder = "simple" | "profile" | "paired" | "late";
type ProviderCatalogContext = {
config: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
env: NodeJS.ProcessEnv;
/** Normalized provider identities selected for this catalog owner; absent means the full catalog. */
providerIds?: readonly string[];
resolveProviderApiKey: (providerId?: string) => {
apiKey: string | undefined;
discoveryApiKey?: string;
};
resolveProviderAuth: (providerId?: string, options?: {
oauthMarker?: string;
}) => {
apiKey: string | undefined;
discoveryApiKey?: string;
mode: "api_key" | "aws-sdk" | "oauth" | "token" | "none";
source: "env" | "profile" | "none";
profileId?: string;
};
};
type ProviderCatalogResult = {
provider: ModelProviderConfig;
outcomes?: readonly ProviderCatalogOutcome[];
} | {
providers: Record<string, ModelProviderConfig>;
outcomes?: readonly ProviderCatalogOutcome[];
} | null | undefined;
type ProviderPluginCatalog = {
order?: ProviderCatalogOrder;
run: (ctx: ProviderCatalogContext) => Promise<ProviderCatalogResult>;
};
type UnifiedModelCatalogProviderContext = ProviderCatalogContext & {
signal?: AbortSignal;
includeLive?: boolean;
timeoutMs?: number;
};
type UnifiedModelCatalogProviderPlugin$1 = {
provider: string;
kinds: readonly UnifiedModelCatalogKind[];
staticCatalog?: (ctx: UnifiedModelCatalogProviderContext) => readonly UnifiedModelCatalogEntry[] | Promise<readonly UnifiedModelCatalogEntry[] | null | undefined> | null | undefined;
liveCatalog?: (ctx: UnifiedModelCatalogProviderContext) => readonly UnifiedModelCatalogEntry[] | Promise<readonly UnifiedModelCatalogEntry[] | null | undefined> | null | undefined;
};
/**
* Built-in model suppression hook context.
*
* @deprecated Use manifest `modelCatalog.suppressions`. Runtime suppression
* hooks are no longer called by model resolution.
*/
type ProviderBuiltInModelSuppressionContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
env: NodeJS.ProcessEnv;
provider: string;
modelId: string;
baseUrl?: string;
};
type ProviderBuiltInModelSuppressionResult = {
suppress: boolean;
errorMessage?: string;
};
/**
* Provider-owned "modern model" policy input.
*
* Live smoke/model-profile selection uses this to keep provider-specific
* inclusion/exclusion rules out of core.
*/
type ProviderModernModelPolicyContext = {
provider: string;
modelId: string;
};
/**
* Final catalog augmentation hook.
*
* Runs after OpenClaw loads the discovered model catalog and merges configured
* opt-in providers. Use this for forward-compat rows or vendor-owned synthetic
* entries that should appear in `models list` and model pickers even when the
* upstream registry has not caught up yet.
*/
type ProviderAugmentModelCatalogContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
env: NodeJS.ProcessEnv;
resolveProviderApiKey?: ProviderCatalogContext["resolveProviderApiKey"];
entries: ModelCatalogEntry[];
};
//#endregion
//#region src/agents/system-prompt-contribution.d.ts
/**
* Provider-owned system prompt contribution types.
* Separates cache-stable prefixes, dynamic suffixes, and section overrides for
* runtime prompt assembly.
*/
/** Core system-prompt sections that providers may replace. */
type ProviderSystemPromptSectionId = "interaction_style" | "tool_call_style" | "execution_bias";
/** Provider guidance merged into the assembled agent system prompt. */
type ProviderSystemPromptContribution = {
/**
* Cache-stable provider guidance inserted above the system-prompt cache boundary.
*
* Use this for static provider/model-family instructions that should preserve
* KV cache reuse across turns.
*/
stablePrefix?: string;
/**
* Provider guidance inserted below the cache boundary.
*
* Use this only for genuinely dynamic text that is expected to vary across
* runs or sessions.
*/
dynamicSuffix?: string;
/**
* Whole-section replacements for selected core prompt sections.
*
* Values should contain the complete rendered section, including any desired
* heading such as `## Tool Call Style`.
*/
sectionOverrides?: Partial<Record<ProviderSystemPromptSectionId, string>>;
};
//#endregion
//#region src/infra/provider-usage.types.d.ts
/** One quota window reported by a provider usage endpoint. */
type UsageWindow = {
label: string;
usedPercent: number;
resetAt?: number;
};
/** Provider-reported monetary or credit facts. Units may be ISO currencies or provider credits. */
type ProviderUsageBilling = {
type: "balance";
label?: string;
amount: number;
unit: string;
} | {
type: "spend";
label?: string;
amount: number;
unit: string;
period?: string;
resetAt?: number;
} | {
type: "budget";
label?: string;
used: number;
limit: number;
unit: string;
period?: string;
resetAt?: number;
};
/** Provider-reported daily cost and token totals. Costs are actual provider billing, not estimates. */
type ProviderUsageCostDaily = {
date: string;
amount: number;
requests?: number;
inputTokens: number;
cacheReadTokens: number;
cacheWriteTokens: number;
outputTokens: number;
totalTokens: number;
};
/** Aggregate model activity for the provider history window. */
type ProviderUsageModelBreakdown = {
name: string;
requests?: number;
inputTokens: number;
cacheReadTokens: number;
cacheWriteTokens: number;
outputTokens: number;
totalTokens: number;
};
/** Aggregate provider billing category for the history window. */
type ProviderUsageCostBreakdown = {
name: string;
amount: number;
};
/** Provider-reported cost history and attribution for one bounded UTC window. */
type ProviderUsageCostHistory = {
unit: string;
periodDays: number;
scope?: string;
daily: ProviderUsageCostDaily[];
models: ProviderUsageModelBreakdown[];
categories: ProviderUsageCostBreakdown[];
};
type ProviderUsageSnapshot = {
provider: UsageProviderId;
displayName: string;
windows: UsageWindow[];
billing?: ProviderUsageBilling[];
costHistory?: ProviderUsageCostHistory;
summary?: string;
plan?: string;
/** Account identity (email) the usage was fetched under, when known. */
accountEmail?: string;
error?: string;
};
/** Normalized provider id. Usage providers are discovered from plugin hooks at runtime. */
type UsageProviderId = string;
//#endregion
//#region src/plugin-sdk/provider-oauth-runtime.d.ts
/** Normalized OAuth credential bundle persisted by provider auth profiles. */
type OAuthCredentials = {
/** Refresh token or provider-equivalent long-lived credential. */
refresh: string;
/** Access token or provider-equivalent bearer credential. */
access: string;
/** Absolute epoch milliseconds when the access token should be considered expired. */
expires: number;
[key: string]: unknown;
};
/** Stable provider id used by OAuth credential and config routing. */
type OAuthProviderId = string;
/** Manual input prompt shown during OAuth login flows. */
type OAuthPrompt$1 = {
/** Prompt text shown to the operator. */
message: string;
/** Optional placeholder for manual text entry. */
placeholder?: string;
/** Whether empty input should be accepted instead of reprompting. */
allowEmpty?: boolean;
};
/** Authorization URL and optional instructions shown before OAuth completion. */
type OAuthAuthInfo = {
/** Provider authorization URL shown to the user. */
url: string;
/** Optional provider-specific instruction text for manual flows. */
instructions?: string;
};
/** One selectable OAuth login option. */
type OAuthSelectOption = {
/** Stable option id returned when the operator selects this entry. */
id: string;
/** Human-readable option label shown in the selector. */
label: string;
};
/** Selector prompt used when a provider offers multiple OAuth login choices. */
type OAuthSelectPrompt = {
/** Prompt text shown above the selectable options. */
message: string;
/** Options available for the operator to choose from. */
options: OAuthSelectOption[];
};
/** UI/runtime callbacks used by provider OAuth login implementations. */
interface OAuthLoginCallbacks {
/** Emits authorization URL/instructions to the UI before waiting for completion. */
onAuth: (info: OAuthAuthInfo) => void;
/** Prompts for manual input such as pasted callback URLs or authorization codes. */
onPrompt: (prompt: OAuthPrompt$1) => Promise<string>;
/** Reports human-readable login progress without exposing secrets. */
onProgress?: (message: string) => void;
/** Optional direct manual-code entry hook used when callback-server flows cannot complete. */
onManualCodeInput?: () => Promise<string>;
/** Show an interactive selector and return the selected option id, or undefined on cancel. */
onSelect?: (prompt: OAuthSelectPrompt) => Promise<string | undefined>;
/** Cancels pending OAuth waits and prompts when aborted. */
signal?: AbortSignal;
}
/** Provider OAuth contract implemented by provider plugins. */
interface OAuthProviderInterface {
/** Stable provider id used for credential and config routing. */
readonly id: OAuthProviderId;
/** Human-readable provider name shown in login flows. */
readonly name: string;
/** Run the login flow and return credentials to persist. */
login(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;
/** Whether login uses a local callback server and supports manual code input. */
usesCallbackServer?: boolean;
/** Refresh expired credentials and return updated credentials to persist. */
refreshToken(credentials: OAuthCredentials): Promise<OAuthCredentials>;
/** Convert credentials to an API key string for the provider. */
getApiKey(credentials: OAuthCredentials): string;
/** Optionally adjust models for this provider, such as updating baseUrl. */
modifyModels?(models: Model[], credentials: OAuthCredentials): Model[];
}
//#endregion
//#region src/agents/system-prompt.types.d.ts
type PromptMode = "full" | "minimal" | "none";
type SilentReplyPromptMode = "generic" | "none";
//#endregion
//#region src/plugins/provider-oauth-flow.d.ts
/** Prompt payload used when OAuth flow code entry needs user input. */
type OAuthPrompt = {
message: string;
placeholder?: string;
};
/** Creates OAuth callbacks that use local browser auth locally and manual code entry on VPS hosts. */
declare function createVpsAwareOAuthHandlers(params: {
isRemote: boolean;
prompter: WizardPrompter;
runtime: RuntimeEnv;
spin: ReturnType<WizardPrompter["progress"]>;
openUrl: (url: string) => Promise<unknown>;
localBrowserMessage: string;
manualPromptMessage?: string;
manualPromptSignal?: AbortSignal;
}): {
onAuth: (event: {
url: string;
}) => Promise<void>;
onPrompt: (prompt: OAuthPrompt) => Promise<string>;
};
//#endregion
//#region src/plugins/provider-authentication.types.d.ts
type ProviderAuthKind = "oauth" | "api_key" | "token" | "device_code" | "custom";
type ProviderAuthSecretStorage = {
/** Final persistence target. The inline credential remains available for staged validation. */
kind: "store";
/** Environment-style prefix used for the host-owned secret-store entry. */
namePrefix: string;
};
type ProviderAuthProfile = {
profileId: string;
credential: AuthProfileCredential;
/** Request host-owned SecretRef materialization at the final persistence boundary. */
secretStorage?: ProviderAuthSecretStorage;
};
/** Standard result payload returned by provider auth methods. */
type ProviderAuthResult = {
profiles: ProviderAuthProfile[];
/**
* Optional config patch to merge after credentials are written.
*
* Use this for provider-owned onboarding defaults such as
* `models.providers.<id>` entries, default aliases, or agent model helpers.
* The caller still persists auth-profile bindings separately.
*/
configPatch?: Partial<OpenClawConfig>;
defaultModel?: string;
notes?: string[];
/**
* Opt in to replace `agents.defaults.models` wholesale with the patch map.
* Default behavior merges the map so other providers' entries survive.
* Set only from migrations that intentionally rename/remove model keys.
*/
replaceDefaultModels?: boolean;
};
/** Interactive auth context passed to provider login/setup methods. */
type ProviderAuthContext = {
config: OpenClawConfig;
env?: NodeJS.ProcessEnv;
agentDir?: string;
workspaceDir?: string;
prompter: WizardPrompter;
runtime: RuntimeEnv;
/** Cancels browser callbacks, device polling, and other app-owned auth work. */
signal?: AbortSignal;
/** Personal-account methods must recheck live caller authority immediately before external effects. */
assertCurrent?: () => void;
/**
* Optional onboarding CLI options that triggered this auth flow.
*
* Present for setup/configure/auth-choice flows so provider methods can
* honor preseeded flags like `--openai-api-key` or generic
* `--token/--token-provider` pairs. Direct `models auth login` usually
* leaves this undefined.
*/
opts?: ProviderAuthOptionBag;
/**
* Onboarding secret persistence preference.
*
* Interactive wizard flows set this when the caller explicitly requested
* plaintext or env/file/exec/store ref storage. Ad-hoc `models auth login` flows
* usually leave it undefined.
*/
secretInputMode?: SecretInputMode;
/**
* Whether the provider auth flow should offer the onboarding secret-storage
* mode picker when `secretInputMode` is unset.
*
* This is true for onboarding/configure flows and false for direct
* `models auth` commands, which should keep a tighter, provider-owned prompt
* surface.
*/
allowSecretRefPrompt?: boolean;
isRemote: boolean;
openUrl: (url: string) => Promise<void>;
oauth: {
createVpsAwareHandlers: typeof createVpsAwareOAuthHandlers;
};
};
type ProviderNonInteractiveApiKeyResult = {
key: string;
source: "profile" | "env" | "flag";
envVarName?: string;
};
type ProviderResolveNonInteractiveApiKeyParams = {
provider: string;
flagValue?: string;
flagName: `--${string}`;
envVar: string;
envVarName?: string;
allowProfile?: boolean;
required?: boolean;
};
type ProviderNonInteractiveApiKeyCredentialParams = {
provider: string;
resolved: ProviderNonInteractiveApiKeyResult;
email?: string;
metadata?: Record<string, string>;
};
type ProviderAuthMethodNonInteractiveContext = {
authChoice: string;
config: OpenClawConfig;
baseConfig: OpenClawConfig;
opts: ProviderAuthOptionBag;
runtime: RuntimeEnv;
agentDir?: string;
workspaceDir?: string;
resolveApiKey: (params: ProviderResolveNonInteractiveApiKeyParams) => Promise<ProviderNonInteractiveApiKeyResult | null>;
toApiKeyCredential: (params: ProviderNonInteractiveApiKeyCredentialParams) => ApiKeyCredential$1 | null;
};
type ProviderAuthMethodNonInteractiveValidationContext = Omit<ProviderAuthMethodNonInteractiveContext, "toApiKeyCredential">;
/** Read-only context for app-guided discovery of already available inference. */
type ProviderAppGuidedSetupContext = {
config: OpenClawConfig;
env: NodeJS.ProcessEnv;
workspaceDir?: string;
signal?: AbortSignal;
};
type ProviderAppGuidedSetupCandidate = {
/** Canonical provider/model reference returned unchanged during activation. */
modelRef: string;
/** Optional provider-owned detail shown beside the auth-choice label. */
detail?: string;
};
type ProviderAppGuidedSetup = {
/**
* Report whether the provider's local service is reachable, even when no
* model is suitable for automatic activation. This probe must be read-only.
*/
detectAvailability?: (ctx: ProviderAppGuidedSetupContext) => Promise<boolean>;
/** Detection is read-only: no model pull, download, login, or config write. */
detect: (ctx: ProviderAppGuidedSetupContext) => Promise<ProviderAppGuidedSetupCandidate | null>;
/** Recheck one detected model and return the config required for a live probe. */
prepare: (ctx: ProviderAppGuidedSetupContext & {
modelRef: string;
}) => Promise<ProviderAuthResult | null>;
};
type ProviderAuthMethod = {
id: string;
label: string;
hint?: string;
kind: ProviderAuthKind;
/** Provider-owned model used to validate app-guided secret setup. */
starterModel?: string;
/**
* Optional wizard/onboarding metadata for this specific auth method.
*
* Use this when one provider exposes multiple setup entries (for example API
* key + OAuth, or region-specific login flows). OpenClaw uses this to expose
* method-specific auth choices while keeping the provider id stable.
*/
wizard?: ProviderPluginWizardSetup;
/** Proven provider identity for reconnecting an owned personal account; absent means a new slot. */
matchesPersonalAccount?: (credential: AuthProfileCredential, existing: AuthProfileCredential) => boolean;
run: (ctx: ProviderAuthContext) => Promise<ProviderAuthResult>;
runNonInteractive?: (ctx: ProviderAuthMethodNonInteractiveContext) => Promise<OpenClawConfig | null>;
/** Side-effect-free prerequisite validation used before destructive reset handling. */
validateNonInteractive?: (ctx: ProviderAuthMethodNonInteractiveValidationContext) => Promise<boolean>;
/** Provider-owned local model discovery for the shared guided setup ladder. */
appGuidedSetup?: ProviderAppGuidedSetup;
};
type ProviderPluginWizardSetup = {
choiceId?: string;
choiceLabel?: string;
choiceHint?: string;
assistantPriority?: number;
assistantVisibility?: "visible" | "manual-only";
onboardingFeatured?: boolean;
groupId?: string;
groupLabel?: string;
groupHint?: string;
methodId?: string;
/**
* Interactive onboarding surfaces where this auth choice should appear.
* Defaults to `["text-inference"]` when omitted.
*/
onboardingScopes?: Array<"text-inference" | "image-generation" | "music-generation">;
/**
* Optional model-allowlist prompt policy applied after this auth choice is
* selected in configure/onboarding flows.
*
* Keep this UI-facing and static. Provider logic that needs runtime state
* should stay in `run`/`runNonInteractive`.
*/
modelAllowlist?: {
allowedKeys?: string[];
initialSelections?: string[];
loadCatalog?: boolean;
message?: string;
};
/**
* Optional default-model prompt policy for this auth/setup choice.
*
* Use this when selecting the auth choice should still force a model picker
* even if the choice was preseeded via CLI/configure, or when "keep current"
* would skip required provider-owned post-selection work.
*/
modelSelection?: {
promptWhenAuthChoiceProvided?: boolean;
allowKeepCurrent?: boolean;
};
};
/** Optional model-picker metadata shown in interactive provider selection flows. */
type ProviderPluginWizardModelPicker = {
label?: string;
hint?: string;
methodId?: string;
};
/** UI metadata that lets provider plugins appear in onboarding and configure flows. */
type ProviderPluginWizard = {
setup?: ProviderPluginWizardSetup;
modelPicker?: ProviderPluginWizardModelPicker;
};
type ProviderOAuthProfileIdRepair = {
/**
* Legacy OAuth profile id to migrate away from.
*
* When omitted, OpenClaw falls back to `<provider>:default`.
*/
legacyProfileId?: string;
/**
* Optional custom doctor prompt label.
*
* Defaults to the provider label when omitted.
*/
promptLabel?: string;
};
type ProviderModelSelectedContext = {
config: OpenClawConfig;
model: string;
prompter: WizardPrompter;
agentDir?: string;
workspaceDir?: string;
};
type ProviderDeferSyntheticProfileAuthContext = {
config?: OpenClawConfig;
provider: string;
providerConfig?: ModelProviderConfig;
resolvedApiKey?: string;
};
type ProviderSystemPromptContributionContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
provider: string;
modelId: string;
promptMode: PromptMode;
runtimeChannel?: string;
runtimeCapabilities?: string[];
agentId?: string;
trigger?: "cron" | "heartbeat" | "manual" | "memory" | "overflow" | "user";
};
type ProviderTransformSystemPromptContext = ProviderSystemPromptContributionContext & {
systemPrompt: string;
};
//#endregion
//#region src/plugins/provider-replay.types.d.ts
type ProviderReplaySanitizeMode = "full" | "images-only";
type ProviderReplayToolCallIdMode = "strict" | "strict9";
type ProviderReasoningOutputMode = "native" | "tagged";
/**
* Provider-owned replay/compaction transcript policy.
*
* These values are consumed by shared history replay and compaction logic.
* Return only the fields the provider wants to override; core fills the rest
* with its default policy.
*/
type ProviderReplayPolicy = {
sanitizeMode?: ProviderReplaySanitizeMode;
sanitizeToolCallIds?: boolean;
toolCallIdMode?: ProviderReplayToolCallIdMode;
duplicateToolCallIdStyle?: "openai";
preserveNativeAnthropicToolUseIds?: boolean;
preserveSignatures?: boolean;
/** Keep per-turn runtime context in place to preserve signed thinking prefixes. */
appendOnlyRuntimeContext?: boolean;
sanitizeThoughtSignatures?: {
allowBase64Only?: boolean;
includeCamelCase?: boolean;
};
dropThinkingBlocks?: boolean;
dropReasoningFromHistory?: boolean;
repairToolUseResultPairing?: boolean;
applyAssistantFirstOrderingFix?: boolean;
validateGeminiTurns?: boolean;
validateAnthropicTurns?: boolean;
allowSyntheticToolResults?: boolean;
};
/**
* Provider-owned replay/compaction policy input.
*
* Use this when transcript replay rules depend on provider/model transport
* behavior and should stay with the provider plugin instead of core tables.
*/
type ProviderReplayPolicyContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
provider: string;
modelId?: string;
modelApi?: string | null;
model?: ProviderRuntimeModel;
};
type ProviderReplaySessionEntry = {
customType: string;
data?: unknown;
};
type ProviderReplaySessionState = {
getCustomEntries(): ProviderReplaySessionEntry[];
appendCustomEntry(customType: string, data: unknown): void;
};
/**
* Provider-owned replay-history sanitization input.
*
* Runs after core applies generic transcript cleanup so plugins can make
* provider-specific replay rewrites without owning the whole compaction flow.
*/
type ProviderSanitizeReplayHistoryContext = ProviderReplayPolicyContext & {
sessionId: string;
messages: AgentMessage[];
allowedToolNames?: Iterable<string>;
sessionState?: ProviderReplaySessionState;
};
/**
* Provider-owned final replay-turn validation input.
*
* Use this for providers that require strict turn ordering or additional
* replay-time transcript validation beyond generic sanitation.
*/
type ProviderValidateReplayTurnsContext = ProviderReplayPolicyContext & {
sessionId?: string;
messages: AgentMessage[];
sessionState?: ProviderReplaySessionState;
};
/**
* Provider-owned tool-schema normalization input.
*
* Runs before tool registration for replay/compaction/inference so providers
* can rewrite schema keywords that their transport family does not support.
*/
type ProviderNormalizeToolSchemasContext = ProviderReplayPolicyContext & {
tools: AnyAgentTool[];
};
type ProviderToolSchemaDiagnostic = {
toolName: string;
toolIndex?: number;
violations: string[];
};
/**
* Provider-owned reasoning output mode input.
*
* Use this when a provider requires a specific reasoning-output contract, such
* as text tags instead of native structured reasoning fields.
*/
type ProviderReasoningOutputModeContext = ProviderReplayPolicyContext;
//#endregion
//#region src/agents/provider-request-config.d.ts
/** Auth override accepted from sanitized provider/model request config. */
type ProviderRequestAuthOverride = {
mode: "provider-default";
} | {
mode: "authorization-bearer";
token: string;
} | {
mode: "header";
headerName: string;
value: string;
prefix?: string;
};
/** TLS override accepted from sanitized provider/model request config. */
type ProviderRequestTlsOverride = {
ca?: string;
cert?: string;
key?: string;
passphrase?: string;
serverName?: string;
insecureSkipVerify?: boolean;
};
/** Proxy override accepted from sanitized provider/model request config. */
type ProviderRequestProxyOverride = {
mode: "env-proxy";
tls?: ProviderRequestTlsOverride;
} | {
mode: "explicit-proxy";
url: string;
tls?: ProviderRequestTlsOverride;
};
/** Transport override block shared by provider and model request config. */
type ProviderRequestTransportOverrides = {
headers?: Record<string, string>;
auth?: ProviderRequestAuthOverride;
proxy?: ProviderRequestProxyOverride;
tls?: ProviderRequestTlsOverride;
};
/** Model-scoped transport overrides, including private-network policy. */
type ModelProviderRequestTransportOverrides$1 = ProviderRequestTransportOverrides & {
allowPrivateNetwork?: boolean;
};
//#endregion
//#region src/llm/model-registry.d.ts
/** Registry abstraction used by model pickers and provider availability checks. */
type ModelRegistry$1 = {
getAll(): Model[];
getAvailable(): Model[];
find(provider: string, modelId: string): Model | undefined;
hasConfiguredAuth(model: Model): boolean;
};
//#endregion
//#region src/plugins/provider-runtime.types.d.ts
type ModelProviderRequestTransportOverrides = ModelProviderRequestTransportOverrides$1;
type ProviderRuntimeProviderConfig = {
baseUrl?: string;
api?: ModelProviderConfig["api"];
auth?: ModelProviderConfig["auth"];
models?: ModelProviderConfig["models"];
headers?: unknown;
};
/**
* Sync hook for provider-owned model ids that are not present in the local
* registry/catalog yet.
*
* Use this for pass-through providers or provider-specific forward-compat
* behavior. The hook should be cheap and side-effect free; async refreshes
* belong in `prepareDynamicModel`.
*/
type ProviderResolveDynamicModelContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
agentRuntimeId?: string;
provider: string;
modelId: string;
modelRegistry: ModelRegistry$1;
providerConfig?: ProviderRuntimeProviderConfig;
authProfileId?: string;
authProfileMode?: AuthProfileCredential["type"] | "aws-sdk";
};
/**
* Optional async preparation for dynamic model resolution.
*
* Called only from async model resolution paths. Providers can return the
* requested model directly or refresh reusable metadata before the sync retry.
*/
type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;
type ProviderPreferRuntimeResolvedModelContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
provider: string;
modelId: string;
};
/**
* Last-chance rewrite hook for provider-owned transport normalization.
*
* Runs after OpenClaw resolves an explicit/discovered/dynamic model and before
* the embedded runner uses it. Typical uses: swap API ids, fix base URLs, or
* patch provider-specific compat bits.
*/
type ProviderNormalizeResolvedModelContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
provider: string;
modelId: string;
model: ProviderRuntimeModel;
};
/**
* Provider-owned model-id normalization before config/runtime lookup.
*
* Use this for provider-specific alias cleanup that should stay with the
* plugin rather than in core string tables.
*/
type ProviderNormalizeModelIdContext = {
provider: string;
modelId: string;
};
/**
* Provider-owned transport normalization for arbitrary provider/model config.
*
* Use this when transport cleanup depends on API/baseUrl rather than the
* owning provider id, for example custom providers that still target a
* plugin-owned transport family.
*/
type ProviderNormalizeTransportContext = {
config?: OpenClawConfig;
workspaceDir?: string;
provider: string;
modelId?: string;
api?: string | null;
baseUrl?: string;
};
/**
* Runtime auth input for providers that need an extra exchange step before
* inference. The incoming `apiKey` is the raw credential resolved from auth
* profiles/env/config. The returned value should be the actual token/key to use
* for the request.
*/
type ProviderPrepareRuntimeAuthContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
env: NodeJS.ProcessEnv;
provider: string;
modelId: string;
model: ProviderRuntimeModel;
apiKey: string;
authMode: string;
profileId?: string;
};
/**
* Result of `prepareRuntimeAuth`.
*
* `apiKey` is required and becomes the runtime credential stored in auth
* storage. `baseUrl` is optional and lets providers like GitHub Copilot swap to
* an entitlement-specific endpoint at request time. `expiresAt` enables generic
* background refresh in long-running turns.
*/
type ProviderPreparedRuntimeAuth = {
apiKey: string;
baseUrl?: string;
request?: ModelProviderRequestTransportOverrides;
expiresAt?: number;
};
/**
* Usage/billing auth input for providers that expose quota/usage endpoints.
*
* This hook is intentionally separate from `prepareRuntimeAuth`: usage
* snapshots often need a different credential source than live inference
* requests, and they run outside the embedded runner.
*
* The helper methods cover the common OpenClaw auth resolution paths:
*
* - `resolveApiKeyFromConfigAndStore`: env/config/plain token/api_key profiles
* - `resolveOAuthToken`: oauth/token profiles resolved through the auth store,
* optionally for an explicit provider override
*
* Plugins can still do extra provider-specific work on top (for example parse a
* token blob, read a legacy credential file, or pick between aliases).
*/
type ProviderResolveUsageAuthContext = {
config: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
env: NodeJS.ProcessEnv;
provider: string;
resolveApiKeyFromConfigAndStore: (params?: {
providerIds?: string[];
envDirect?: Array<string | undefined>;
}) => string | undefined;
/** Ordered API-key/token candidates, including resolved SecretRefs, for credential classification. */
resolveApiKeyCandidatesFromConfigAndStore?: (params?: {
providerIds?: string[];
envDirect?: Array<string | undefined>;
}) => Promise<string[]>;
resolveOAuthToken: (params?: {
provider?: string;
excludeProfileIds?: string[];
}) => Promise<ProviderUsageAuthToken | null>;
};
type ProviderUsageAuthToken = {
token: string;
accountId?: string;
/** Non-secret plan metadata from the resolved credential (e.g. Claude "max"). */
subscriptionType?: string;
rateLimitTier?: string;
/** Account email captured on the resolved credential, when known. */
email?: string;
};
/**
* Result of `resolveUsageAuth`.
*
* Two shapes are supported:
* - `{ token: string; accountId?: string }` — use this token for provider usage endpoints.
* - `{ handled: true }` — this provider handled the request but has no usable
* usage token; core must skip further fallback (generic API-key/OAuth fallback
* must not run).
*
* Returning `null` or `undefined` means "not handled by this provider"; core
* proceeds to generic fallback resolution.
*/
type ProviderResolvedUsageAuth = ProviderUsageAuthToken | {
handled: true;
};
/**
* Usage/quota snapshot input for providers that own their usage endpoint
* fetch/parsing behavior.
*
* This hook runs after `resolveUsageAuth` succeeds. Core still owns summary
* fan-out, timeout wrapping, filtering, and formatting; the provider plugin
* owns the provider-specific HTTP request + response normalization.
*/
type ProviderFetchUsageSnapshotContext = {
config: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
env: NodeJS.ProcessEnv;
provider: string;
token: string;
accountId?: string;
authProfileId?: string;
/** Non-secret plan metadata from the resolved credential (e.g. Claude "max"). */
subscriptionType?: string;
rateLimitTier?: string;
/** Account email captured on the resolved credential, when known. */
email?: string;
timeoutMs: number;
fetchFn: typeof fetch;
};
/**
* Provider-owned auth-doctor hint input.
*
* Called when OAuth refresh fails and OpenClaw wants a provider-specific repair
* hint to append to the generic re-auth message. Use this for legacy profile-id
* migrations or other provider-owned auth-store cleanup guidance.
*/
type ProviderAuthDoctorHintContext = {
config?: OpenClawConfig;
store: AuthProfileStore;
provider: string;
profileId?: string;
};
/**
* Provider-owned extra-param normalization before OpenClaw builds its generic
* stream option wrapper.
*
* Use this to set provider defaults or rewrite provider-specific config keys
* into the merged `extraParams` object. Return the full next extraParams object.
*/
/** Provider-facing effort after OpenClaw lowers orchestration-only modes. */
type ProviderTransportThinkingLevel = Exclude<ThinkLevel, "ultra">;
type ProviderPrepareExtraParamsContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
agentId?: string;
nativeWebSearchAllowedByToolPolicy?: boolean;
provider: string;
modelId: string;
model?: ProviderRuntimeModel;
extraParams?: Record<string, unknown>;
thinkingLevel?: ProviderTransportThinkingLevel;
};
type ProviderExtraParamsForTransportContext = Omit<ProviderPrepareExtraParamsContext, "extraParams"> & {
model?: ProviderRuntimeModel;
transport?: "sse" | "websocket" | "websocket-cached" | "auto";
extraParams: Record<string, unknown>;
};
type ProviderExtraParamsForTransportResult = {
patch?: Record<string, unknown> | null;
};
type ProviderResolvePromptOverlayContext = ProviderSystemPromptContributionContext & {
baseOverlay?: ProviderSystemPromptContribution;
};
type ProviderFollowupFallbackRouteContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
provider: string;
modelId: string;
payload: ReplyPayload;
originatingChannel?: string;
originatingTo?: string;
originRoutable: boolean;
dispatcherAvailable: boolean;
};
type ProviderFollowupFallbackRouteResult = {
route?: "origin" | "dispatcher" | "drop";
reason?: string;
};
type ProviderResolveAuthProfileIdContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
provider: string;
modelId: string;
preferredProfileId?: string;
lockedProfileId?: string;
profileOrder: string[];
authStore: AuthProfileStore;
};
//#endregion
//#region src/plugins/provider-transport.types.d.ts
/**
* Provider-owned transport creation.
*
* Use this when the provider needs to replace shared model runtime's default transport with a
* custom StreamFn (for example a native API transport that cannot be expressed
* as a wrapper around `streamSimple`).
*/
type ProviderCreateStreamFnContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
provider: string;
modelId: string;
model: ProviderRuntimeModel;
};
/**
* Provider-owned stream wrapper hook after OpenClaw applies its generic
* transport-independent wrappers.
*
* Use this for provider-specific payload/header/model mutations that still run
* through the normal `shared model runtime` stream path.
*/
type ProviderWrapStreamFnContext = ProviderPrepareExtraParamsContext & {
model?: ProviderRuntimeModel;
/** Wire-format API before simple completion projects an internal transport alias. */
sourceApi?: ProviderRuntimeModel["api"];
streamFn?: StreamFn;
};
/**
* Provider-owned WebSocket session policy.
*/
type ProviderWebSocketSessionPolicy = {
headers?: Record<string, string>;
degradeCooldownMs?: number;
};
/**
* Provider-owned transport turn state.
*
* Use this for provider-native request headers or metadata that should stay
* stable across retries while still being attached by generic core transports.
*/
type ProviderTransportTurnState = {
headers?: Record<string, string>;
metadata?: Record<string, string>;
websocket?: ProviderWebSocketSessionPolicy;
};
/**
* Provider-owned request identity for transport turns.
*
* Use this when the provider exposes native request/session metadata that must
* be attached by both HTTP and WebSocket transports.
*/
type ProviderResolveTransportTurnStateContext = {
provider: string;
modelId: string;
model?: ProviderRuntimeModel;
sessionId?: string;
turnId: string;
attempt: number;
transport: "stream" | "websocket";
};
/**
* Provider-owned WebSocket session policy input.
*/
type ProviderResolveWebSocketSessionPolicyContext = {
provider: string;
modelId: string;
model?: ProviderRuntimeModel;
sessionId?: string;
};
/**
* Provider-owned failover error classification input.
*
* Use this when provider-specific transport or API errors need classification
* hints that generic string matching cannot express safely.
*/
type ProviderFailoverErrorContext = {
provider?: string;
modelId?: string;
errorMessage: string;
status?: number;
code?: string;
errorType?: string;
};
/**
* Generic embedding provider shape returned by provider plugins.
*
* Keep this aligned with the memory embedding contract without forcing the
* plugin system to import memory internals directly.
*/
type PluginEmbeddingProvider = {
id: string;
model: string;
maxInputTokens?: number;
embedQuery: (text: string, options?: {
signal?: AbortSignal;
}) => Promise<number[]>;
embedBatch: (texts: string[], options?: {
signal?: AbortSignal;
}) => Promise<number[][]>;
embedBatchInputs?: (inputs: unknown[], options?: {
signal?: AbortSignal;
}) => Promise<number[][]>;
client?: unknown;
};
/**
* Provider-owned embedding transport creation.
*
* Use this when a provider wants memory embeddings to live with the provider
* plugin instead of the core memory switchboard.
*/
type ProviderCreateEmbeddingProviderContext = {
config: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
provider: string;
model: string;
remote?: {
baseUrl?: string;
apiKey?: unknown;
headers?: Record<string, string>;
};
providerApiKey?: string;
inputType?: string;
queryInputType?: string;
documentInputType?: string;
outputDimensionality?: number;
taskType?: string;
};
/**
* Provider-owned prompt-cache eligibility.
*
* Return `true` or `false` to override OpenClaw's built-in provider cache TTL
* detection for this provider. Return `undefined` to fall back to core rules.
*/
type ProviderCacheTtlEligibilityContext = {
provider: string;
modelId: string;
modelApi?: string;
};
/**
* Provider-owned missing-auth message override.
*
* Runs only after OpenClaw exhausts normal env/profile/config auth resolution
* for the requested provider. Return a custom message to replace the generic
* "No API key found" error.
*/
type ProviderBuildMissingAuthMessageContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
env: NodeJS.ProcessEnv;
provider: string;
listProfileIds: (providerId: string) => string[];
};
/**
* Provider-owned unknown-model hint override.
*
* Runs after catalog/runtime lookup misses for the requested provider. Return a
* hint suffix that OpenClaw should append to the generic `Unknown model`
* error.
*/
type ProviderBuildUnknownModelHintContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
env: NodeJS.ProcessEnv;
provider: string;
modelId: string;
baseUrl?: string;
};
//#endregion
//#region src/plugins/provider-plugin.types.d.ts
type ProviderPlugin$1 = {
id: string;
pluginId?: string;
label: string;
docsPath?: string;
aliases?: string[];
/**
* Internal-only aliases used for runtime/config hook lookup.
*
* Unlike `aliases`, these values are not treated as user-facing provider ids
* for auth/setup surfaces. Use them for legacy config keys or compat-only
* hook routing.
*/
hookAliases?: string[];
/**
* Provider-related env vars shown in setup/search/help surfaces.
*
* Keep entries in preferred display order. This can include direct auth env
* vars or setup inputs such as OAuth client id/secret vars.
*/
envVars?: string[];
auth: ProviderAuthMethod[];
/**
* Legacy text-provider catalog hook.
*
* @deprecated New catalog/control-plane surfaces should use
* `api.registerModelCatalogProvider`. This hook remains the text runtime
* source until the unified loader fully replaces it.
* Returns provider config/model definitions that merge into models.providers.
*/
catalog?: ProviderPluginCatalog;
/**
* Legacy offline text-provider catalog hook for display-only surfaces.
*
* @deprecated New static rows should be registered with
* `api.registerModelCatalogProvider`.
*
* Unlike `catalog`, this hook must not perform network I/O or require real
* credentials. Use it for bundled/static rows that can be shown before auth is
* configured.
*/
staticCatalog?: ProviderPluginCatalog;
/**
* Show catalog row labels as the literal `<provider>/<entry.id>`
* composition instead of the canonical (deduped) key.
*
* `modelKey` strips a duplicate `<provider>/` prefix so storage and
* lookups stay stable. This flag only changes the picker label — the
* option value and persisted config remain canonical.
*
* Set when the leading `<provider>/` segment in the native model id is
* a meaningful vendor namespace (e.g. NVIDIA's `nvidia/nemotron-...`
* alongside `moonshotai/kimi-k2.5`).
*/
preserveLiteralProviderPrefix?: boolean;
/**
* Sync runtime fallback for model ids not present in the local catalog.
*
* Hook order:
* 1. discovered/static model lookup
* 2. plugin `resolveDynamicModel`
* 3. core fallback heuristics
* 4. generic provider-config fallback
*
* Keep this hook cheap and deterministic. Async model discovery belongs in
* `prepareDynamicModel`, which can return the prepared model directly.
*/
resolveDynamicModel?: (ctx: ProviderResolveDynamicModelContext) => ProviderRuntimeModel | null | undefined;
/**
* Optional async preparation for dynamic model resolution.
*
* OpenClaw calls this only from async model resolution paths. Return the
* requested model directly, or return nothing to retry `resolveDynamicModel`.
*/
prepareDynamicModel?: (ctx: ProviderPrepareDynamicModelContext) => Promise<ProviderRuntimeModel | void>;
/**
* Lets a provider plugin opt exact configured models into a runtime
* metadata comparison pass before the embedded runner returns the explicit
* entry unchanged.
*/
preferRuntimeResolvedModel?: (ctx: ProviderPreferRuntimeResolvedModelContext) => boolean;
/**
* Provider-owned transport normalization.
*
* Use this to rewrite a resolved model without forking the generic runner:
* swap API ids, update base URLs, or adjust compat flags for a provider's
* transport quirks.
*/
normalizeResolvedModel?: (ctx: ProviderNormalizeResolvedModelContext) => ProviderRuntimeModel | null | undefined;
/**
* Provider-owned model-id normalization.
*
* Runs before model lookup/canonicalization. Use this for alias cleanup such
* as provider-owned preview/legacy model ids.
*/
normalizeModelId?: (ctx: ProviderNormalizeModelIdContext) => string | null | undefined;
/**
* Provider-owned transport-family normalization before generic model
* assembly.
*
* Use this for API/baseUrl cleanup that may apply to custom provider ids
* which still target the provider's transport family.
*/
normalizeTransport?: (ctx: ProviderNormalizeTransportContext) => {
api?: string | null;
baseUrl?: string;
} | null | undefined;
/**
* Provider-owned config normalization for `models.providers.<id>`.
*
* Use this for provider-specific baseUrl/model-id cleanup that should stay
* with the plugin rather than in core config-policy tables.
*/
normalizeConfig?: (ctx: ProviderNormalizeConfigContext) => ModelProviderConfig | null | undefined;
/**
* Provider-owned final native-streaming compat pass for config providers.
*
* Use this when a provider opts specific native base URLs into
* `supportsUsageInStreaming` or similar transport compatibility flags.
*/
applyNativeStreamingUsageCompat?: (ctx: ProviderNormalizeConfigContext) => ModelProviderConfig | null | undefined;
/**
* Provider-owned config apiKey/env marker resolution.
*
* Use this when a provider resolves auth from env vars such as AWS/GCP
* markers rather than a normal API-key env var.
*/
resolveConfigApiKey?: (ctx: ProviderResolveConfigApiKeyContext) => string | null | undefined;
/**
* Provider-owned replay/compaction policy override.
*
* Use this when transcript replay or compaction should follow provider-owned
* rules that are more expressive than the static `capabilities` bag.
*/
buildReplayPolicy?: (ctx: ProviderReplayPolicyContext) => ProviderReplayPolicy | null | undefined;
/**
* Provider-owned replay-history sanitization.
*
* Runs after OpenClaw performs generic transcript cleanup. Use this for
* provider-specific replay rewrites that should stay with the provider
* plugin rather than in shared core compaction helpers.
*/
sanitizeReplayHistory?: (ctx: ProviderSanitizeReplayHistoryContext) => Promise<AgentMessage[] | null | undefined> | AgentMessage[] | null | undefined;
/**
* Provider-owned final replay-turn validation.
*
* Use this when provider transports need stricter replay-time validation or
* turn reshaping after generic sanitation. Returning a non-null value
* replaces the built-in replay validators rather than composing with them.
*/
validateReplayTurns?: (ctx: ProviderValidateReplayTurnsContext) => Promise<AgentMessage[] | null | undefined> | AgentMessage[] | null | undefined;
/**
* Provider-owned tool-schema normalization.
*
* Use this for transport-family schema cleanup before OpenClaw registers
* tools with the embedded runner.
*/
normalizeToolSchemas?: (ctx: ProviderNormalizeToolSchemasContext) => AnyAgentTool[] | null | undefined;
/**
* Provider-owned tool-schema diagnostics after normalization.
*
* Use this when a provider wants to surface transport-specific schema
* warnings without teaching core about provider-specific keyword rules.
*/
inspectToolSchemas?: (ctx: ProviderNormalizeToolSchemasContext) => ProviderToolSchemaDiagnostic[] | null | undefined;
/**
* Provider-owned reasoning output mode.
*
* Use this when a provider requires tagged reasoning/final output instead of
* native structured reasoning fields.
*/
resolveReasoningOutputMode?: (ctx: ProviderReasoningOutputModeContext) => ProviderReasoningOutputMode | null | undefined;
/**
* Provider-owned extra-param normalization before generic stream option
* wrapping.
*
* Typical uses: set provider-default `transport`, map provider-specific
* config aliases, or inject extra request metadata sourced from
* `agents.defaults.models.<provider>/<model>.params`.
*/
prepareExtraParams?: (ctx: ProviderPrepareExtraParamsContext) => Record<string, unknown> | null | undefined;
/**
* Provider-owned request params after transport/model resolution.
*
* Use this for transport-family request knobs that should be keyed by the
* resolved model API/transport rather than a hardcoded core allowlist.
*/
extraParamsForTransport?: (ctx: ProviderExtraParamsForTransportContext) => ProviderExtraParamsForTransportResult | null | undefined;
/**
* Provider-owned transport factory.
*
* Use this when the provider needs a fully custom StreamFn instead of a
* wrapper around the normal `streamSimple` path.
*/
createStreamFn?: (ctx: ProviderCreateStreamFnContext) => StreamFn | null | undefined;
/**
* Provider-owned stream wrapper applied after generic OpenClaw wrappers.
*
* Typical uses: provider attribution headers, request-body rewrites, or
* provider-specific compat payload patches that do not justify a separate
* transport implementation.
*/
wrapStreamFn?: (ctx: ProviderWrapStreamFnContext) => StreamFn | null | undefined;
/**
* Provider-owned wrapper for direct `completeSimple` callers.
*
* Opt in only when the provider must enforce the same wire contract outside
* the embedded agent runtime.
*/
wrapSimpleCompletionStreamFn?: (ctx: ProviderWrapStreamFnContext) => StreamFn | null | undefined;
/**
* Provider-owned native transport turn identity.
*
* Use this when a provider wants generic transports to attach provider-native
* request headers or metadata on each turn without hardcoding vendor logic in
* core.
*/
resolveTransportTurnState?: (ctx: ProviderResolveTransportTurnStateContext) => ProviderTransportTurnState | null | undefined;
/**
* Provider-owned WebSocket session policy.
*
* @deprecated Return `websocket` from `resolveTransportTurnState`. When both
* hooks provide a field, the new hook takes precedence.
*/
resolveWebSocketSessionPolicy?: (ctx: ProviderResolveWebSocketSessionPolicyContext) => ProviderWebSocketSessionPolicy | null | undefined;
/**
* Provider-owned embedding provider factory.
*
* Use this when memory embedding behavior belongs with the provider plugin
* rather than the core embedding switchboard.
*/
createEmbeddingProvider?: (ctx: ProviderCreateEmbeddingProviderContext) => Promise<PluginEmbeddingProvider | null | undefined> | PluginEmbeddingProvider | null | undefined;
/**
* Runtime auth exchange hook.
*
* Called after OpenClaw resolves the raw configured credential but before the
* runner stores it in runtime auth storage. This lets plugins exchange a
* source credential (for example a GitHub token) into a short-lived runtime
* token plus optional base URL override.
*/
prepareRuntimeAuth?: (ctx: ProviderPrepareRuntimeAuthContext) => Promise<ProviderPreparedRuntimeAuth | null | undefined>;
/**
* Usage/billing auth resolution hook.
*
* Called by provider-usage surfaces (`/usage`, status snapshots, reporting).
* Use this when a provider's usage endpoint needs provider-owned token
* extraction, blob parsing, or alias handling.
*/
resolveUsageAuth?: (ctx: ProviderResolveUsageAuthContext) => Promise<ProviderResolvedUsageAuth | null | undefined> | ProviderResolvedUsageAuth | null | undefined;
/**
* Usage/quota snapshot fetch hook.
*
* Called after `resolveUsageAuth` by `/usage` and related reporting surfaces.
* Use this when the provider's usage endpoint or payload shape is
* provider-specific and you want that logic to live with the provider plugin
* instead of the core switchboard.
*/
fetchUsageSnapshot?: (ctx: ProviderFetchUsageSnapshotContext) => Promise<ProviderUsageSnapshot | null | undefined> | ProviderUsageSnapshot | null | undefined;
/**
* Provider-owned failover context-overflow matcher.
*
* Return true when the provider recognizes the raw error as a context-window
* overflow shape that generic heuristics would miss.
*/
matchesContextOverflowError?: (ctx: ProviderFailoverErrorContext) => boolean | undefined;
/**
* Provider-owned failover error classification.
*
* Return a failover reason when the provider recognizes a provider-specific
* raw error shape. Return undefined to fall back to generic classification.
*/
classifyFailoverReason?: (ctx: ProviderFailoverErrorContext) => FailoverReason | null | undefined;
/**
* Provider-owned cache TTL eligibility.
*
* Use this when a proxy provider supports Anthropic-style prompt caching for
* only a subset of upstream models.
*/
isCacheTtlEligible?: (ctx: ProviderCacheTtlEligibilityContext) => boolean | undefined;
/**
* Provider-owned missing-auth message override.
*
* Return a custom message when the provider wants a more specific recovery
* hint than OpenClaw's generic auth-store guidance.
*/
buildMissingAuthMessage?: (ctx: ProviderBuildMissingAuthMessageContext) => string | null | undefined;
/**
* Provider-owned unknown-model hint override.
*
* Return a suffix when the provider wants a more specific recovery hint than
* OpenClaw's generic `Unknown model` error after catalog/runtime lookup
* fails.
*/
buildUnknownModelHint?: (ctx: ProviderBuildUnknownModelHintContext) => string | null | undefined;
/**
* Provider-owned built-in model suppression.
*
* Return `{ suppress: true }` to hide a stale upstream row. Include
* `errorMessage` when OpenClaw should surface a provider-specific hint for
* direct model resolution failures.
*
* @deprecated Use manifest `modelCatalog.suppressions`. Runtime suppression
* hooks are no longer called by model resolution.
*/
suppressBuiltInModel?: (ctx: ProviderBuiltInModelSuppressionContext) => ProviderBuiltInModelSuppressionResult | null | undefined;
/**
* Provider-owned final catalog augmentation.
*
* @deprecated Use `api.registerModelCatalogProvider` for supplemental catalog
* rows. This hook is kept only for existing text-provider runtime
* compatibility during the migration window.
*
* Return extra rows to append to the final catalog after discovery/config
* merging. OpenClaw deduplicates by `provider/id`, so plugins only need to
* describe the desired supplemental rows.
*/
augmentModelCatalog?: (ctx: ProviderAugmentModelCatalogContext) => Array<ModelCatalogEntry> | ReadonlyArray<ModelCatalogEntry> | Promise<Array<ModelCatalogEntry> | ReadonlyArray<ModelCatalogEntry> | null | undefined> | null | undefined;
/**
* Provider-owned thinking level profile.
*
* Prefer this over the individual thinking capability hooks when a provider
* or model exposes a custom set of thinking levels. OpenClaw stores the
* canonical `id`, shows `label` when provided, and downgrades stale stored
* values by profile rank.
*/
resolveThinkingProfile?: (ctx: ProviderDefaultThinkingPolicyContext) => ProviderThinkingProfile | null | undefined;
/**
* Provider-owned system-prompt contribution.
*
* Use this when a provider/model family needs cache-aware prompt tuning
* without replacing the full OpenClaw-owned system prompt.
*/
resolveSystemPromptContribution?: (ctx: ProviderSystemPromptContributionContext) => ProviderSystemPromptContribution | null | undefined;
/**
* Provider-owned GPT/model prompt overlay seam.
*
* Runs after OpenClaw's built-in overlay is resolved and before the
* provider's regular system-prompt contribution is merged.
*/
resolvePromptOverlay?: (ctx: ProviderResolvePromptOverlayContext) => ProviderSystemPromptContribution | null | undefined;
/**
* Provider-owned fallback route override for model/profile failure handling.
*
* Return undefined/null to keep OpenClaw's default fallback policy.
*/
followupFallbackRoute?: (ctx: ProviderFollowupFallbackRouteContext) => ProviderFollowupFallbackRouteResult | null | undefined;
/**
* Provider-owned auth profile resolver.
*
* Return a profile id from the supplied order to prefer it for this attempt;
* invalid or missing ids are ignored by core.
*/
resolveAuthProfileId?: (ctx: ProviderResolveAuthProfileIdContext) => string | null | undefined;
/**
* Provider-owned final system-prompt transform.
*
* Use this sparingly when a provider transport needs small compatibility
* rewrites after OpenClaw has assembled the complete prompt. Return
* `undefined`/`null` to leave the prompt unchanged.
*/
transformSystemPrompt?: (ctx: ProviderTransformSystemPromptContext) => string | null | undefined;
/**
* Provider-owned bidirectional text replacements.
*
* `input` applies to system prompts and text message content before transport.
* `output` applies to assistant text deltas/final text before OpenClaw handles
* its own control markers or channel delivery.
*/
textTransforms?: PluginTextTransforms;
/**
* Provider-owned global config defaults.
*
* Use this when config materialization needs provider-specific defaults that
* depend on auth mode, env, or provider model-family semantics.
*/
applyConfigDefaults?: (ctx: ProviderApplyConfigDefaultsContext) => OpenClawConfig | null | undefined;
/**
* Provider-owned "modern model" matcher used by live profile/smoke filters.
*
* Return true when the given provider/model ref should be treated as a
* preferred modern model candidate.
*/
isModernModelRef?: (ctx: ProviderModernModelPolicyContext) => boolean | undefined;
wizard?: ProviderPluginWizard;
/**
* Provider-owned auth-profile API-key formatter.
*
* OpenClaw uses this when a stored auth profile is already valid and needs to
* be converted into the runtime `apiKey` string expected by the provider. Use
* this for providers whose auth profile stores extra metadata alongside the
* bearer token (for example Gemini CLI's `{ token, projectId }` payload).
*/
formatApiKey?: (cred: AuthProfileCredential) => string;
/**
* Provider-owned OAuth login adapter for the session SDK AuthStorage API.
*
* This keeps the public callback-based login contract usable without seeding
* provider implementations into core. Modern setup flows should use `auth`.
*/
loginOAuth?: (callbacks: OAuthLoginCallbacks) => Promise<OAuthCredentials>;
/**
* Legacy auth-profile ids that generic auth must ignore and `openclaw doctor` should remove.
*
* Use this when a provider plugin replaces an older core-managed profile id
* and wants cleanup/migration messaging to live with the provider instead of
* in hardcoded doctor tables. A runtime-only external CLI profile remains usable by its exact
* provider when it intentionally reuses a retired id.
*/
deprecatedProfileIds?: string[];
/**
* Legacy OAuth profile-id migrations that `openclaw doctor` should offer.
*
* Use this when a provider moved from a legacy default OAuth profile id to a
* newer identity-based id and wants doctor to own the config rewrite without
* another core-specific migration branch.
*/
oauthProfileIdRepairs?: ProviderOAuthProfileIdRepair[];
/**
* Provider-owned OAuth refresh.
*
* OpenClaw calls this before falling back to the shared `shared model runtime` OAuth
* refreshers. Use it when the provider has a custom refresh endpoint, or when
* the provider needs custom refresh-failure behavior that should stay out of
* core auth-profile code.
*/
refreshOAuth?: (cred: OAuthCredential$1) => Promise<OAuthCredential$1>;
/**
* Provider-owned auth-doctor hint.
*
* Return a multiline repair hint when OAuth refresh fails and the provider
* wants to steer users toward a specific auth-profile migration or recovery
* path. Return nothing to keep OpenClaw's generic error text.
*/
buildAuthDoctorHint?: (ctx: ProviderAuthDoctorHintContext) => string | Promise<string | null | undefined> | null | undefined;
/**
* Provider-owned config-backed auth resolution.
*
* Providers own any provider-specific fallback secret rules here so core
* auth/discovery code can stay generic and avoid parsing provider-private
* config layouts.
*
* The returned `apiKey` may be:
* - a real credential from the active runtime snapshot, suitable for runtime use
* - a non-secret marker (for example a managed SecretRef marker), suitable only
* for discovery/bootstrap callers
*
* Runtime callers must not treat non-secret markers as runnable credentials;
* they should retry against the active runtime snapshot when available.
*
* Use this when the provider can operate without a real secret for certain
* configured local/self-hosted cases and wants auth resolution to treat that
* config as available.
*/
resolveSyntheticAuth?: (ctx: ProviderResolveSyntheticAuthContext) => ProviderSyntheticAuthResult | null | undefined;
/**
* Prepare external availability before synchronous synthetic-auth reads.
* Keep process/network I/O here; OpenClaw publishes the completed result for this generation.
*/
prepareSyntheticAuth?: (ctx: ProviderResolveSyntheticAuthContext & {
env?: NodeJS.ProcessEnv;
signal?: AbortSignal;
}) => Promise<ProviderSyntheticAuthResult | null | undefined>;
/**
* Provider-owned external auth profile discovery.
*
* Use this when credentials are managed by an external tool and should be visible
* to runtime auth resolution without being written back into `auth-profiles.json`
* by core.
*/
resolveExternalAuthProfiles?: (ctx: ProviderResolveExternalAuthProfilesContext) => Array<ProviderExternalAuthProfile> | ReadonlyArray<ProviderExternalAuthProfile> | null | undefined;
/**
* Provider-owned precedence rule for stored synthetic auth profiles.
*
* Return true when a stored profile API key is only a provider-owned
* synthetic placeholder and should yield to env/config-backed auth before
* OpenClaw falls back to that stored profile.
*/
shouldDeferSyntheticProfileAuth?: (ctx: ProviderDeferSyntheticProfileAuthContext) => boolean | undefined;
onModelSelected?: (ctx: ProviderModelSelectedContext) => Promise<void>;
};
//#endregion
//#region src/plugins/session-catalog.d.ts
type SessionCatalogListProviderParams = {
/** Gateway always supplies this; optional only for pre-existing external provider types. */
agentId?: string;
/** False when Gateway-local scans must not inherit a root from process HOME. */
allowProcessHomeFallback?: boolean;
/** Trimmed, non-empty search capped at 500 UTF-16 code units by the gateway. */
search?: string;
limitPerHost?: number;
hostIds?: string[];
cursors?: Record<string, string>;
/** Request-owned shared entries. Providers must not mutate or retain them past `list`. */
sessionEntries?: SessionCatalogEntrySnapshot;
/** Lazily lists Gateway nodes once per catalog request. Providers must not retain this past `list`. */
listNodes?: () => ReturnType<PluginRuntime["nodes"]["list"]>;
/** Publishes completed hosts without waiting for slower machines in the same list. */
onHost?: (host: SessionCatalogHost) => void;
/** Register bounded host publication work before `list` settles; includes the onHost callback. */
waitUntil?: (completion: Promise<void>) => void;
/** Catalog owner retirement, independent of the requesting connection's lifetime. */
signal?: AbortSignal;
};
type SessionCatalogReadProviderParams = Omit<SessionsCatalogReadParams, "catalogId"> & {
/** Gateway always supplies this; optional only for pre-existing external provider types. */
agentId?: string;
/** False when Gateway-local reads must not inherit a root from process HOME. */
allowProcessHomeFallback?: boolean;
};
type SessionCatalogContinueProviderParams = Omit<SessionsCatalogContinueParams, "catalogId"> & {
/** Gateway always supplies this; optional only for pre-existing external provider types. */
agentId?: string;
/** False when Gateway-local continuation must not inherit a root from process HOME. */
allowProcessHomeFallback?: boolean;
/** Caller's gateway scopes so providers can gate high-authority continues up front. */
clientScopes?: readonly string[];
};
type SessionCatalogArchiveProviderParams = Omit<SessionsCatalogArchiveParams, "catalogId"> & {
/** Gateway always supplies this; optional only for pre-existing external provider types. */
agentId?: string;
/** False when Gateway-local archive must not inherit a root from process HOME. */
allowProcessHomeFallback?: boolean;
};
type SessionCatalogStartTerminalProviderParams = {
/** False when Gateway-local terminal start must not inherit process HOME. */
allowProcessHomeFallback?: boolean;
agentId: string;
cwd: string;
initialMessage?: string;
/** Present only when the caller selected a catalog host backed by this node. */
nodeId?: string;
/** Selected local catalog source; node ownership is carried by nodeId. */
hostId?: string;
};
type SessionCatalogTerminalPlan = {
kind: "local";
argv: string[];
cwd?: string;
title?: string;
/** Bounded command-specific environment overrides. */
env?: Record<string, string>;
/** PATH that resolved argv[0], needed by env-based script interpreters. */
pathEnv?: string;
} | {
kind: "node";
nodeId: string;
command: string;
paramsJSON: string;
cwd?: string;
title?: string;
};
type SessionCatalogCreateTarget = {
model: string;
/** Concrete runtime pinned onto the created session so config reloads cannot retarget it. */
agentRuntime: string;
};
interface SessionCatalogEntrySummary {
sessionKey: string;
entry: SessionEntry$1;
}
/** Shared, logically frozen store state for one request; copy locally before mutating. */
type SessionCatalogEntrySnapshot = {
entriesForAgent: (agentId: string) => readonly SessionCatalogEntrySummary[];
/** Request-wide flatten; optional for compatibility with pre-flatten plugin hosts. */
entriesForCatalog?: () => SessionCatalogAgentEntry[];
};
type SessionCatalogAgentEntry = SessionCatalogEntrySummary & {
agentId: string;
};
type SessionUpstreamJsonValue = null | boolean | number | string | SessionUpstreamJsonValue[] | {
[key: string]: SessionUpstreamJsonValue;
};
type SessionUpstreamKind = "claude-cli" | "codex-app-server" | "opencode-cli" | "pi-cli";
type SessionUpstreamProbe = {
sessionKey: string;
agentId: string;
threadId: string;
hostId: string;
upstreamKind: SessionUpstreamKind;
upstreamRef: SessionUpstreamJsonValue;
marker: SessionUpstreamJsonValue | null;
ownRecentUserTexts: string[];
};
type SessionUpstreamActivity = {
kind: "activity";
sessionKey: string;
humanTurns: number;
nextMarker: SessionUpstreamJsonValue;
occurredAt?: number;
dedupeId?: string;
} | {
kind: "missing";
sessionKey: string;
};
type SessionCatalogContinueProviderResult = {
sessionKey: string;
/** Plugin binding installed for this authenticated Control UI session. */
conversationBinding?: {
summary?: string;
detachHint?: string;
data?: Record<string, unknown>;
};
/** Publishes provider state only after the requested binding is durable. */
afterConversationBound?: () => Promise<void>;
/** Upstream link seed so the monitor can detect direct external activity. */
upstream?: {
kind: SessionUpstreamKind;
ref: SessionUpstreamJsonValue;
marker: SessionUpstreamJsonValue;
};
};
type SessionCatalogGatewayCopy = {
displayName?: string;
preferredModel?: string;
};
type SessionCatalogCreateParams = {
/** Agent whose model/runtime policy must authorize the catalog target. */
agentId?: string;
};
type SessionCatalogProvider = {
id: string;
label: string;
/** Provider rows are Gateway-hosted artifacts visible to authenticated operators. */
audience?: "gateway-operators";
/** Closed plugin-owned route contract; invalid or colliding declarations are not projected. */
shareRoute?: SessionCatalogShareRoute;
/** Declares that every HOME-sensitive action honors the host isolation policy. */
supportsProcessHomeIsolation?: true;
/** Config-derived target; the Gateway memoizes it for one runtime-config object identity. */
resolveCreateSession?: (params: SessionCatalogCreateParams) => SessionCatalogCreateTarget | undefined;
list: (params: SessionCatalogListProviderParams) => Promise<SessionCatalogHost[]>;
/** Items are newest-first by source order; nextCursor continues to older items. */
read: (params: SessionCatalogReadProviderParams) => Promise<SessionsCatalogReadResult>;
continueSession?: (params: SessionCatalogContinueProviderParams) => Promise<SessionCatalogContinueProviderResult>;
/** Copy catalog history into a new ordinary Gateway-owned session. */
copyToGatewaySession?: (params: SessionCatalogContinueProviderParams) => Promise<SessionCatalogGatewayCopy>;
checkUpstreamActivity?: (probes: SessionUpstreamProbe[], policy?: {
allowProcessHomeFallback?: boolean;
}) => Promise<SessionUpstreamActivity[]>;
archive?: (params: SessionCatalogArchiveProviderParams) => Promise<{
ok: true;
}>;
openTerminal?: (request: {
allowProcessHomeFallback?: boolean;
/** Gateway always supplies this; optional only for pre-existing external provider types. */
agentId?: string;
hostId: string;
threadId: string;
}) => Promise<SessionCatalogTerminalPlan>;
startTerminalSession?: (request: SessionCatalogStartTerminalProviderParams) => Promise<SessionCatalogTerminalPlan>;
};
//#endregion
//#region src/plugins/plugin-command.types.d.ts
type ChannelId = ChannelId$1;
type PluginCommandSessionTarget = {
agentId: string;
sessionId: string;
sessionKey: string;
storePath: string;
};
type PluginCommandDiagnosticsSession = {
/** Stable host session key when available. */
sessionKey?: string;
/** Ephemeral OpenClaw session id when available. */
sessionId?: string;
/** Canonical SQLite identity for active transcript access. */
sessionTarget?: PluginCommandSessionTarget;
/**
* Deprecated transcript locator for this OpenClaw session when available.
*
* SQLite-backed sessions use a `sqlite:<agentId>:<sessionId>:<storePath>`
* marker, not a filesystem path. Use session id/key plus transcript-runtime
* helpers for active transcript reads.
*
* @deprecated Use session identity fields with `plugin-sdk/session-transcript-runtime`.
*/
sessionFile?: string;
/** Embedded agent harness selected for this session. */
agentHarnessId?: string;
/** Channel/provider for this session when available. */
channel?: string;
/** Provider channel id when available. */
channelId?: ChannelId;
/** Account id for multi-account channels when available. */
accountId?: string;
/** Thread/topic id when available. */
messageThreadId?: string | number;
/** Parent conversation id for thread-capable channels when available. */
threadParentId?: string;
};
/**
* Context passed to plugin command handlers.
*/
type PluginCommandContext = {
/** The sender's identifier (for example a channel-scoped user ID) */
senderId?: string;
/** The channel/surface (for example "chat" or "team-chat") */
channel: string;
/** Provider channel id */
channelId?: ChannelId;
/** Whether the sender is on the allowlist */
isAuthorizedSender: boolean;
/** Whether the sender is an owner for owner-only command surfaces. */
senderIsOwner?: boolean;
/** Gateway client scopes for internal control-plane callers */
gatewayClientScopes?: string[];
/** Host-resolved agent that owns the active session. */
agentId?: string;
/** Stable host session key for the active conversation when available. */
sessionKey?: string;
/** Ephemeral host session id for the active conversation when available. */
sessionId?: string;
/** Canonical SQLite identity for active transcript access. */
sessionTarget?: PluginCommandSessionTarget;
/**
* Deprecated transcript locator for the active OpenClaw session when available.
*
* SQLite-backed sessions use a `sqlite:<agentId>:<sessionId>:<storePath>`
* marker, not a filesystem path. Use session id/key plus transcript-runtime
* helpers for active transcript reads.
*
* @deprecated Use session identity fields with `plugin-sdk/session-transcript-runtime`.
*/
sessionFile?: string;
/** 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?: string | number;
/** Parent conversation id for thread-capable channels */
threadParentId?: string;
/** Sensitive diagnostics-only session inventory for owner-gated commands. */
diagnosticsSessions?: PluginCommandDiagnosticsSession[];
/** Host-bound runtime capabilities scoped to this command invocation. */
runtimeContext?: {
llm?: Pick<PluginRuntimeCore["llm"], "complete">;
compactCurrent?: () => Promise<{
compacted: boolean;
reason?: string;
tokensBefore?: number;
tokensAfter?: number;
}>;
};
/** Internal diagnostics-only marker that exec approval already authorized upload. */
diagnosticsUploadApproved?: boolean;
/** Internal diagnostics-only marker to preview upload effects without exposing ids. */
diagnosticsPreviewOnly?: boolean;
/** Internal diagnostics-only marker for owner-private routed confirmations. */
diagnosticsPrivateRouted?: boolean;
requestConversationBinding: (params?: PluginConversationBindingRequestParams) => Promise<PluginConversationBindingRequestResult>;
detachConversationBinding: () => Promise<{
removed: boolean;
}>;
getCurrentConversationBinding: () => Promise<PluginConversationBinding | null>;
};
/**
* Result returned by a plugin command handler.
*/
type PluginCommandResult = ReplyPayload & {
/** Allows the agent session to continue processing after the command. */
continueAgent?: boolean;
/** Suppresses channel fallback replies when the handler already delivered a response. */
suppressReply?: boolean;
};
/**
* Handler function for plugin commands.
*/
type PluginCommandHandler = (ctx: PluginCommandContext) => PluginCommandResult | Promise<PluginCommandResult>;
/**
* Definition for a plugin-registered command.
*/
declare const AGENT_PROMPT_SURFACE_KINDS: readonly ["openclaw_main", "pi_main", "codex_app_server", "cli_backend", "acp_backend", "subagent"];
type AgentPromptSurfaceKind = (typeof AGENT_PROMPT_SURFACE_KINDS)[number];
type AgentPromptGuidanceEntry = {
text: string;
surfaces?: readonly AgentPromptSurfaceKind[];
};
type AgentPromptGuidance = string | AgentPromptGuidanceEntry;
type OpenClawPluginCommandDefinition$1 = {
/** 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", teamChat: "voice2" }`).
*/
nativeNames?: Partial<Record<string, string>> & {
default?: string;
};
/**
* Optional native progress placeholder text for native command surfaces.
* `default` applies to all native providers unless a provider-specific
* override exists.
*/
nativeProgressMessages?: Partial<Record<string, string>> & {
default?: string;
};
/** Description shown in /help and command menus */
description: string;
/** Localized descriptions for native command surfaces that support them. */
descriptionLocalizations?: Record<string, string>;
/**
* Optional channel ids this command belongs to.
* Omit to keep the command available on every channel surface.
*/
channels?: readonly string[];
/** Optional system-prompt guidance for agents when this command is registered. */
agentPromptGuidance?: readonly AgentPromptGuidance[];
/** Whether this command accepts arguments */
acceptsArgs?: boolean;
/** Optional bounded presentation for clients that explicitly support it. */
clientPresentation?: {
/** Parsed invocation shape eligible for client handling. */
when: "no-arguments";
action: {
kind: "device-pairing";
};
};
/** Whether only authorized senders can use this command (default: true) */
requireAuth?: boolean;
/** Operator scopes required by gateway clients; command owners may satisfy this on chat surfaces. */
requiredScopes?: OperatorScope[];
/** Whether a trusted bundled handler needs owner status for subcommand-level authorization. */
exposeSenderIsOwner?: boolean;
/**
* Allows a bundled plugin to claim a command name that is otherwise reserved
* by core. External plugins cannot use this field.
*/
ownership?: "plugin" | "reserved";
/** The handler function */
handler: PluginCommandHandler;
};
//#endregion
//#region src/plugins/board-widget-content-kind.types.d.ts
/** Plugin-owned source kind rendered through the board's sandboxed document host. */
type PluginBoardWidgetContentKind = {
/** Agent-facing kind, for example `diagram`. Must be globally unique. */
kind: string;
/** Short label shown in dashboard chrome. */
label: string;
/** Capability-scoped static resources used by the composed document. */
resources: {
surface: string;
paths: string[];
/**
* Public static renderer bytes served without Gateway credentials.
* Declaring this reader reserves every path globally across content kinds,
* including registrations without a public reader.
* Public paths must be canonical URL pathnames and cannot use `/mcp-app-sandbox`.
*/
readPublicResource?: (path: string) => Promise<{
body: Uint8Array;
contentType: string;
} | undefined>;
};
/** Reject malformed or unsupported source before it reaches persistent storage. */
validateSource: (source: string) => void;
/** Build the untrusted document body; core adds the canonical bridge and CSP shell. */
composeDocument: (params: {
source: string;
title: string;
resourceUrls: Readonly<Record<string, string>>;
promptGranted: boolean;
}) => string;
};
//#endregion
//#region src/hooks/internal-hook-types.d.ts
type InternalHookEventType = "command" | "session" | "agent" | "gateway" | "message";
interface InternalHookEvent {
/** The type of event (command, session, agent, gateway, etc.) */
type: InternalHookEventType;
/** The specific action within the type (e.g., 'new', 'reset', 'stop') */
action: string;
/** The session key this event relates to */
sessionKey: string;
/** Additional context specific to the event */
context: Record<string, unknown>;
/** Timestamp when the event occurred */
timestamp: Date;
/** Messages to send back to the user (hooks can push to this array) */
messages: string[];
}
type InternalHookHandler = (event: InternalHookEvent) => Promise<void> | void;
//#endregion
//#region src/gateway/server-channel-runtime.types.d.ts
/** Snapshot of channel runtime state keyed by channel and account id. */
type ChannelRuntimeSnapshot = {
channels: Partial<Record<ChannelId$1, ChannelAccountSnapshot>>;
channelAccounts: Partial<Record<ChannelId$1, Record<string, ChannelAccountSnapshot>>>;
};
/** The lifecycle owner's decision for one requested account start, separate from connectivity. */
type ChannelAccountStartOutcome = {
status: "handed-off";
} | {
status: "retry";
reason: "stop-in-flight" | "task-owned";
} | {
status: "skipped";
reason: "unsupported" | "autostart-suppressed" | "ambient-suppressed" | "disabled" | "unconfigured" | "secret-unavailable" | "unlinked" | "manual-stop";
};
type StartChannelOptions = {
preserveRestartAttempts?: boolean;
preserveManualStop?: boolean;
/** Reload leaves snapshot-cold accounts stopped without bypassing credential-file reinspection. */
skipUnavailableAccounts?: boolean;
deferAccountStartUntil?: Promise<void>;
manual?: boolean;
};
//#endregion
//#region src/gateway/server-public.d.ts
/** A capability for one host iteration; native completion belongs to the host. */
type GatewayHostLifecycle = {
/** Present only when this host owns process exit; the identity never crosses RPC. */
externalRestart?: GatewaySuspendHandoffOwner;
request(action: "start" | "stop" | "restart", assertCaller: () => void): Promise<Result<{
outcome: "already-running" | "scheduled";
}, string>>;
};
//#endregion
//#region src/gateway/server-request-entry.d.ts
type RequestEntryOptions = Pick<GatewayRequestOptions, "client" | "context"> & {
req: Pick<GatewayRequestOptions["req"], "method" | "params">;
};
type GatewayRequestEntry = {
assertOpen: () => void;
release: () => void;
};
/** One Gateway's preparation leases; handler execution belongs to its existing runtime owner. */
declare class GatewayRequestEntryLifetime {
private readonly stopping;
private readonly active;
private sealed;
readonly signal: AbortSignal;
enter(options: RequestEntryOptions): GatewayRequestEntry;
beginClose(): void;
waitForPendingEntries(): Promise<void>;
sealAndJoin(): Promise<void>;
}
//#endregion
//#region src/gateway/talk-session-target.types.d.ts
type PreparedTalkSessionTarget = Readonly<{
agentId: string;
/** Voice records and close/resume retain the client's exact key, not its storage alias. */
sessionKey: string;
canonicalKey: string;
storePath: string;
}>;
//#endregion
//#region src/cli/outbound-send-mapping.d.ts
type CliOutboundSendSource = {
[channelId: string]: unknown;
};
//#endregion
//#region src/cli/deps.types.d.ts
/** CLI dependency bag currently used by outbound send command plumbing. */
type CliDeps = CliOutboundSendSource;
//#endregion
//#region src/gateway/server-in-process-dispatch.types.d.ts
type GatewayMethodDispatchResponse = {
ok: boolean;
payload?: unknown;
error?: ErrorShape;
meta?: Record<string, unknown>;
};
//#endregion
//#region src/agents/generated-attachments.d.ts
type AgentGeneratedAttachment = {
type?: "image" | "audio" | "video" | "file";
path?: string;
url?: string;
mediaUrl?: string;
filePath?: string;
mimeType?: string;
name?: string;
sizeBytes?: number;
durationMs?: number;
width?: number;
height?: number;
};
//#endregion
//#region src/agents/internal-event-contract.d.ts
declare const AGENT_INTERNAL_EVENT_TYPE_TASK_COMPLETION: "task_completion";
declare const AGENT_INTERNAL_EVENT_SOURCES: readonly ["subagent", "cron", "image_generation", "video_generation", "music_generation"];
declare const AGENT_INTERNAL_EVENT_STATUSES: readonly ["ok", "timeout", "error", "unknown"];
type AgentInternalEventSource = (typeof AGENT_INTERNAL_EVENT_SOURCES)[number];
type AgentInternalEventStatus = (typeof AGENT_INTERNAL_EVENT_STATUSES)[number];
//#endregion
//#region src/agents/internal-events.d.ts
type AgentTaskCompletionInternalEvent = {
type: typeof AGENT_INTERNAL_EVENT_TYPE_TASK_COMPLETION;
source: AgentInternalEventSource;
childSessionKey: string;
childSessionId?: string;
announceType: string;
taskLabel: string;
status: AgentInternalEventStatus;
statusLabel: string;
result: string;
modelRouteChange?: string;
attachments?: AgentGeneratedAttachment[];
mediaUrls?: string[];
statsLine?: string;
replyInstruction: string;
};
/** Internal event variants that can be rendered into agent prompt context. */
type AgentInternalEvent = AgentTaskCompletionInternalEvent;
//#endregion
//#region src/gateway/server-methods/agent-request-types.d.ts
type AgentRunRequest = {
message: string;
agentId?: string;
provider?: string;
model?: string;
to?: string;
replyTo?: string;
sessionId?: string;
sessionKey?: string;
expectedExistingSessionId?: string;
thinking?: string;
deliver?: boolean;
attachments?: Array<{
type?: string;
mimeType?: string;
fileName?: string;
content?: unknown;
}>;
channel?: string;
replyChannel?: string;
accountId?: string;
replyAccountId?: string;
threadId?: string;
groupId?: string;
groupChannel?: string;
groupSpace?: string;
lane?: string;
cwd?: string;
extraSystemPrompt?: string;
modelRun?: boolean;
promptMode?: "full" | "minimal" | "none";
bootstrapContextMode?: "full" | "lightweight";
bootstrapContextRunKind?: "default" | "heartbeat" | "cron";
acpTurnSource?: "manual_spawn";
internalRuntimeHandoffId?: string;
internalExecutionIdentityRetry?: boolean;
internalExecutionIdentityRecoveryAttempt?: number;
execApprovalFollowupExpectedSessionId?: string;
internalEvents?: AgentInternalEvent[];
suppressPromptPersistence?: boolean;
sessionEffects?: "visible" | "internal";
idempotencyKey: string;
sourceReplyDeliveryMode?: "automatic" | "message_tool_only";
disableMessageTool?: boolean;
swarmCollector?: boolean;
swarmOutputSchema?: Record<string, unknown>;
forceRestartSafeTools?: boolean;
forceCodeModeTools?: boolean;
timeout?: number;
bestEffortDeliver?: boolean;
cleanupBundleMcpOnRunEnd?: boolean;
label?: string;
inputProvenance?: InputProvenance;
workspaceDir?: string;
voiceWakeTrigger?: string;
};
//#endregion
//#region src/plugins/runtime/tool-grant.d.ts
/** Owner-scoped additive plugin tools for one trusted agent run. */
type RuntimePluginToolGrant = {
pluginId: string;
toolNames: readonly string[];
};
//#endregion
//#region src/gateway/server-methods/session-creation-provenance.d.ts
type TrustedSessionCreation = {
skillLibrarySelections?: SkillLibrarySelection[];
via: SessionCreatedVia;
actor?: SessionCreatedActor;
/** Creator-owned isolation requirement resolved only by the trusted Gateway boundary. */
sandbox?: "required";
/** Exact spawning session retained separately from the stable actor identity. */
requesterSessionKey?: string;
/** Immutable completion recipient for a spawn-owned visible session. */
completionOwnerSessionKey?: string;
/** Effective caller tool-policy snapshot for an in-process visible spawn. */
inheritedToolPolicy?: {
version: 1;
allow: string[];
deny: string[];
};
};
//#endregion
//#region src/gateway/server-methods/client-types.d.ts
/** Trusted in-process spawn control plane that already owns this run's task row.
Gateway CLI tracking only covers runs nobody else records, so a marked run
must never get a second row. */
type GatewayAgentRunTaskOwner = "plugin_subagent" | "native_subagent";
/** Caller identity captured by a built-in agent tool before trusted in-process dispatch. */
type TrustedAgentToolCaller = Readonly<{
agentId: string;
sessionKey: string;
}>;
/** Closure-bound streaming hooks attached only to trusted plugin-owned synthetic clients. */
type GatewayNodeInvokeStream = {
onProgress: (chunk: string) => void;
onDispatchReady: (invokeId: string) => void;
idleTimeoutMs?: number;
isRuntimeCurrent: () => boolean;
};
/** Per-connection client metadata captured after the gateway handshake. */
type GatewayClient = {
connect: ConnectParams;
/** Transport-owned revocation marker; retained callers have no authority after invalidation. */
invalidated?: boolean;
/** Host-owned transport retirement notification; does not cancel ordinary admitted RPCs. */
connectionSignal?: AbortSignal;
connId?: string;
presenceKey?: string;
clientIp?: string;
/** Client id verified against the server-approved device pairing record. */
pairedClientId?: string;
authenticatedUserId?: string;
/** Verified Tailscale provider identity; generic proxy identities must not infer this. */
authenticatedUserIsTailscaleProvider?: boolean;
authenticatedGitHubIdentitySync?: AuthenticatedGitHubIdentitySync;
authenticatedUserProfile?: {
profileId: string;
displayName: string | null;
avatarRevision?: string;
hasAvatar: boolean;
updatedAt: number;
};
pluginSurfaceUrls?: Record<string, string>;
pluginNodeCapabilitySurfaces?: Record<string, PluginNodeCapabilitySurface>;
pluginNodeCapabilities?: Record<string, {
capability: string;
expiresAtMs: number;
}>;
isDeviceTokenAuth?: boolean;
internal?: {
/** Handshake-attested direct-local transport; never accepted from wire params. */
isLocalClient?: true;
/** Authenticated Control UI admin admission; never accepted from wire params. */
controlUiAdmin?: true;
/** Marks the server-constructed client used by trusted in-process dispatch. */
syntheticClient?: true;
/** Host-owned role authority retained separately from an autonomous run principal. */
operatorRoleActor?: GatewayOperatorRoleActor;
/** Overrides persisted sender attribution without changing the authorizing client identity. */
senderAttribution?: {
id: string;
name?: string;
identity?: TranscriptSenderIdentity;
};
/** Trusted session creation provenance; never accepted from Gateway wire params. */
sessionCreation?: TrustedSessionCreation;
/** Trusted built-in agent tool caller; never accepted from Gateway wire params. */
agentToolCaller?: TrustedAgentToolCaller;
allowModelOverride?: boolean;
approvalRuntime?: boolean;
cronRunContinuation?: boolean;
agentRuntimeIdentity?: AgentRuntimeIdentity;
pluginRuntimeOwnerId?: string;
/** Host-attested session provenance for a trusted official plugin node invocation. */
nodeInvokeApprovalSessionKey?: string;
/** Plugin-owned in-process invoke hooks; never accepted from Gateway wire params. */
nodeInvokeStream?: GatewayNodeInvokeStream;
agentRunTracking?: GatewayAgentRunTaskOwner;
/** Host-captured requester lineage for opt-in plugin subagent completion delivery. */
pluginSubagentRequester?: PluginSubagentRequesterContext;
/** Host-owned exact media set for a scoped automatic recovery delivery. */
internalDeliveryMediaUrls?: string[];
internalDeliverySuppressText?: boolean;
/** Plugin-owned tools authorized for this internal subagent run. */
runtimePluginToolGrant?: RuntimePluginToolGrant;
/** Host-owned exact tool cap for a tracked plugin subagent run. */
pluginSubagentToolsAllow?: string[];
/** Opaque in-process subagent-completion capability; never accepted from wire params. */
delegatedToolPolicyHandoffId?: string;
};
};
//#endregion
//#region src/gateway/agent-turn/internal-facade.types.d.ts
type InternalAgentTurnPrincipalOptions = {
assertContextCurrent?: () => void;
client: GatewayClient;
isWebchatConnect?: (params: ConnectParams | null | undefined) => boolean;
};
type InternalAgentTurnDispatchOptions = {
assertAdmissionCurrent?: () => void;
cancelOnDeadline?: boolean;
expectFinal?: boolean;
onAccepted?: (payload: unknown) => void;
onExecutionStarted?: () => void;
onSignalAbort?: () => Promise<void> | void;
signal?: AbortSignal;
timeoutMs?: number;
};
type InternalAgentTurnFacade = {
dispatch: <T = unknown>(request: AgentRunRequest, options?: InternalAgentTurnDispatchOptions | number) => Promise<T>;
dispatchRaw: (request: AgentRunRequest, options?: InternalAgentTurnDispatchOptions) => Promise<GatewayMethodDispatchResponse>;
wait: <T = unknown>(params: AgentWaitParams, timeoutMs?: number, signal?: AbortSignal, onSignalAbort?: () => Promise<void> | void) => Promise<T>;
};
type InternalAgentTurnFacadeFactory = (principal: InternalAgentTurnPrincipalOptions) => InternalAgentTurnFacade | Promise<InternalAgentTurnFacade>;
//#endregion
//#region src/gateway/server-chat-progress-snapshot.d.ts
type ChatRunProgressSnapshot = {
events: AgentEventPayload[];
byteLength: number;
lastSeq: number;
};
//#endregion
//#region src/gateway/server-chat-state.d.ts
type ChatRunTiming = {
ackedAtMs: number;
connId: string;
dispatchStartedAtMs?: number;
firstAssistantEventSent?: boolean;
receivedAtMs: number;
};
type ChatRunRegistration = {
sessionKey: string;
agentId?: string;
clientRunId: string;
chatSendTiming?: ChatRunTiming;
};
type ChatRunEntry = ChatRunRegistration & {
registeredSequence: number;
};
type ChatAbortMarker = {
abortedAtMs: number;
sequence: number;
};
type BufferedAgentEvent = {
sessionKey?: string;
agentId?: string;
controlUiVisible?: boolean;
isCurrent?: () => boolean;
payload: AgentEventPayload & {
spawnedBy?: string;
};
};
type ChatRunPlanSnapshot = {
steps: AgentPlanStep[];
explanation?: string;
};
type ChatRunAgentTextState = {
lastSentAt?: number;
bufferedEvent?: BufferedAgentEvent;
};
type ChatRunToolRecipientState = {
connIds: Set<string>;
updatedAt: number;
finalizedAt?: number;
};
type PendingLiveTextFlush = {
timer: NodeJS.Timeout;
flush: () => void;
};
type ChatRunRecord = {
registrations?: ChatRunEntry[];
rawBuffer?: string;
buffer?: string;
bufferIsCurrent?: () => boolean;
/** Retire queued connection snapshots when this buffering generation is cleared. */
liveTextGroup?: AbortController;
/** Projection stays valid only while source and managed-media facts match the run state. */
bufferProjection?: {
source: string;
suppress: boolean;
};
planSnapshot?: ChatRunPlanSnapshot;
progressSnapshot?: ChatRunProgressSnapshot;
/** Last time any buffered assistant text changed, including suppressed raw buffers. */
bufferUpdatedAt?: number;
deltaSentAt?: number;
assistantScope?: {
itemId: string;
prefix: string;
};
managedMediaUrls?: Set<string>;
deltaLastBroadcastText?: string;
agentText?: Partial<Record<"assistant" | "thinking" | "preamble" | "answer_candidate", ChatRunAgentTextState>>;
abortMarker?: ChatAbortMarker;
toolRecipient?: ChatRunToolRecipientState;
/** Fixed-deadline trailing wake-up owned by this run's buffered state. */
pendingTextFlushes?: Partial<Record<"chat" | "agent", PendingLiveTextFlush>>;
};
type ChatRunRegistry = {
add: (sessionId: string, entry: ChatRunRegistration) => void;
peek: (sessionId: string) => ChatRunEntry | undefined;
shift: (sessionId: string) => ChatRunEntry | undefined;
remove: (sessionId: string, clientRunId: string, sessionKey?: string) => ChatRunEntry | undefined;
};
type ChatRunState = {
runs: Map<string, ChatRunRecord>;
registry: ChatRunRegistry;
toolEventRecipients: ToolEventRecipientRegistry;
getOrCreate: (runId: string) => ChatRunRecord;
resolveBuffer: (runId: string, options?: {
final?: boolean;
}) => {
text: string;
suppress: boolean;
};
hasAbortMarker: (runId: string) => boolean;
deleteAbortMarker: (runId: string) => void;
recordProgressEvent: (runId: string, event: AgentEventPayload, mode?: "full" | "summary") => void;
clearRun: (runId: string) => void;
clear: () => void;
};
type ToolEventRecipientRegistry = {
add: (runId: string, connId: string) => void;
get: (runId: string) => ReadonlySet<string> | undefined;
markFinal: (runId: string) => void;
};
//#endregion
//#region src/gateway/chat-abort.d.ts
type ChatAbortControllerEntry = {
controller: AbortController;
sessionId: string;
sessionKey: string;
lifecycleGeneration?: string;
/** Exact operational instance created by this controller registration. */
operationalRunInstance?: OperationalRunInstanceRef;
/** Exact approval lease captured when this controller's execution was admitted. */
agentRunDelegatedAuthority?: AgentRunDelegatedAuthority;
agentId?: string;
startedAtMs: number;
/** False until lane admission reaches the execution boundary. */
executionStarted?: boolean;
expiresAtMs: number;
ownerConnId?: string;
ownerDeviceId?: string;
providerId?: string;
authProviderId?: string;
abortStopReason?: string;
/** Latest argument-free validation diagnostic for operator-initiated aborts. */
toolErrorSummary?: string;
/**
* False for backend/internal agent runs that may share a session key but must
* not be projected into operator chat surfaces.
*/
controlUiVisible?: boolean;
/**
* Controls only the sessions.list active-run projection. Terminal lifecycle
* clears this before chat.send settles, while the entry stays as the retry
* idempotency guard until normal cleanup removes it.
*/
projectSessionActive?: boolean;
/** True after the terminal session-store update has completed. */
projectSessionTerminalPersisted?: boolean;
/** A terminal lifecycle event was observed and is awaiting persistence. */
projectSessionTerminalPending?: boolean;
/** Store timestamp expected from the observed terminal lifecycle event. */
projectSessionTerminalObservedAt?: number;
/** In-flight terminal session-store update used by restart shutdown. */
projectSessionTerminalPersistence?: Promise<void>;
/** Caller completion requested cleanup before terminal lifecycle persistence settled. */
registrationCleanupRequested?: boolean;
/** False after the owning reply run commits a terminal outcome. */
isAbortable?: (entry: ChatAbortControllerEntry) => boolean;
/** Runs once when this registration is actually removed. */
onRemoved?: () => void;
/**
* Which RPC owns this registration. Absent (undefined) is treated as
* `"chat-send"` so pre-existing callers that constructed entries without
* a kind keep their behavior. Consumers that need "chat.send specifically
* is active" must check `kind !== "agent"`, not just `.has(runId)`.
*/
kind?: "chat-send" | "agent";
/** Side questions stay independent from main-turn TUI session stops. */
turnKind?: "main" | "btw";
};
//#endregion
//#region src/gateway/config-reload-status.types.d.ts
type GatewayHotReloadStatus = "active" | "disabled";
//#endregion
//#region src/gateway/config-revision-token.d.ts
type GatewayConfigRevisionProjector = {
projectRawHash: (hash: string) => string;
projectResolvedHash: (hash: string) => string;
};
//#endregion
//#region src/gateway/device-scope-upgrade.d.ts
type UpgradeOwner = {
deviceId: string;
publicKey: string;
};
/** Coordinates live device scope-upgrade waiters with the durable pairing store. */
declare class ScopeUpgradeCoordinator {
private readonly entries;
private readonly work;
private lifetimeBound;
private bindGatewayLifetime;
close(): Promise<void>;
register(params: {
requestId: string;
expiresAtMs: number;
owner: UpgradeOwner;
requestedScopes: string[];
initialToken?: string;
initialApprovedAtMs?: number;
}): boolean;
notify(requestId: string, resolution: "approved" | "rejected"): void;
wait(requestId: string, owner: UpgradeOwner): Promise<ScopeUpgradeResult | null>;
private waitForResult;
private readDurableResult;
private retainTerminal;
}
//#endregion
//#region src/gateway/operator-approval-placement-grants.d.ts
type PlacementStandingGrantMintSpec = NonNullable<PluginApprovalRequestPayload["placementGrant"]>;
type PlacementStandingGrantRecord = PlacementStandingGrantMintSpec & {
mintedByApprovalId: string;
expiresAtMs: number;
};
type ConsumePlacementStandingGrantResult = {
outcome: "consumed";
grant: PlacementStandingGrantRecord;
} | {
outcome: "no-grant" | "expired" | "approval-missing" | "approval-not-allow-always" | "placement-missing" | "placement-changed" | "node-changed" | "pairing-changed";
};
type PlacementGrantResolutionInput = Pick<PlacementStandingGrantMintSpec, "pluginId" | "command" | "approvalScope" | "agentId" | "sessionKey" | "nodeId" | "pairingGeneration">;
type PlacementStandingGrantRuntime = {
resolveBinding: (input: PlacementGrantResolutionInput) => PlacementStandingGrantMintSpec | null;
retain: (grant: PlacementStandingGrantMintSpec & {
approvalId: string;
nowMs: number;
expiresAtMs: number | null;
}) => boolean;
validate: (binding: PlacementStandingGrantMintSpec) => ConsumePlacementStandingGrantResult;
consume: (binding: PlacementStandingGrantMintSpec) => ConsumePlacementStandingGrantResult;
};
//#endregion
//#region src/gateway/operator-approval-standing-grants.d.ts
/** Cron identity plus exact operation binding recorded at approval creation. */
type CronStandingGrantMintSpec = {
agentId: string;
cronJobId: string;
jobConfigRevision: string;
operationBinding: string;
};
//#endregion
//#region src/gateway/operator-approval-store.d.ts
type OperatorApprovalKind = "exec" | "plugin" | "system-agent";
type OperatorApprovalStatus = "pending" | "allowed" | "denied" | "expired" | "cancelled";
type OperatorApprovalDecision = "allow-once" | "allow-always" | "deny";
type OperatorApprovalTerminalReason = "user" | "timeout" | "malformed-verdict" | "no-route" | "run-aborted" | "gateway-restart" | "storage-corrupt";
type OperatorApprovalResolverKind = "device" | "channel" | "runtime" | "system";
type OperatorApprovalRequester = {
deviceId: string | null;
clientId: string | null;
deviceTokenAuth: boolean;
};
type OperatorApprovalSource = {
agentId: string | null;
sessionKey: string | null;
sessionId: string | null;
runId: string | null;
toolCallId: string | null;
toolName: string | null;
};
type OperatorApprovalResolver = {
kind: OperatorApprovalResolverKind;
id: string | null;
};
type OperatorApprovalRecord = {
id: string;
resolutionRef: string;
kind: OperatorApprovalKind;
status: OperatorApprovalStatus;
presentation: ApprovalPresentation;
requester: OperatorApprovalRequester;
reviewerDeviceIds: string[];
source: OperatorApprovalSource;
audienceSessionKeys: string[];
runtimeEpoch: string;
createdAtMs: number;
expiresAtMs: number;
updatedAtMs: number;
decision: OperatorApprovalDecision | null;
terminalReason: OperatorApprovalTerminalReason | null;
resolvedAtMs: number | null;
resolver: OperatorApprovalResolver | null;
consumedAtMs: number | null;
consumedBy: string | null;
};
type ResolveOperatorApprovalResult = {
outcome: "resolved";
record: OperatorApprovalRecord;
} | {
outcome: "expired";
record: OperatorApprovalRecord;
} | {
outcome: "already-resolved";
retry: "same" | "conflict";
record: OperatorApprovalRecord;
} | {
outcome: "decision-not-allowed";
record: OperatorApprovalRecord;
} | {
outcome: "not-found";
} | {
outcome: "corrupt";
};
type ForceDenyOperatorApprovalResult = {
outcome: "denied";
record: OperatorApprovalRecord;
} | {
outcome: "expired";
record: OperatorApprovalRecord;
} | {
outcome: "not-due";
record: OperatorApprovalRecord;
} | {
outcome: "already-terminal";
record: OperatorApprovalRecord;
} | {
outcome: "not-found";
} | {
outcome: "corrupt";
};
//#endregion
//#region src/gateway/exec-approval-manager.types.d.ts
type ExecApprovalResolutionSource = "operator" | "auto-review";
type ExecApprovalRecord<TPayload = ExecApprovalRequestPayload> = {
id: string;
request: TPayload;
createdAtMs: number;
expiresAtMs: number;
requestedByConnId?: string | null;
requestedByDeviceId?: string | null;
requestedByClientId?: string | null;
requestedByDeviceTokenAuth?: boolean;
approvalReviewerDeviceIds?: string[];
resolvedAtMs?: number;
decision?: ExecApprovalDecision;
consumedDecision?: ExecApprovalDecision;
resolutionSource?: ExecApprovalResolutionSource;
askFallbackConsumed?: boolean;
resolvedBy?: string | null;
status?: OperatorApprovalStatus;
terminalReason?: OperatorApprovalTerminalReason | null;
runtimeEpoch?: string;
resolverKind?: OperatorApprovalResolver["kind"] | null;
consumedAtMs?: number | null;
consumedBy?: string | null;
executionIdentityToken?: ExecutionIdentityAdmissionToken;
/** Exact source authority retained only for use-time liveness validation. */
agentRuntimeDelegatedAuthority?: AgentRuntimeDelegatedAuthority;
/** Closure-bound authority for approvals created by in-process delegated tools. */
approvalAuthority?: () => boolean | void;
approvalSignals?: readonly AbortSignal[];
/** Process-local persistence proof; never serialized with approval presentation. */
mcpToolApprovalActive?: () => boolean;
};
type OperatorApprovalLifecycleEvent = {
phase: "pending" | "terminal";
record: OperatorApprovalRecord;
};
type OperatorStandingGrantMintSpec = ({
kind: "cron";
} & CronStandingGrantMintSpec) | {
kind: "mcp-tool";
agentId: string;
server: string;
tool: string;
} | ({
kind: "placement";
} & PlacementStandingGrantMintSpec);
type ExecApprovalManagerOptions<TPayload> = {
approvalKind?: OperatorApprovalKind;
persistence: {
runtimeEpoch: string;
databaseOptions?: OpenClawStateDatabaseOptions;
};
resolveAllowedDecisions?: (request: TPayload) => readonly ExecApprovalDecision[];
/** Gateway owns lineage lookup; absence seeds only the requesting session. */
resolveAudienceSessionKeys?: (sourceSessionKey: string, sourceAgentId?: string | null) => string[];
onError?: (error: Error, context: {
approvalId: string;
approvalKind: OperatorApprovalKind;
operation: "expire";
}) => void;
onLifecycle?: (event: OperatorApprovalLifecycleEvent) => void;
/** Eligible allow-always requests derive one scoped grant, or return null. */
resolveStandingGrantMint?: (request: TPayload) => OperatorStandingGrantMintSpec | null;
/** Installs a placement grant after the durable approval CAS succeeds. */
retainPlacementStandingGrant?: PlacementStandingGrantRuntime["retain"];
resolveStandingGrantExpiresAtMs?: (nowMs: number) => number | null;
/** Timer, lookup, and replay expiry must all release the same local waiter. */
onExpired?: (record: OperatorApprovalRecord, liveRecord: ExecApprovalRecord<TPayload>) => void;
validateAgentRuntimeDelegatedAuthority?: (authority: AgentRuntimeDelegatedAuthority) => boolean;
};
type WithLiveRecord<TResult, TPayload> = TResult extends {
record: OperatorApprovalRecord;
} ? TResult & {
liveRecord?: ExecApprovalRecord<TPayload>;
} : TResult;
type ExecApprovalResolveResult<TPayload = ExecApprovalRequestPayload> = WithLiveRecord<ResolveOperatorApprovalResult, TPayload>;
type ExecApprovalForceDenyResult<TPayload = ExecApprovalRequestPayload> = WithLiveRecord<ForceDenyOperatorApprovalResult, TPayload>;
type ExecApprovalDurableLookup = {
outcome: "found";
record: OperatorApprovalRecord;
} | {
outcome: "missing" | "corrupt";
id: string;
};
type ExecApprovalIdLookupResult = {
kind: "exact" | "prefix";
id: string;
} | {
kind: "ambiguous";
ids: string[];
} | {
kind: "none";
};
//#endregion
//#region src/gateway/exec-approval-lifecycle.d.ts
type DecisionHandoff = {
start: (decision: ExecApprovalDecision | null) => void;
cancel: () => void;
};
type PendingEntry<TPayload> = {
record: ExecApprovalRecord<TPayload>;
resolve: (decision: ExecApprovalDecision | null) => void;
timer: ReturnType<typeof setTimeout> | null;
cleanupTimer: ReturnType<typeof setTimeout> | null;
handoffRetainCount: number;
handoffReleasedAtMs: number | null;
retainForManagerLifetime: boolean;
promise: Promise<ExecApprovalDecision | null>;
handoffs: Set<DecisionHandoff>;
admissionContinuation: GatewayRootWorkAdmissionContinuationScope | null;
};
/** Owns local observations and genuine decision effects, never durable decision policy. */
declare abstract class ExecApprovalLifecycle<TPayload> {
protected readonly pending: Map<string, PendingEntry<TPayload>>;
protected retired: boolean;
private observingClosed;
private readonly observers;
private readonly work;
private draining;
abstract get runtimeEpoch(): string;
protected abstract expireDue(recordId: string): boolean;
protected abstract reportError(error: unknown, context: {
approvalId: string;
operation: "expire";
}): void;
beginClose(): void;
retire(): void;
drain(): Promise<void>;
trackActiveWork<T>(run: () => T | Promise<T>): Promise<T>;
protected canUseRetainedBinding(): boolean;
protected assertNotRetired(): void;
protected registerEntry(record: ExecApprovalRecord<TPayload>): Promise<ExecApprovalDecision | null>;
/** Registers the real effect before an observer can leave or a synchronous verdict can win. */
registerDecisionHandoff(recordId: string, run: (decision: ExecApprovalDecision | null) => Promise<void>): {
observation: Promise<void>;
abandon: () => void;
};
protected observeEntry<T>(entry: PendingEntry<TPayload>, completion: Promise<T>): Promise<T>;
protected settleLocalEntry(params: {
recordId: string;
decision: ExecApprovalDecision | null;
resolvedAtMs: number;
resolvedBy: string | null;
resolverKind: OperatorApprovalResolver["kind"] | null;
status: OperatorApprovalStatus;
terminalReason: OperatorApprovalTerminalReason | null;
consumedAtMs?: number | null;
consumedBy?: string | null;
resolutionSource?: ExecApprovalResolutionSource;
retainForManagerLifetime?: boolean;
}): boolean;
private scheduleResolvedCleanup;
protected resolvedGraceAnchorMs(entry: PendingEntry<TPayload>, nowMs: number): number | null;
/** Final release starts a fresh grace only while the manager still owns its lifecycle. */
retainForHandoff(recordId: string): (() => void) | null;
protected scheduleExpiryTimer(entry: PendingEntry<TPayload>): void;
getSnapshot(recordId: string): ExecApprovalRecord<TPayload> | null;
/** Reads a live local binding without entering durable storage or mutating expiry. */
getLiveSnapshot(recordId: string): ExecApprovalRecord<TPayload> | null;
/** Re-enters only the pending approval's exact original root. */
runPendingContinuation<T>(recordId: string, run: () => Promise<T>): Promise<T> | null;
listPendingRecords(): ExecApprovalRecord<TPayload>[];
lookupApprovalId(input: string, opts?: {
includeResolved?: boolean;
filter?: (record: ExecApprovalRecord<TPayload>) => boolean;
}): ExecApprovalIdLookupResult;
}
//#endregion
//#region src/gateway/exec-approval-manager.d.ts
/** Approval creation and persistence precede every local wait or delivery handoff. */
declare class ExecApprovalManager<TPayload = ExecApprovalRequestPayload> extends ExecApprovalLifecycle<TPayload> {
protected readonly options: ExecApprovalManagerOptions<TPayload>;
constructor(options: ExecApprovalManagerOptions<TPayload>);
get approvalKind(): OperatorApprovalKind;
get runtimeEpoch(): string;
private resolveApprovalSource;
private allowedDecisionsForRequest;
create(request: TPayload, timeoutMs: number, id?: string | null): ExecApprovalRecord<TPayload>;
/** Synchronously persists/registers the request before returning its authority promise. */
register(record: ExecApprovalRecord<TPayload>, _timeoutMs: number): Promise<ExecApprovalDecision | null>;
private isRuntimeAuthorityActive;
private emitLifecycle;
/** Persist the first verdict, then release the process-local waiter. */
resolveDetailed(recordId: string, decision: ExecApprovalDecision, resolver: OperatorApprovalResolver, localResolvedBy?: string | null, localResolutionSource?: ExecApprovalResolutionSource, options?: {
/** Explicit grant expiry override; undefined defers to the configured default. */
grantExpiresAtMs?: number | null;
}): ExecApprovalResolveResult<TPayload>;
/** Persist a fail-closed terminal state, then release the local waiter. */
forceDenyDetailed(recordId: string, reason: OperatorApprovalTerminalReason, resolver: OperatorApprovalResolver, status?: "denied" | "expired" | "cancelled", localDecision?: ExecApprovalDecision | null, requireDue?: boolean, localResolvedBy?: string | null): ExecApprovalForceDenyResult<TPayload>;
private settleLocalFromStore;
/** Settle one durable terminal transition and report whether this manager published it. */
reconcileDurableTerminal(record: OperatorApprovalRecord): boolean;
/** Reconciles durable truth with an existing waiter without rehydrating its request. */
reconcileDurableLookup(lookup: ExecApprovalDurableLookup, localResolvedBy?: string | null): OperatorApprovalRecord | null;
private settleLocalStorageFailure;
private persistStorageCorruptDeny;
protected reportError(error: unknown, context: {
approvalId: string;
operation: "expire";
}): void;
protected expireDue(recordId: string): boolean;
resolve(recordId: string, decision: ExecApprovalDecision, resolvedBy?: string | null, options?: {
grantExpiresAtMs?: number | null;
}): boolean;
/**
* Trusted auto-review resolution (identity-matched approval runtime).
* Always allow-once; system.run replay validation treats the resulting
* record more strictly than an operator decision (see #103515).
*/
resolveAutoReview(recordId: string, resolvedBy?: string | null): boolean;
/**
* One-shot ask-fallback re-admission for a timed-out approval. This is
* pre-gate policy on the process-local record only: the durable row stays
* `expired` and no execution authority is minted here. The shipped askFallback
* policy (docs/tools/exec-approvals.md) still applies; system.run replay
* uses this flag to keep re-admission single-use.
*/
consumeAskFallback(recordId: string): boolean;
expire(recordId: string, resolvedBy?: string | null): boolean;
consumeAllowOnce(recordId: string, consumerId?: string): boolean;
/** Observes a registered decision; Gateway closure rejects the wait, not the approval. */
awaitDecision(recordId: string): Promise<ExecApprovalDecision | null> | null;
/** Projects an allowed decision only while its exact runtime authority is live. */
projectDecisionIfActive(recordId: string, decision: ExecApprovalDecision | null): ExecApprovalDecision | null;
/** Atomically closes a live approval whose exact runtime owner is gone. */
forceDenyIfRuntimeAuthorityClosed(recordId: string): ExecApprovalForceDenyResult<TPayload> | null;
}
//#endregion
//#region src/plugins/runtime-degraded-state.d.ts
/** Boot-stable quarantine state for configured plugins whose payload failed verification. */
type PluginVerificationFailureReason = "missing-install-path" | "missing-package-dir" | "missing-package-json" | "unreadable-package-json" | "invalid-package-json" | "missing-bundle-manifest" | "invalid-bundle-manifest" | "missing-main-entry" | "missing-extension-entry" | "missing-openclaw-peer-link";
//#endregion
//#region src/gateway/health/types.d.ts
type ProtocolHealth = Snapshot["health"];
type ProtocolPlugin = NonNullable<ProtocolHealth["plugins"]>;
type UnavailablePlugin = NonNullable<ProtocolPlugin["unavailable"]>[number];
/** Health snapshot for one configured channel account. */
type ChannelAccountHealthSummary = ChannelAccountSnapshot & {
authAgeMs?: number | null;
[key: string]: unknown;
};
/** Channel-level health summary with optional per-account details. */
type ChannelHealthSummary = ChannelAccountHealthSummary & {
accounts?: Record<string, ChannelAccountHealthSummary>;
};
type AgentHealthSummary = NonNullable<ProtocolHealth["agents"]>[number];
/** Plugin registry health summary. */
type PluginHealthSummary = Omit<ProtocolPlugin, "unavailable"> & {
unavailable?: Array<Omit<UnavailablePlugin, "diagnostic"> & {
diagnostic: Omit<UnavailablePlugin["diagnostic"], "reason"> & {
reason: PluginVerificationFailureReason;
};
}>;
};
/** Full gateway health payload consumed by `openclaw health`. */
type HealthSummary = ProtocolHealth & {
ok: true;
ts: number;
durationMs: number;
plugins?: PluginHealthSummary;
channels: Record<string, ChannelHealthSummary>;
channelOrder: string[];
channelLabels: Record<string, string>;
heartbeatSeconds: number;
agents: AgentHealthSummary[];
sessions: NonNullable<ProtocolHealth["sessions"]>;
};
//#endregion
//#region src/gateway/mention-inbox.types.d.ts
type MentionCommittedInput = {
sourceId: string;
sessionKey: string;
agentId?: string;
sessionId: string;
messageId: string;
senderProfileId: string;
recipientProfileIds: readonly string[];
excerpt?: string;
};
/** Keep the Gateway context independent of its context-consuming Inbox implementation. */
type MentionInbox = {
mentionable: (client: GatewayClient | null, input: UsersMentionableParams) => Result<UsersMentionableResult, ErrorShape>;
validateRecipients: (client: GatewayClient | null, input: UsersMentionableParams, profileIds: readonly string[]) => Result<readonly string[], ErrorShape>;
list: (client: GatewayClient | null) => Result<MentionsListResult, ErrorShape>;
dismiss: (client: GatewayClient | null, ids: readonly string[]) => Result<MentionsListResult, ErrorShape>;
recordCommittedInput: (input: MentionCommittedInput) => void;
invalidate: () => void;
dispose: () => void;
};
//#endregion
//#region src/shared/node-host-stats.d.ts
type NodeHostStats = NodeHostStatsPayload & {
updatedAtMs: number;
};
//#endregion
//#region src/infra/node-pairing-surface.d.ts
type NodeApprovalSurface = {
caps: string[];
commands: string[];
permissions?: Record<string, boolean>;
};
//#endregion
//#region src/infra/device-pairing-node-state.d.ts
/** Registry projection of a paired device's authenticated node-role state. */
type PairedDeviceNodeBinding = {
identity: string;
generation?: string;
};
//#endregion
//#region src/plugins/computer-use-contract.d.ts
declare const ComputerUseCapabilityDescriptorSchema: Type.TObject<{
contractVersion: Type.TLiteral<2>;
provider: Type.TObject<{
id: Type.TString;
label: Type.TString;
generation: Type.TString;
}>;
actions: Type.TArray<Type.TEnum<["screenshot", "left_click", "right_click", "middle_click", "double_click", "triple_click", "mouse_move", "left_click_drag", "left_mouse_down", "left_mouse_up", "scroll", "type", "key", "hold_key", "wait", "list_apps", "list_windows", "get_accessibility_tree", "get_cursor_position", "get_window_state", "launch_app", "kill_app", "bring_to_front", "set_value", "zoom", "get_browser_state", "browser_prepare", "browser_navigate", "browser_click", "browser_type", "browser_dialog", "browser_set_input_files", "browser_download", "browser_pointer", "escalate_scope", "get_recording_state", "start_recording", "stop_recording", "replay_trajectory", "invoke_menu"]>>;
targets: Type.TArray<Type.TEnum<["screen", "window", "element", "browser"]>>;
deliveryModes: Type.TArray<Type.TEnum<["background", "foreground"]>>;
observations: Type.TArray<Type.TEnum<["image", "accessibility", "browser"]>>;
features: Type.TObject<{
recording: Type.TBoolean;
agentCursor: Type.TBoolean;
multiDisplay: Type.TBoolean;
}>;
}>;
type ComputerUseCapabilityDescriptor = Static<typeof ComputerUseCapabilityDescriptorSchema>;
//#endregion
//#region src/gateway/node-plugin-tool-snapshot.d.ts
type RegisteredNodePluginToolCommand = {
pluginId: string;
command: {
command?: string;
agentTool?: {
name?: string;
description?: string;
parameters?: unknown;
mcp?: {
server?: string;
tool?: string;
};
};
};
};
//#endregion
//#region src/gateway/node-registry.invoke-stream.d.ts
type NodeInvokeProgressParams = {
invokeId: string;
nodeId: string;
connId: string | undefined;
seq: number;
chunk: string;
};
type NodeInvokeResultParams = {
id: string;
nodeId: string;
connId: string | undefined;
ok: boolean;
payload?: unknown;
payloadJSON?: string | null;
error?: {
code?: string;
message?: string;
} | null;
};
//#endregion
//#region src/gateway/node-registry.d.ts
/** Connected node session advertised over Gateway websocket. */
type NodeSession = {
nodeId: string;
connId: string;
/** Persistent device key and node-token identity authenticated for this connection. */
pairingIdentity?: string;
/** Persistent pairing generation authenticated before this session was registered. */
pairingGeneration?: string;
client: GatewayWsClient;
clientId?: string;
clientMode?: string;
displayName?: string;
platform?: string;
version?: string;
coreVersion?: string;
uiVersion?: string;
deviceFamily?: string;
modelIdentifier?: string;
remoteIp?: string;
declaredCaps: string[];
sessionCapsCeiling?: string[];
caps: string[];
declaredCommands: string[];
sessionCommandsCeiling?: string[];
commands: string[];
declaredComputerUse?: ComputerUseCapabilityDescriptor;
computerUse?: ComputerUseCapabilityDescriptor;
declaredNodePluginTools: NodePluginToolDescriptor[];
nodePluginTools: NodePluginToolDescriptor[];
nodeSkills: NodeSkillDescriptor[];
declaredPermissions?: Record<string, boolean>;
permissions?: Record<string, boolean>;
pathEnv?: string;
connectedAtMs: number;
lastActiveAtMs?: number;
presenceUpdatedAtMs?: number;
hostStats?: NodeHostStats;
};
type PairingBoundNodeSession = NodeSession & {
pairingIdentity: string;
};
/** Result payload returned from node.invoke. */
type NodeInvokeResult = {
ok: boolean;
payload?: unknown;
payloadJSON?: string | null;
error?: {
code?: string;
message?: string;
} | null;
};
/** Connectivity probe result for a registered node. */
type NodeConnectivityResult = {
ok: true;
} | {
ok: false;
error: {
code: string;
message: string;
};
};
declare const SERIALIZED_EVENT_PAYLOAD: unique symbol;
type SerializedEventPayload = {
readonly json: string;
readonly [SERIALIZED_EVENT_PAYLOAD]: true;
};
/** Event transport for nodes that cannot keep a WebSocket open, such as watchOS. */
type NodeEventTransport = {
send: (event: string, payload: unknown) => boolean;
sendRaw: (event: string, payloadJSON?: SerializedEventPayload | null) => boolean;
checkConnectivity?: (timeoutMs: number) => Promise<NodeConnectivityResult>;
};
type PairedDeviceNodeBindingSnapshot = PairedDeviceNodeBinding;
type NodeSessionRegistrationOptions = {
remoteIp?: string | undefined;
pairingIdentity: string;
pairingGeneration?: string | undefined;
approvedSurface?: NodeApprovalSurface;
};
type NodeRegistryOptions = {
listRegisteredNodePluginToolCommands?: (() => readonly RegisteredNodePluginToolCommand[] | undefined) | undefined;
getConfig?: () => OpenClawConfig;
resolveCurrentPairingState?: (nodeId: string) => Promise<PairedDeviceNodeBindingSnapshot | undefined>;
isPairingStateCurrent?: (nodeId: string, expected: PairedDeviceNodeBinding) => boolean;
onPairingGenerationChanged?: (params: {
nodeId: string;
previousPairingGeneration: string;
nextPairingGeneration: string;
preserveSessionState: boolean;
}) => void;
onPairingInvalidated?: (params: {
nodeId: string;
connId: string;
}) => void;
};
/** Registry of currently connected Gateway nodes. */
declare class NodeRegistry {
private readonly options;
private nodesById;
private nodesByConn;
private eventTransportsByConn;
private pendingInvokes;
private invokeStreams;
private authorizedSystemRunEvents;
private pairingGenerationEventChains;
private committedConfig;
constructor(options?: NodeRegistryOptions);
private listConnectedSessions;
private capturePairingLease;
private currentSessionForLease;
private settlePairingLease;
private resolvePairingLease;
private refreshSessionPolicy;
private isCommandAllowed;
refreshRuntimePolicy(config?: OpenClawConfig | undefined): NodeSession[];
/** Register a websocket client as the current connection for its node id. */
register(client: GatewayWsClient, opts: NodeSessionRegistrationOptions): PairingBoundNodeSession;
/** Register a node whose events are delivered by an HTTP polling transport. */
registerTransport(client: GatewayWsClient, opts: NodeSessionRegistrationOptions, transport: NodeEventTransport): PairingBoundNodeSession;
private registerSession;
/** Unregister one connection and reject invokes tied to that connection. */
unregister(connId: string): string | null;
/** List connected node sessions. */
listConnected(): NodeSession[];
/** Filter connected sessions against an already-loaded pairing-state snapshot. */
listConnectedForPairingStates(currentPairingStates: ReadonlyMap<string, PairedDeviceNodeBindingSnapshot>): NodeSession[];
/** Reconcile connected sessions through the synchronous persistent-pairing owner. */
listCurrentConnectedSync(): NodeSession[];
/** Resolve persistent pairing state before projecting connected sessions. */
listCurrentConnected(): Promise<NodeSession[]>;
private invalidateSessionForPairingChange;
/** Immediately retires one exact transport after its persisted pairing authority changes. */
invalidateConnectionForPairingChange(connId: string, reason?: string): boolean;
/** Return a connected node session by node id. */
get(nodeId: string): NodeSession | undefined;
private getRegisteredSession;
/** Return only the session authenticated for the requested persistent pairing generation. */
getForPairingGeneration(nodeId: string, pairingGeneration: string): NodeSession | undefined;
private getRegisteredSessionForPairingGeneration;
/** Revalidates that one inbound node connection still owns its persisted pairing state. */
isConnectionCurrentPairingState(connId: string): Promise<boolean>;
/** Stores the latest resource snapshot for the exact authenticated node connection. */
updateHostStats(params: {
nodeId: string;
connId?: string;
stats: NodeHostStatsPayload;
observedAtMs?: number;
}): NodeHostStats | null;
/** Updates recent input activity for the exact authenticated node connection. */
updatePresenceActivity(params: {
nodeId: string;
connId?: string;
idleSeconds: number;
saturated?: boolean;
observedAtMs?: number;
}): NodeSession | null;
/** Clears recent input activity for the exact authenticated node connection. */
clearPresenceActivity(params: {
nodeId: string;
connId?: string;
}): boolean | null;
/** Returns the connected node with the freshest reported local input. */
getActiveNode(connectedNodes?: readonly NodeSession[]): NodeSession | undefined;
private publishActiveNodeContext;
/** Probe websocket liveness with ping/pong when the socket supports it. */
checkConnectivity(nodeId: string, timeoutMs?: number): Promise<NodeConnectivityResult>;
updateNodePluginTools(nodeId: string, connId: string | undefined, tools: readonly NodePluginToolDescriptor[]): NodeSession | null;
updateNodeSkills(nodeId: string, connId: string | undefined, skills: readonly NodeSkillDescriptor[]): NodeSession | null;
updateSurface(nodeId: string, surface: {
caps?: readonly string[];
commands: readonly string[];
permissions?: Record<string, boolean> | undefined;
}, generationTransition?: {
expectedConnId: string;
expectedPairingIdentity: string;
expectedPairingGeneration?: string;
nextPairingGeneration: string;
}): NodeSession | null;
private clearPresenceIfAccessibilityUnavailable;
invoke(params: {
nodeId: string;
expectedConnId?: string;
expectedPairingGeneration?: string;
command: string;
params?: unknown;
timeoutMs?: number;
/** Inactivity deadline reset by each ordered progress chunk. */
idleTimeoutMs?: number;
onProgress?: (chunk: string) => void;
signal?: AbortSignal;
idempotencyKey?: string;
sessionKey?: string;
/** Receives the id and armed hard deadline after a successful dispatch. */
onDispatchReady?: (invokeId: string, deadlineAtMs?: number) => void;
/** Revalidates caller authority at the registry-owned transport handoff. */
isDispatchAuthorized?: () => boolean;
}): Promise<NodeInvokeResult>;
/** Internal cleanup retains its owner through replies without admitting new root work. */
invokeLifecycle(params: Parameters<NodeRegistry["invoke"]>[0] & {
isDispatchAuthorized: () => boolean;
}): Promise<NodeInvokeResult>;
/** Send one ordered input frame to a pending streaming invoke. */
sendInvokeInput(invokeId: string, payload: unknown): void;
/** Synchronous effect fence for callbacks retained across awaited host work. */
isInvokeCurrent(invokeId: string, nodeId: string, connId: string): boolean;
handleInvokeProgress(params: NodeInvokeProgressParams): boolean;
/** Continues only the exact live owner of a pending node invocation. */
runPendingInvokeContinuation<T>(params: {
invokeId: string;
nodeId: string;
connId: string | undefined;
run: () => Promise<T>;
}): Promise<T> | null;
/** Authorize an inbound system.run event against a recently issued node invoke. */
authorizeSystemRunEvent(params: {
nodeId: string;
connId?: string;
runId?: string;
sessionKey: string;
terminal: boolean;
}): boolean;
private rememberAuthorizedSystemRunEvent;
private forgetAuthorizedSystemRunEvent;
private authorizedSystemRunEventExpiresAt;
private matchAuthorizedSystemRunEvent;
private matchSingleAuthorizedSystemRunEvent;
private authorizedSystemRunSessionMatches;
private allowsLegacyMacRunIdFallback;
private pruneAuthorizedSystemRunEvents;
private authorizedSystemRunEventKey;
handleInvokeResult(params: NodeInvokeResultParams): boolean;
sendEvent(nodeId: string, event: string, payload?: unknown): boolean;
sendEventRaw(nodeId: string, event: string, payloadJSON?: SerializedEventPayload | null): boolean;
/** Sends command-free events only to the exact authenticated pairing connection. */
sendEventForPairingIdentity(params: {
nodeId: string;
connId: string;
pairingIdentity: string;
event: string;
payload?: unknown;
}): Promise<boolean>;
/** Sends only to a session that still owns the requested persistent pairing generation. */
sendEventRawForPairingGeneration(nodeId: string, pairingGeneration: string, event: string, payloadJSON?: SerializedEventPayload | null): Promise<boolean>;
private sendEventRawForPairingGenerationNow;
private sendEventInternal;
private sendEventRawInternal;
private sendEventToSession;
private observeEventSend;
private isNodeWebSocketOpen;
private rejectSlowNodeSocket;
}
//#endregion
//#region src/gateway/portals/portal-http-proxy.d.ts
type PortalTarget = {
kind: "local";
port: number;
} | {
kind: "worker";
environmentId: string;
ownerEpoch: number;
remotePort: number;
connect: () => Promise<Duplex>;
};
//#endregion
//#region src/gateway/portals/portal-service.d.ts
type GatewayPortalOpenParams = {
targetPort: number;
target?: PortalTarget;
/** Revalidated before metadata mutation or publication after asynchronous listener startup. */
assertCurrent?: () => void;
/** Ownership transfers to open; unused targets are released even when it rejects or reuses a portal. */
onClose?: () => Promise<void> | void;
origin?: string;
title?: string;
description?: string;
path?: string;
};
type GatewayPortalService = {
open: (params: GatewayPortalOpenParams) => Promise<PortalOpenResult>;
list: () => PortalSummary[];
listWorkerPortals: (environmentId: string, ownerEpoch: number) => PortalSummary[];
close: (id: string, assertCurrent?: () => void) => Promise<void>;
closeWorkerPortals: (environmentId: string, ownerEpoch?: number) => Promise<void>;
closeAll: () => Promise<void>;
};
//#endregion
//#region src/gateway/question-manager.d.ts
type QuestionManagerRequest = {
id?: string;
questions: Question[];
agentId?: string;
sessionKey?: string;
runId?: string;
timeoutMs: number;
onResolved?: (event: QuestionResolvedEvent) => void;
isRequesterActive?: () => boolean;
/** Trusted handler binds the run; the manager owns expiry and terminal release. */
registerHumanInputWait?: (isPending: () => boolean) => ((resolved: boolean) => void) | undefined;
};
/** Process-local lifecycle owner for pending questions. */
declare class QuestionManager {
private readonly entries;
private closed;
request(params: QuestionManagerRequest): QuestionRecord;
get(id: string): QuestionRecord | null;
/** Called by the Gateway's existing authority-close observer. */
cancelClosedAuthorities(): void;
list(): QuestionRecord[];
/** Re-enters only the still-pending question's original admitted root. */
runPendingContinuation<T>(id: string, run: () => Promise<T>): Promise<T> | null;
waitAnswer(id: string, timeoutMs?: number, includeResolutionId?: boolean): Promise<QuestionWaitAnswerResult>;
resolve(id: string, answers: QuestionAnswers, resolvedBy?: string, options?: {
commit?: () => void;
resolutionId?: string;
}): QuestionResolveResult;
cancel(id: string, resolvedBy?: string): QuestionResolveResult;
private cancelEntry;
/** Retires this Gateway's owner only after received mutations have joined. */
close(): void;
/** Reusable on open owners (v2026.8.1 SDK context); never reopens a closed owner. */
reset(): void;
private requireEntry;
private requirePendingEntry;
/** Validates answers against stored questions and returns them in canonical form. */
private validateAnswers;
private invalidAnswer;
private notFound;
private expire;
private finish;
}
//#endregion
//#region src/cron/scratch-store.d.ts
type CronJobScratch = {
content: string;
revision: number;
sourceSha256?: string;
updatedAtMs: number;
};
/**
* Present scratch content plus the persisted revision. An unset scratch keeps a
* tombstone row so `currentRevision` stays monotonic across unset/recreate and
* stale compare-and-swap writers cannot resurrect old content.
*/
type CronJobScratchState = {
currentRevision: number;
scratch?: CronJobScratch;
};
type CronJobScratchWriteResult = {
ok: true;
currentRevision: number;
scratch?: CronJobScratch;
} | {
ok: false;
reason: "revision-conflict";
currentRevision: number;
};
//#endregion
//#region src/gateway/server-cron-contract.d.ts
type GatewayCronServiceContract = CronServiceContract & {
/** Remove an owned declarative job family from obsolete SQLite store partitions. */
removeStaleJobFamily(family: {
declarationKey: string;
name: string;
ownerPluginTag: string;
}, opts?: {
commitGuard?: () => void;
}): Promise<number>;
readScratch(id: string): Promise<CronJobScratchState>;
writeScratch(id: string, params: {
content: string | null;
expectedRevision?: number;
sourceSha256?: string;
commitGuard?: () => void;
}): Promise<CronJobScratchWriteResult>;
/** Serialize agent-job removal with the roster commit and restore on failure. */
removeAgentJobsTransactional<T>(agentId: string, commit: () => Promise<T>): Promise<T>;
/** Temporarily disarm ticks without running startup recovery on resume. */
pauseScheduling(): void;
resumeScheduling(): void;
/** Scheduler-owned work not represented by active cron run markers. */
getSuspensionBlockerCount?(): number;
/** Materialize lazy cron dependencies before a synchronous operator wake. */
prepareWake?(): Promise<void>;
/** Stop cron and await scheduler-owned child process teardown. */
stopAndDrain?(): Promise<void>;
};
//#endregion
//#region src/agents/subagents/announce/subagent-announce-handoff.d.ts
type TrustedSubagentCompletionHandoff = {
kind: "subagent-completion";
sourceSessionKey: string;
sourceSessionId?: string;
targetSessionKey: string;
targetSessionId: string;
provider: string;
model: string;
};
type SubagentCompletionToolHandoffRegistration = {
sourceSessionKey: string;
sourceSessionId?: string;
targetSessionKey: string;
targetSessionId: string;
idempotencyKey: string;
};
//#endregion
//#region src/gateway/server-instance-runtime.types.d.ts
type GatewayInstanceAgentDispatchOptions = {
allowModelOverride?: boolean;
allowSyntheticModelOverride?: boolean;
allowSyntheticCronRunContinuation?: boolean;
delegatedToolPolicyHandoff?: SubagentCompletionToolHandoffRegistration;
expectFinal?: boolean;
/** Instance-owned dispatch always uses a synthetic client. */
forceSyntheticClient?: boolean;
internalDeliveryMediaUrls?: string[];
internalDeliverySuppressText?: boolean;
onAccepted?: (payload: unknown) => void;
onExecutionStarted?: () => void;
onSignalAbort?: () => Promise<void> | void;
scopes?: string[];
signal?: AbortSignal;
syntheticScopes?: string[];
};
type GatewayApprovalEventPublisher = {
publishRequested: (kind: ChannelApprovalKind, request: unknown) => number;
publishResolved: (kind: ChannelApprovalKind, resolved: unknown) => void;
};
type GatewayRecoveryRuntime = {
abortAgent: (params: {
agentId: string;
runId: string;
sessionKey: string;
}, timeoutMs?: number) => Promise<{
aborted?: boolean;
runIds?: string[];
}>;
dispatchAgent: <T = unknown>(params: AgentRunRequest, timeoutMs?: number, options?: GatewayInstanceAgentDispatchOptions) => Promise<T>;
waitForAgent: <T = unknown>(params: AgentWaitParams, timeoutMs?: number) => Promise<T>;
sendRecoveryNotice: (params: {
channel: string;
to: string;
accountId?: string;
threadId?: string | number;
text: string;
idempotencyKey: string;
/** Revalidated after lazy runtime loading and immediately before outbound dispatch. */
isCurrent?: () => boolean;
}) => Promise<{
/** True when delivery produced zero platform results (policy/channel suppression). */
suppressed: boolean;
}>;
};
//#endregion
//#region src/gateway/server-model-catalog.types.d.ts
/** Catalog entries and policy come from the same completed prepared generation. */
type PreparedGatewayModelCatalog = {
entries: ModelCatalogEntry[];
pluginRegistry?: ProviderThinkingRegistry;
};
type GatewayModelCatalogSnapshot = ModelCatalogSnapshot & {
agentId: string;
agentDir: string;
catalogComplete: boolean;
workspaceDir: string;
config: OpenClawConfig;
};
//#endregion
//#region src/gateway/server-shared.d.ts
type DedupeEntry = {
ts: number;
ok: boolean;
/** Optional effectful-request fingerprint for methods with caller-supplied operation ids. */
requestIdentity?: string;
payload?: unknown;
error?: ErrorShape;
};
//#endregion
//#region src/gateway/server/event-loop-health.d.ts
type GatewayEventLoopHealthReason = "event_loop_delay" | "event_loop_utilization" | "cpu";
type GatewayEventLoopHealth = {
degraded: boolean;
degradedSinceMs: number | null;
reasons: GatewayEventLoopHealthReason[];
intervalMs: number;
delayP99Ms: number;
delayMaxMs: number;
utilization: number;
cpuCoreRatio: number;
};
//#endregion
//#region src/gateway/terminal/launch.d.ts
/** Why a terminal cannot open, or `null` when it can. */
type TerminalLaunchBlock = {
kind: "disabled";
} | {
kind: "owner-required";
message: string;
} | {
kind: "unknown-agent";
agentId: string;
} | {
kind: "sandboxed";
agentId: string;
mode: "all";
};
/** Resolved plan for a host terminal session. */
type TerminalLaunchPlan = {
agentId: string;
cwd: string;
shell: string;
args: string[];
initialCommand?: string[];
cwdOverride?: string;
};
/** Terminal launch resolution result: either a runnable plan or a block reason. */
type TerminalLaunchResolution = {
ok: true;
plan: TerminalLaunchPlan;
} | {
ok: false;
block: TerminalLaunchBlock;
};
//#endregion
//#region src/infra/terminal-file-upload.d.ts
type TerminalUploadFile = {
name: string;
contentBase64: string;
};
type TerminalUploadResult = {
path: string;
size: number;
};
//#endregion
//#region src/process/terminal-pty.d.ts
/** Live PTY handle shared by gateway terminals and node-host commands. */
type TerminalPtyHandle = {
pid: number;
write(data: string): void;
resize(cols: number, rows: number): void;
pause(): void;
resume(): void;
onData(listener: (chunk: string) => void): void;
onExit(listener: (event: {
exitCode: number;
signal?: number;
}) => void): void;
kill(signal?: string): void;
};
declare function spawnTerminalPty(params: {
file: string;
args: string[];
cwd?: string;
env: Record<string, string>;
cols: number;
rows: number;
}): Promise<TerminalPtyHandle>;
//#endregion
//#region src/gateway/terminal/backend.d.ts
type TerminalBackendExit = {
exitCode?: number;
signal?: number;
error?: string;
};
interface TerminalBackend {
write(data: string): void;
resize(cols: number, rows: number): void;
pause(): void;
resume(): void;
kill(): void;
onData(callback: (data: string) => void): void;
onExit(callback: (exit: TerminalBackendExit) => void): void;
}
type LocalTerminalBackendSpawner = typeof spawnTerminalPty;
//#endregion
//#region src/gateway/terminal/session-manager.types.d.ts
type TerminalEventSink = (connId: string, event: string, payload: unknown) => void;
type AgentTerminalOwner = {
kind: "agent";
agentSessionKey: string;
agentSessionId: string;
agentId: string;
};
type TerminalOwner = {
kind: "conn";
connId: string;
} | AgentTerminalOwner;
type AgentTerminalSessionDrain = {
drained: Promise<void>;
hasWork(): boolean;
release(): void;
};
type TerminalSessionManagerOptions = {
emit: TerminalEventSink;
getBufferedAmount?: (connId: string) => number | undefined;
spawn?: LocalTerminalBackendSpawner;
maxSessions?: number;
env?: NodeJS.ProcessEnv;
/** Detach grace; 0 preserves kill-on-disconnect. Gateway wiring owns its default. */
detachGraceMs?: number;
maxDetachedSessions?: number;
scrollbackChars?: number;
};
type TerminalOpenRequest = {
owner: TerminalOwner;
/** Operator connection initially viewing an agent-owned session. */
viewerConnId?: string;
agentId: string;
cwd: string;
shell: string;
title?: string;
args: string[];
cols: number;
rows: number;
env: Record<string, string>;
/** Request-scoped cancellation; a late backend is killed before registration. */
signal?: AbortSignal;
createBackend?: () => Promise<TerminalBackend>;
stageUpload?: (file: TerminalUploadFile) => Promise<TerminalUploadResult>;
};
type TerminalOpenOutcome = {
ok: true;
sessionId: string;
agentId: string;
cwd: string;
shell: string;
} | {
ok: false;
code: "limit" | "spawn_failed" | "closed";
message: string;
};
type TerminalAgentActionOutcome = {
ok: true;
} | {
ok: false;
code: "session_unavailable" | "backend_failed";
};
//#endregion
//#region src/gateway/terminal/session-types.d.ts
type TerminalSessionSummary = {
sessionId: string;
agentId: string;
shell: string;
title?: string;
cwd: string;
attached: boolean;
owner: "conn" | `agent:${string}`;
createdAtMs: number;
};
type TerminalAttachSummary = Omit<TerminalSessionSummary, "attached" | "createdAtMs"> & {
buffer: string;
seq: number;
};
//#endregion
//#region src/gateway/terminal/session-manager.d.ts
/**
* Tracks live PTY sessions keyed by session id, with a reverse index for
* connection owners and viewers so disconnect cleanup stays bounded.
*/
declare class TerminalSessionManager {
private readonly sessions;
private readonly pendingOpens;
private readonly agentSessionDrain;
private readonly connections;
private readonly emit;
private readonly getBufferedAmount;
private readonly spawn?;
private readonly maxSessions;
private detachGraceMs;
private readonly maxDetachedSessions;
private readonly scrollbackChars;
private opening;
private spawning;
constructor(options: TerminalSessionManagerOptions);
/** Number of live sessions; used by tests and health surfaces. */
get size(): number;
/** Spawns a shell and wires its output/exit to its live connection recipients. */
open(request: TerminalOpenRequest): Promise<TerminalOpenOutcome>;
/** Writes client input to a session; returns false when the session is gone. */
write(connId: string, sessionId: string, data: string): boolean;
/** Writes agent input after proving exact agent-session ownership. */
writeAgent(owner: AgentTerminalOwner, sessionId: string, data: string): TerminalAgentActionOutcome;
private writeSession;
/** Applies a new PTY grid size; returns false when the session is gone. */
resize(connId: string, sessionId: string, cols: number, rows: number): boolean;
/** Resizes an agent-owned PTY after proving exact agent-session ownership. */
resizeAgent(owner: AgentTerminalOwner, sessionId: string, cols: number, rows: number): TerminalAgentActionOutcome;
private resizeSession;
/** Stages a file on the same host as an owned terminal session. */
upload(connId: string, sessionId: string, file: TerminalUploadFile): Promise<TerminalUploadResult | undefined>;
/** Closes one session on operator request. */
close(connId: string, sessionId: string): boolean;
/** Closes an agent-owned PTY after proving session-key ownership. */
closeAgent(owner: AgentTerminalOwner, sessionId: string): TerminalAgentActionOutcome;
/** Closes every live or spawning PTY bound to one exact terminal task. */
closeTaskSessions(taskId: string): number;
/** Fences and closes one durable agent-session incarnation through archive commit. */
beginAgentSessionDrain(owner: AgentTerminalOwner): AgentTerminalSessionDrain;
/**
* Rebinds a connection-owned session, or co-attaches a viewer to an
* agent-owned session. Operator-to-operator attach remains take-over; only
* agent-owned sessions gain shared viewers.
*/
attach(connId: string, sessionId: string): TerminalAttachSummary | undefined;
/** Every live session, oldest first; all admin connections see the same list. */
list(): TerminalSessionSummary[];
/** Raw buffered output for one session, or undefined when it is gone. */
snapshot(sessionId: string): string | undefined;
/** Raw buffer for an agent-owned session, guarded by the caller session key. */
snapshotAgent(owner: AgentTerminalOwner, sessionId: string): string | undefined;
/** Live sessions owned by one agent tool caller. */
listAgent(owner: AgentTerminalOwner): TerminalSessionSummary[];
private trackPendingOpen;
private hasAgentSessionWork;
private resolveAgentSessionDrainIfIdle;
private openAbortMessage;
private untrackPendingOpen;
/**
* Handles a dropped connection: detaches its sessions for later reattach
* when a grace period is configured, otherwise kills them (legacy behavior,
* still selected by detachedSessionTimeoutSeconds: 0).
*/
handleDisconnect(connId: string): void;
/** Closes live and pending sessions whose agent no longer permits a host shell. */
closeDisallowedAgents(isAllowed: (agentId: string) => boolean): void;
/** Parks a session ownerless with a reaper; PTY output keeps buffering. */
private detach;
updateDetachGraceMs(graceMs: number): void;
private scheduleDetachedExpiry;
private enforceDetachedCap;
/** Tears down all sessions silently on Gateway shutdown; their sockets are closing too. */
disposeAll(): void;
/**
* Claims the longest-idle agent-owned session as an eviction candidate when
* the pool is exhausted. Viewer-attached and connection-owned sessions are
* never evicted; an idle viewer-free background job losing its PTY under
* pressure is the accepted tradeoff for keeping the pool available. Claimed
* sessions are skipped so concurrent opens select distinct victims.
*/
private claimLongestIdleAgentSession;
private removeViewer;
private interactiveSession;
/** Agents may operate only PTYs created by their exact trusted session key. */
private agentOwnedSession;
private finalize;
}
//#endregion
//#region src/gateway/worker-environments/placement-projector.d.ts
type WorkerSessionPlacementReader = {
getMany(sessionIds: readonly string[]): ReadonlyMap<string, WorkerSessionPlacementRecord>;
/** Runtime consumers may cancel work when the exact captured turn claim closes. */
registerTurnClaimClosedHandler?: (handler: (claim: WorkerSessionTurnClaim) => void) => () => void;
getPlacementMoves?(sessionIds: readonly string[]): ReadonlyMap<string, WorkerPlacementMoveIntent>;
};
type WorkerPlacementDiskSpaceReader = {
read(record: WorkerSessionPlacementRecord): SessionPlacementDiskSpace | undefined;
version(): number;
};
type WorkerPlacementRunnerAvailabilityReader = {
read(record: WorkerSessionPlacementRecord): SessionPlacementRunner | undefined;
version(): number;
};
//#endregion
//#region src/gateway/server-methods/chat-metadata-contract.d.ts
type ChatMetadataSessionEntry = Partial<Pick<SessionEntry$1, "sessionId" | "agentHarnessId" | "modelSelectionLocked" | "pluginOwnerId" | "providerOverride" | "modelOverride" | "authProfileOverride" | "authProfileOverrideSource" | "authProfileOverrideCompactionCount">>;
type ChatMetadataReadParams = {
agentId: string;
sessionKey?: string;
requesterProfileId?: string;
sessionEntry?: ChatMetadataSessionEntry;
draftAccountSelection?: UserModelAccountSelection;
};
type ChatMetadataResult = {
commands?: unknown[];
models?: unknown[];
swarmEnabled: boolean;
accountSelection?: ChatAccountSelection;
};
//#endregion
//#region src/gateway/server-methods/chat-startup-projection-contract.d.ts
type ChatStartupProjectionReadParams = {
agentId: string;
requesterProfileId?: string;
sessionKey?: string;
sessionEntry?: ChatMetadataSessionEntry;
readPolicy?: "current" | "ready";
};
type ChatStartupProjectionResult = {
metadata?: ChatMetadataResult;
sessionModelCatalog: ModelCatalogEntry[];
defaultModelCatalog: ModelCatalogEntry[];
};
//#endregion
//#region src/gateway/server-methods/shared-types.d.ts
/**
* Shared gateway request types used by every server-method module.
*/
type SubsystemLogger = ReturnType<typeof createSubsystemLogger>;
/** Minimal hosted OpenClaw contract retained by the gateway request router. */
/**
* Structural mirror of the engine's SystemAgentAssistantTurn. Kept local as a
* leaf contract: importing the assistant module here closes a madge cycle
* through the agents/config cluster.
*/
type SystemAgentHistoryTurn = {
role: "user" | "assistant";
text: string;
};
type GatewaySystemAgentSession = {
engine: {
handle: (message: string, options?: {
uiContext?: {
page: string;
};
}) => Promise<{
text: string;
action: "none" | "exit" | "open-tui" | "open-setup";
sensitive?: boolean;
question?: SystemAgentChatQuestion;
}>;
answerWizard: (answer: WizardAnswer) => Promise<{
text: string;
action: "none" | "exit" | "open-tui" | "open-setup";
sensitive?: boolean;
question?: SystemAgentChatQuestion;
}>;
cancelWizard: (cancel: SystemAgentWizardCancel) => Promise<{
text: string;
action: "none" | "exit" | "open-tui" | "open-setup";
sensitive?: boolean;
question?: SystemAgentChatQuestion;
}>;
decorateRejoinReply: (reply: {
text: string;
action: "none";
}) => {
text: string;
action: "none" | "exit" | "open-tui" | "open-setup";
sensitive?: boolean;
wizardInputPending?: boolean;
question?: SystemAgentChatQuestion;
step?: WizardStep;
};
noteAssistantMessage: (text: string) => void;
seedHistory: (turns: readonly SystemAgentHistoryTurn[]) => void;
historyLength: () => number;
historySince: (index: number) => SystemAgentHistoryTurn[];
getPendingOperatorProposal: () => {
operation: SystemAgentOperation;
hash: string;
} | null;
resolveOperatorApproval: (decision: "allow-once" | "allow-always" | "deny" | null, proposalHash: string, beforePersistentApply?: () => void, terminalStatus?: "expired" | "cancelled") => Promise<{
text: string;
action: "none" | "exit" | "open-tui" | "open-setup";
applied?: boolean;
} | null>;
dispose: () => Promise<void>;
};
welcome: string;
welcomeQuestion?: SystemAgentChatQuestion;
/** Audit cursor captured with the pending caretaker welcome; cleared after delivery. */
welcomeAuditSequence?: number;
lastUsedAt: number;
ownerKey: string;
pendingApproval?: {
id: string;
proposalHash: string;
completion: Promise<NonNullable<Awaited<ReturnType<GatewaySystemAgentSession["engine"]["resolveOperatorApproval"]>>>>;
};
};
/** Kernel-owned services and state that can be constructed without binding sockets. */
type GatewayKernelContext = {
deps: CliDeps;
/** Host-bound plugin ingress; the transport owns its shared hook dispatch queue. */
dispatchHookAgentTurn?: (pluginId: string, params: Parameters<PluginRuntimeCore["hooks"]["dispatchHookAgentTurn"]>[0]) => ReturnType<PluginRuntimeCore["hooks"]["dispatchHookAgentTurn"]>;
configRevisionProjector: GatewayConfigRevisionProjector;
cron: GatewayCronServiceContract;
cronStorePath: string;
getRuntimeConfig: () => OpenClawConfig;
/** Live reload owner, including same-config restart work and shutdown. */
isConfigReloadSettled: () => boolean;
/** Prepared listener certificate pin; undefined when Gateway TLS is disabled. */
gatewayTlsFingerprint?: string;
sessionCompanion?: SessionCompanionService;
sessionObserver?: SessionObserverService;
/** Temporary profile-owned mentions for this exact Gateway lifetime. */
mentionInbox?: MentionInbox;
resolveTerminalLaunchPolicy: (agentId?: string) => TerminalLaunchResolution;
isTerminalEnabled: () => boolean;
execApprovalManager?: ExecApprovalManager;
questionManager?: QuestionManager;
scopeUpgradeCoordinator?: ScopeUpgradeCoordinator;
/** Exact authority cancels bound approvals; legacy run ids cancel only unbound exec requests. */
cancelRunBoundApprovals?: (target: string | AgentRunDelegatedAuthority) => number;
pluginApprovalManager?: ExecApprovalManager<PluginApprovalRequestPayload>;
placementStandingGrants?: PlacementStandingGrantRuntime;
systemAgentApprovalManager?: ExecApprovalManager<SystemAgentApprovalRequestPayload>;
forwardPluginApprovalRequest?: (request: PluginApprovalRequest$1) => Promise<boolean>;
approvalWebPushDelivery?: {
handleRequested: <TPayload>(record: ExecApprovalRecord<TPayload>) => boolean | Promise<boolean>;
handleResolved: (resolved: {
id: string;
}) => Promise<void>;
handleExpired: (request: {
id: string;
}) => Promise<void>;
};
pluginApprovalIosPushDelivery?: {
handleRequested?: (request: PluginApprovalRequest$1, opts?: {
isTargetVisible?: (target: {
deviceId: string;
scopes: readonly string[];
}) => boolean;
}) => Promise<boolean>;
handleExpired?: (request: PluginApprovalRequest$1) => Promise<void>;
};
listSessionPendingApprovals?: (sessionKey: string, client: GatewayClient | null) => SessionApprovalReplay;
loadGatewayModelCatalog: (params?: {
agentId?: string;
agentDir?: string;
readOnly?: boolean;
workspaceDir?: string;
}) => Promise<ModelCatalogEntry[]>;
loadGatewayModelCatalogSnapshot: (params?: {
agentId?: string;
agentDir?: string;
readOnly?: boolean;
workspaceDir?: string;
}) => Promise<GatewayModelCatalogSnapshot>;
readPreparedGatewayModelCatalog?: (params?: {
agentId?: string;
agentDir?: string;
workspaceDir?: string;
}) => Promise<PreparedGatewayModelCatalog | undefined>;
readChatMetadata: (params: ChatMetadataReadParams) => Promise<ChatMetadataResult>;
readChatStartupProjection?: (params: ChatStartupProjectionReadParams) => Promise<ChatStartupProjectionResult | undefined>;
getHealthCache: () => HealthSummary | null;
logHealth: {
error: (message: string) => void;
};
logGateway: SubsystemLogger;
incrementPresenceVersion: () => number;
getHealthVersion: () => number;
/** Instance-local native approval subscribers; never derived from a network client. */
approvalEvents?: GatewayApprovalEventPublisher;
recoveryRuntime?: GatewayRecoveryRuntime;
/** Uses the lifecycle owner's module graph for plugin and detached agent turns. */
createAgentTurnFacade?: InternalAgentTurnFacadeFactory;
enforceSharedGatewayAuthGenerationForConfigWrite?: (nextConfig: OpenClawConfig) => void;
nodeRegistry: NodeRegistry;
agentRunSeq: Map<string, number>;
chatAbortControllers: Map<string, ChatAbortControllerEntry>;
/** Cancel identities for turns waiting in the followup/collect queue. */
chatQueuedTurns: Map<string, QueuedChatTurnEntry>;
chatRunState: ChatRunState;
addChatRun: (sessionId: string, entry: ChatRunRegistration) => void;
removeChatRun: (sessionId: string, clientRunId: string, sessionKey?: string) => ChatRunEntry | undefined;
dedupe: Map<string, DedupeEntry>;
wizardSessions: Map<string, WizardSession>;
systemAgentSessions: Map<string, GatewaySystemAgentSession>;
findRunningWizard: () => string | null;
purgeWizardSession: (id: string) => void;
wizardRunner: (opts: OnboardOptions, runtime: RuntimeEnv, prompter: WizardPrompter) => Promise<void>;
channelWizardRunner: ChannelSetupWizardRunner;
unavailableGatewayMethods?: ReadonlySet<string>;
};
/** Socket-bound services and connection state supplied by the Gateway transports. */
type GatewayTransportContext = {
portalService?: GatewayPortalService;
getMcpAppSandboxPort?: () => number | undefined;
ensureSandboxHostPort?: () => Promise<number>;
broadcast: GatewayBroadcastFn;
broadcastToConnIds: GatewayBroadcastToConnIdsFn;
getClientConnIds?: (filter?: (client: GatewayClient) => boolean) => ReadonlySet<string>;
nodeSendToSession: (sessionKey: string, event: string, payload: unknown) => void;
nodeSendToAllSubscribed: (event: string, payload: unknown) => void;
nodeSubscribe: (nodeId: string, sessionKey: string, connId?: string) => void;
nodeUnsubscribe: (nodeId: string, sessionKey: string, connId?: string) => void;
nodeUnsubscribeAll: (nodeId: string) => void;
hasConnectedTalkNode: () => Promise<boolean>;
isConnectionActive?: (connId: string) => boolean;
/** Server-stamped activity from an accepted request on the exact live person connection. */
recordClientActivity?: (client: GatewayClient | null) => void;
hasExecApprovalClients?: (excludeConnId?: string) => boolean;
getApprovalClientConnIds?: <TPayload>(params?: {
approvalKind?: "exec" | "plugin" | "system-agent";
excludeConnId?: string;
filter?: (client: GatewayClient, record?: ExecApprovalRecord<TPayload>) => boolean;
record?: ExecApprovalRecord<TPayload>;
}) => ReadonlySet<string>;
disconnectClientsForDevice?: (deviceId: string, opts?: {
role?: string;
}) => void;
disconnectClientsForUserProfile?: (profileId: string) => void;
invalidateClientsForDevice?: (deviceId: string, opts?: {
role?: string;
reason?: string;
}) => void;
hasConnectedClientsForDevice?: (deviceId: string) => boolean;
refreshConnectedUserProfile?: (profile: {
id: string;
displayName: string | null;
avatarRevision: string;
hasAvatar: boolean;
updatedAt: number;
}) => void;
disconnectClientsUsingSharedGatewayAuth?: () => void;
terminalSessions?: TerminalSessionManager;
subscribeSessionEvents: (connId: string) => void;
unsubscribeSessionEvents: (connId: string) => void;
subscribeSessionMessageEvents: (connId: string, sessionKey: string, opts?: {
includeApprovals?: boolean;
provisional?: boolean;
}) => ((() => void) & {
commit: () => void;
}) | undefined;
unsubscribeSessionMessageEvents: (connId: string, sessionKey: string) => void;
unsubscribeAllSessionEvents: (connId: string) => void;
getSessionEventSubscriberConnIds: () => ReadonlySet<string>;
registerToolEventRecipient: (runId: string, connId: string) => void;
};
/** Resident-owned services bridged into request handling by the server lifecycle. */
type GatewayResidentBridgeContext = {
getGatewayMethodRegistry?: () => GatewayMethodRegistry;
controlUiSessionPullRequests?: ReturnType<typeof createControlUiSessionPullRequestSubscriptions>;
sessionViewerPresence?: ReturnType<typeof createSessionViewerPresenceDeclarations>;
notifyPluginMetadataChanged: () => void;
refreshHealthSnapshot: (opts?: {
probe?: boolean;
includeSensitive?: boolean;
}) => Promise<HealthSummary>;
/** Durable cloud-worker lifecycle; absent from lightweight in-process contexts. */
workerEnvironmentService?: WorkerEnvironmentServiceContract;
/** Gateway-host desktop acquisition and observation; present only after enabled startup. */
hostDesktopService?: HostDesktopService;
/** Durable per-session worker placement; absent only from lightweight in-process contexts. */
workerSessionPlacementService?: WorkerSessionPlacementReader & Partial<WorkerSessionPlacementRetirementService>;
/** Process-local health samples fenced to the exact active placement owner. */
workerPlacementDiskSpaceReader?: WorkerPlacementDiskSpaceReader;
/** Process-current paired-device runner proof for active placement projection. */
workerPlacementRunnerAvailabilityReader?: WorkerPlacementRunnerAvailabilityReader;
/** Use-time approval authority validation over the live run/worker owners. */
validateAgentRuntimeApprovalAuthority?: AgentRuntimeApprovalAuthorityValidator;
/** One-way local-to-worker dispatch; absent when cloud workers are disabled. */
workerPlacementDispatchService?: WorkerPlacementDispatchContract;
githubPublicationService?: GitHubPublicationCoordinator;
githubOAuthService?: ReturnType<typeof createGitHubOAuthLifecycle>;
modelAccountConnectService?: ReturnType<typeof createModelAccountConnectService>;
getRuntimeSnapshot: () => ChannelRuntimeSnapshot;
getEventLoopHealth?: () => GatewayEventLoopHealth | undefined;
getConfigReloaderHotReloadStatus?: () => GatewayHotReloadStatus | undefined;
startChannel: (channel: ChannelId$1, accountId?: string, opts?: StartChannelOptions) => Promise<ReadonlyMap<string, ChannelAccountStartOutcome>>;
stopChannel: (channel: ChannelId$1, accountId?: string) => Promise<void>;
markChannelLoggedOut: (channelId: ChannelId$1, cleared: boolean, accountId?: string) => void;
broadcastVoiceWakeChanged: (triggers: string[]) => void;
broadcastVoiceWakeRoutingChanged: (config: VoiceWakeRoutingConfig) => void;
};
/** Complete runtime context available to gateway request handlers. */
type GatewayContextResolver = () => GatewayRequestContext | undefined;
type GatewayRequestContext = GatewayKernelContext & GatewayTransportContext & GatewayResidentBridgeContext & {
/** Retains original execution while callers may receive an early response. */
trackExecution: typeof trackAsyncWork;
/** Local commands can dispatch methods without owning a Gateway server. */
localEmbedded?: true;
/** Live instance routing only; never authorization or wire state. */
resolveGatewayContext?: GatewayContextResolver;
hostLifecycle?: GatewayHostLifecycle;
/** Entry-only access; the kernel owns closure. Absent in embedded-only contexts. */
requestEntryLifetime?: Pick<GatewayRequestEntryLifetime, "enter" | "signal">;
};
/** Full dispatch context for raw request frames before params are normalized. */
type GatewayRequestOptions = {
req: RequestFrame;
client: GatewayClient | null;
isWebchatConnect: (params: ConnectParams | null | undefined) => boolean;
respond: RespondFn;
context: GatewayRequestContext;
methodRegistry?: GatewayMethodRegistryView;
/** In-process Gateway lifetime guard composed into durable session mutations. */
sessionMutationCommitGuard?: () => void;
/** In-process caller lifetime; never serialized into a Gateway request frame. */
signal?: AbortSignal;
};
/** Commit-time guard captured by the pre-dispatch session participation check. */
type SessionMutationAuthorization = {
talkSessionTarget?: PreparedTalkSessionTarget;
assertCurrent: () => void;
assertTargetCurrent: (target: {
sessionKey: string;
agentId?: string;
/** Internal ensure result: may materialize a previously id-less Talk target, never replace it. */
ensuredSessionId?: string;
}) => void;
};
/** Normalized method invocation options passed to registered handlers. */
type GatewayRequestHandlerOptions = {
req: RequestFrame;
params: Record<string, unknown>;
client: GatewayClient | null;
isWebchatConnect: (params: ConnectParams | null | undefined) => boolean;
respond: RespondFn;
context: GatewayRequestContext;
sessionMutationCommitGuard?: () => void;
sessionMutationAuthorization?: SessionMutationAuthorization;
/** In-process caller lifetime; absent for ordinary transport requests. */
signal?: AbortSignal;
};
/** Single gateway method implementation. */
type GatewayRequestHandler = (opts: GatewayRequestHandlerOptions) => Promise<void> | void;
/** Registry fragment keyed by gateway protocol method name. */
type GatewayRequestHandlers = Record<string, GatewayRequestHandler>;
//#endregion
//#region src/tasks/detached-task-runtime-contract.d.ts
type DetachedTaskCreateParams = {
runtime: TaskRuntime;
taskKind?: string;
sourceId?: string;
requesterSessionKey?: string;
ownerKey?: string;
scopeKind?: TaskScopeKind;
requesterOrigin?: TaskDeliveryState["requesterOrigin"];
parentFlowId?: string;
childSessionKey?: string;
parentTaskId?: string;
agentId?: string;
requesterAgentId?: string;
runId?: string;
label?: string;
task: string;
preferMetadata?: boolean;
notifyPolicy?: TaskNotifyPolicy;
deliveryStatus?: TaskDeliveryStatus;
detail?: JsonValue;
};
type DetachedRunningTaskCreateParams = DetachedTaskCreateParams & {
startedAt?: number;
lastEventAt?: number;
progressSummary?: string | null;
};
type DetachedTaskStartParams = {
runId: string;
runtime?: TaskRuntime;
sessionKey?: string;
startedAt?: number;
lastEventAt?: number;
progressSummary?: string | null;
eventSummary?: string | null;
};
type DetachedTaskProgressParams = {
runId: string;
runtime?: TaskRuntime;
sessionKey?: string;
lastEventAt?: number;
progressSummary?: string | null;
eventSummary?: string | null;
};
type DetachedTaskFinalizeCommonParams = {
runId: string;
runtime?: TaskRuntime;
sessionKey?: string;
childSessionKey?: string | null;
endedAt: number;
lastEventAt?: number;
progressSummary?: string | null;
terminalSummary?: string | null;
preserveTerminalSummary?: boolean;
detail?: JsonValue;
suppressDelivery?: boolean;
};
type DetachedTaskCompleteParams = DetachedTaskFinalizeCommonParams & {
terminalOutcome?: TaskTerminalOutcome | null;
};
type DetachedTaskFailParams = DetachedTaskFinalizeCommonParams & {
status?: Extract<TaskStatus, "failed" | "timed_out" | "cancelled">;
error?: string;
};
type DetachedTaskFinalizeParams = DetachedTaskFinalizeCommonParams & {
status: Extract<TaskStatus, "succeeded" | "failed" | "timed_out" | "cancelled">;
error?: string;
clearError?: boolean;
terminalOutcome?: TaskTerminalOutcome | null;
};
type DetachedTaskDeliveryStatusParams = {
runId: string;
runtime?: TaskRuntime;
sessionKey?: string;
deliveryStatus: TaskDeliveryStatus;
error?: string;
};
type DetachedTaskCancelParams = {
cfg: OpenClawConfig;
taskId: string;
reason?: string;
};
type DetachedTaskCancelResult = {
found: boolean;
cancelled: boolean;
reason?: string;
task?: TaskRecord;
};
type DetachedTaskRecoveryAttemptParams = {
taskId: string;
runtime: TaskRuntime;
task: TaskRecord;
now: number;
};
type DetachedTaskRecoveryAttemptResult = {
recovered: boolean;
};
type DetachedTaskFindParams = {
runId: string;
runtime: TaskRuntime;
sessionKey: string;
createdAtOrAfter: number;
createdBefore?: number;
allowSessionFallback?: boolean;
};
type DetachedTaskLifecycleRuntime = {
createQueuedTaskRun: (params: DetachedTaskCreateParams) => TaskRecord | null;
createRunningTaskRun: (params: DetachedRunningTaskCreateParams) => TaskRecord | null;
startTaskRunByRunId: (params: DetachedTaskStartParams) => TaskRecord[];
recordTaskRunProgressByRunId: (params: DetachedTaskProgressParams) => TaskRecord[];
finalizeTaskRunByRunId?: (params: DetachedTaskFinalizeParams) => TaskRecord[];
completeTaskRunByRunId: (params: DetachedTaskCompleteParams) => TaskRecord[];
failTaskRunByRunId: (params: DetachedTaskFailParams) => TaskRecord[];
setDetachedTaskDeliveryStatusByRunId: (params: DetachedTaskDeliveryStatusParams) => TaskRecord[];
/**
* Resolve the task owned by one run generation. Custom runtimes should
* implement this when their records are not mirrored into core task state.
*/
findTaskRun?: (params: DetachedTaskFindParams) => TaskRecord | undefined;
/**
* Return `found: false` when this runtime does not own the task so core can
* fall back to the legacy detached-task cancel path.
*/
cancelDetachedTaskRunById: (params: DetachedTaskCancelParams) => Promise<DetachedTaskCancelResult>;
/**
* Give a registered detached runtime one last chance to recover a stale task
* before core marks it lost during maintenance.
*/
tryRecoverTaskBeforeMarkLost?: (params: DetachedTaskRecoveryAttemptParams) => DetachedTaskRecoveryAttemptResult | Promise<DetachedTaskRecoveryAttemptResult>;
};
type DetachedTaskLifecycleRuntimeRegistration = {
pluginId: string;
runtime: DetachedTaskLifecycleRuntime;
};
//#endregion
//#region src/plugins/agent-tool-result-middleware-types.d.ts
type OpenClawAgentToolResult<TResult = unknown> = AgentToolResult<TResult>;
type AgentToolResultMiddlewareRuntime = "openclaw" | "codex";
type AgentToolResultMiddlewareEvent = {
threadId?: string;
turnId?: string;
toolCallId: string;
toolName: string;
args: Record<string, unknown>;
cwd?: string;
isError?: boolean;
result: OpenClawAgentToolResult;
};
type AgentToolResultMiddlewareContext = {
runtime: AgentToolResultMiddlewareRuntime;
agentId?: string;
sessionId?: string;
sessionKey?: string;
runId?: string;
};
type AgentToolResultMiddlewareResult = {
result: OpenClawAgentToolResult;
};
type AgentToolResultMiddleware = (event: AgentToolResultMiddlewareEvent, ctx: AgentToolResultMiddlewareContext) => Promise<AgentToolResultMiddlewareResult | void> | AgentToolResultMiddlewareResult | void;
type AgentToolResultMiddlewareOptions = {
matcher?: PluginToolMatcher;
runtimes?: AgentToolResultMiddlewareRuntime[];
};
type AgentToolResultMiddlewareScope = {
matcher?: PluginToolMatcher;
runtimes: AgentToolResultMiddlewareRuntime[];
};
//#endregion
//#region src/plugins/codex-app-server-extension-types.d.ts
/** Tool-result event emitted to Codex app-server plugin extensions. */
type CodexAppServerToolResultEvent = {
threadId: string;
turnId: string;
toolCallId: string;
toolName: string;
args: Record<string, unknown>;
result: AgentToolResult<unknown>;
};
/** Session context passed with Codex app-server extension events. */
type CodexAppServerExtensionContext = {
agentId?: string;
sessionId?: string;
sessionKey?: string;
runId?: string;
};
/** Optional replacement result returned by a Codex app-server extension handler. */
type CodexAppServerToolResultHandlerResult = {
result: AgentToolResult<unknown>;
};
/** Runtime event surface exposed to Codex app-server extension factories. */
type CodexAppServerExtensionRuntime = {
on: (event: "tool_result", handler: (event: CodexAppServerToolResultEvent, ctx: CodexAppServerExtensionContext) => Promise<CodexAppServerToolResultHandlerResult | void> | CodexAppServerToolResultHandlerResult | void) => void;
};
/** Factory signature for Codex app-server plugin extensions. */
type CodexAppServerExtensionFactory = (runtime: CodexAppServerExtensionRuntime) => Promise<void> | void;
//#endregion
//#region src/plugins/config-activation-shared.d.ts
type PluginActivationSource = "disabled" | "explicit" | "auto" | "default";
//#endregion
//#region src/plugins/registry-types.d.ts
type ChannelPlugin$1 = ChannelPlugin$3;
type CliBackendPlugin$1 = CliBackendPlugin;
type ImageGenerationProviderPlugin = ImageGenerationProviderPlugin$1;
type MediaUnderstandingProviderPlugin = MediaUnderstandingProviderPlugin$1;
type TranscriptSourceProvider = TranscriptSourceProvider$1;
type MusicGenerationProviderPlugin = MusicGenerationProviderPlugin$1;
type OpenClawPluginCliRootCommandDescriptor = OpenClawPluginCliRootCommandDescriptor$1;
type OpenClawPluginCliRegistrar = OpenClawPluginCliRegistrar$1;
type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition$1;
type PluginInteractiveHandlerRegistration = PluginInteractiveHandlerRegistration$1;
type OpenClawPluginGatewayRuntimeScopeSurface = OpenClawPluginGatewayRuntimeScopeSurface$1;
type OpenClawGatewayDiscoveryService = OpenClawGatewayDiscoveryService$1;
type OpenClawPluginHttpRouteHandler = OpenClawPluginHttpRouteHandler$1;
type OpenClawPluginHttpRouteMatch = OpenClawPluginHttpRouteMatch$1;
type OpenClawPluginHostedMediaResolver = OpenClawPluginHostedMediaResolver$1;
type OpenClawPluginReloadRegistration = OpenClawPluginReloadRegistration$1;
type OpenClawPluginSecurityAuditCollector = OpenClawPluginSecurityAuditCollector$1;
type OpenClawPluginService = OpenClawPluginService$1;
type OpenClawPluginToolFactory = OpenClawPluginToolFactory$1;
type PluginConversationBindingResolvedEvent = PluginConversationBindingResolvedEvent$1;
type TypedPluginHookRegistration = PluginHookRegistration$1;
type PluginOrigin = PluginOrigin$1;
type PluginTextTransformRegistration$1 = PluginTextTransformRegistration;
type MigrationProviderPlugin = MigrationProviderPlugin$1;
type ProviderPlugin = ProviderPlugin$1;
type RealtimeTranscriptionProviderPlugin = RealtimeTranscriptionProviderPlugin$1;
type RealtimeVoiceProviderPlugin = RealtimeVoiceProviderPlugin$1;
type SpeechProviderPlugin = SpeechProviderPlugin$1;
type VideoGenerationProviderPlugin = VideoGenerationProviderPlugin$1;
type WebFetchProviderPlugin = WebFetchProviderPlugin$1;
type WebSearchProviderPlugin = WebSearchProviderPlugin$1;
type WorkerProvider = WorkerProvider$1;
type UnifiedModelCatalogProviderPlugin = UnifiedModelCatalogProviderPlugin$1;
/** Agent tool factory registered by one plugin runtime. */
type PluginToolRegistration = {
pluginId: string;
pluginName?: string;
factory: OpenClawPluginToolFactory;
names: string[];
declaredNames?: string[];
optional: boolean;
/** Loader-owned provenance. Missing values are conservative legacy registrations. */
origin?: PluginOrigin;
source: string;
rootDir?: string;
};
type PluginCliRegistration = {
pluginId: string;
pluginName?: string;
register: OpenClawPluginCliRegistrar;
parentPath: string[];
commands: string[];
descriptors: OpenClawPluginCliRootCommandDescriptor[];
source: string;
rootDir?: string;
};
/** Gateway HTTP route registered by a plugin runtime. */
type PluginHttpRouteRegistration = {
/** Retired ingress awaiting a lifecycle replacement; responds with Retry-After. */
handoff?: true;
pluginId?: string;
path: string;
handler: OpenClawPluginHttpRouteHandler;
handleUpgrade?: OpenClawPluginHttpRouteUpgradeHandler;
auth: OpenClawPluginHttpRouteAuth;
match: OpenClawPluginHttpRouteMatch;
gatewayRuntimeScopeSurface?: OpenClawPluginGatewayRuntimeScopeSurface;
gatewayMethodDispatchAllowed?: boolean;
nodeCapability?: {
surface: string;
ttlMs?: number;
};
source?: string;
};
type PluginHostedMediaResolverRegistration = {
pluginId: string;
pluginName?: string;
resolver: OpenClawPluginHostedMediaResolver;
source: string;
rootDir?: string;
};
type PluginChannelRegistration = {
pluginId: string;
pluginName?: string;
plugin: ChannelPlugin$1;
/** Exact record-bound runtime resolver captured when the active plugin registered the channel. */
resolveChannelRuntime?: () => PluginRuntime["channel"];
/** Loader-owned provenance. Missing values are conservative legacy registrations. */
origin?: PluginOrigin;
source: string;
rootDir?: string;
};
type PluginChannelSetupRegistration = {
pluginId: string;
pluginName?: string;
plugin: ChannelPlugin$1;
/** Loader-owned provenance. Missing values are conservative legacy registrations. */
origin?: PluginOrigin;
source: string;
enabled: boolean;
rootDir?: string;
};
type PluginProviderRegistration = {
pluginId: string;
pluginName?: string;
provider: ProviderPlugin;
source: string;
rootDir?: string;
};
type PluginModelCatalogProviderRegistration = {
pluginId: string;
pluginName?: string;
provider: UnifiedModelCatalogProviderPlugin;
source: string;
rootDir?: string;
};
type PluginSessionCatalogRegistration = {
pluginId: string;
pluginName?: string;
provider: SessionCatalogProvider;
source: string;
rootDir?: string;
};
type PluginDashboardDataBindingRegistration = PluginManifestDashboardDataBinding & {
pluginId: string;
capabilityId: string;
handler: GatewayRequestHandlers[string];
};
type PluginDashboardActionVerbRegistration = PluginManifestDashboardActionVerb & {
pluginId: string;
capabilityId: string;
handler: GatewayRequestHandlers[string];
};
type PluginBoardWidgetContentKindRegistration = {
pluginId: string;
pluginKind: string;
definition: PluginBoardWidgetContentKind;
};
type PluginCliBackendRegistration = {
pluginId: string;
pluginName?: string;
builtWithOpenClawVersion?: string;
backend: CliBackendPlugin$1;
source: string;
rootDir?: string;
};
type PluginTextTransformsRegistration = {
pluginId: string;
pluginName?: string;
transforms: PluginTextTransformRegistration$1;
source: string;
rootDir?: string;
};
type PluginOwnedProviderRegistration<T extends {
id: string;
}> = {
pluginId: string;
pluginName?: string;
provider: T;
source: string;
rootDir?: string;
};
type PluginSpeechProviderRegistration = PluginOwnedProviderRegistration<SpeechProviderPlugin>;
type PluginEmbeddingProviderRegistration = PluginOwnedProviderRegistration<EmbeddingProviderAdapter>;
type PluginRealtimeTranscriptionProviderRegistration = PluginOwnedProviderRegistration<RealtimeTranscriptionProviderPlugin>;
type PluginRealtimeVoiceProviderRegistration = PluginOwnedProviderRegistration<RealtimeVoiceProviderPlugin>;
type PluginMediaUnderstandingProviderRegistration = PluginOwnedProviderRegistration<MediaUnderstandingProviderPlugin>;
type PluginTranscriptsSourceProviderRegistration = PluginOwnedProviderRegistration<TranscriptSourceProvider>;
type PluginImageGenerationProviderRegistration = PluginOwnedProviderRegistration<ImageGenerationProviderPlugin>;
type PluginVideoGenerationProviderRegistration = PluginOwnedProviderRegistration<VideoGenerationProviderPlugin>;
type PluginMusicGenerationProviderRegistration = PluginOwnedProviderRegistration<MusicGenerationProviderPlugin>;
type PluginWebFetchProviderRegistration = PluginOwnedProviderRegistration<WebFetchProviderPlugin>;
type PluginWebSearchProviderRegistration = PluginOwnedProviderRegistration<WebSearchProviderPlugin>;
type PluginWorkerProviderRegistration = PluginOwnedProviderRegistration<WorkerProvider>;
type PluginMigrationProviderRegistration = PluginOwnedProviderRegistration<MigrationProviderPlugin>;
type PluginCodexAppServerExtensionFactoryRegistration = {
pluginId: string;
pluginName?: string;
rawFactory: CodexAppServerExtensionFactory;
factory: CodexAppServerExtensionFactory;
source: string;
rootDir?: string;
};
type PluginAgentToolResultMiddlewareRegistration = {
pluginId: string;
pluginName?: string;
rawHandler: AgentToolResultMiddleware;
handler: AgentToolResultMiddleware;
runtimes: AgentToolResultMiddlewareRuntime[];
scopes?: AgentToolResultMiddlewareScope[];
source: string;
rootDir?: string;
};
type PluginAgentToolResultMiddlewareOwner = {
pluginId: string;
runtimes: AgentToolResultMiddlewareRuntime[];
manifest: PluginManifestRecord;
};
type PluginAgentHarnessRegistration = {
pluginId: string;
pluginName?: string;
harness: AgentHarness;
nativeCompaction?: AgentHarnessNativeCompaction;
source: string;
rootDir?: string;
};
type PluginHookRegistration = {
pluginId: string;
entry: HookEntry;
events: string[];
source: string;
rootDir?: string;
};
type PluginServiceRegistration = {
pluginId: string;
pluginName?: string;
service: OpenClawPluginService;
source: string;
origin: PluginOrigin;
trustedOfficialInstall?: boolean;
rootDir?: string;
};
type PluginGatewayDiscoveryServiceRegistration = {
pluginId: string;
pluginName?: string;
service: OpenClawGatewayDiscoveryService;
source: string;
rootDir?: string;
};
type PluginReloadRegistration = {
pluginId: string;
pluginName?: string;
registration: OpenClawPluginReloadRegistration;
source: string;
rootDir?: string;
};
type PluginNodeHostCommandRegistration = {
pluginId: string;
pluginName?: string;
command: OpenClawPluginNodeHostCommand;
source: string;
rootDir?: string;
};
type PluginNodeInvokePolicyRegistration = {
pluginId: string;
pluginName?: string;
policy: OpenClawPluginNodeInvokePolicy;
pluginConfig?: Record<string, unknown>;
source: string;
rootDir?: string;
};
type PluginWidgetPresenterRegistration = {
pluginId: string;
pluginName?: string;
presenter: WidgetPresenter;
source: string;
rootDir?: string;
};
type PluginSecurityAuditCollectorRegistration = {
pluginId: string;
pluginName?: string;
collector: OpenClawPluginSecurityAuditCollector;
source: string;
rootDir?: string;
};
type PluginCommandRegistration = {
pluginId: string;
pluginName?: string;
command: OpenClawPluginCommandDefinition;
source: string;
rootDir?: string;
trustedOwnerStatusExposure?: true;
};
type PluginLegacyInternalHookRegistration = {
pluginId: string;
name: string;
event: string;
handler: InternalHookHandler;
};
type PluginSessionDiscussionRegistration = {
pluginId: string;
provider: SessionDiscussionProvider;
};
type PluginInteractiveHandlerRegistryRegistration = PluginInteractiveHandlerRegistration & {
pluginId: string;
pluginName?: string;
pluginRoot?: string;
};
type PluginSessionExtensionRegistryRegistration = {
pluginId: string;
pluginName?: string;
extension: PluginSessionExtensionRegistration;
source: string;
rootDir?: string;
};
type PluginTrustedToolPolicyRegistryRegistration = {
pluginId: string;
pluginName?: string;
policy: PluginTrustedToolPolicyRegistration;
origin?: PluginRecord["origin"];
source: string;
rootDir?: string;
};
type PluginToolMetadataRegistryRegistration = {
pluginId: string;
pluginName?: string;
metadata: PluginToolMetadataRegistration;
source: string;
rootDir?: string;
};
type PluginControlUiDescriptorRegistryRegistration = {
pluginId: string;
pluginName?: string;
descriptor: PluginControlUiDescriptor;
source: string;
rootDir?: string;
};
type PluginRuntimeLifecycleRegistryRegistration = {
pluginId: string;
pluginName?: string;
lifecycle: PluginRuntimeLifecycleRegistration;
source: string;
rootDir?: string;
};
type PluginAgentEventSubscriptionRegistryRegistration = {
pluginId: string;
pluginName?: string;
subscription: PluginAgentEventSubscriptionRegistration;
source: string;
rootDir?: string;
};
type PluginSessionSchedulerJobRegistryRegistration = {
pluginId: string;
pluginName?: string;
job: PluginSessionSchedulerJobRegistration;
generation?: number;
source: string;
rootDir?: string;
};
type PluginSessionActionRegistryRegistration = {
pluginId: string;
pluginName?: string;
action: PluginSessionActionRegistration;
source: string;
rootDir?: string;
};
type PluginConversationBindingResolvedHandlerRegistration = {
pluginId: string;
pluginName?: string;
pluginRoot?: string;
handler: (event: PluginConversationBindingResolvedEvent) => void | Promise<void>;
source: string;
rootDir?: string;
};
type PluginRecord = {
id: string;
name: string;
packageVersion?: string;
version?: string;
builtWithOpenClawVersion?: string;
packageName?: string;
description?: string;
format?: PluginFormat;
bundleFormat?: PluginBundleFormat;
bundleCapabilities?: string[];
kind?: PluginKind | PluginKind[];
source: string;
rootDir?: string;
origin: PluginOrigin;
workspaceDir?: string;
trustedOfficialInstall?: boolean;
trust?: PluginTrust;
enabled: boolean;
explicitlyEnabled?: boolean;
activated?: boolean;
imported?: boolean;
/** Families authoritatively supplied by a descriptor entry, including empty collections. */
capabilityCatalog?: Array<keyof PluginCapabilityCatalog>;
compat?: readonly PluginCompatCode[];
activationSource?: PluginActivationSource;
activationReason?: string;
status: "loaded" | "disabled" | "error";
error?: string;
failedAt?: Date;
failurePhase?: "validation" | "load" | "register";
toolNames: string[];
hookNames: string[];
channelIds: string[];
cliBackendIds: string[];
providerIds: string[];
syntheticAuthRefs?: string[];
embeddingProviderIds: string[];
speechProviderIds: string[];
realtimeTranscriptionProviderIds: string[];
realtimeVoiceProviderIds: string[];
mediaUnderstandingProviderIds: string[];
transcriptSourceProviderIds: string[];
imageGenerationProviderIds: string[];
videoGenerationProviderIds: string[];
musicGenerationProviderIds: string[];
webFetchProviderIds: string[];
webSearchProviderIds: string[];
migrationProviderIds: string[];
contextEngineIds?: string[];
agentHarnessIds: string[];
cliCommands: string[];
services: string[];
gatewayDiscoveryServiceIds: string[];
commands: string[];
commandAliases?: PluginManifestRecord["commandAliases"];
httpRoutes: number;
hookCount: number;
configSchema: boolean;
configUiHints?: Record<string, PluginConfigUiHint>;
configJsonSchema?: JsonSchemaObject;
contracts?: PluginManifestContracts;
dashboard?: PluginManifestDashboard;
controlUi?: PluginManifestControlUi;
mcpServers?: Record<string, PluginManifestMcpServer>;
memorySlotSelected?: boolean;
dependencyStatus?: PluginDependencyStatus;
};
type PluginRegistry = {
plugins: PluginRecord[];
tools: PluginToolRegistration[];
hooks: PluginHookRegistration[];
typedHooks: TypedPluginHookRegistration[];
channels: PluginChannelRegistration[];
channelSetups: PluginChannelSetupRegistration[];
providers: PluginProviderRegistration[];
modelCatalogProviders: PluginModelCatalogProviderRegistration[];
sessionCatalogs: PluginSessionCatalogRegistration[];
cliBackends: PluginCliBackendRegistration[];
textTransforms: PluginTextTransformsRegistration[];
embeddingProviders: PluginEmbeddingProviderRegistration[];
speechProviders: PluginSpeechProviderRegistration[];
realtimeTranscriptionProviders: PluginRealtimeTranscriptionProviderRegistration[];
realtimeVoiceProviders: PluginRealtimeVoiceProviderRegistration[];
mediaUnderstandingProviders: PluginMediaUnderstandingProviderRegistration[];
transcriptSourceProviders: PluginTranscriptsSourceProviderRegistration[];
imageGenerationProviders: PluginImageGenerationProviderRegistration[];
videoGenerationProviders: PluginVideoGenerationProviderRegistration[];
musicGenerationProviders: PluginMusicGenerationProviderRegistration[];
webFetchProviders: PluginWebFetchProviderRegistration[];
webSearchProviders: PluginWebSearchProviderRegistration[];
workerProviders: Map<string, PluginWorkerProviderRegistration>;
migrationProviders: PluginMigrationProviderRegistration[];
codexAppServerExtensionFactories: PluginCodexAppServerExtensionFactoryRegistration[];
agentToolResultMiddlewareOwners: PluginAgentToolResultMiddlewareOwner[];
agentToolResultMiddlewares: PluginAgentToolResultMiddlewareRegistration[];
agentHarnesses: PluginAgentHarnessRegistration[];
pluginRuntimeArtifacts: Map<string, ResolvedPluginRuntimeArtifact>;
compactionProviders: RegisteredCompactionProvider[];
detachedTaskRuntimes: DetachedTaskLifecycleRuntimeRegistration[];
legacyInternalHooks: PluginLegacyInternalHookRegistration[];
memoryCapabilities: MemoryPluginCapabilityRegistration[];
memoryCorpusSupplements: MemoryCorpusSupplementRegistration[];
memoryPromptPreparations: MemoryPromptPreparationRegistration[];
memoryPromptSupplements: MemoryPromptSupplementRegistration[];
sessionDiscussionProviders: Map<string, PluginSessionDiscussionRegistration>;
contextEngines: Map<string, ContextEngineRegistration>;
gatewayHandlers: GatewayRequestHandlers;
gatewayMethodDescriptors: GatewayMethodDescriptor[];
dashboardDataBindings: Map<string, PluginDashboardDataBindingRegistration>;
dashboardActionVerbs: Map<string, PluginDashboardActionVerbRegistration>;
boardWidgetContentKinds: Map<string, PluginBoardWidgetContentKindRegistration>;
coreGatewayMethodNames: string[];
httpRoutes: PluginHttpRouteRegistration[];
hostedMediaResolvers: PluginHostedMediaResolverRegistration[];
widgetPresenters: PluginWidgetPresenterRegistration[];
mcpServerConnectionResolvers: PluginMcpServerConnectionResolverRegistration[];
cliRegistrars: PluginCliRegistration[];
reloads: PluginReloadRegistration[];
nodeHostCommands: PluginNodeHostCommandRegistration[];
nodeInvokePolicies: PluginNodeInvokePolicyRegistration[];
securityAuditCollectors: PluginSecurityAuditCollectorRegistration[];
services: PluginServiceRegistration[];
gatewayDiscoveryServices: PluginGatewayDiscoveryServiceRegistration[];
commands: PluginCommandRegistration[];
interactiveHandlers: PluginInteractiveHandlerRegistryRegistration[];
sessionExtensions: PluginSessionExtensionRegistryRegistration[];
trustedToolPolicies: PluginTrustedToolPolicyRegistryRegistration[];
toolMetadata: PluginToolMetadataRegistryRegistration[];
controlUiDescriptors: PluginControlUiDescriptorRegistryRegistration[];
runtimeLifecycles: PluginRuntimeLifecycleRegistryRegistration[];
agentEventSubscriptions: PluginAgentEventSubscriptionRegistryRegistration[];
sessionSchedulerJobs: PluginSessionSchedulerJobRegistryRegistration[];
sessionActions: PluginSessionActionRegistryRegistration[];
conversationBindingResolvedHandlers: PluginConversationBindingResolvedHandlerRegistration[];
diagnostics: PluginDiagnostic[];
};
//#endregion
//#region packages/retry/src/index.d.ts
type RetryConfig = {
attempts?: number;
minDelayMs?: number;
maxDelayMs?: number;
/** Fractional symmetric spread or full jitter. */
jitter?: number | "full";
};
type RetryDelayContext = {
attempt: number;
maxAttempts: number;
err: unknown;
label?: string;
};
type RetryInfo = RetryDelayContext & {
delayMs: number;
};
type RetryOptions = RetryConfig & {
label?: string;
shouldRetry?: (err: unknown, attempt: number) => boolean;
retryAfterMs?: (err: unknown) => number | undefined;
retryAfterMaxDelayMs?: number;
delayMs?: number | ((context: RetryDelayContext) => number);
onRetry?: (info: RetryInfo) => unknown;
random?: () => number;
sleep?: (ms: number) => Promise<void>;
};
//#endregion
//#region src/infra/net/pinned-dispatcher-pool.d.ts
type PinnedDispatcherLease = {
dispatcher: Dispatcher;
reused: boolean;
release: () => Promise<void>;
};
type PinnedDispatcherPoolOptions = {
maxEntries: number;
idleTtlMs: number;
};
/**
* Bounded cache of reusable DNS-pinned dispatchers.
*
* Callers must perform fresh DNS and SSRF validation before every acquisition
* and include the resulting origin, address set, and connection policy in the key.
*/
declare class PinnedDispatcherPool {
private readonly entries;
private readonly ownedEntries;
private readonly maxEntries;
private readonly idleTtlMs;
private closed;
constructor(options: PinnedDispatcherPoolOptions);
acquire(params: {
key: string;
groupKey: string;
createDispatcher: () => Dispatcher;
}): PinnedDispatcherLease | undefined;
closeAll(): Promise<void>;
private createLease;
private retireEntry;
private startClose;
}
//#endregion
//#region src/infra/net/fetch-guard.d.ts
type FetchLike$1 = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
declare const GUARDED_FETCH_MODE: {
readonly STRICT: "strict";
readonly TRUSTED_ENV_PROXY: "trusted_env_proxy";
readonly TRUSTED_EXPLICIT_PROXY: "trusted_explicit_proxy";
};
type GuardedFetchMode = (typeof GUARDED_FETCH_MODE)[keyof typeof GUARDED_FETCH_MODE];
type GuardedFetchOptions = {
url: string;
fetchImpl?: FetchLike$1;
/** Final synchronous check after transport preparation and before each request or redirect. */
beforeRequest?: () => void | undefined;
init?: RequestInit;
capture?: false | {
flowId?: string;
meta?: Record<string, unknown>;
sensitiveRequestHeaderNames?: readonly string[];
};
maxRedirects?: number;
/**
* Allow replaying unsafe request methods and bodies across cross-origin redirects.
* Sensitive cross-origin headers (for example Authorization/Cookie) are still stripped.
* Defaults to false.
*/
allowCrossOriginUnsafeRedirectReplay?: boolean;
timeoutMs?: number;
signal?: AbortSignal;
requireHttps?: boolean;
policy?: SsrFPolicy;
lookupFn?: LookupFn;
dispatcherPolicy?: PinnedDispatcherPolicy;
/** Resolve a synchronous per-hop override so redirects can change proxy or direct routing. */
resolveDispatcherPolicy?: (url: URL) => PinnedDispatcherPolicy | undefined;
retainAuthorizationRedirectHostnameAllowlist?: string[];
mode?: GuardedFetchMode;
pinDns?: boolean;
/** @deprecated use `mode: "trusted_env_proxy"` for trusted/operator-controlled URLs. */
proxy?: "env";
/**
* @deprecated use `mode: "trusted_env_proxy"` instead.
*/
dangerouslyAllowEnvProxyWithoutPinnedDns?: boolean;
auditContext?: string;
/** Internal opt-in for reusing freshly revalidated, direct pinned dispatchers. */
dispatcherPool?: PinnedDispatcherPool;
};
//#endregion
//#region src/plugins/registry-contribution-types.d.ts
type ContextEngineFactoryContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
};
type ContextEngineFactory = (ctx: ContextEngineFactoryContext) => ContextEngine | Promise<ContextEngine>;
type ContextEngineRegistrationLifecycle = "runtime" | "readOnlyDiscovery";
type ContextEngineRegistration = {
factory: ContextEngineFactory;
owner: string;
lifecycle: ContextEngineRegistrationLifecycle;
};
type CompactionProviderSummarizationInstructions = {
identifierPolicy?: "strict" | "off" | "custom";
identifierInstructions?: string;
};
interface CompactionProvider {
id: string;
label: string;
summarize(params: {
messages: unknown[];
signal?: AbortSignal;
compressionRatio?: number;
customInstructions?: string;
summarizationInstructions?: CompactionProviderSummarizationInstructions;
previousSummary?: string;
}): Promise<string>;
}
type RegisteredCompactionProvider = {
provider: CompactionProvider;
ownerPluginId?: string;
};
type MemoryPromptSectionParams = {
availableTools: Set<string>;
citationsMode?: MemoryCitationsMode;
agentId?: string;
agentSessionKey?: string;
sandboxed?: boolean;
};
type MemoryPromptSectionBuilder = (params: MemoryPromptSectionParams) => string[];
type MemoryPromptSectionPreparer = (params: MemoryPromptSectionParams) => Promise<readonly string[]>;
type MemoryCorpusSearchResult = {
corpus: string;
path: string;
title?: string;
kind?: string;
score: number;
snippet: string;
id?: string;
startLine?: number;
endLine?: number;
citation?: string;
source?: string;
provenanceLabel?: string;
sourceType?: string;
sourcePath?: string;
updatedAt?: string;
};
type MemoryCorpusGetResult = {
corpus: string;
path: string;
title?: string;
kind?: string;
content: string;
fromLine: number;
lineCount: number;
id?: string;
provenanceLabel?: string;
sourceType?: string;
sourcePath?: string;
updatedAt?: string;
};
type MemoryCorpusSupplement = {
search(params: {
query: string;
maxResults?: number;
agentId?: string;
agentSessionKey?: string;
sandboxed?: boolean;
}): Promise<MemoryCorpusSearchResult[]>;
get(params: {
lookup: string;
fromLine?: number;
lineCount?: number;
agentId?: string;
agentSessionKey?: string;
sandboxed?: boolean;
}): Promise<MemoryCorpusGetResult | null>;
};
type MemoryCorpusSupplementRegistration = {
pluginId: string;
supplement: MemoryCorpusSupplement;
};
type MemoryPromptSupplementRegistration = {
pluginId: string;
builder: MemoryPromptSectionBuilder;
};
type MemoryPromptPreparationRegistration = {
pluginId: string;
prepare: MemoryPromptSectionPreparer;
};
type MemoryFlushPlan = {
softThresholdTokens: number;
forceFlushTranscriptBytes: number;
reserveTokensFloor: number;
model?: string;
prompt: string;
systemPrompt: string;
relativePath: string;
};
type MemoryFlushPlanResolver = (params: {
cfg?: OpenClawConfig;
nowMs?: number;
contextWindowTokens?: number;
}) => MemoryFlushPlan | null;
type RegisteredMemorySearchManager = Omit<MemorySearchManager, "readFile"> & {
readFile(params: Parameters<MemorySearchManager["readFile"]>[0]): Promise<LegacyMemoryReadResult | MemoryReadResult>;
};
type MemoryRuntimeBackendConfig = {
backend: "builtin";
};
type MemoryPluginRuntime = {
getMemorySearchManager(params: {
cfg: OpenClawConfig;
agentId: string;
purpose?: "default" | "status" | "cli";
/** Request a read-only source freshness scan; runtimes may ignore unsupported diagnostics. */
inspectSources?: boolean;
}): Promise<{
manager: RegisteredMemorySearchManager | null;
debug?: {
backend?: "builtin";
purpose?: "default" | "status" | "cli";
managerMs?: number;
};
error?: string;
}>;
resolveMemoryBackendConfig(params: {
cfg: OpenClawConfig;
agentId: string;
}): MemoryRuntimeBackendConfig;
/** Authorize raw hits before caller-visible use; absent runtimes must not expose session hits. */
authorizeSearchHits?(params: {
cfg: OpenClawConfig;
agentId: string;
requesterSessionKey: string | undefined;
sandboxed: boolean;
hits: MemorySearchResult[];
}): Promise<MemorySearchResult[]>;
classifyWorkspaceMemoryPaths?(params: {
cfg: OpenClawConfig;
agentId: string;
workspaceDir: string;
relativePaths: string[];
}): Promise<Array<{
relativePath: string;
originClass: MemoryOriginClass;
}>>;
closeMemorySearchManager?(params: {
cfg: OpenClawConfig;
agentId: string;
}): Promise<void>;
closeAllMemorySearchManagers?(): Promise<void>;
};
type MemoryPluginPublicArtifactContentType = "markdown" | "json" | "text";
type MemoryPluginPublicArtifact = {
kind: string;
workspaceDir: string;
relativePath: string;
absolutePath: string;
agentIds: string[];
contentType: MemoryPluginPublicArtifactContentType;
};
type MemoryPluginPublicArtifactsProvider = {
listArtifacts(params: {
cfg: OpenClawConfig;
}): Promise<MemoryPluginPublicArtifact[]>;
};
type MemoryPluginCapability = {
promptBuilder?: MemoryPromptSectionBuilder;
flushPlanResolver?: MemoryFlushPlanResolver;
runtime?: MemoryPluginRuntime;
publicArtifacts?: MemoryPluginPublicArtifactsProvider;
/** Local deterministic recall tool required by provider-owned direct lookup. */
deterministicRecallToolName?: string;
/** Whether recall may read protected same-agent private session transcripts. */
supportsPrivateTranscriptRecall?: boolean;
};
type MemoryPluginCapabilityRegistration = {
pluginId: string;
capability: MemoryPluginCapability;
/**
* Registrar-provided memory slot ownership. Only the slot owner may displace
* earlier fields during resolution; undeclared registrations contribute what
* the owner lacks but never take over its runtime or consolidation surface.
*/
memorySlotSelected?: boolean;
};
type SessionDiscussionState = "none" | "available" | "open";
type SessionDiscussionInfo = {
state: SessionDiscussionState;
embedUrl?: string;
openUrl?: string;
};
type SessionDiscussionProvider = {
id: string;
info(params: {
sessionKey: string;
agentId: string;
}): Promise<SessionDiscussionInfo>;
open(params: {
sessionKey: string;
agentId: string;
}): Promise<SessionDiscussionInfo>;
};
type ResolvedPluginRuntimeArtifact = {
source: string;
rootDir: string;
};
//#endregion
//#region src/plugins/plugin-api.types.d.ts
type ChannelPlugin = ChannelPlugin$3;
type PluginTextTransformRegistration = PluginTextTransforms;
type OpenClawPluginSessionStateApi = {
/** Register plugin-owned session state projected into Gateway session rows. */
registerSessionExtension: (extension: PluginSessionExtensionRegistration) => void;
};
type OpenClawPluginSessionWorkflowApi = {
/** Queue one plugin-owned context injection for the next agent turn in a session. */
enqueueNextTurnInjection: (injection: PluginNextTurnInjection) => Promise<PluginNextTurnInjectionEnqueueResult>;
/**
* Register cleanup metadata for a plugin-owned session scheduler job.
* This does not schedule work or create task records; it only lets the host
* clean external scheduler state during reset/delete/disable.
*/
registerSessionSchedulerJob: (job: PluginSessionSchedulerJobRegistration) => PluginSessionSchedulerJobHandle | undefined;
/** Send host-validated files to the active direct-outbound route for a session. */
sendSessionAttachment: (params: PluginSessionAttachmentParams) => Promise<PluginSessionAttachmentResult>;
/**
* Schedule a future agent turn in a session through Cron.
* Cron owns timing and creates the task ledger entry when the turn runs.
*/
scheduleSessionTurn: (params: PluginSessionTurnScheduleParams) => Promise<PluginSessionSchedulerJobHandle | undefined>;
/** Remove Cron-backed scheduled session turns that share a plugin-owned tag. */
unscheduleSessionTurnsByTag: (params: PluginSessionTurnUnscheduleByTagParams) => Promise<PluginSessionTurnUnscheduleByTagResult>;
};
type OpenClawPluginSessionControlsApi = {
/** Register a typed session action that clients can dispatch through the Gateway. */
registerSessionAction: (action: PluginSessionActionRegistration) => void;
/** Register a generic Control UI contribution descriptor. */
registerControlUiDescriptor: (descriptor: PluginControlUiDescriptor) => void;
};
type OpenClawPluginSessionApi = {
state: OpenClawPluginSessionStateApi;
workflow: OpenClawPluginSessionWorkflowApi;
controls: OpenClawPluginSessionControlsApi;
};
type OpenClawPluginAgentEventsApi = {
/** Subscribe to sanitized agent events through the host-owned plugin lifecycle. */
registerAgentEventSubscription: (subscription: PluginAgentEventSubscriptionRegistration) => void;
/** Emit a host-routed, plugin-attributed event for workflow/UI subscribers. */
emitAgentEvent: (params: PluginAgentEventEmitParams) => PluginAgentEventEmitResult;
};
type OpenClawPluginAgentApi = {
events: OpenClawPluginAgentEventsApi;
};
type OpenClawPluginRunContextApi = {
/** Store namespaced, JSON-compatible data for the active run. Cleared on run end/error. */
setRunContext: (patch: PluginRunContextPatch) => boolean;
/** Read namespaced plugin data for a run. */
getRunContext: (params: PluginRunContextGetParams) => PluginJsonValue | undefined;
/** Clear one namespace or all namespaces this plugin owns for a run. */
clearRunContext: (params: {
runId: string;
namespace?: string;
}) => void;
};
type OpenClawPluginLifecycleApi = {
/** Register cleanup hooks for plugin-owned host state and background work. */
registerRuntimeLifecycle: (lifecycle: PluginRuntimeLifecycleRegistration) => void;
};
/**
* Main registration API injected into native plugin entry files.
* @experimental All plugin APIs are experimental. Pin and test OpenClaw host versions.
* @see https://docs.openclaw.ai/plugins/sdk-overview#api-stability
*/
type OpenClawPluginApi = {
id: string;
name: string;
version?: string;
description?: string;
source: string;
rootDir?: string;
registrationMode: PluginRegistrationMode;
config: OpenClawConfig;
pluginConfig?: Record<string, unknown>;
/**
* In-process runtime helpers for trusted native plugins.
*
* This surface is broader than hooks. Prefer hooks for third-party
* automation/integration unless you need native registry integration.
*/
runtime: PluginRuntime;
logger: PluginLogger;
/**
* Grouped facade over the existing flat session-related plugin API.
* Flat methods remain supported for compatibility.
*/
session: OpenClawPluginSessionApi;
/** Grouped facade for agent-event workflow seams. */
agent: OpenClawPluginAgentApi;
/** Grouped facade for run-scoped plugin scratch state. */
runContext: OpenClawPluginRunContextApi;
/** Grouped facade for plugin-owned lifecycle cleanup hooks. */
lifecycle: OpenClawPluginLifecycleApi;
registerTool: (tool: AnyAgentTool | OpenClawPluginToolFactory$1, opts?: OpenClawPluginToolOptions) => void;
registerHook: (events: string | string[], handler: InternalHookHandler, opts?: OpenClawPluginHookOptions) => void;
registerHttpRoute: (params: OpenClawPluginHttpRouteParams) => void;
/** Register a plugin-owned resolver for browser-style hosted media URLs. */
registerHostedMediaResolver: (resolver: OpenClawPluginHostedMediaResolver$1) => void;
/** Register a plugin-owned destination for presenting hosted widget documents. */
registerWidgetPresenter: (presenter: WidgetPresenter) => void;
/** Bind a declared MCP server's transport to the trusted message requester. */ registerMcpServerConnectionResolver: (resolver: OpenClawPluginMcpServerConnectionResolver) => void;
/** Register a native messaging channel plugin (channel capability). */
registerChannel: (registration: OpenClawPluginChannelRegistration | ChannelPlugin) => void;
/**
* Register a gateway RPC method for this plugin.
*
* Reserved core admin namespaces (`config.*`, `exec.approvals.*`,
* `wizard.*`, `update.*`) always normalize to `operator.admin` even if a
* narrower scope is requested.
*/
registerGatewayMethod: (method: string, handler: GatewayRequestHandler, opts?: {
scope?: OperatorScope;
profileAccess?: "independent" | "required";
}) => void;
/** Register a sandboxed board widget source kind owned by this plugin. */
registerBoardWidgetContentKind: (definition: PluginBoardWidgetContentKind) => void;
/** Register a read-only external-session catalog with optional native adoption actions. */
registerSessionCatalog: (provider: SessionCatalogProvider) => void;
registerCli: (registrar: OpenClawPluginCliRegistrar$1, opts?: OpenClawPluginCliRegistrationOptions) => void;
/**
* Register a plugin-owned node feature command group under `openclaw nodes`.
*
* This is equivalent to `registerCli(registrar, { parentPath: ["nodes"], ... })`
* and is intended for paired-node capabilities such as camera, screen, or Canvas.
*/
registerNodeCliFeature: (registrar: OpenClawPluginCliRegistrar$1, opts?: OpenClawPluginNodeCliFeatureOptions) => void;
registerReload: (registration: OpenClawPluginReloadRegistration$1) => void;
registerNodeHostCommand: (command: OpenClawPluginNodeHostCommand) => void;
registerNodeInvokePolicy: (policy: OpenClawPluginNodeInvokePolicy) => void;
registerSecurityAuditCollector: (collector: OpenClawPluginSecurityAuditCollector$1) => void;
registerService: (service: OpenClawPluginService$1) => void;
/** Register a local gateway discovery advertiser such as mDNS/Bonjour. */
registerGatewayDiscoveryService: (service: OpenClawGatewayDiscoveryService$1) => void;
/** Register a text-only CLI backend used by the local CLI runner. */
registerCliBackend: (backend: CliBackendPlugin) => void;
/** Register plugin-owned prompt/message compatibility text transforms. */
registerTextTransforms: (transforms: PluginTextTransformRegistration) => void;
/** Register a lightweight config migration that can run before plugin runtime loads. */
registerConfigMigration: (migrate: PluginConfigMigration) => void;
/** Register an importer for `openclaw migrate` (migration capability). */
registerMigrationProvider: (provider: MigrationProviderPlugin$1) => void;
/** Register a lightweight config probe that can auto-enable this plugin generically. */
registerAutoEnableProbe: (probe: PluginSetupAutoEnableProbe) => void;
/** Register a native model/provider plugin (text inference capability). */
registerProvider: (provider: ProviderPlugin$1) => void;
/** Register a cloud-worker lifecycle provider. */
registerWorkerProvider: (provider: WorkerProvider$1) => void;
/** Register provider-owned model catalog rows for text and media generation. */
registerModelCatalogProvider: (provider: UnifiedModelCatalogProviderPlugin$1) => void;
/** Register a general embedding provider (embedding capability). */
registerEmbeddingProvider: (adapter: EmbeddingProviderAdapter) => void;
/** Register a speech synthesis provider (speech capability). */
registerSpeechProvider: (provider: SpeechProviderPlugin$1) => void;
/** Register a realtime transcription provider (streaming STT capability). */
registerRealtimeTranscriptionProvider: (provider: RealtimeTranscriptionProviderPlugin$1) => void;
/** Register a realtime voice provider (duplex voice capability). */
registerRealtimeVoiceProvider: (provider: RealtimeVoiceProviderPlugin$1) => void;
/** Register a media understanding provider (media understanding capability). */
registerMediaUnderstandingProvider: (provider: MediaUnderstandingProviderPlugin$1) => void;
/** Register a transcripts source provider (live or imported meeting transcript capability). */
registerTranscriptSourceProvider: (provider: TranscriptSourceProvider$1) => void;
/** Register an image generation provider (image generation capability). */
registerImageGenerationProvider: (provider: ImageGenerationProviderPlugin$1) => void;
/** Register a video generation provider (video generation capability). */
registerVideoGenerationProvider: (provider: VideoGenerationProviderPlugin$1) => void;
/** Register a music generation provider (music generation capability). */
registerMusicGenerationProvider: (provider: MusicGenerationProviderPlugin$1) => void;
/** Register a web fetch provider (web fetch capability). */
registerWebFetchProvider: (provider: WebFetchProviderPlugin$1) => void;
/** Register a web search provider (web search capability). */
registerWebSearchProvider: (provider: WebSearchProviderPlugin$1) => void;
registerInteractiveHandler: (registration: PluginInteractiveHandlerRegistration$1) => void;
onConversationBindingResolved: (handler: (event: PluginConversationBindingResolvedEvent$1) => void | Promise<void>) => 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$1) => void;
/** Register a context engine implementation (exclusive slot - only one active at a time). */
registerContextEngine: (id: string, factory: ContextEngineFactory) => void;
/** Register a compaction provider (pluggable summarization backend). */
registerCompactionProvider: (provider: CompactionProvider) => void;
/** Register an agent harness implementation. */
registerAgentHarness: (harness: AgentHarness, options?: AgentHarnessRegistrationOptions) => void;
/**
* Register a Codex app-server extension factory for Codex harness tool-result
* middleware. Only bundled plugins may use this seam, and
* `contracts.embeddedExtensionFactories` must include `"codex-app-server"`.
*/
registerCodexAppServerExtensionFactory: (factory: CodexAppServerExtensionFactory) => void;
/**
* Register runtime-neutral tool-result middleware. Declare
* `contracts.agentToolResultMiddleware` for every targeted runtime.
*/
registerAgentToolResultMiddleware: (handler: AgentToolResultMiddleware, options?: AgentToolResultMiddlewareOptions) => void;
/**
* Register plugin-owned session state that can be projected into Gateway session rows.
* @deprecated Use `api.session.state.registerSessionExtension(...)`.
*/
registerSessionExtension: (extension: PluginSessionExtensionRegistration) => void;
/**
* Queue one plugin-owned context injection for the next agent turn in a session.
* @deprecated Use `api.session.workflow.enqueueNextTurnInjection(...)`.
*/
enqueueNextTurnInjection: (injection: PluginNextTurnInjection) => Promise<PluginNextTurnInjectionEnqueueResult>;
/**
* Register a trusted pre-tool policy. Installed plugins must declare the
* policy id in `contracts.trustedToolPolicies`.
*/
registerTrustedToolPolicy: (policy: PluginTrustedToolPolicyRegistration) => void;
/**
* Register display/policy metadata for a plugin-owned tool. Metadata is
* scoped to the (pluginId, toolName) pair at projection time, so plugins
* cannot decorate other plugins' tools or core tools through this surface.
*/
registerToolMetadata: (metadata: PluginToolMetadataRegistration) => void;
/**
* Register a generic Control UI contribution descriptor.
* @deprecated Use `api.session.controls.registerControlUiDescriptor(...)`.
*/
registerControlUiDescriptor: (descriptor: PluginControlUiDescriptor) => void;
/**
* Register cleanup hooks for plugin-owned host state and background work.
* @deprecated Use `api.lifecycle.registerRuntimeLifecycle(...)`.
*/
registerRuntimeLifecycle: (lifecycle: PluginRuntimeLifecycleRegistration) => void;
/**
* Subscribe to sanitized agent events through the host-owned plugin lifecycle.
* @deprecated Use `api.agent.events.registerAgentEventSubscription(...)`.
*/
registerAgentEventSubscription: (subscription: PluginAgentEventSubscriptionRegistration) => void;
/**
* Emit a host-routed, plugin-attributed agent event for workflow/UI subscribers.
* @deprecated Use `api.agent.events.emitAgentEvent(...)`.
*/
emitAgentEvent: (params: PluginAgentEventEmitParams) => PluginAgentEventEmitResult;
/**
* Store namespaced, JSON-compatible data for the active run. Cleared on run end/error.
* @deprecated Use `api.runContext.setRunContext(...)`.
*/
setRunContext: (patch: PluginRunContextPatch) => boolean;
/**
* Read namespaced plugin data for a run.
* @deprecated Use `api.runContext.getRunContext(...)`.
*/
getRunContext: (params: PluginRunContextGetParams) => PluginJsonValue | undefined;
/**
* Clear one namespace or all namespaces this plugin owns for a run.
* @deprecated Use `api.runContext.clearRunContext(...)`.
*/
clearRunContext: (params: {
runId: string;
namespace?: string;
}) => void;
/**
* Register cleanup metadata for a plugin-owned session scheduler job.
* This does not schedule work or create task records; it only lets the host
* clean external scheduler state during reset/delete/disable.
*
* @deprecated Use `api.session.workflow.registerSessionSchedulerJob(...)`.
*/
registerSessionSchedulerJob: (job: PluginSessionSchedulerJobRegistration) => PluginSessionSchedulerJobHandle | undefined;
/**
* Register a typed session action that clients can dispatch through the Gateway.
* @deprecated Use `api.session.controls.registerSessionAction(...)`.
*/
registerSessionAction: (action: PluginSessionActionRegistration) => void;
/**
* Send one or more host-validated files to the active direct-outbound channel for a session.
*
* This API is intended for bundled plugins running with the host channel/session
* integration available. Calls may resolve to `{ ok: false }` instead of attaching
* files when global side effects are disabled or when the required plugin/channel
* runtime is not loaded, so callers must handle rejection via the returned result.
*
* @deprecated Use `api.session.workflow.sendSessionAttachment(...)`.
*/
sendSessionAttachment: (params: PluginSessionAttachmentParams) => Promise<PluginSessionAttachmentResult>;
/**
* Schedule a future agent turn in a session through Cron.
* Cron owns timing and creates the task ledger entry when the turn runs.
* Bundled plugins only; workspace plugins receive undefined.
*
* @deprecated Use `api.session.workflow.scheduleSessionTurn(...)`.
*/
scheduleSessionTurn: (params: PluginSessionTurnScheduleParams) => Promise<PluginSessionSchedulerJobHandle | undefined>;
/**
* Remove Cron-backed scheduled session turns that share the same plugin-owned tag.
* Bundled plugins only; workspace plugins receive a zero-count result.
*
* @deprecated Use `api.session.workflow.unscheduleSessionTurnsByTag(...)`.
*/
unscheduleSessionTurnsByTag: (params: PluginSessionTurnUnscheduleByTagParams) => Promise<PluginSessionTurnUnscheduleByTagResult>;
/** Register the active detached task runtime for this plugin (exclusive slot). */
registerDetachedTaskRuntime: (runtime: DetachedTaskLifecycleRuntime) => void;
/** Register the active memory capability for this memory plugin (exclusive slot). */
registerMemoryCapability: (capability: MemoryPluginCapability) => void;
/** Register an additive memory-adjacent prompt section (non-exclusive). */
registerMemoryPromptSupplement: (builder: MemoryPromptSectionBuilder) => void;
/** Register an async memory prompt preparation step (non-exclusive). */
registerMemoryPromptPreparation: (prepare: (params: MemoryPromptSectionParams) => Promise<readonly string[]>) => void;
/** Register an additive memory-adjacent search/read corpus supplement (non-exclusive). */
registerMemoryCorpusSupplement: (supplement: MemoryCorpusSupplement) => void;
resolvePath: (input: string) => string;
/** Register a lifecycle hook handler */
on: <K extends PluginHookName>(hookName: K, handler: PluginHookHandlerMap[K], opts?: PluginHookRegistrationOptions<K>) => void;
};
//#endregion
//#region src/plugins/plugin-config-schema.types.d.ts
type PluginConfigValidation = {
ok: true;
value?: unknown;
} | {
ok: false;
errors: string[];
};
/**
* Config schema contract accepted by plugin manifests and runtime registration.
*
* Plugins can provide a Zod-like parser, a lightweight `validate(...)`
* function, or both. `jsonSchema` is optional runtime schema metadata.
*/
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;
/**
* @deprecated Declare config presentation metadata in the plugin's
* `openclaw.plugin.json` manifest via top-level `uiHints`. The host reads
* manifest hints and does not consume runtime config-schema hints.
*/
uiHints?: Record<string, PluginConfigUiHint>;
jsonSchema?: JsonSchemaObject;
};
//#endregion
//#region src/plugins/plugin-definition.types.d.ts
/** Module-level plugin definition loaded from a native plugin entry file. */
type OpenClawPluginDefinition = {
id?: string;
name?: string;
description?: string;
version?: string;
/**
* @deprecated Declare exclusive plugin kind in `openclaw.plugin.json` via
* manifest `kind`. Runtime-exported `kind` is kept as a compatibility
* fallback for older plugins and may require loading plugin runtime on
* metadata-only command paths.
*/
kind?: PluginKind | PluginKind[];
configSchema?: OpenClawPluginConfigSchema;
reload?: OpenClawPluginReloadRegistration$1;
nodeHostCommands?: OpenClawPluginNodeHostCommand[];
securityAuditCollectors?: OpenClawPluginSecurityAuditCollector$1[];
register?: (api: OpenClawPluginApi) => void;
};
//#endregion
//#region src/tts/directives.d.ts
type ParseTtsDirectiveOptions = {
cfg?: OpenClawConfig;
providers?: readonly SpeechProviderPlugin$1[];
providerConfigs?: Record<string, SpeechProviderConfig>;
preferredProviderId?: string;
};
/** Parse TTS directives from final message text, leaving markdown code spans unchanged. */
declare function parseTtsDirectives(text: string, policy: SpeechModelOverridePolicy, options?: ParseTtsDirectiveOptions): TtsDirectiveParseResult;
//#endregion
//#region src/plugins/capability-provider-runtime.d.ts
declare function prepareMediaCapabilityProviders(params: {
cfg?: OpenClawConfig;
pluginMetadataSnapshot: Pick<PluginMetadataSnapshot, "index" | "plugins">;
registry?: PluginRegistry;
}): Readonly<{
mediaUnderstandingProviders: readonly MediaUnderstandingProvider[] | undefined;
imageGenerationProviders: readonly ImageGenerationProvider[] | undefined;
videoGenerationProviders: readonly VideoGenerationProvider[] | undefined;
musicGenerationProviders: readonly MusicGenerationProvider[] | undefined;
}>;
//#endregion
//#region src/agents/embedded-agent-runner/model.inline-provider.d.ts
/**
* Normalizes inline `models.providers` config into runtime model entries.
*/
type InlineModelEntry = Omit<ModelDefinitionConfig, "api" | "contextWindow"> & {
api?: Api;
contextWindow?: number;
provider: string;
baseUrl?: string;
headers?: Record<string, string>;
};
//#endregion
//#region src/plugins/prepared-message-tool-catalog.d.ts
type PreparedMessageToolCatalogEntry = Readonly<{
id: string;
actions?: ChannelMessageActionAdapter;
reconcilesUnknownSend: boolean;
}>;
type PreparedMessageToolCatalog = Readonly<{
version: number;
channels: readonly PreparedMessageToolCatalogEntry[];
getChannel: (id: string) => PreparedMessageToolCatalogEntry | undefined;
}>;
//#endregion
//#region src/agents/agent-auth-credential-modes.d.ts
/** Secret-free credential modes captured by a prepared agent runtime. */
type PreparedAgentCredentialModes = Readonly<Record<string, "api_key" | "oauth" | "token">>;
//#endregion
//#region src/agents/prepared-model-catalog.types.d.ts
type PublishedModelCatalogOwnerCandidate = Readonly<{
/** Captured during preparation; undefined is a known-unbound runtime. */
catalogOwner: Readonly<{
agentId: string;
workspaceDir: string;
}> | undefined;
agentId?: string;
agentDir: string;
workspaceDir?: string;
config: OpenClawConfig;
observationConfig: OpenClawConfig;
authModes: PreparedAgentCredentialModes;
authStore?: AuthProfileStore;
metadataSnapshot: PluginMetadataSnapshot;
/** Registry owned by this prepared generation; omitted from read-only builds. */
pluginRegistry?: PluginRegistry;
/** Reports whether this exact lifecycle generation is still published. */
isCurrent: () => boolean;
modelCatalog: ModelCatalogSnapshot;
}>;
//#endregion
//#region src/agents/model-ref-shared.d.ts
type ModelRef = {
provider: string;
model: string;
};
//#endregion
//#region src/agents/modes/interactive/theme/theme.d.ts
type ThemeColor = "accent" | "border" | "borderAccent" | "borderMuted" | "success" | "error" | "warning" | "muted" | "dim" | "text" | "thinkingText" | "userMessageText" | "customMessageText" | "customMessageLabel" | "toolTitle" | "toolOutput" | "mdHeading" | "mdLink" | "mdLinkUrl" | "mdCode" | "mdCodeBlock" | "mdCodeBlockBorder" | "mdQuote" | "mdQuoteBorder" | "mdHr" | "mdListBullet" | "toolDiffAdded" | "toolDiffRemoved" | "toolDiffContext" | "syntaxComment" | "syntaxKeyword" | "syntaxFunction" | "syntaxVariable" | "syntaxString" | "syntaxNumber" | "syntaxType" | "syntaxOperator" | "syntaxPunctuation" | "thinkingOff" | "thinkingMinimal" | "thinkingLow" | "thinkingMedium" | "thinkingHigh" | "thinkingXhigh" | "bashMode";
type ThemeBg = "selectedBg" | "userMessageBg" | "customMessageBg" | "toolPendingBg" | "toolSuccessBg" | "toolErrorBg";
type ColorMode = "truecolor" | "256color";
declare class Theme {
readonly name?: string;
readonly sourcePath?: string;
sourceInfo?: SourceInfo;
private fgColors;
private bgColors;
private mode;
constructor(fgColors: Record<ThemeColor, string | number>, bgColors: Record<ThemeBg, string | number>, mode: ColorMode, options?: {
name?: string;
sourcePath?: string;
sourceInfo?: SourceInfo;
});
fg(color: ThemeColor, text: string): string;
bg(color: ThemeBg, text: string): string;
bold(text: string): string;
italic(text: string): string;
underline(text: string): string;
inverse(text: string): string;
strikethrough(text: string): string;
getFgAnsi(color: ThemeColor): string;
getBgAnsi(color: ThemeBg): string;
getColorMode(): ColorMode;
getThinkingBorderColor(level: "off" | "minimal" | "low" | "medium" | "high" | "xhigh"): (str: string) => string;
getBashModeBorderColor(): (str: string) => string;
}
//#endregion
//#region src/agents/sessions/footer-data-provider.d.ts
/** Read-only footer data supplied to session extensions. */
interface ReadonlyFooterDataProvider {
/** Current git branch, null if not in repo, "detached" if detached HEAD */
getGitBranch(): string | null;
/** Extension status texts set via ctx.ui.setStatus() */
getExtensionStatuses(): ReadonlyMap<string, string>;
/** Number of unique providers with available models (for footer display) */
getAvailableProviderCount(): number;
/** Subscribe to git branch changes. Returns unsubscribe function. */
onBranchChange(callback: () => void): () => void;
}
//#endregion
//#region src/agents/sessions/keybindings.d.ts
/** OpenClaw-specific key ids added to the shared pi-tui keybinding registry. */
interface AppKeybindings {
"app.interrupt": true;
"app.clear": true;
"app.exit": true;
"app.suspend": true;
"app.thinking.cycle": true;
"app.model.cycleForward": true;
"app.model.cycleBackward": true;
"app.model.select": true;
"app.tools.expand": true;
"app.thinking.toggle": true;
"app.session.toggleNamedFilter": true;
"app.editor.external": true;
"app.message.followUp": true;
"app.message.dequeue": true;
"app.clipboard.pasteImage": true;
"app.session.new": true;
"app.session.tree": true;
"app.session.fork": true;
"app.session.resume": true;
"app.tree.foldOrUp": true;
"app.tree.unfoldOrDown": true;
"app.tree.editLabel": true;
"app.tree.toggleLabelTimestamp": true;
"app.session.togglePath": true;
"app.session.toggleSort": true;
"app.session.rename": true;
"app.session.delete": true;
"app.session.deleteNoninvasive": true;
"app.models.save": true;
"app.models.enableAll": true;
"app.models.clearAll": true;
"app.models.toggleProvider": true;
"app.models.reorderUp": true;
"app.models.reorderDown": true;
"app.tree.filter.default": true;
"app.tree.filter.noTools": true;
"app.tree.filter.userOnly": true;
"app.tree.filter.labeledOnly": true;
"app.tree.filter.all": true;
"app.tree.filter.cycleForward": true;
"app.tree.filter.cycleBackward": true;
}
declare module "@earendil-works/pi-tui" {
interface Keybindings extends AppKeybindings {}
}
/** Keybinding manager that loads OpenClaw defaults plus optional user overrides. */
declare class KeybindingsManager$1 extends KeybindingsManager {
private configPath;
constructor(userBindings?: KeybindingsConfig, configPath?: string);
/** Creates a manager from the agent keybindings.json file. */
static create(agentDir?: string): KeybindingsManager$1;
/** Reloads user overrides from disk when this manager was created with a config path. */
reload(): void;
/** Returns the currently resolved keybinding map after defaults and overrides. */
getEffectiveConfig(): KeybindingsConfig;
private static loadFromFile;
}
//#endregion
//#region src/agents/plugin-model-catalog.d.ts
type PersistedPluginModelCatalog = {
pluginId: string;
contents: string;
};
type PluginModelCatalogMetadataSnapshot = Pick<PluginMetadataSnapshot, "owners"> & {
index?: {
plugins: ReadonlyArray<{
enabled: boolean;
pluginId: string;
}>;
};
normalizePluginId?: (pluginId: string) => string;
};
//#endregion
//#region src/agents/sessions/auth-storage.d.ts
type ApiKeyCredential = {
type: "api_key";
key: string;
};
type OAuthCredential = {
type: "oauth";
} & OAuthCredentials;
type TokenCredential = {
type: "token";
token: string;
expires?: number;
};
type AuthCredential = ApiKeyCredential | OAuthCredential | TokenCredential;
type AuthStorageData = Record<string, AuthCredential>;
type AuthStatus = {
configured: boolean;
source?: "stored" | "runtime" | "environment" | "fallback" | "models_json_key" | "models_json_command";
label?: string;
};
type LockResult<T> = {
result: T;
next?: string;
};
interface AuthStorageBackend {
readonly migrationOwnerAgentDir?: string;
withLock<T>(fn: (current: string | undefined) => LockResult<T>): T;
withLockAsync<T>(fn: (current: string | undefined) => Promise<LockResult<T>>): Promise<T>;
}
/**
* Provider-keyed credential facade backed by the canonical auth-profile store.
*/
declare class AuthStorage {
private data;
private runtimeOverrides;
private fallbackResolver?;
private loadError;
private errors;
private storage;
private migrationOwnerAgentDir?;
private constructor();
static forAgent(agentDir?: string): AuthStorage;
/**
* @deprecated Use AuthStorage.forAgent(agentDir). The path-taking compatibility
* form is eligible for removal after 2026-10-01 and a clean published-plugin
* reader sweep; it no longer reads or writes JSON.
*/
static create(authPath?: string): AuthStorage;
static fromStorage(storage: AuthStorageBackend): AuthStorage;
static inMemory(data?: AuthStorageData): AuthStorage;
/**
* Set a runtime API key override (not persisted to disk).
* Used for CLI --api-key flag.
*/
setRuntimeApiKey(provider: string, apiKey: string): void;
/**
* Remove a runtime API key override.
*/
removeRuntimeApiKey(provider: string): void;
/**
* Set a fallback resolver for API keys not found in auth.json or env vars.
* Used for custom provider keys from models.json.
*/
setFallbackResolver(resolver: (provider: string) => string | undefined): void;
private recordError;
private getCanonicalLoadError;
private parseStorageData;
/**
* Reload credentials from storage.
*/
reload(): void;
private persistProviderChange;
/**
* Get credential for a provider.
*/
get(provider: string): AuthCredential | undefined;
/**
* Set credential for a provider.
*/
set(provider: string, credential: AuthCredential): void;
/**
* Remove credential for a provider.
*/
remove(provider: string): void;
/**
* List all providers with credentials.
*/
list(): string[];
/**
* Check if credentials exist for a provider in auth.json.
*/
has(provider: string): boolean;
/**
* Check if any form of auth is configured for a provider.
* Unlike getApiKey(), this doesn't refresh OAuth tokens.
*/
hasAuth(provider: string): boolean;
/**
* Return auth status without exposing credential values or refreshing tokens.
*/
getAuthStatus(provider: string): AuthStatus;
/**
* Get all credentials (for passing to getOAuthApiKey).
*/
getAll(): AuthStorageData;
drainErrors(): Error[];
/**
* Login to an OAuth provider.
*/
login(providerId: OAuthProviderId, callbacks: OAuthLoginCallbacks): Promise<void>;
/**
* Logout from a provider.
*/
logout(provider: string): void;
/**
* Refresh OAuth token with backend locking to prevent race conditions.
* Multiple agent sessions may try to refresh simultaneously when tokens expire.
*/
private refreshOAuthTokenWithLock;
/**
* Get API key for a provider.
* Priority:
* 1. Runtime override (CLI --api-key)
* 2. API key from auth.json
* 3. OAuth token from auth.json (auto-refreshed with locking)
* 4. Environment variable
* 5. Fallback resolver (models.json custom providers)
*/
getApiKey(providerId: string, options?: {
includeFallback?: boolean;
}): Promise<string | undefined>;
/**
* Get all OAuth providers registered for this auth/session runtime.
*/
getOAuthProviders(): OAuthProviderInterface[];
}
//#endregion
//#region src/agents/sessions/model-registry.d.ts
declare const ProviderAuthModeSchema: Type.TUnion<[Type.TLiteral<"api-key">, Type.TLiteral<"aws-sdk">, Type.TLiteral<"oauth">, Type.TLiteral<"token">]>;
type ProviderAuthMode = Static<typeof ProviderAuthModeSchema>;
type ResolvedRequestAuth = {
ok: true;
apiKey?: string;
headers?: Record<string, string>;
} | {
ok: false;
error: string;
};
type ModelRegistryOptions = {
includePluginCatalogs?: boolean;
modelsJsonContents?: string | null;
pluginCatalogs?: readonly PersistedPluginModelCatalog[];
pluginMetadataSnapshot?: PluginModelCatalogMetadataSnapshot;
sourceSnapshot?: ModelRegistry;
workspaceDir?: string;
};
/**
* Model registry - loads and manages models, resolves API keys via AuthStorage.
*/
declare class ModelRegistry {
private models;
private providerRequestConfigs;
private modelRequestHeaders;
private registeredProviders;
private loadError;
readonly authStorage: AuthStorage;
private modelsJsonPath;
private modelsJsonContents;
private pluginCatalogs;
private pluginMetadataSnapshot;
private includePluginCatalogs;
private baseCatalogSnapshot;
private sourceSnapshot;
private constructor();
private captureCatalogSnapshot;
private restoreSourceCatalog;
static create(authStorage: AuthStorage, modelsJsonPath?: string, options?: ModelRegistryOptions): ModelRegistry;
static inMemory(authStorage: AuthStorage): ModelRegistry;
/** Creates a request-isolated registry from this lifecycle-owned catalog snapshot. */
fork(authStorage: AuthStorage): ModelRegistry;
/**
* Reload models from disk (models.json).
*/
refresh(): void;
/** Get any root or generated plugin catalog load error. */
getError(): string | undefined;
/** Returns the exact plugin metadata generation captured with this registry. */
getProviderMetadataOwners(): PluginMetadataSnapshotOwnerMaps | undefined;
private loadModels;
private loadCapturedPluginCatalogs;
private loadCustomModels;
private validateConfig;
private parseModels;
/**
* Get all configured models.
*/
getAll(): Model[];
/**
* Get only models that have auth configured.
* This is a fast check that doesn't refresh OAuth tokens.
*/
getAvailable(): Model[];
/**
* Find a model by provider and ID.
*/
find(provider: string, modelId: string): Model | undefined;
/**
* Get API key for a model.
*/
hasConfiguredAuth(model: Model): boolean;
private getModelRequestKey;
private storeProviderRequestConfig;
private storeModelHeaders;
/**
* Get API key and request headers for a model.
*/
getApiKeyAndHeaders(model: Model): Promise<ResolvedRequestAuth>;
/**
* Return auth status for a provider, including request auth configured in models.json.
* This intentionally does not execute command-backed config values.
*/
getProviderAuthStatus(provider: string): AuthStatus;
/**
* Get display name for a provider.
*/
getProviderDisplayName(provider: string): string;
/**
* Get API key for a provider.
*/
getApiKeyForProvider(provider: string): Promise<string | undefined>;
/**
* Check if a model is using OAuth credentials (subscription).
*/
isUsingOAuth(model: Model): boolean;
/**
* Register a provider dynamically (from extensions).
*
* If provider has models: replaces all existing models for this provider.
* Provider-level request settings are stored for already-known models but
* never create implicit model rows.
* If provider has oauth: registers OAuth provider for /login support.
*/
registerProvider(providerName: string, config: ProviderConfigInput): void;
/**
* Unregister a previously registered provider.
*
* Removes the provider from the registry and reloads models from disk.
* Also resets dynamic OAuth and API stream registrations before reapplying
* remaining dynamic providers.
* Has no effect if the provider was never registered.
*/
unregisterProvider(providerName: string): void;
/**
* Upsert a provider config into registeredProviders.
* If the provider is already registered, defined values in the incoming config
* override existing ones; undefined values are preserved from the stored config.
* If the provider is not registered, the incoming config is stored as-is.
*/
private upsertRegisteredProvider;
private validateProviderConfig;
private applyProviderConfig;
}
/**
* Input type for registerProvider API.
*/
interface ProviderConfigInput {
name?: string;
baseUrl?: string;
apiKey?: string;
auth?: ProviderAuthMode;
api?: Api;
streamSimple?: (model: Model, context: Context, options?: SimpleStreamOptions) => AssistantMessageEventStreamContract;
headers?: Record<string, string>;
authHeader?: boolean;
/** OAuth provider for /login support */
oauth?: Omit<OAuthProviderInterface, "id">;
models?: Array<{
id: string;
name: string;
api?: Api;
baseUrl?: string;
reasoning: boolean;
thinkingLevelMap?: Model["thinkingLevelMap"];
input: ("text" | "image")[];
cost: {
input: number;
output: number;
cacheRead: number;
cacheWrite: number;
};
contextWindow: number;
maxTokens: number;
params?: Record<string, unknown>;
headers?: Record<string, string>;
compat?: Model["compat"];
}>;
}
//#endregion
//#region src/agents/sessions/extensions/types.d.ts
/** Options for extension UI dialogs. */
interface ExtensionUIDialogOptions {
/** AbortSignal to programmatically dismiss the dialog. */
signal?: AbortSignal;
/** Timeout in milliseconds. Dialog auto-dismisses with live countdown display. */
timeout?: number;
}
/** Placement for extension widgets. */
type WidgetPlacement = "aboveEditor" | "belowEditor";
/** Options for extension widgets. */
interface ExtensionWidgetOptions {
/** Where the widget is rendered. Defaults to "aboveEditor". */
placement?: WidgetPlacement;
}
/** Raw terminal input listener for extensions. */
type TerminalInputHandler = (data: string) => {
consume?: boolean;
data?: string;
} | undefined;
/** Working indicator configuration for the interactive streaming loader. */
interface WorkingIndicatorOptions {
/** Animation frames. Use an empty array to hide the indicator entirely. Custom frames are rendered verbatim. */
frames?: string[];
/** Frame interval in milliseconds for animated indicators. */
intervalMs?: number;
}
/** Wrap the current autocomplete provider with additional behavior. */
type AutocompleteProviderFactory = (current: AutocompleteProvider) => AutocompleteProvider;
type EditorFactory = (tui: TUI, theme: EditorTheme, keybindings: KeybindingsManager$1) => EditorComponent;
/**
* UI context for extensions to request interactive UI.
* Each mode (interactive, RPC, print) provides its own implementation.
*/
interface ExtensionUIContext {
/** Show a selector and return the user's choice. */
select(title: string, options: string[], opts?: ExtensionUIDialogOptions): Promise<string | undefined>;
/** Show a confirmation dialog. */
confirm(title: string, message: string, opts?: ExtensionUIDialogOptions): Promise<boolean>;
/** Show a text input dialog. */
input(title: string, placeholder?: string, opts?: ExtensionUIDialogOptions): Promise<string | undefined>;
/** Show a notification to the user. */
notify(message: string, type?: "info" | "warning" | "error"): void;
/** Listen to raw terminal input (interactive mode only). Returns an unsubscribe function. */
onTerminalInput(handler: TerminalInputHandler): () => void;
/** Set status text in the footer/status bar. Pass undefined to clear. */
setStatus(key: string, text: string | undefined): void;
/** Set the working/loading message shown during streaming. Call with no argument to restore default. */
setWorkingMessage(message?: string): void;
/** Show or hide the built-in interactive working loader row during streaming. */
setWorkingVisible(visible: boolean): void;
/**
* Configure the interactive working indicator shown during streaming.
*
* - Omit the argument to restore the default animated spinner.
* - Use `frames: ["●"]` for a static indicator.
* - Use `frames: []` to hide the indicator entirely.
* - Custom frames are rendered as provided, so extensions must add their own colors.
*/
setWorkingIndicator(options?: WorkingIndicatorOptions): void;
/** Set the label shown for hidden thinking blocks. Call with no argument to restore default. */
setHiddenThinkingLabel(label?: string): void;
/** Set a widget to display above or below the editor. Accepts string array or component factory. */
setWidget(key: string, content: string[] | undefined, options?: ExtensionWidgetOptions): void;
setWidget(key: string, content: ((tui: TUI, theme: Theme) => Component & {
dispose?(): void;
}) | undefined, options?: ExtensionWidgetOptions): void;
/** Set a custom footer component, or undefined to restore the built-in footer.
*
* The factory receives a FooterDataProvider for data not otherwise accessible:
* git branch and extension statuses from setStatus(). Token stats, model info,
* etc. are available via ctx.sessionManager and ctx.model.
*/
setFooter(factory: ((tui: TUI, theme: Theme, footerData: ReadonlyFooterDataProvider) => Component & {
dispose?(): void;
}) | undefined): void;
/** Set a custom header component (shown at startup, above chat), or undefined to restore the built-in header. */
setHeader(factory: ((tui: TUI, theme: Theme) => Component & {
dispose?(): void;
}) | undefined): void;
/** Set the terminal window/tab title. */
setTitle(title: string): void;
/** Show a custom component with keyboard focus. */
custom<T>(factory: (tui: TUI, theme: Theme, keybindings: KeybindingsManager$1, done: (result: T) => void) => (Component & {
dispose?(): void;
}) | Promise<Component & {
dispose?(): void;
}>, options?: {
overlay?: boolean;
/** Overlay positioning/sizing options. Can be static or a function for dynamic updates. */
overlayOptions?: OverlayOptions | (() => OverlayOptions);
/** Called with the overlay handle after the overlay is shown. Use to control visibility. */
onHandle?: (handle: OverlayHandle) => void;
}): Promise<T>;
/** Paste text into the editor, triggering paste handling (collapse for large content). */
pasteToEditor(text: string): void;
/** Set the text in the core input editor. */
setEditorText(text: string): void;
/** Get the current text from the core input editor. */
getEditorText(): string;
/** Show a multi-line editor for text editing. */
editor(title: string, prefill?: string): Promise<string | undefined>;
/** Stack additional autocomplete behavior on top of the built-in provider. */
addAutocompleteProvider(factory: AutocompleteProviderFactory): void;
/**
* Set a custom editor component via factory function.
* Pass undefined to restore the default editor.
*
* The factory receives:
* - `theme`: EditorTheme for styling borders and autocomplete
* - `keybindings`: KeybindingsManager for app-level keybindings
*
* For full app keybinding support (escape, ctrl+d, model switching, etc.),
* extend `CustomEditor` from `openclaw/plugin-sdk/agent-sessions` and call
* `super.handleInput(data)` for keys you don't handle.
*
* @example
* ```ts
* import { CustomEditor } from "openclaw/plugin-sdk/agent-sessions";
*
* class VimEditor extends CustomEditor {
* private mode: "normal" | "insert" = "insert";
*
* handleInput(data: string): void {
* if (this.mode === "normal") {
* // Handle vim normal mode keys...
* if (data === "i") { this.mode = "insert"; return; }
* }
* super.handleInput(data); // App keybindings + text editing
* }
* }
*
* ctx.ui.setEditorComponent((tui, theme, keybindings) =>
* new VimEditor(tui, theme, keybindings)
* );
* ```
*/
setEditorComponent(factory: EditorFactory | undefined): void;
/** Get the currently configured custom editor factory, or undefined when using the default editor. */
getEditorComponent(): EditorFactory | undefined;
/** Get the current theme for styling. */
readonly theme: Theme;
/** Get all available themes with their names and file paths. */
getAllThemes(): {
name: string;
path: string | undefined;
}[];
/** Load a theme by name without switching to it. Returns undefined if not found. */
getTheme(name: string): Theme | undefined;
/** Set the current theme by name or Theme object. */
setTheme(theme: string | Theme): {
success: boolean;
error?: string;
};
/** Get current tool output expansion state. */
getToolsExpanded(): boolean;
/** Set tool output expansion state. */
setToolsExpanded(expanded: boolean): void;
}
interface ContextUsage$1 {
/** Estimated context tokens, or null if any (e.g. right after compaction, before next LLM response). */
tokens: number | null;
contextWindow: number;
/** Context usage as percentage of context window, or null if tokens is unknown. */
percent: number | null;
}
interface CompactOptions {
customInstructions?: string;
onComplete?: (result: CompactionResult) => void;
onError?: (error: Error) => void;
}
/**
* Context passed to extension event handlers.
*/
interface ExtensionContext {
/** UI methods for user interaction */
ui: ExtensionUIContext;
/** Whether UI is available (false in print/RPC mode) */
hasUI: boolean;
/** Current working directory */
cwd: string;
/** Session manager (read-only) */
sessionManager: ReadonlySessionManager;
/** Model registry for API key resolution */
modelRegistry: ModelRegistry;
/** Current model (may be undefined) */
model: Model | undefined;
/** Whether the agent is idle (not streaming) */
isIdle(): boolean;
/** The current abort signal, or undefined when the agent is not streaming. */
signal: AbortSignal | undefined;
/** Abort the current agent operation */
abort(): void;
/** Whether there are queued messages waiting */
hasPendingMessages(): boolean;
/** Gracefully shut down OpenClaw and exit. Available in all contexts. */
shutdown(): void;
/** Get current context usage for the active model. */
getContextUsage(): ContextUsage$1 | undefined;
/** Trigger compaction without awaiting completion. */
compact(options?: CompactOptions): void;
/** Get the current effective system prompt. */
getSystemPrompt(): string;
}
/** Rendering options for tool results */
interface ToolRenderResultOptions {
/** Whether the result view is expanded */
expanded: boolean;
/** Whether this is a partial/streaming result */
isPartial: boolean;
}
/** Context passed to tool renderers. */
interface ToolRenderContext<TState = unknown, TArgs = unknown> {
/** Current tool call arguments. Shared across call/result renders for the same tool call. */
args: TArgs;
/** Unique id for this tool execution. Stable across call/result renders for the same tool call. */
toolCallId: string;
/** Invalidate just this tool execution component for redraw. */
invalidate: () => void;
/** Previously returned component for this render slot, if any. */
lastComponent: Component | undefined;
/** Shared renderer state for this tool row. Initialized by tool-execution.ts. */
state: TState;
/** Working directory for this tool execution. */
cwd: string;
/** Whether the tool execution has started. */
executionStarted: boolean;
/** Whether the tool call arguments are complete. */
argsComplete: boolean;
/** Whether the tool result is partial/streaming. */
isPartial: boolean;
/** Whether the result view is expanded. */
expanded: boolean;
/** Whether inline images are currently shown in the TUI. */
showImages: boolean;
/** Whether the current result is an error. */
isError: boolean;
}
type BivariantCallback<TArgs extends unknown[], TResult> = {
bivarianceHack(...args: TArgs): TResult;
}["bivarianceHack"];
/**
* Tool definition for registerTool().
*/
interface ToolDefinition<TParams extends TSchema = TSchema, TDetails = unknown, TState = unknown> {
/** Tool name (used in LLM tool calls) */
name: string;
/** Human-readable label for UI */
label: string;
/** Preserve lifecycle telemetry without rendering transient channel progress. */
hideFromChannelProgress?: boolean;
/** Tool results contain externally controlled network content. */
resultContentSource?: AgentTool["resultContentSource"];
/** Description for LLM */
description: string;
/** Optional one-line snippet for the Available tools section in the default system prompt. Custom tools are omitted from that section when this is not provided. */
promptSnippet?: string;
/** Optional guideline bullets appended to the default system prompt Guidelines section when this tool is active. */
promptGuidelines?: string[];
/** Parameter schema (TypeBox) */
parameters: TParams;
/** Exact schema for the structured value returned in AgentToolResult.details. */
outputSchema?: TSchema;
/** Controls whether ToolExecutionComponent renders the standard colored shell or the tool renders its own framing. */
renderShell?: "default" | "self";
/** Optional compatibility shim to prepare raw tool call arguments before schema validation. Must return an object conforming to TParams. */
prepareArguments?: (args: unknown) => Static<TParams>;
/**
* Per-tool execution mode override.
* - "sequential": this tool must execute one at a time with other tool calls.
* - "parallel": this tool can execute concurrently with other tool calls.
*
* If omitted, the default execution mode applies.
*/
executionMode?: ToolExecutionMode;
/** Execute the tool. */
execute(toolCallId: string, params: Static<TParams>, signal: AbortSignal | undefined, onUpdate: AgentToolUpdateCallback<TDetails> | undefined, ctx: ExtensionContext): Promise<AgentToolResult<TDetails>>;
/** Custom rendering for tool call display */
renderCall?: BivariantCallback<[args: Static<TParams>, theme: Theme, context: ToolRenderContext<TState, Static<TParams>>], Component>;
/** Custom rendering for tool result display */
renderResult?: BivariantCallback<[result: AgentToolResult<TDetails>, options: ToolRenderResultOptions, theme: Theme, context: ToolRenderContext<TState, Static<TParams>>], Component>;
}
//#endregion
//#region src/agents/model-catalog-lookup.d.ts
type ModelThinkingCompat = {
thinkingFormat?: ModelCompatConfig["thinkingFormat"];
supportedReasoningEfforts?: readonly string[] | null;
};
type PreparedModelThinkingCapability = Readonly<{
provider: string;
modelId: string;
agentRuntime: string;
/** Present only when the capability came from a physical provider route. */
route?: Readonly<{
api: string;
baseUrl: string;
}>;
compat: ModelThinkingCompat;
}>;
//#endregion
//#region src/agents/prepared-model-runtime.configured.d.ts
type PreparedConfiguredRuntimeModel = Readonly<{
provider: string;
modelId: string;
model: ProviderRuntimeModel;
}>;
//#endregion
//#region src/agents/prepared-model-runtime.types.d.ts
type PreparedModelRuntimeSnapshot = Readonly<{
catalogOwner: PublishedModelCatalogOwnerCandidate["catalogOwner"];
agentId?: string;
agentDir: string;
inheritedAuthDir?: string;
workspaceDir?: string;
/** Run-prepared repository root; null means discovery completed without a match. */
repoRoot?: string | null;
/** Stable identity derived from repoRoot; null means the run is outside a repository. */
projectKey?: string | null;
/** Session active project set, ordered most-recent first; empty before run binding. */
activeProjectKeys: readonly string[];
config: OpenClawConfig;
/** Native observations retain preparation identity across model-neutral config publications. */
observationConfig: OpenClawConfig;
isCurrent: () => boolean;
/** Secret-free usable auth modes captured by this exact lifecycle generation. */
authModes: PreparedAgentCredentialModes;
metadataSnapshot: PluginMetadataSnapshot;
messageToolCatalog?: PreparedMessageToolCatalog;
mediaCapabilityProviders?: ReturnType<typeof prepareMediaCapabilityProviders>;
/** Registry value owned by this generation; omitted from read-only builds. */
pluginRegistry?: PluginRegistry;
allowGatewaySubagentBinding: boolean;
/**
* Configured model projection used by turn admission and synchronous callers.
* Full inventory discovery is deliberately outside the startup publication boundary.
*/
modelCatalog: ModelCatalogSnapshot;
/** Reads a completed full catalog without starting provider discovery. */
readFullModelCatalog?: () => ModelCatalogSnapshot | undefined;
/** Builds this generation's full control-plane catalog without replacing turn facts. */
loadFullModelCatalog?: (options?: {
refresh?: boolean;
}) => Promise<ModelCatalogSnapshot>;
/** Full static models for configured refs, resolved once at the lifecycle boundary. */
configuredRuntimeModels: readonly PreparedConfiguredRuntimeModel[];
/** Inline provider projection prepared once for all resolutions owned by this snapshot. */
inlineProviderModels: readonly InlineModelEntry[];
createStores: () => PreparedModelRuntimeStores;
}>;
type PreparedModelRuntimeStores = {
authStorage: AuthStorage;
modelRegistry: ModelRegistry;
};
//#endregion
//#region src/plugins/provider-runtime.d.ts
declare function runProviderDynamicModel(params: {
provider: string;
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
context: ProviderResolveDynamicModelContext;
}): ProviderRuntimeModel | undefined;
declare function prepareProviderDynamicModel(params: {
provider: string;
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
context: ProviderPrepareDynamicModelContext;
}): Promise<ProviderRuntimeModel | void>;
declare function shouldPreferProviderRuntimeResolvedModel(params: {
provider: string;
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
context: ProviderPreferRuntimeResolvedModelContext;
}): boolean;
declare function normalizeProviderResolvedModelWithPlugin(params: {
provider: string;
modelId?: string | null;
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
pluginMetadataSnapshot?: PluginMetadataRegistryView;
context: {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
provider: string;
modelId: string;
model: ProviderRuntimeModel;
};
}): ProviderRuntimeModel | undefined;
declare function applyProviderResolvedTransportWithPlugin(params: {
provider: string;
modelId?: string | null;
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
context: ProviderNormalizeResolvedModelContext;
}): ProviderRuntimeModel | undefined;
declare function normalizeProviderTransportWithPlugin(params: {
provider: string;
modelId?: string | null;
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
context: ProviderNormalizeTransportContext;
}): {
api?: string | null;
baseUrl?: string;
} | undefined;
declare function buildProviderUnknownModelHintWithPlugin(params: {
provider: string;
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
context: ProviderBuildUnknownModelHintContext;
}): string | undefined;
//#endregion
//#region src/agents/embedded-agent-runner/model.provider-hooks.d.ts
type ProviderRuntimeHooks = {
applyProviderResolvedTransportWithPlugin?: (params: Parameters<typeof applyProviderResolvedTransportWithPlugin>[0]) => unknown;
buildProviderUnknownModelHintWithPlugin: (params: Parameters<typeof buildProviderUnknownModelHintWithPlugin>[0]) => string | undefined;
prepareProviderDynamicModel: (params: Parameters<typeof prepareProviderDynamicModel>[0]) => ReturnType<typeof prepareProviderDynamicModel>;
runProviderDynamicModel: (params: Parameters<typeof runProviderDynamicModel>[0]) => unknown;
shouldPreferProviderRuntimeResolvedModel?: (params: Parameters<typeof shouldPreferProviderRuntimeResolvedModel>[0]) => boolean;
normalizeProviderResolvedModelWithPlugin: (params: Parameters<typeof normalizeProviderResolvedModelWithPlugin>[0]) => unknown;
normalizeProviderTransportWithPlugin: typeof normalizeProviderTransportWithPlugin;
};
//#endregion
//#region src/agents/embedded-agent-runner/model.d.ts
type CommonModelResolutionOptions = {
authStorage?: AuthStorage;
modelRegistry?: ModelRegistry;
agentId?: string;
runtimeHooks?: ProviderRuntimeHooks;
skipProviderRuntimeHooks?: boolean;
workspaceDir?: string;
authProfileId?: string;
authProfileMode?: AuthProfileCredential["type"] | "aws-sdk";
preferredProfile?: string;
};
type AsyncModelResolutionOptions = CommonModelResolutionOptions & {
allowBundledStaticCatalogFallback?: boolean;
preferBundledStaticCatalogTransport?: boolean;
agentRuntimeId?: string;
skipAgentDiscovery?: boolean;
preparedModelRuntime?: PreparedModelRuntimeSnapshot;
};
declare function resolveModelAsync(provider: string, modelId: string, agentDir?: string, cfg?: OpenClawConfig, options?: AsyncModelResolutionOptions): Promise<{
model?: Model;
error?: string;
authStorage: AuthStorage;
modelRegistry: ModelRegistry;
}>;
//#endregion
//#region src/agents/model-auth-runtime-shared.d.ts
/** Resolved credential material and provenance for one provider request. */
type ResolvedProviderAuth = {
apiKey?: string;
profileId?: string;
source: string;
mode: "api-key" | "oauth" | "token" | "aws-sdk";
};
/** Require a normalized API key or throw a provider-auth error. */
declare function requireApiKey(auth: ResolvedProviderAuth, provider: string): string;
//#endregion
//#region src/agents/model-auth-model.d.ts
type ModelAuthMode = "api-key" | "oauth" | "token" | "mixed" | "aws-sdk" | "unknown";
//#endregion
//#region src/agents/simple-completion-runtime.d.ts
type AllowedMissingApiKeyMode = ResolvedProviderAuth["mode"];
type SimpleCompletionModelOptions = {
maxTokens?: number;
temperature?: number;
reasoning?: ThinkLevel | ThinkingLevel;
strictReasoningTags?: boolean;
signal?: AbortSignal;
};
type PreparedSimpleCompletionModel = {
model: Model;
auth: ResolvedProviderAuth;
/** Non-reversible owner proof captured from the same auth snapshot. */
sourceAuthFingerprint?: string;
} | {
error: string;
auth?: ResolvedProviderAuth;
};
declare function prepareSimpleCompletionModel(params: {
cfg: OpenClawConfig | undefined;
agentId?: string;
provider: string;
modelId: string;
agentDir?: string;
profileId?: string;
preferredProfile?: string;
allowMissingApiKeyModes?: ReadonlyArray<AllowedMissingApiKeyMode>;
allowBundledStaticCatalogFallback?: boolean;
skipAgentDiscovery?: boolean;
bindAuthOwner?: boolean;
modelResolver?: typeof resolveModelAsync;
/** Internal caller-owned generation. Public plugin callers use the agent helper below. */
preparedModelRuntime?: PreparedModelRuntimeSnapshot;
workspaceDir?: string;
agentRuntimeId?: string;
}): Promise<PreparedSimpleCompletionModel>;
declare function completeWithPreparedSimpleCompletionModel(params: {
assertCurrent?: () => void;
model: Model;
auth: ResolvedProviderAuth;
context: Parameters<typeof completeSimple>[1];
cfg?: OpenClawConfig;
options?: SimpleCompletionModelOptions;
}): Promise<AssistantMessage>;
//#endregion
//#region src/tts/tts-types.d.ts
/** Resolved directive override policy after config defaults are applied. */
type ResolvedTtsModelOverrides = SpeechModelOverridePolicy;
/** Fully resolved TTS runtime config consumed by synthesis and status paths. */
type ResolvedTtsConfig = {
auto: TtsAutoMode;
mode: TtsMode;
provider: TtsProvider;
providerSource: "config" | "default";
persona?: string;
personas: Record<string, ResolvedTtsPersona>;
summaryModel?: string;
modelOverrides: ResolvedTtsModelOverrides;
providerConfigs: Record<string, SpeechProviderConfig>;
prefsPath?: string;
maxTextLength: number;
timeoutMs: number;
timeoutMsSource?: "config" | "default";
rawConfig?: TtsConfig;
sourceConfig?: OpenClawConfig;
};
//#endregion
//#region src/tts/tts-core.d.ts
type SummarizeTextDeps = {
completeWithPreparedSimpleCompletionModel: typeof completeWithPreparedSimpleCompletionModel;
prepareSimpleCompletionModel: typeof prepareSimpleCompletionModel;
requireApiKey: typeof requireApiKey;
};
type SummarizeResult = {
summary: string;
latencyMs: number;
inputLength: number;
outputLength: number;
};
/** Summarize long text before synthesis using the configured summary model. */
declare function summarizeText(params: {
text: string;
targetLength: number;
cfg: OpenClawConfig;
config: ResolvedTtsConfig;
timeoutMs: number;
}, deps?: SummarizeTextDeps): Promise<SummarizeResult>;
//#endregion
//#region src/tts/tts-config.d.ts
/** Routing context used to layer global, agent, channel, and account TTS config. */
type TtsConfigResolutionContext = {
agentId?: string;
channelId?: string;
accountId?: string;
};
//#endregion
//#region src/tts/tts-settings.d.ts
declare function setTtsMachinePrefsPathResolver(resolver?: () => string | undefined): void;
declare function resolveModelOverridePolicy(overrides: TtsModelOverrideConfig | undefined): ResolvedTtsModelOverrides;
declare function resolveTtsConfig(cfgInput: OpenClawConfig, contextOrAgentId?: string | TtsConfigResolutionContext): ResolvedTtsConfig;
declare function resolveTtsPrefsPath(config: ResolvedTtsConfig): string;
declare function resolveTtsAutoMode(params: {
config: ResolvedTtsConfig;
prefsPath: string;
sessionAuto?: string;
}): TtsAutoMode;
declare function buildTtsSystemPromptHint(cfg: OpenClawConfig, agentId?: string, options?: {
messageToolOnly?: boolean;
}): string | undefined;
declare function isTtsEnabled(config: ResolvedTtsConfig, prefsPath: string, sessionAuto?: string): boolean;
declare function getTtsPersona(config: ResolvedTtsConfig, prefsPath: string): ResolvedTtsPersona | undefined;
declare function listTtsPersonas(config: ResolvedTtsConfig): ResolvedTtsPersona[];
declare function getTtsMaxLength(prefsPath: string): number;
declare function isSummarizationEnabled(prefsPath: string): boolean;
//#endregion
//#region src/tts/tts-provider-resolution.d.ts
declare function getResolvedSpeechProviderConfig(config: ResolvedTtsConfig, providerId: string, cfg?: OpenClawConfig): SpeechProviderConfig;
declare function resolveTtsProviderOrder(primary: TtsProvider, cfg?: OpenClawConfig, providers?: readonly SpeechProviderPlugin$1[]): TtsProvider[];
declare function isTtsProviderConfigured(config: ResolvedTtsConfig, provider: TtsProvider | SpeechProviderPlugin$1, cfg?: OpenClawConfig): boolean;
//#endregion
//#region src/tts/tts-runtime-types.d.ts
type TtsAttemptReasonCode = "success" | "no_provider_registered" | "not_configured" | "unsupported_for_streaming" | "unsupported_for_telephony" | "timeout" | "provider_error";
type TtsProviderAttempt = {
provider: string;
outcome: "success" | "skipped" | "failed";
reasonCode: TtsAttemptReasonCode;
persona?: string;
personaBinding?: "applied" | "missing" | "none";
latencyMs?: number;
error?: string;
};
type TtsAttemptOutcome = {
success: boolean;
error?: string;
latencyMs?: number;
provider?: string;
persona?: string;
fallbackFrom?: string;
attemptedProviders?: string[];
attempts?: TtsProviderAttempt[];
};
type TtsMediaOutcome = TtsAttemptOutcome & {
outputFormat?: string;
};
type TtsProviderMediaOutcome = TtsMediaOutcome & {
providerModel?: string;
providerVoice?: string;
};
type TtsVoiceMediaOutcome = TtsProviderMediaOutcome & {
voiceCompatible?: boolean;
fileExtension?: string;
target?: "audio-file" | "voice-note";
};
type TtsResult = TtsMediaOutcome & {
audioPath?: string;
voiceCompatible?: boolean;
audioAsVoice?: boolean;
target?: "audio-file" | "voice-note";
};
type TtsSynthesisResult = TtsVoiceMediaOutcome & {
audioBuffer?: Buffer;
};
type TtsStreamResult = TtsVoiceMediaOutcome & {
audioStream?: ReadableStream<Uint8Array>;
release?: () => Promise<void>;
};
type TtsSynthesisStreamResult = TtsStreamResult;
type TtsTelephonyResult = TtsProviderMediaOutcome & {
audioBuffer?: Buffer;
sampleRate?: number;
};
type TtsStatusEntry = TtsAttemptOutcome & {
timestamp: number;
textLength: number;
summarized: boolean;
};
//#endregion
//#region src/tts/tts-synthesis-support.d.ts
declare function formatTtsProviderError(provider: TtsProvider, err: unknown): string;
declare function sanitizeTtsErrorForLog(err: unknown): string;
//#endregion
//#region src/tts/tts-synthesis.d.ts
type TtsAudioPersistence = (params: {
audioBuffer: Buffer;
cfg: OpenClawConfig;
fileExtension: string;
outputFormat?: string;
}) => Promise<string>;
declare function supportsNativeVoiceNoteTts(channel: string | undefined): boolean;
declare function supportsTranscodedVoiceNoteTts(channel: string | undefined): boolean;
declare function resolveTtsSynthesisTarget(channel: string | undefined): "audio-file" | "voice-note";
declare function shouldDeliverTtsAsVoice(params: {
channel: string | undefined;
target: "audio-file" | "voice-note" | undefined;
voiceCompatible: boolean | undefined;
fileExtension?: string;
outputFormat?: string;
}): boolean;
declare function textToSpeechCore(params: {
text: string;
cfg: OpenClawConfig;
prefsPath?: string;
channel?: string;
overrides?: TtsDirectiveOverrides;
disableFallback?: boolean;
timeoutMs?: number;
agentId?: string;
accountId?: string;
}, persistTtsAudio: TtsAudioPersistence): Promise<TtsResult>;
type SpeechSynthesisParams = {
text: string;
cfg: OpenClawConfig;
prefsPath?: string;
channel?: string;
overrides?: TtsDirectiveOverrides;
disableFallback?: boolean;
timeoutMs?: number;
agentId?: string;
accountId?: string;
};
declare function synthesizeSpeech(params: SpeechSynthesisParams): Promise<TtsSynthesisResult>;
//#endregion
//#region src/tts/runtime-availability.d.ts
/** Host-owned availability guard shared by every speech runtime entrypoint. */
/** Installs the process-lifecycle availability guard owned by the OpenClaw host. */
declare function setSpeechRuntimeAvailabilityGuard(guard: (() => void) | undefined): void;
//#endregion
//#region src/tts/tts-settings-writes.d.ts
declare function setTtsAutoMode(prefsPath: string, mode: TtsAutoMode): void;
declare function setTtsEnabled(prefsPath: string, enabled: boolean): void;
declare function setTtsPersona(prefsPath: string, persona: string | null | undefined): void;
declare function setTtsProvider(prefsPath: string, provider: TtsProvider): void;
declare function setTtsMaxLength(prefsPath: string, maxLength: number): void;
declare function setSummarizationEnabled(prefsPath: string, enabled: boolean): void;
//#endregion
//#region src/tts/tts-payload.d.ts
declare function getLastTtsAttempt(): TtsStatusEntry | undefined;
declare function setLastTtsAttempt(entry: TtsStatusEntry | undefined): void;
declare function listSpeechVoices(params: {
provider: string;
cfg?: OpenClawConfig;
config?: ResolvedTtsConfig;
apiKey?: string;
baseUrl?: string;
}): Promise<SpeechVoiceOption[]>;
//#endregion
//#region src/tts/tts-request.d.ts
type PreparedTtsRequest = {
cfg: OpenClawConfig;
directives: TtsDirectiveParseResult;
};
/** Merge a surface TTS override and resolve its inline synthesis directives. */
declare function prepareTtsRequest(params: {
cfg: OpenClawConfig;
override?: TtsConfig;
text: string;
}): PreparedTtsRequest;
declare function resolveExplicitTtsOverrides(params: {
cfg: OpenClawConfig;
prefsPath?: string;
provider?: string;
modelId?: string;
voiceId?: string;
agentId?: string;
channelId?: string;
accountId?: string;
}): TtsDirectiveOverrides;
//#endregion
//#region src/tts/tts-streaming.d.ts
declare function streamSpeech(params: {
text: string;
cfg: OpenClawConfig;
prefsPath?: string;
channel?: string;
overrides?: TtsDirectiveOverrides;
disableFallback?: boolean;
timeoutMs?: number;
agentId?: string;
accountId?: string;
}): Promise<TtsSynthesisStreamResult>;
declare function textToSpeechStream(params: {
text: string;
cfg: OpenClawConfig;
prefsPath?: string;
channel?: string;
overrides?: TtsDirectiveOverrides;
disableFallback?: boolean;
timeoutMs?: number;
agentId?: string;
accountId?: string;
}): Promise<TtsStreamResult>;
//#endregion
//#region src/tts/tts-telephony.d.ts
declare function textToSpeechTelephony(params: {
text: string;
cfg: OpenClawConfig;
prefsPath?: string;
overrides?: TtsDirectiveOverrides;
timeoutMs?: number;
}): Promise<TtsTelephonyResult>;
declare namespace runtime_api_d_exports {
export { ResolvedTtsConfig, ResolvedTtsModelOverrides, TtsDirectiveOverrides, TtsDirectiveParseResult, TtsStreamResult, TtsSynthesisResult, TtsSynthesisStreamResult, TtsTelephonyResult, buildTtsSystemPromptHint, getLastTtsAttempt, getResolvedSpeechProviderConfig, getTtsMaxLength, getTtsPersona, getTtsProvider, isSummarizationEnabled, isTtsEnabled, isTtsProviderConfigured, listSpeechVoices, listTtsPersonas, prepareTtsRequest, resolveExplicitTtsOverrides, resolveTtsAutoMode, resolveTtsConfig, resolveTtsPrefsPath, resolveTtsProviderOrder, setLastTtsAttempt, setSpeechRuntimeAvailabilityGuard, setSummarizationEnabled, setTtsAutoMode, setTtsEnabled, setTtsMachinePrefsPathResolver, setTtsMaxLength, setTtsPersona, setTtsProvider, streamSpeech, synthesizeSpeech, testApi, textToSpeechStream, textToSpeechTelephony };
}
declare function getTtsProvider(config: ResolvedTtsConfig, prefsPath: string): TtsProvider;
declare const testApi: {
parseTtsDirectives: typeof parseTtsDirectives;
resolveModelOverridePolicy: typeof resolveModelOverridePolicy;
supportsNativeVoiceNoteTts: typeof supportsNativeVoiceNoteTts;
supportsTranscodedVoiceNoteTts: typeof supportsTranscodedVoiceNoteTts;
resolveTtsSynthesisTarget: typeof resolveTtsSynthesisTarget;
shouldDeliverTtsAsVoice: typeof shouldDeliverTtsAsVoice;
summarizeText: typeof summarizeText;
getResolvedSpeechProviderConfig: typeof getResolvedSpeechProviderConfig;
formatTtsProviderError: typeof formatTtsProviderError;
sanitizeTtsErrorForLog: typeof sanitizeTtsErrorForLog;
};
//#endregion
//#region src/tts/tts.d.ts
declare function textToSpeech(params: Parameters<typeof textToSpeechCore>[0]): Promise<TtsResult>;
//#endregion
//#region src/sessions/session-initialization.d.ts
/** Creation-only authority. Copied fields never identify an initializer to the host. */
type SessionInitialization = {
assertCurrent: () => void;
assertRollbackCurrent: () => void;
/** Prepares child policy data without constructing tools or acquiring run authority. */
prepareNativeToolPolicy?: (model: SessionNativeToolModel) => Promise<Readonly<{
webSearchAllowed: boolean;
}>>;
};
/** Native model selection data; the creation owner fixes every authority-bearing input. */
type SessionNativeToolModel = Readonly<{
provider: string;
runtimeProvider?: string;
id: string;
}>;
//#endregion
//#region src/agents/scheduled-tool-policy.d.ts
/** Trusted runtime context for a scheduled run with a server-stamped tool cap. */
type ScheduledToolPolicyContext = (Extract<CronScheduledToolPolicy, {
mode: "trusted";
}> | (Extract<CronScheduledToolPolicy, {
mode: "account";
}> & {
/** Missing legacy runtime contexts are treated as unknown and fail closed. */
ownerOrigin?: CronScheduledToolCallerOrigin;
})) & {
/** Restrict-only policy for the rebuilt exec tool; absence keeps baseline exec. */
execTarget?: {
host: "gateway";
ask?: "always";
};
};
declare namespace reply_run_finalization_lease_d_exports {
export { ReplyOperationStaleReason$1 as ReplyOperationStaleReason, beginReplyOperationFinalizationWork, createReplyRunFinalizationLease, createReplyRunSettleTimer, formatReplyOperationResult, resetReplyRunSettleTimersForTesting };
}
type ReplyOperationStaleReason$1 = "terminal_unreleased" | "finalization_stalled" | "no_activity" | "stuck_recovery";
declare function formatReplyOperationResult(result: {
kind: "completed";
} | {
kind: string;
code: string;
} | null): string;
type FinalizationLease = {
begin(): void;
beginWork(timeoutMs: number): () => void;
clear(): void;
recordActivity(): void;
};
type ReplyRunSettleTimer = {
clear(): void;
renew(timeoutMs: number): void;
scheduleOnce(timeoutMs: number): void;
};
declare function createReplyRunSettleTimer(params: {
canExpire: () => boolean;
onExpire: () => void;
}): ReplyRunSettleTimer;
declare function createReplyRunFinalizationLease(params: {
owner: object;
canExpire: () => boolean;
onActivity: () => void;
onExpire: () => void;
onFinalizationProgress: () => void;
}): FinalizationLease;
declare function beginReplyOperationFinalizationWork(owner: object, timeoutMs: number): () => void;
declare function resetReplyRunSettleTimersForTesting(): void;
//#endregion
//#region src/auto-reply/reply/reply-run-registry.contracts.d.ts
type ReplyRunKey = string;
type ReplyBackendKind = "embedded" | "cli";
type ReplyBackendCancelReason = "user_abort" | "restart" | "superseded";
type ReplyTurnKind = "visible" | "heartbeat" | "queued_followup";
type ReplyBackendQueueMessageOptions = {
steeringMode?: "all";
/** True when this queue item came from the channel's current user turn. */
isInboundUserMessage?: boolean;
/** Exact tool authority resolved for an inbound user turn before steering. */
toolAuthorityFingerprint?: string;
/** Internal proof that a mismatched route recomputes to the active run's full authority. */
pendingInputAuthorityFingerprint?: string;
debounceMs?: number;
/** Ordered current-turn images to inject with the steering text. */
images?: ImageContent$1[];
imageOrder?: PromptImageOrderEntry[];
/** Ordered facts represented by attachment text in this steering prompt. */
media?: MediaFact[];
deliveryTimeoutMs?: number;
waitForTranscriptCommit?: boolean;
/** Stable source identity for exact queued-message commit/cancellation matching. */
queueIdentity?: string;
abortSignal?: AbortSignal;
/** Releases arrival ordering once the runtime has actually accepted this queue item. */
onQueueAccepted?: (accepted: boolean) => void;
sourceReplyDeliveryMode?: SourceReplyDeliveryMode;
taskSuggestionDeliveryMode?: TaskSuggestionDeliveryMode;
/** Prepared channel turn to merge only at transcript persistence. */
userTurnTranscriptRecorder?: UserTurnTranscriptRecorder;
};
type ReplyToolAuthorityRoute = Readonly<{
provider: string;
model: string;
}>;
/** Per-message authority facts projected against an active run's frozen owner state. */
type ReplyToolAuthorityOverlay = Readonly<{
permissionMode?: SessionEntry$1["permissionMode"];
toolOverrides?: SessionEntry$1["toolOverrides"];
originatingChannel?: OriginatingChannelType;
messageProvider?: string;
chatType?: ChatType;
agentAccountId?: string;
conversationToolPolicy?: GroupToolPolicyConfig;
groupId?: string;
groupChannel?: string;
groupSpace?: string;
memberRoleIds?: string[];
spawnedBy?: string;
senderId?: string;
senderName?: string;
senderUsername?: string;
senderE164?: string;
senderIsOwner: boolean;
inputProvenance?: InputProvenance;
trustedInternalHandoff?: TrustedSubagentCompletionHandoff;
scheduledToolPolicy?: ScheduledToolPolicyContext;
runtimePluginToolGrant?: RuntimePluginToolGrant;
toolsAllow?: string[];
disableTools: boolean;
traceAuthorized: boolean;
approvalReviewerDeviceId?: string;
clientCaps?: string[];
toolBindings?: Readonly<Record<string, unknown>>;
}>;
type ReplyToolAuthoritySnapshot = Readonly<{
fingerprint(route?: ReplyToolAuthorityRoute): string;
project: (overlay: ReplyToolAuthorityOverlay, route: ReplyToolAuthorityRoute) => string;
}>;
type ReplyBackendQueueMessageResult = {
/** Input is non-replayable, but its delivery or commitment could not be confirmed. */
transcriptCommit: "unconfirmed";
errorMessage: string;
};
type ReplyBackendMessageInjection = {
/** Runtime-owned admission state; independent from token streaming. */
isAvailable(): boolean;
queueMessage(text: string, options?: ReplyBackendQueueMessageOptions): Promise<void | ReplyBackendQueueMessageResult>;
};
/** V2 sinks invoke the host-owned, per-injection assertion at their final effect. */
type ReplyBackendMessageInjectionV2 = {
readonly version: 2;
isAvailable(): boolean;
queueMessage(text: string, options: ReplyBackendQueueMessageOptions | undefined, assertCurrent: () => void, authorityKind: "run" | "source-bound"): Promise<void | ReplyBackendQueueMessageResult>;
claimPendingUserInputAnswer?(text: string, options: ReplyBackendQueueMessageOptions | undefined, assertCurrent: () => void, authorityKind: "run" | "source-bound"): Promise<boolean>;
cancelPendingUserInput?(resolvedBy: string, assertCurrent: () => void, authorityKind: "run" | "source-bound"): Promise<boolean>;
};
type ReplyBackendHandle = {
readonly kind: ReplyBackendKind;
readonly runId?: string;
/** Exact authority of this concrete backend attempt, after fallback selection. */
readonly toolAuthorityFingerprint?: string;
readonly sourceReplyDeliveryMode?: SourceReplyDeliveryMode;
readonly taskSuggestionDeliveryMode?: TaskSuggestionDeliveryMode;
/** True only when queueMessage preserves images supplied in its options. */
readonly supportsQueueMessageImages?: boolean;
claimPendingUserInputAnswer?: (text: string, options?: ReplyBackendQueueMessageOptions) => Promise<boolean>;
cancelPendingUserInput?: (resolvedBy: string) => Promise<boolean>;
cancel(reason?: ReplyBackendCancelReason): void;
readonly messageInjection?: ReplyBackendMessageInjection;
/** V1 remains compatible with v2026.8.1; source-bound input requires V2. */
readonly messageInjectionV2?: ReplyBackendMessageInjectionV2;
/** @deprecated Compatibility for shipped embedded handles. Use messageInjection. */
isStreaming?: () => boolean;
isStopped?: () => boolean;
isAbortable?: () => boolean;
/** @deprecated Compatibility for shipped embedded handles. Use messageInjection. */
queueMessage?: (text: string, options?: ReplyBackendQueueMessageOptions) => Promise<void | ReplyBackendQueueMessageResult>;
/**
* Compatibility-only hook so legacy "abort compacting runs" paths can still
* find embedded runs that are compacting during the main run phase.
*/
isCompacting?: () => boolean;
};
/** Prevents steering a turn into a run that cannot preserve its model-facing input. */
type ReplyOperationPhase = "queued" | "waiting_for_deferred_maintenance" | "waiting_for_global_lane" | "preflight_compacting" | "memory_flushing" | "running" | "completed" | "failed" | "aborted";
type ReplyOperationFailureCode = "gateway_draining" | "command_lane_cleared" | "aborted_by_user" | "session_corruption_reset" | "run_stalled" | "run_failed";
type ReplyOperationAbortCode = "aborted_by_user" | "aborted_for_restart" | "aborted_for_supersession";
type ReplyOperationResult = {
kind: "completed";
} | {
kind: "failed";
code: ReplyOperationFailureCode;
cause?: unknown;
} | {
kind: "aborted";
code: ReplyOperationAbortCode;
};
type ReplyOperation = {
readonly key: ReplyRunKey;
readonly sessionId: string;
readonly turnKind: ReplyTurnKind;
/** Gateway lifecycle that admitted this process-local owner. */
readonly lifecycleGeneration?: string;
readonly routeThreadId?: string | number;
/** Transcript branch leaf from which this operation was admitted. */
readonly originatingLeafEntryId?: string | null;
readonly abortSignal: AbortSignal;
readonly resetTriggered: boolean;
/**
* True when this operation was admitted to recover a terminal session (a
* leftover failed/timeout/killed run). Concurrent visible turns reading the
* same terminal store snapshot must NOT force-clear such an operation: it is a
* sibling recovery already in flight, not the proven stale leftover.
*/
readonly terminalRecovery: boolean;
/**
* Sticky fact for audio accepted into this operation after its originating turn.
* Final delivery reads it because the original dispatch context cannot change.
*/
readonly acceptedSteeredInboundAudio: boolean;
/** Immutable tool authority accepted by the active backend for steered user turns. */
readonly toolAuthorityFingerprint?: string;
/** Concrete provider/model route currently selected for this operation. */
readonly toolAuthorityRoute?: ReplyToolAuthorityRoute;
readonly phase: ReplyOperationPhase;
readonly result: ReplyOperationResult | null;
/** Set when a stale-watchdog expiry forced this operation's run_stalled result. */
readonly staleExpiryReason?: ReplyOperationStaleReason;
readonly startedAtMs: number;
readonly lastActivityAtMs: number;
/** True when this operation has owned the supplied session ID. */
hasOwnedSessionId(sessionId: string): boolean;
recordActivity(): void;
setPhase(next: "queued" | "waiting_for_deferred_maintenance" | "waiting_for_global_lane" | "preflight_compacting" | "memory_flushing" | "running"): void;
/** Mark this operation as waiting on prior same-session maintenance. */
markWaitingForDeferredMaintenance(): void;
/** Return a maintenance-waiting operation to queued if the run has not started. */
markDeferredMaintenanceWaitEnded(): void;
/** Mark this operation as waiting for process-global run capacity. */
markWaitingForGlobalLane(): void;
/** Return a global-lane-waiting operation to queued once capacity is granted. */
markGlobalLaneWaitEnded(): void;
/** Mark this operation as an in-flight terminal-session recovery. */
markTerminalRecovery(): void;
markAcceptedSteeredInboundAudio(): void;
/** Freeze the complete caller policy before a concrete backend attempt attaches. */
bindToolAuthoritySnapshot(snapshot: ReplyToolAuthoritySnapshot): void;
/** Project an inbound turn through the current concrete route; settled owners fail closed. */
projectToolAuthorityFingerprint(overlay: ReplyToolAuthorityOverlay): string | undefined;
/** Prepare fingerprint and projection together for the final concrete attempt route. */
bindToolAuthorityRoute(route: ReplyToolAuthorityRoute): string;
updateSessionId(nextSessionId: string): void;
/**
* Move this queued operation to another session key's run slot. Native command
* turns admit under the slash SOURCE key; when the command continues into a full
* agent turn it must own the TARGET session's slot so concurrent target inbounds
* queue/steer instead of double-admitting. Throws ReplyRunAlreadyActiveError when
* the target slot is owned.
*/
updateSessionKey(nextSessionKey: string): void;
attachBackend(handle: ReplyBackendHandle): void;
detachBackend(handle: ReplyBackendHandle): void;
/** Reject later aborts after the backend has committed its terminal outcome. */
freezeAbort(): void;
/**
* Keep a failed operation active until complete() releases the session lane.
* Dispatch uses this while a user-visible failure payload still needs delivery.
*/
retainFailureUntilComplete(): void;
/** Settles after the lifecycle owner's final delivery/persistence barrier. */
readonly ownerSettlement?: Promise<void>;
complete(): void;
/**
* Complete the operation, clear active-run state, then run follow-up work.
* Use when the follow-up can create another ReplyOperation for this session.
*/
completeThen(afterClear: () => void): void;
/**
* Clear active-run state immediately, but delay registered after-clear work
* until delivery or another external barrier settles.
*/
completeWithAfterClearBarrier(barrier: PromiseLike<unknown>, timeout?: number | ReplyFollowupAdmissionBarrierTimeoutPolicy): void;
fail(code: Exclude<ReplyOperationFailureCode, "aborted_by_user">, cause?: unknown): void;
abortByUser(): boolean;
abortForRestart(): boolean;
supersede(beforeSupersede?: () => void): boolean;
};
type ReplyOperationStaleReason = ReplyOperationStaleReason$1;
//#endregion
//#region src/skills/types.d.ts
type SkillTelemetrySource = "bundled" | "unknown" | "workspace";
type SkillUsagePath = {
/** Path visible to the tool runtime when it reads SKILL.md. */
readPath: string;
/** Canonical source SKILL.md path used as the lifecycle identity. */
skillFile: string;
skillName: string;
skillSource: SkillTelemetrySource;
};
type ExplicitSkillSelection = {
name: string;
path: string;
};
type SkillEligibilityContext = {
nodeSkills?: {
canExec: boolean;
node?: string;
};
remote?: {
platforms: string[];
hasBin: (bin: string) => boolean;
hasAnyBin: (bins: string[]) => boolean;
note?: string;
};
};
type SkillSnapshot = {
librarySelections?: SkillLibrarySelection[];
prompt: string;
/** Complete eligible sync identities, including skills hidden from the model prompt. */
skills: Array<{
name: string;
/** Config key can differ from the prompt-facing skill name. */
skillKey?: string;
primaryEnv?: string;
requiredEnv?: string[];
}>;
/** Normalized agent-level filter used to build this snapshot; undefined means unrestricted. */
skillFilter?: string[];
/** Sparse per-session overlay applied after the agent-level filter. */
skillOverrides?: Record<string, boolean>;
/** Effective node-exec eligibility used to select connected node-hosted skills. */
nodeSkillsEligibility?: SkillEligibilityContext["nodeSkills"];
resolvedSkills?: Skill[];
/** Present only when a session merges skills from distinct agent and execution roots. */
skillRoots?: {
agentWorkspaceDir: string;
executionSkillsDir: string;
};
version?: number;
promptFormatVersion?: number;
};
//#endregion
//#region src/skills/library/authoring.d.ts
type SkillLibraryAuthoringInput = {
action: "list" | "read" | "create" | "update" | "share" | "unshare" | "transfer" | "activate" | "remove" | "rollback";
skillId?: string;
expectedRevision?: string;
revision?: string;
slug?: string;
content?: string;
files?: SkillLibraryFile[];
deleteFiles?: string[];
};
/** Host-held namespace capability; never persisted or reconstructed from session attribution. */
type SkillLibraryAuthoringCapability = {
target: "personal";
defaultTarget: "workspace" | "personal";
multipleProfiles: boolean;
assertWorkspaceCurrent?: () => void;
bind: (context: AdmittedRunContext) => void;
invoke: (params: SkillLibraryAuthoringInput) => Promise<SkillsLibraryReceipt | SkillsLibraryReadResult | SkillsLibraryActivateResult | SkillsLibraryListResult>;
};
//#endregion
//#region src/skills/workshop/collection-contracts.d.ts
type SkillCollectionReconcileResult = {
backupId: string;
kept: string[];
written: string[];
dropped: Array<{
name: string;
reason: string;
}>;
};
type SkillCollectionReconcileContext = {
agentIds?: string[];
approvedSkillNames?: Set<string>;
approvedSkillNamesByAgent?: Array<Set<string>>;
readSkillHashes?: Map<string, string>;
readSkillTreeHashes?: Map<string, string>;
readSkillBytes?: Map<string, number>;
readByteCount?: number;
assertCurrent?: () => void;
reconciling?: boolean;
result?: SkillCollectionReconcileResult;
};
//#endregion
//#region src/skills/workshop/types.d.ts
type SkillProposalOrigin = {
agentId?: string;
sessionKey?: string;
runId?: string;
messageId?: string;
};
type SkillWorkshopPreparedPatch = {
skillFile: string;
contentHash: string;
oldString: string;
};
/** Run-scoped budget shared by every workshop tool instance created across runner retries. */
type SkillWorkshopProposalMutationBudget = {
remaining: number;
/** Distinct proposal records successfully mutated by this run. */
completed?: number;
/** Successful persisted mutation calls, including repeated revisions. */
successfulMutations?: number;
/** Failed or incompletely checkpointed reservations in the current model run. */
failedMutations?: number;
/** Run-local identity set used to keep idea counts distinct. */
mutatedProposalIds?: Set<string>;
/** Content hash per live skill read this run; autonomous updates require a matching receipt. */
readSkillHashes?: Map<string, string>;
/** Single-use exact-span patch authority prepared from authoritative live content. */
preparedSkillPatches?: Map<string, SkillWorkshopPreparedPatch>;
};
type SkillWorkshopProposalReviewProgress = {
proposalIds: string[];
remaining: number;
successfulMutations: number;
};
/** Shared completion latch for proposal-only reviewers that require a durable final checkpoint. */
type SkillWorkshopProposalReviewCompletion = {
activeMutations?: Set<Promise<void>>;
completed: boolean;
complete: () => Promise<void>;
phase?: "open" | "completing" | "completed";
recordProgress?: (progress: SkillWorkshopProposalReviewProgress) => Promise<void>;
};
/** Exact proposal revision an operator reviewed before requesting an agent-authored revision. */
type SkillWorkshopProposalRevisionConstraint = {
readonly agentId: string;
readonly workspaceDir: string;
readonly proposalId: string;
readonly expectedRevisionHash: string;
};
type SkillWorkshopRunOptions = {
libraryAuthoring?: SkillLibraryAuthoringCapability;
env?: NodeJS.ProcessEnv;
proposalOnly?: boolean;
updateProposals?: boolean;
autonomousCapture?: boolean;
origin?: SkillProposalOrigin;
proposalMutationBudget?: SkillWorkshopProposalMutationBudget;
proposalReviewCompletion?: SkillWorkshopProposalReviewCompletion;
collectionReconcile?: SkillCollectionReconcileContext;
proposalRevision?: SkillWorkshopProposalRevisionConstraint;
};
//#endregion
//#region src/agents/agent-scope.d.ts
type ModelFallbackAvailability = {
kind: "active";
models: string[];
source: "explicit" | "inherited";
} | {
kind: "none_configured";
source: "explicit" | "inherited";
} | {
kind: "disabled_by_model_override";
} | {
kind: "disabled_by_model_selection_lock";
};
//#endregion
//#region src/agents/bash-tools.exec-approval-output.d.ts
type ExecApprovalContinuationPromptRange = {
start: number;
end: number;
};
//#endregion
//#region src/infra/event-session-routing.d.ts
/** Routing policy derived from config and the source session for an event. */
type EventSessionRoutingPolicy = {
mainKey?: string;
sessionScope?: SessionScope;
dmScope?: string | null;
allowFrom?: ReadonlyArray<string | number> | null;
channel?: string | null;
accountId?: string | null;
preserveSessionKey?: boolean;
};
//#endregion
//#region src/infra/exec-auto-review.d.ts
/** Risk level returned by exec auto-reviewers for approval routing decisions. */
type ExecAutoReviewRisk = "unknown" | "low" | "medium" | "high";
/** Auto-review outcome: either approve once or send the command to normal approval. */
type ExecAutoReviewDecision = {
decision: "allow-once";
rationale: string;
risk: "low";
} | {
decision: "ask";
rationale: string;
risk: ExecAutoReviewRisk;
};
/** Execution host whose command policy context is being reviewed. */
type ExecAutoReviewHost = "gateway" | "node" | "codex-app-server";
/** Command and policy facts supplied to an exec auto-reviewer. */
type ExecAutoReviewInput = {
command: string;
argv?: readonly string[];
resolvedPath?: string | null;
cwd?: string | null;
envKeys?: readonly string[];
host: ExecAutoReviewHost;
reason: "approval-required" | "allowlist-miss" | "strict-inline-eval" | "heredoc" | "execution-plan-miss";
analysis: {
parsed: boolean;
allowlistMatched: boolean;
safeBinMatched?: boolean;
durableApprovalMatched?: boolean;
inlineEval: boolean;
heredoc?: boolean;
shellWrapper?: boolean;
};
agent?: {
id?: string | null;
sessionKey?: string | null;
};
};
/** Reviewer function used by gateway/node exec paths before human approval fallback. */
type ExecAutoReviewer = (input: ExecAutoReviewInput) => Promise<ExecAutoReviewDecision> | ExecAutoReviewDecision;
//#endregion
//#region src/agents/sandbox/fs-bridge.types.d.ts
/**
* Public sandbox filesystem bridge contracts.
*
* Tool and backend code use this interface to access files through the sandbox
* boundary instead of reaching directly into host paths.
*/
/** Resolved sandbox path with host, relative, and container views. */
type SandboxResolvedPath = {
hostPath?: string;
relativePath: string;
containerPath: string;
};
/** Minimal file stat shape returned by sandbox fs bridge implementations. */
type SandboxFsStat = {
type: "file" | "directory" | "other";
size: number;
mtimeMs: number;
};
/** Filesystem operations exposed across the sandbox boundary. */
type SandboxFsBridge = {
resolvePath(params: {
filePath: string;
cwd?: string;
}): SandboxResolvedPath;
/** Reads a safely opened regular file, rejecting growth beyond an optional byte limit. */
readFile(params: {
filePath: string;
cwd?: string;
signal?: AbortSignal;
maxBytes?: number;
}): Promise<Buffer>;
/** Streams a regular file within the sandbox when the backend supports native copying. */
copyFile?(params: {
sourcePath: string;
destinationPath: string;
cwd?: string;
mkdir?: boolean;
signal?: AbortSignal;
}): Promise<void>;
writeFile(params: {
filePath: string;
cwd?: string;
data: Buffer | string;
encoding?: BufferEncoding;
mkdir?: boolean;
signal?: AbortSignal;
}): Promise<void>;
/**
* Atomically creates a file only when no entry already exists at the path.
* Backends without this capability must omit it rather than emulate it with
* a check followed by writeFile.
*/
createFileExclusive?(params: {
filePath: string;
cwd?: string;
data: Buffer | string;
encoding?: BufferEncoding;
mkdir?: boolean;
signal?: AbortSignal;
}): Promise<"created" | "exists">;
mkdirp(params: {
filePath: string;
cwd?: string;
signal?: AbortSignal;
}): Promise<void>;
remove(params: {
filePath: string;
cwd?: string;
recursive?: boolean;
force?: boolean;
signal?: AbortSignal;
}): Promise<void>;
rename(params: {
from: string;
to: string;
cwd?: string;
signal?: AbortSignal;
}): Promise<void>;
stat(params: {
filePath: string;
cwd?: string;
signal?: AbortSignal;
}): Promise<SandboxFsStat | null>;
};
//#endregion
//#region src/agents/sandbox/backend-handle.types.d.ts
/**
* Backend-neutral sandbox runtime handles used by Docker, SSH, and future sandbox providers.
*/
type SandboxBackendId = string;
/** Shell exec specification prepared by a sandbox backend for process launch. */
type SandboxBackendExecSpec = {
argv: string[];
env: NodeJS.ProcessEnv;
stdinMode: "pipe-open" | "pipe-closed";
finalizeToken?: unknown;
};
type SandboxBackendWorkdirValidation = "host" | "backend";
type SandboxBackendWorkdirValidator = (workdir: string) => Promise<string | null>;
type SandboxBackendPreparedWorkdirDiscarder = (workdir: string) => void;
/** Parameters for backend-managed shell commands used by fs bridges and probes. */
type SandboxBackendCommandParams = {
script: string;
args?: string[];
stdin?: Buffer | string;
allowFailure?: boolean;
signal?: AbortSignal;
};
/** Buffered command result returned by sandbox backend shell helpers. */
type SandboxBackendCommandResult = {
stdout: Buffer;
stderr: Buffer;
code: number;
};
/** Runtime context passed to backend-provided filesystem bridge factories. */
type SandboxFsBridgeContext = {
workspaceDir: string;
agentWorkspaceDir: string;
skillsWorkspaceDir?: string;
readOnlyResourceMounts?: Array<{
hostPath: string;
containerPath: string;
}>;
workspaceAccess: "none" | "ro" | "rw";
containerName: string;
containerWorkdir: string;
docker: {
binds?: string[];
};
backend?: {
runShellCommand(params: SandboxBackendCommandParams): Promise<SandboxBackendCommandResult>;
};
};
/** Live sandbox backend handle for command execution, cleanup, and optional fs bridge creation. */
type SandboxBackendHandle = {
id: SandboxBackendId;
runtimeId: string;
runtimeLabel: string;
workdir: string;
env?: Record<string, string>;
configLabel?: string;
configLabelKind?: string;
/**
* Remote backends own cwd existence checks because valid runtime paths may
* not exist in the local workspace mirror. Backend validation must be paired
* with validateWorkdir so cwd is proved after before_tool_call adjustments
* and before env resolution, approval, preflight, and launch.
*/
workdirValidation?: SandboxBackendWorkdirValidation;
validateWorkdir?: SandboxBackendWorkdirValidator;
/** Discard one-shot state created while validating a backend-owned cwd. */
discardPreparedWorkdir?: SandboxBackendPreparedWorkdirDiscarder;
/** Remote cwd roots managed by backend validation. Defaults to workdir. */
workdirRoots?: readonly string[];
capabilities?: {
browser?: boolean;
};
buildExecSpec(params: {
command: string;
workdir?: string;
env: Record<string, string>;
usePty: boolean;
}): Promise<SandboxBackendExecSpec>;
finalizeExec?: (params: {
status: "completed" | "failed";
exitCode: number | null;
timedOut: boolean;
token?: unknown;
}) => Promise<void>;
runShellCommand(params: SandboxBackendCommandParams): Promise<SandboxBackendCommandResult>;
createFsBridge?: (params: {
sandbox: SandboxFsBridgeContext;
}) => SandboxFsBridge;
};
//#endregion
//#region src/agents/bash-tools.shared.d.ts
/** Sandbox metadata needed to map host workspaces into container exec calls. */
type BashSandboxWorkdirMount = {
hostPath: string;
containerPath: string;
};
type BashSandboxConfig = {
containerName: string;
workspaceDir: string;
containerWorkdir: string;
workdirValidation?: SandboxBackendWorkdirValidation;
validateWorkdir?: SandboxBackendWorkdirValidator;
discardPreparedWorkdir?: (workdir: string) => void;
workdirRoots?: readonly string[];
/** Approved read-only skill mounts that may be selected as an exec workdir. */
readOnlyWorkspaceSkillMounts?: readonly BashSandboxWorkdirMount[];
env?: Record<string, string>;
buildExecSpec?: (params: {
command: string;
workdir?: string;
env: Record<string, string>;
usePty: boolean;
}) => Promise<SandboxBackendExecSpec>;
finalizeExec?: (params: {
status: "completed" | "failed";
exitCode: number | null;
timedOut: boolean;
token?: unknown;
}) => Promise<void>;
};
//#endregion
//#region src/auto-reply/heartbeat-tool-response.d.ts
/** Allowed heartbeat response outcomes. */
declare const HEARTBEAT_TOOL_OUTCOMES: readonly ["no_change", "progress", "done", "blocked", "needs_attention"];
type HeartbeatToolOutcome = (typeof HEARTBEAT_TOOL_OUTCOMES)[number];
/** Allowed heartbeat notification priorities. */
declare const HEARTBEAT_TOOL_PRIORITIES: readonly ["low", "normal", "high"];
type HeartbeatToolPriority = (typeof HEARTBEAT_TOOL_PRIORITIES)[number];
/** Normalized response emitted by the heartbeat response tool. */
type HeartbeatToolResponse = {
outcome: HeartbeatToolOutcome;
notify: boolean;
summary: string;
notificationText?: string;
reason?: string;
priority?: HeartbeatToolPriority;
nextCheck?: string;
/** Complete replacement for the current heartbeat monitor's private scratch. */
scratch?: string;
};
//#endregion
//#region src/agents/accepted-session-spawn.d.ts
type AcceptedSessionSpawn = {
runId: string;
childSessionKey: string;
/** True only when this child owns a terminal completion for its requester. */
expectsCompletionMessage?: boolean;
};
//#endregion
//#region src/agents/agent-run-terminal-receipt.d.ts
type AgentRunTerminalModelRef = {
provider: string;
model: string;
};
type AgentRunTerminalReceipt = {
runId: string;
sessionId: string;
turnId: string;
requested: AgentRunTerminalModelRef;
effective: AgentRunTerminalModelRef & {
responseModel: string;
};
successfulToolNames: string[];
/** A final reply was delivered to the external source conversation. */
sourceReplyDelivered?: true;
rerouted: boolean;
terminalDisposition: "visible" | "not-visible";
};
//#endregion
//#region src/agents/agent-run-terminal-reply.d.ts
type AgentRunTerminalReplySnapshot = {
disposition: "visible";
text: string;
modelRouteChange?: string;
} | {
disposition: "silent";
} | {
disposition: "empty";
code?: "message-tool-not-called";
};
//#endregion
//#region src/agents/embedded-agent-messaging.types.d.ts
type MessagingToolSend = {
tool: string;
provider: string;
accountId?: string;
to?: string;
threadId?: string;
threadImplicit?: boolean;
threadSuppressed?: boolean;
text?: string;
mediaUrls?: string[];
hasRichContent?: true;
/** Current-source progress (`false`) or completed reply (`true`). */
sourceReplyFinal?: boolean;
};
type MessagingToolSourceReplyPayload = Pick<ReplyPayload, "audioAsVoice" | "attachments" | "channelData" | "interactive" | "mediaUrl" | "mediaUrls" | "presentation" | "text" | "trustedLocalMedia"> & {
idempotencyKey?: string;
transcriptOwner?: true;
/** Current-source progress (`false`) or completed reply (`true`). */
sourceReplyFinal?: boolean;
};
//#endregion
//#region src/agents/mcp-connect-action.d.ts
type McpConnectAction = {
serverName: string;
authorizationUrl: string;
};
//#endregion
//#region src/agents/mcp-codex-tool-approval.d.ts
type McpCodexToolAnnotations = {
readOnlyHint?: boolean;
destructiveHint?: boolean;
idempotentHint?: boolean;
openWorldHint?: boolean;
};
//#endregion
//#region src/agents/agent-bundle-mcp-types.d.ts
/** Catalog metadata for one configured MCP server. */
type McpServerCatalog = {
serverName: string;
safeServerName?: string;
launchSummary: string;
toolCount: number;
resources?: {
listChanged?: boolean;
};
prompts?: {
listChanged?: boolean;
};
tools?: {
listChanged?: boolean;
filteredCount?: number;
};
requestTimeoutMs?: number;
supportsParallelToolCalls?: boolean;
toolFilter?: McpServerToolFilterConfig;
deniedToolNames?: string[];
codexApprovalMode?: McpCodexToolApprovalMode;
};
/** MCP tool entry after server-name sanitization and schema normalization. */
type McpCatalogTool = {
serverName: string;
safeServerName: string;
toolName: string;
title?: string;
description?: string;
inputSchema: TSchema;
fallbackDescription: string;
uiResourceUri?: string;
uiVisibility?: Array<"app" | "model">;
/** Listed by the server but excluded from OpenClaw's callable tool catalog. */
excludedFromOpenClawCatalog?: true;
deniedBySession?: true;
codexAnnotations?: McpCodexToolAnnotations;
};
/** Complete tool catalog for a session-scoped MCP runtime. */
type McpToolCatalog = {
version: number;
generatedAt: number;
servers: Record<string, McpServerCatalog>;
tools: McpCatalogTool[];
/** Complete raw catalog used to project policy into native MCP clients. */
policyTools?: McpCatalogTool[];
/** Listed tools hidden only by the session override, retained for read-only inventory. */
sessionDeniedTools?: McpCatalogTool[];
diagnostics?: readonly McpToolCatalogDiagnostic[];
};
type McpToolCatalogDiagnostic = {
serverName: string;
safeServerName: string;
launchSummary: string;
message: string;
};
//#endregion
//#region src/agents/mcp-ui-resource.d.ts
type McpAppChannelView = {
viewId: string;
};
//#endregion
//#region src/agents/model-fallback.types.d.ts
type FallbackAttempt = {
provider: string;
model: string;
error: string;
reason?: FailoverReason;
authMode?: string;
status?: number;
code?: string;
};
/** Original route plus the outer fallback stage that admitted one real attempt. */
type ModelFallbackAttemptProvenance = {
requestedProvider: string;
requestedModel: string;
stage: "initial" | "fallback";
fallbackReason?: FailoverReason;
};
//#endregion
//#region src/plugin-sdk/provider-model-types.d.ts
/** A concrete provider route. Order expresses provider default, never credential precedence. */
type ProviderModelRouteAuthRequirement = "api-key" | "subscription";
type ProviderRouteOverridePresence = "none" | "present";
type ProviderModelRouteRuntimePolicy = {
/** Agent runtime ids that can reproduce this route without losing transport behavior. */
compatibleIds: readonly string[];
};
//#endregion
//#region src/agents/provider-model-auth-source-plan.d.ts
type ProviderModelAuthEvidence = "aws-sdk" | "environment" | "none" | "profile" | "provider-config" | "runtime" | "synthetic";
/**
* Whether config authorizes this credential, as opposed to where it was found.
*
* `evidence` is provenance and is reported as such by status/probe surfaces; it
* cannot carry authorization, because a *declared* credential can legitimately
* be discovered in the environment (a `${VAR}` marker or a SecretRef naming a
* canonical variable). `"ambient"` means the opposite: the credential appears in
* neither the provider entry nor `auth.profiles`/`auth.order`, so nothing in
* config points at it and it may bill an account the operator never named here.
*/
type ProviderModelAuthAuthorization = "declared" | "ambient";
/** Secret-free credential-source fact safe to carry across request boundaries. */
type ProviderModelAuthSourceClassification = {
kind: "profile";
} | {
kind: "direct";
evidence: ProviderModelAuthEvidence;
authorization: ProviderModelAuthAuthorization;
};
//#endregion
//#region src/agents/runtime-plan/types.d.ts
/** Runtime transport selected for one model attempt. */
type AgentRuntimeTransport = "sse" | "websocket" | "websocket-cached" | "auto";
/** Thinking levels accepted by runtime-plan extra-param preparation. */
type AgentRuntimeThinkLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive" | "max";
/** System prompt rendering mode selected for one attempt. */
type AgentRuntimePromptMode = "full" | "minimal" | "none";
/** Trigger source that can alter provider system prompt contributions. */
type AgentRuntimePromptTrigger = "cron" | "heartbeat" | "manual" | "memory" | "overflow" | "user";
/** Normalized failure reason used by model fallback classification. */
type AgentRuntimeFailoverReason = "auth" | "auth_permanent" | "format" | "rate_limit" | "overloaded" | "billing" | "server_error" | "timeout" | "tls_certificate" | "context_overflow" | "model_not_found" | "session_expired" | "empty_response" | "no_error_details" | "unclassified" | "unknown";
/** Provider model descriptor consumed by runtime-plan hooks. */
type AgentRuntimeModel = {
id?: string;
name?: string;
api?: string;
provider?: string;
baseUrl?: string;
reasoning?: boolean;
input?: readonly string[];
cost?: {
input: number;
output: number;
cacheRead: number;
cacheWrite: number;
};
contextWindow?: number;
maxTokens?: number;
contextTokens?: number;
compat?: unknown;
};
/** Text replacement rule used by provider input/output transforms. */
type AgentRuntimeTextReplacement = {
from: string | RegExp;
to: string;
};
/** Provider text transforms applied around model calls. */
type AgentRuntimeTextTransforms = {
input?: AgentRuntimeTextReplacement[];
output?: AgentRuntimeTextReplacement[];
};
/** Resolved provider runtime handle forwarded to plugin-owned hooks. */
type AgentRuntimeProviderHandle = {
provider: string;
modelId?: string | null;
config?: unknown;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
applyAutoEnable?: boolean;
};
type PreparedAgentRuntimeProviderHandle = AgentRuntimeProviderHandle & {
modelId: string | null;
prepared: true;
};
type AgentRuntimeInteractiveButtonStyle = "primary" | "secondary" | "success" | "danger";
/** Portable action control exposed to agent runtime reply payloads. */
type AgentRuntimeMessagePresentationButton = {
/** User-visible button label. */
label: string;
/** Typed action sent when pressed. */
action?: MessagePresentationAction;
/** @deprecated Use action. */
value?: string;
/** @deprecated Use an action with type "url". */
url?: string;
/** @deprecated Use an action with type "web-app". */
webApp?: {
url: string;
};
/** @deprecated Use an action with type "web-app". */
web_app?: {
url: string;
};
/** Higher values are kept first when channel action limits require dropping controls. */
priority?: number;
/** Disabled action hint; channels without disabled-state support render fallback text. */
disabled?: boolean;
/** Optional visual style hint for renderers that support styled actions. */
style?: AgentRuntimeInteractiveButtonStyle;
};
/** Portable select/menu option exposed to agent runtime reply payloads. */
type AgentRuntimeMessagePresentationOption = {
/** User-visible option label. */
label: string;
/** Typed action sent when selected. */
action?: Extract<MessagePresentationAction, {
type: "command" | "callback" | "model-picker";
}>;
/** @deprecated Use action. */
value?: string;
};
type AgentRuntimeLegacyInteractiveReply = {
blocks: Array<{
type: "text";
text: string;
} | {
type: "buttons";
buttons: AgentRuntimeMessagePresentationButton[];
} | {
type: "select";
placeholder?: string;
options: AgentRuntimeMessagePresentationOption[];
}>;
};
/** Portable reply presentation severity/style hint. */
type AgentRuntimeMessagePresentationTone = "info" | "success" | "warning" | "danger" | "neutral";
type AgentRuntimeMessagePresentationChartBlock = {
type: "chart";
chartType: "pie";
title: string;
segments: Array<{
label: string;
value: number;
}>;
} | {
type: "chart";
chartType: "bar" | "area" | "line";
title: string;
categories: string[];
series: Array<{
name: string;
values: number[];
}>;
xLabel?: string;
yLabel?: string;
};
type AgentRuntimeMessagePresentationTableCell = string | number;
type AgentRuntimeMessagePresentationTableBlock = {
type: "table";
caption: string;
headers: string[];
rows: AgentRuntimeMessagePresentationTableCell[][];
rowHeaderColumnIndex?: number;
};
/** Portable structured reply block rendered or downgraded by channels. */
type AgentRuntimeMessagePresentationBlock = {
type: "text";
text: string;
} | {
type: "context";
text: string;
} | {
type: "divider";
} | {
type: "buttons";
buttons: AgentRuntimeMessagePresentationButton[];
} | {
type: "select";
placeholder?: string;
options: AgentRuntimeMessagePresentationOption[];
} | AgentRuntimeMessagePresentationChartBlock | AgentRuntimeMessagePresentationTableBlock;
/** Portable structured reply presentation for channel adapters. */
type AgentRuntimeMessagePresentation = {
/** Optional short heading rendered before blocks when supported. */
title?: string;
/** Optional severity/status tone for renderers that support toned presentations. */
tone?: AgentRuntimeMessagePresentationTone;
/** Ordered portable blocks rendered or downgraded by channel adapters. */
blocks: AgentRuntimeMessagePresentationBlock[];
};
/** Delivery pin options attached to runtime reply payloads. */
type AgentRuntimeReplyPayloadDeliveryPin = {
enabled: boolean;
notify?: boolean;
required?: boolean;
};
/** Delivery instructions attached to runtime reply payloads. */
type AgentRuntimeReplyPayloadDelivery = {
pin?: boolean | AgentRuntimeReplyPayloadDeliveryPin;
};
type AgentRuntimeReplyPayloadLocation = {
latitude: number;
longitude: number;
accuracy?: number;
name?: string;
address?: string;
};
/** Portable reply payload emitted by agent runtimes before channel rendering. */
type AgentRuntimeReplyPayload = {
text?: string;
fallbackText?: {
text: string;
replacesPayloadIndex?: number;
};
mediaUrl?: string;
mediaUrls?: string[];
attachments?: Array<{
type?: "image" | "audio" | "video" | "file";
path?: string;
url?: string;
mediaUrl?: string;
filePath?: string;
mimeType?: string;
name?: string;
sizeBytes?: number;
durationMs?: number;
width?: number;
height?: number;
trustedLocalMedia?: boolean;
}>;
trustedLocalMedia?: boolean;
sensitiveMedia?: boolean;
presentation?: AgentRuntimeMessagePresentation;
presentationTextMode?: "fallback";
delivery?: AgentRuntimeReplyPayloadDelivery;
/**
* @deprecated Use presentation.
*/
interactive?: AgentRuntimeLegacyInteractiveReply;
btw?: {
question: string;
};
replyToId?: string;
replyToTag?: boolean;
replyToCurrent?: boolean;
audioAsVoice?: boolean;
videoAsNote?: boolean;
location?: AgentRuntimeReplyPayloadLocation;
spokenText?: string;
ttsSupplement?: {
spokenText: string;
visibleTextAlreadyDelivered?: boolean;
};
isError?: boolean;
isReasoning?: boolean;
/** Marks pre-tool commentary (💬) — a display lane, suppressed unless the channel opts in. */
isCommentary?: boolean;
isReasoningSnapshot?: boolean;
isCompactionNotice?: boolean;
isFallbackNotice?: boolean;
isStatusNotice?: boolean;
channelData?: Record<string, unknown>;
};
/** Stable section IDs for provider system prompt overrides. */
type AgentRuntimeSystemPromptSectionId = "interaction_style" | "tool_call_style" | "execution_bias";
/** Provider-owned system prompt contribution and section overrides. */
type AgentRuntimeSystemPromptContribution = {
stablePrefix?: string;
dynamicSuffix?: string;
sectionOverrides?: Partial<Record<AgentRuntimeSystemPromptSectionId, string>>;
};
/** Context passed when resolving provider system prompt contributions. */
type AgentRuntimeSystemPromptContributionContext = {
config?: unknown;
agentDir?: string;
workspaceDir?: string;
provider: string;
modelId: string;
promptMode: AgentRuntimePromptMode;
runtimeChannel?: string;
runtimeCapabilities?: string[];
agentId?: string;
trigger?: AgentRuntimePromptTrigger;
};
/** Provider fallback route decision for follow-up delivery. */
type AgentRuntimeFollowupFallbackRouteResult = {
route?: "origin" | "dispatcher" | "drop";
reason?: string;
};
/** Tool-call id sanitizer mode for provider transcript policy. */
type AgentRuntimeToolCallIdMode = "strict" | "strict9";
/** Provider transcript sanitation, repair, and validation policy. */
type AgentRuntimeTranscriptPolicy = {
sanitizeMode: "full" | "images-only";
sanitizeToolCallIds: boolean;
toolCallIdMode?: AgentRuntimeToolCallIdMode;
duplicateToolCallIdStyle?: "openai";
preserveNativeAnthropicToolUseIds: boolean;
repairToolUseResultPairing: boolean;
preserveSignatures: boolean;
sanitizeThoughtSignatures?: {
allowBase64Only?: boolean;
includeCamelCase?: boolean;
};
dropThinkingBlocks: boolean;
dropReasoningFromHistory?: boolean;
applyGoogleTurnOrdering: boolean;
validateGeminiTurns: boolean;
validateAnthropicTurns: boolean;
allowSyntheticToolResults: boolean;
};
/** Classified model-call failure or success observation for fallback. */
type AgentRuntimeOutcomeClassification = {
message: string;
reason?: AgentRuntimeFailoverReason;
status?: number;
code?: string;
rawError?: string;
} | {
error: unknown;
} | null | undefined;
/** Runtime hook that classifies run results for model fallback. */
type AgentRuntimeOutcomeClassifier = (params: {
provider: string;
model: string;
result: unknown;
hasDirectlySentBlockReply?: boolean;
hasBlockReplyPipelineOutput?: boolean;
}) => AgentRuntimeOutcomeClassification;
/** Resolved provider/model/harness/transport reference for an attempt. */
type AgentRuntimeResolvedRef = {
provider: string;
modelId: string;
modelApi?: string;
harnessId?: string;
transport?: AgentRuntimeTransport;
};
/** Concrete provider-owned route selected for one runtime attempt. */
type AgentRuntimeAuthModelRoute = {
provider: string;
modelId: string;
api: ModelApi;
baseUrl: string;
authRequirement: "api-key" | "subscription";
/** Secret-free request behavior that the selected runtime must reproduce. */
requestTransportOverrides: ProviderRouteOverridePresence;
/** Provider-owned native-runtime compatibility for this concrete route. */
runtimePolicy?: ProviderModelRouteRuntimePolicy;
};
/** Common native-runtime support proven across every route left to the harness. */
type AgentRuntimeAuthDeferredRouteSupport = {
requestTransportOverrides: ProviderRouteOverridePresence;
runtimePolicy: ProviderModelRouteRuntimePolicy;
};
/** Auth forwarding decision for one runtime attempt. */
type AgentRuntimeCredentialSource = ProviderModelAuthSourceClassification | {
kind: "none";
};
/** Actual provider/model/source tuple owned by one physical model attempt. */
type AgentRuntimeModelAttempt = {
provider: string;
model: string;
credentialSource: AgentRuntimeCredentialSource;
};
type AgentRuntimeAuthPlan = {
providerForAuth: string;
/** Model whose order, cooldown, and route facts produced this plan. */
modelId?: string;
authProfileProviderForAuth: string;
harnessAuthProvider?: string;
/** Preferred or user-locked profile; automatic selection may not have resolved its secret yet. */
forwardedAuthProfileId?: string;
forwardedAuthProfileSource?: "auto" | "user";
/** Ordered exhaustive candidates for the selected route; a singleton is terminal. */
forwardedAuthProfileCandidateIds?: string[];
/** Exact selected credential/config mode; secret-free route materialization input. */
selectedAuthMode?: string;
/** Concrete provider-owned route selected before runtime dispatch. */
modelRoute?: AgentRuntimeAuthModelRoute;
/** Secret-free support shared by every route deferred to harness-owned auth. */
deferredRouteSupport?: AgentRuntimeAuthDeferredRouteSupport;
/** Redacted source selected for this concrete physical attempt. */
credentialSource?: AgentRuntimeCredentialSource;
};
/** Prompt transforms and provider contribution hooks for one runtime attempt. */
type AgentRuntimePromptPlan = {
provider: string;
modelId: string;
textTransforms?: AgentRuntimeTextTransforms;
resolveSystemPromptContribution(context: AgentRuntimeSystemPromptContributionContext): AgentRuntimeSystemPromptContribution | undefined;
transformSystemPrompt(context: AgentRuntimeSystemPromptContributionContext & {
systemPrompt: string;
}): string;
};
/** Prepared plugin metadata snapshot kept opaque to runtime-plan consumers. */
type AgentRuntimePreparedMetadataSnapshot = object;
/** Prepared metadata loader used by tool planning without eager manifest reads. */
type PreparedOpenClawToolPlanning = {
metadataSnapshot?: AgentRuntimePreparedMetadataSnapshot;
};
/** Tool normalization and diagnostics hooks for one runtime attempt. */
type AgentRuntimeToolPlan = {
preparedPlanning?: PreparedOpenClawToolPlanning;
normalize<TSchemaType extends TSchema = TSchema, TResult = unknown>(tools: AgentTool<TSchemaType, TResult>[], params?: {
workspaceDir?: string;
modelApi?: string;
model?: AgentRuntimeModel;
}): AgentTool<TSchemaType, TResult>[];
logDiagnostics(tools: AgentTool[], params?: {
workspaceDir?: string;
modelApi?: string;
model?: AgentRuntimeModel;
}): void;
};
/** Delivery behavior hooks for one runtime attempt. */
type AgentRuntimeDeliveryPlan = {
isSilentPayload(payload: Pick<AgentRuntimeReplyPayload, "text" | "mediaUrl" | "mediaUrls" | "presentation" | "interactive" | "channelData">): boolean;
resolveFollowupRoute(params: {
payload: AgentRuntimeReplyPayload;
originatingChannel?: string;
originatingTo?: string;
originRoutable: boolean;
dispatcherAvailable: boolean;
}): AgentRuntimeFollowupFallbackRouteResult | undefined;
};
/** Outcome classification hooks for one runtime attempt. */
type AgentRuntimeOutcomePlan = {
classifyRunResult: AgentRuntimeOutcomeClassifier;
};
/** Extra transport parameter plan for one runtime attempt. */
type AgentRuntimeTransportPlan = {
extraParams: Record<string, unknown>;
resolveExtraParams(params?: {
extraParamsOverride?: Record<string, unknown>;
thinkingLevel?: AgentRuntimeThinkLevel;
agentId?: string;
workspaceDir?: string;
model?: AgentRuntimeModel;
resolvedTransport?: AgentRuntimeTransport;
}): Record<string, unknown>;
};
/** Complete prepared runtime plan consumed by embedded-agent attempts. */
type AgentRuntimePlan = {
resolvedRef: AgentRuntimeResolvedRef;
providerRuntimeHandle?: PreparedAgentRuntimeProviderHandle;
auth: AgentRuntimeAuthPlan;
prompt: AgentRuntimePromptPlan;
tools: AgentRuntimeToolPlan;
transcript: {
policy: AgentRuntimeTranscriptPolicy;
resolvePolicy(params?: {
workspaceDir?: string;
modelApi?: string;
model?: AgentRuntimeModel;
}): AgentRuntimeTranscriptPolicy;
};
delivery: AgentRuntimeDeliveryPlan;
outcome: AgentRuntimeOutcomePlan;
transport: AgentRuntimeTransportPlan;
observability: {
resolvedRef: string;
provider: string;
modelId: string;
modelApi?: string;
harnessId?: string;
authProfileId?: string;
transport?: AgentRuntimeTransport;
};
};
//#endregion
//#region src/agents/usage.d.ts
type ContextUsage = NonNullable<Usage["contextUsage"]>;
/** Normalized token counts used by runtime accounting. */
type NormalizedUsage = {
input?: number;
output?: number;
cacheRead?: number;
cacheWrite?: number;
cacheWrite1h?: number;
contextUsage?: ContextUsage;
reasoningTokens?: number;
total?: number;
cost?: Pick<Usage["cost"], "total" | "totalOrigin">;
};
//#endregion
//#region src/agents/embedded-agent-runner/types.d.ts
type BlockReplyFlushContext = {
/** Boundary that requested the flush. */
reason: "message_end" | "terminal";
} | {
/** Tool boundary separating pre-tool narration from the eventual answer. */
reason: "tool_start";
assistantMessageIndex: number;
} | {
/** Pre-compaction delivery is safe only for a completed assistant attempt. */
reason: "pre_compaction";
attemptAccepted: boolean;
};
type EmbeddedAgentUsage = Omit<NormalizedUsage, "contextUsage">;
type EmbeddedAgentMeta = {
sessionId: string;
sessionFile?: string;
provider: string;
model: string;
contextTokens?: number;
contextTokensSource?: "runtime" | "runtime-configured" | "resolved";
agentHarnessId?: string;
/** Runtime-owned selection, independent of the final response or credential source. */
runtimeModelSelection?: ModelRef;
/** Redacted credential source selected for the terminal physical model attempt. */
credentialSource?: AgentRuntimeCredentialSource;
fallbackAttempts?: FallbackAttempt[];
cliSessionBinding?: CliSessionBinding;
clearCliSessionBinding?: boolean;
compactionCount?: number;
/**
* Token count estimate after the most recent successful auto-compaction.
* Used as the freshest context snapshot when the follow-up model call omits
* usage metadata.
*/
compactionTokensAfter?: number;
/**
* Prompt/context snapshot from the latest model request. Prefer this for
* context-window utilization because provider usage totals can include cached
* and completion tokens that are useful for billing but noisy as live context.
*/
promptTokens?: number;
usage?: EmbeddedAgentUsage;
/** Terminal cumulative usage reserved for turn-level diagnostics. */
diagnosticUsage?: EmbeddedAgentUsage;
/**
* Usage from the last individual API call (not accumulated across tool-use
* loops or compaction retries). Used for context-window utilization display
* (`totalTokens` in sessions.json) because the accumulated `usage.input`
* sums input tokens from every API call in the run, which overstates the
* actual context size.
*/
lastCallUsage?: NormalizedUsage;
contextBudgetStatus?: SessionContextBudgetStatus;
/**
* True when code mode owned the model tool surface for this run. Config
* alone is not proof: the "auto" tier engages per model capability, raw
* model runs and plugin-harness surfaces can decline engagement, and the
* shell tool is also named `exec`, so consumers must read this flag
* instead of config or tool names.
*/
codeModeEngaged?: boolean;
/** Completed assistant/provider round trips accumulated across run attempts. */
assistantTurns?: number;
/**
* Code-mode/tool-search inner bridge calls for the run's catalog. These are
* invisible to the provider; `toolSummary.calls` stays the outer count.
*/
bridgeCalls?: {
search: number;
describe: number;
call: number;
};
/** Estimated USD cost of the run's accumulated usage. Omitted when the model has no cost data. */
costUsd?: number;
terminalReceipt?: Omit<AgentRunTerminalReceipt, "terminalDisposition">;
};
type TraceAttempt = {
provider: string;
model: string;
result: "success" | "timeout" | "surface_error" | "candidate_failed" | "rotate_profile" | "same_model_transient" | "fallback_model" | "aborted" | "error";
reason?: string;
stage?: "prompt" | "assistant";
elapsedMs?: number;
status?: number;
};
type ExecutionTrace = {
winnerProvider?: string;
winnerModel?: string;
attempts?: TraceAttempt[];
fallbackUsed?: boolean;
runner?: "embedded" | "cli";
};
type RequestShapingTrace = {
authMode?: string;
thinking?: string;
reasoning?: string;
verbose?: string;
trace?: string;
fallbackEligible?: boolean;
blockStreaming?: string;
};
type PromptSegmentTrace = {
key: string;
chars: number;
};
type ToolSummaryTrace = {
calls: number;
tools: string[];
failures?: number;
totalToolTimeMs?: number;
};
type CompletionTrace = {
finishReason?: string;
stopReason?: string;
refusal?: boolean;
};
type ContextManagementTrace = {
sessionCompactions?: number;
lastTurnCompactions?: number;
preflightCompactionApplied?: boolean;
postCompactionContextInjected?: boolean;
};
type EmbeddedRunLivenessState = "working" | "paused" | "blocked" | "abandoned";
type EmbeddedRunFailureSignal = {
kind: "execution_denied";
source: "tool";
toolName?: string;
code: "SYSTEM_RUN_DENIED" | "INVALID_REQUEST";
message: string;
fatalForCron: true;
};
type EmbeddedRunTerminalToolFailure = {
source: "tool";
toolName: "exec" | "wait";
code: "UNKNOWN_TOOL_ID";
};
type EmbeddedAgentRunMeta = {
durationMs: number;
agentMeta?: EmbeddedAgentMeta;
aborted?: boolean;
systemPromptReport?: SessionSystemPromptReport;
finalPromptText?: string;
finalAssistantVisibleText?: string;
finalAssistantRawText?: string;
replayInvalid?: boolean;
livenessState?: EmbeddedRunLivenessState;
timeoutPhase?: AgentRunTimeoutPhase;
providerStarted?: boolean;
agentHarnessResultClassification?: "empty" | "reasoning-only" | "planning-only";
terminalReplyKind?: "silent-empty";
/** An exact, successfully settled tool batch intentionally completed the turn without a reply. */
intentionalTerminalCompletion?: "tool-batch";
terminalReply?: AgentRunTerminalReplySnapshot;
yielded?: boolean;
/** Explicit user-facing waiting status supplied to sessions_yield. */
yieldAcknowledgment?: string;
/** A visible parent delegated its otherwise-empty result to completion children. */
continuationPending?: true;
error?: {
kind: "context_overflow" | "compaction_failure" | "compaction_replay_refresh_required" | "role_ordering" | "image_size" | "retry_limit" | "incomplete_turn" | "hook_block";
message: string;
/** True only when model fallback can retry this terminal error without repeating side effects. */
fallbackSafe?: boolean;
/** True when the payload includes a trusted structured terminal tool summary. */
terminalPresentation?: boolean;
};
failureSignal?: EmbeddedRunFailureSignal;
/** Bounded, sanitized unresolved Code Mode failure for operator diagnostics. */
terminalToolFailure?: EmbeddedRunTerminalToolFailure;
/** Stop reason for the agent run (e.g., "completed", "tool_calls"). */
stopReason?: string;
/** Pending tool calls when stopReason is "tool_calls". */
pendingToolCalls?: Array<{
id: string;
name: string;
arguments: string;
}>;
executionTrace?: ExecutionTrace;
requestShaping?: RequestShapingTrace;
promptSegments?: PromptSegmentTrace[];
toolSummary?: ToolSummaryTrace;
completion?: CompletionTrace;
contextManagement?: ContextManagementTrace;
};
type EmbeddedAgentRunResult = {
latestMcpAppChannelView?: McpAppChannelView;
latestMcpConnectAction?: McpConnectAction;
payloads?: Array<{
text?: string;
mediaUrl?: string;
mediaUrls?: string[];
replyToId?: string;
isError?: boolean;
isReasoning?: boolean;
/** Marks pre-tool commentary (💬) — a display lane, suppressed unless the channel opts in. */
isCommentary?: boolean;
audioAsVoice?: boolean;
trustedLocalMedia?: boolean;
channelData?: Record<string, unknown>;
}>;
meta: EmbeddedAgentRunMeta;
diagnosticTrace?: DiagnosticTraceContext;
didSendViaMessagingTool?: boolean;
didDeliverSourceReplyViaMessageTool?: boolean;
sourceReplyDelivered?: true;
didSendDeterministicApprovalPrompt?: boolean;
messagingToolSentTexts?: string[];
messagingToolSentMediaUrls?: string[];
messagingToolSentTargets?: MessagingToolSend[];
messagingToolSourceReplyPayloads?: MessagingToolSourceReplyPayload[];
acceptedSessionSpawns?: AcceptedSessionSpawn[];
heartbeatToolResponse?: HeartbeatToolResponse;
successfulCronAdds?: number;
};
type EmbeddedAgentCompactResult = {
ok: boolean;
compacted: boolean;
compactionKind?: "context-engine" | "native-harness" | "server-endpoint";
reason?: string;
/** Structured failure metadata used by model fallback classification. */
failure?: {
reason?: string;
status?: number;
code?: string;
rawError?: string;
};
result?: {
/** Identifies summaryless provider compaction in RPC and UI consumers. */
kind?: "server-endpoint";
sessionTarget?: ContextEngineSessionTarget;
/** Server-endpoint compaction has no transcript summary or first-kept entry. */
summary?: string;
firstKeptEntryId?: string;
tokensBefore: number;
tokensAfter?: number;
details?: unknown;
sessionId?: string;
sessionFile?: string;
};
};
type EmbeddedFullAccessBlockedReason = "sandbox" | "host-policy" | "channel" | "runtime";
//#endregion
//#region src/agents/exec-auto-reviewer.d.ts
/** Config for the optional model-backed exec reviewer. */
type ExecReviewerConfig = {
model?: AgentModelConfig;
timeoutMs?: number;
};
//#endregion
//#region src/agents/bash-tools.exec-types.d.ts
/** Runtime defaults passed into exec/process tool factories. */
type ExecToolDefaults = {
hasCronTool?: boolean;
host?: ExecTarget;
mode?: ExecMode;
bypassHostApprovalFloors?: boolean;
security?: ExecSecurity;
ask?: ExecAsk;
trigger?: string;
node?: string;
/** Default working directory for node-host execution only. */
nodeCwd?: string;
pathPrepend?: string[];
safeBins?: string[];
strictInlineEval?: boolean;
commandHighlighting?: boolean;
safeBinTrustedDirs?: string[];
safeBinProfiles?: Record<string, SafeBinProfileFixture>;
reviewer?: ExecReviewerConfig;
config?: OpenClawConfig;
/** Host-prepared non-secret environment and store projection exclusions. */
preparedRunEnvironment?: PreparedGitHubToolEnvironment;
autoReviewer?: ExecAutoReviewer;
agentId?: string;
backgroundMs?: number;
timeoutSec?: number;
approvalWarningText?: string;
approvalFollowupText?: string;
approvalFollowup?: ExecApprovalFollowupFactory;
approvalFollowupMode?: "agent" | "direct";
approvalRunningNoticeMs?: number;
sandbox?: BashSandboxConfig;
/** Immutable session policy that forbids execution outside its provisioned sandbox. */
sandboxRequired?: boolean;
elevated?: ExecElevatedDefaults;
allowBackground?: boolean;
/** Final run-local availability of the process continuation tool. */
processToolAvailabilityRef?: {
value?: boolean;
};
scopeKey?: string;
sessionKey?: string;
/** Stable agent run that owns any approval created by this tool. */
runId?: string;
/** Exact admitted execution instance that owns secret-egress proxy access. */
operationalRunInstance?: OperationalRunInstanceRef;
/** Durable session that receives detached exec completion events and approval followups. */
notifySessionKey?: string;
/** Ephemeral session UUID active when this exec tool was built. Regenerated
* on `/new` and `/reset`, so it pins exec-approval followups to the original
* session instance and lets stale followups drop after a session rebind. */
sessionId?: string;
/** `session.store` template from the runtime config. Lets the direct/denied
* exec approval followup path resolve the session key's current sessionId and
* drop the followup when the key was rebound by `/new` or `/reset`. */
sessionStore?: string;
/** @deprecated SDK declaration compatibility; coding-tool routing comes from config. */
mainKey?: string;
/** @deprecated SDK declaration compatibility; coding-tool routing comes from config. */
sessionScope?: "per-sender" | "global";
/** Start-time routing policy for detached exec system events. */
eventRouting?: EventSessionRoutingPolicy;
messageProvider?: string;
currentChannelId?: string;
currentThreadTs?: string;
/** Channel-owned sender/chat metadata. Exec subprocesses receive only sender/chat IDs. */
channelContext?: PluginHookChannelContext;
accountId?: string;
approvalReviewerDeviceId?: string;
/** Deny approval-requiring commands without creating operator approval events. */
nonInteractiveApproval?: boolean;
notifyOnExit?: boolean;
notifyOnExitEmptySuccess?: boolean;
cwd?: string;
};
/** Outcome passed to approval follow-up factories after approved async exec. */
type ExecApprovalFollowupOutcome = {
status: "completed" | "failed";
exitCode: number | null;
exitReason?: TerminationReason;
timedOut: boolean;
aggregated: string;
reason?: string;
};
type ExecApprovalFollowupContext = {
approvalId: string;
sessionId: string;
trigger?: string;
outcome: ExecApprovalFollowupOutcome;
};
/** Hook that can append domain-specific text to approval follow-up messages. */
type ExecApprovalFollowupFactory = (context: ExecApprovalFollowupContext) => string | undefined | Promise<string | undefined>;
/** Effective elevated-exec defaults derived from config/runtime policy. */
type ExecElevatedDefaults = {
enabled: boolean;
allowed: boolean;
defaultLevel: "on" | "off" | "ask" | "full";
fullAccessAvailable?: boolean;
fullAccessBlockedReason?: EmbeddedFullAccessBlockedReason;
};
//#endregion
//#region src/agents/bootstrap-mode.d.ts
type BootstrapContextRunKind = "default" | "heartbeat" | "cron";
//#endregion
//#region src/agents/command/shared-types.d.ts
/**
* Shared command types that are imported by both public and runtime modules.
*/
/** Best-effort provider stream parameter overrides for an agent command. */
type AgentStreamParams = {
/** Provider stream params override (best-effort). */
temperature?: number;
topP?: number;
maxTokens?: number;
/** Stop sequences forwarded to the provider (best-effort). */
stop?: string[];
/** Provider fast-mode override (best-effort). */
fastMode?: boolean;
responseFormat?: Record<string, unknown>;
frequencyPenalty?: number;
presencePenalty?: number;
seed?: number;
};
/** Simplified tool definition for client-provided OpenResponses hosted tools. */
type ClientToolDefinition = {
type: "function";
function: {
name: string;
description?: string;
parameters?: Record<string, unknown>;
/** Strict argument enforcement (Responses API). Propagated from the request. */
strict?: boolean;
};
};
//#endregion
//#region src/gateway/cron-creator-authority-grant.d.ts
type CronCreatorAuthorityRunScope = {
readonly runId: string;
readonly callerOrigin: CronScheduledToolCallerOrigin;
readonly signal: AbortSignal;
readonly grantTokens: Set<string>;
readonly controlUiAdmin?: true;
active: boolean;
abort: () => void;
};
//#endregion
//#region src/agents/tools/cron-tool.types.d.ts
type CronCreatorToolAllowlistEntry = string | {
/** Canonical policy name persisted into toolsAllow caps. */
name: string;
pluginId?: string;
/** Runtime-specific alias the creator surface presented for this tool. */
aliasName?: string;
/** Restrict-only execution policy carried by a host-created alias projection. */
execTarget?: {
host: "gateway";
ask?: "always";
};
};
type CronToolsAllowCaptureProvenance = {
version: 1;
source: "final-executable-surface";
};
type CronToolsAllowCaptureRef = {
value?: CronToolsAllowCaptureProvenance;
};
type CronCreatorToolAuthorityMaterialization = {
tools: readonly CronCreatorToolAllowlistEntry[];
provenance: CronToolsAllowCaptureProvenance;
/** Opaque runtime-owned authority captured with the same exact executable surface. */
runtimeAuthority?: CronRuntimeAuthority;
};
type CronCreatorToolAuthoritySnapshot = Omit<CronCreatorToolAuthorityMaterialization, "runtimeAuthority"> & {
/** Gateway-process one-shot proof consumed only at the matching cron write. */
grant: CronCreatorAuthorityGrant;
};
type CronToolOptions = {
agentSessionKey?: string;
agentId?: string;
/** Authenticated source account; authority must not be inferred from delivery. */
agentAccountId?: string;
/**
* Resolved config for the calling context. Shapes the advertised schema and
* description: when cron.triggers.enabled is off, trigger-gated surfaces
* (trigger, script payloads, stream schedules) are not advertised. Omitting
* config keeps the full surface for config-less callers.
*/
config?: OpenClawConfig;
currentDeliveryContext?: DeliveryContext;
/**
* Effective tool surface visible to the caller that created or edited a cron job.
* Cron agent turns and trigger scripts use fresh runtimes, so agent-origin jobs
* need this cap persisted before the original session policy is lost.
*/
creatorToolAllowlist?: CronCreatorToolAllowlistEntry[];
/** Host-owned proof that creatorToolAllowlist reached the final executable surface. */
creatorToolAllowlistCaptureRef?: CronToolsAllowCaptureRef;
/** Attempt-cached authority resolved only when a mutation changes its tool cap. */
resolveCreatorToolAuthority?: (options?: {
signal?: AbortSignal;
}) => Promise<CronCreatorToolAuthoritySnapshot>;
/** Visible fail-closed reason when a queued local turn cannot retain fresh MCP authority. */
creatorAuthorityUnavailableReason?: "queued-local-operator-configured-mcp";
selfRemoveOnlyJobId?: string;
runId?: string;
};
//#endregion
//#region src/agents/cron-creator-authority-context.d.ts
/** Opaque in-process capability minted only by an admitted exact run. */
type CronCreatorAuthorityCapability = CronCreatorAuthorityRunScope;
//#endregion
//#region src/agents/embedded-agent-payloads.d.ts
/**
* Channel-facing reply payload emitted by embedded agents. Keep this type
* small: channel adapters decide how to render text, media, and reply targets.
*/
type BlockReplyPayload = {
text?: string;
mediaUrls?: string[];
attachments?: ReplyMediaAttachment[];
audioAsVoice?: boolean;
trustedLocalMedia?: boolean;
sensitiveMedia?: boolean;
isReasoning?: boolean;
/** Marks pre-tool commentary (💬) — a display lane, suppressed unless the channel opts in. */
isCommentary?: boolean;
replyToId?: string;
replyToTag?: boolean;
replyToCurrent?: boolean;
/** Portable controls attached to a harness-owned blocking prompt. */
presentation?: MessagePresentation;
/** Runtime-authored text is the fallback for the portable presentation. */
presentationTextMode?: "fallback";
/** Channel-specific routing metadata for runtime-owned interactions. */
channelData?: Record<string, unknown>;
};
//#endregion
//#region src/infra/agent-activity-events.d.ts
/** Status rendered for an item-level agent activity event. */
type AgentItemEventStatus = "running" | "completed" | "failed" | "blocked";
/** Incremental command output payload associated with an item/tool call. */
type AgentCommandOutputEventFields = {
itemId: string;
phase: "delta" | "end";
title: string;
toolCallId: string;
name?: string;
output?: string;
status?: AgentItemEventStatus | "running";
exitCode?: number | null;
durationMs?: number;
cwd?: string;
};
//#endregion
//#region src/agents/embedded-agent-block-chunker.d.ts
/**
* Splits streamed embedded-agent replies into Markdown-safe message chunks.
*/
type BlockReplyChunking = {
minChars: number;
maxChars: number;
breakPreference?: "paragraph" | "newline" | "sentence";
/** When true, prefer \n\n paragraph boundaries once minChars has been satisfied. */
flushOnParagraph?: boolean;
};
//#endregion
//#region src/agents/embedded-agent-subscribe.shared-types.d.ts
/** Rendering mode for completed tool results in subscribed replies. */
type ToolResultFormat = "markdown" | "plain";
/** Detail level for in-flight tool progress messages. */
type ToolProgressDetailMode = "explain" | "raw";
type EmbeddedAgentEvent = {
stream: string;
data: Record<string, unknown> & Omit<Partial<AgentCommandOutputEventFields>, "phase" | "status"> & {
phase?: string;
status?: string;
args?: Record<string, unknown>;
summary?: string;
commandBearing?: boolean;
isError?: boolean;
};
sessionKey?: string;
};
//#endregion
//#region src/shared/fast-mode.d.ts
type FastModeAutoProgressState = {
offAnnounced: boolean;
resetAnnounced: boolean;
};
//#endregion
//#region src/context-engine/host-compat.d.ts
type ContextEngineHostSupport = {
id: string;
label: string;
capabilities: readonly ContextEngineHostCapability[];
};
//#endregion
//#region src/agents/harness/context-engine-logical-turn.d.ts
type EffectiveContextEngineRef = Readonly<{
engine: ContextEngine;
registeredId: string;
ownerPluginId?: string;
mode: "configured" | "legacy-degraded";
reason?: string;
}>;
type ContextEngineLogicalTurnLease = {
/** Compatibility getter for internal callers while the single context object is threaded. */
readonly engine: ContextEngine;
readonly effectiveEngine: ContextEngine;
readonly effectiveEngineId: string;
readonly effectiveEnginePluginId?: string;
readonly degraded: boolean;
readonly degradedReason?: string;
selectForHost: (params: {
host: ContextEngineHostSupport;
operation: ContextEngineOperation;
requiresDurableCommit: boolean;
}) => EffectiveContextEngineRef;
degradeBeforeStart: (reason: string) => EffectiveContextEngineRef;
begin: () => EffectiveContextEngineRef;
deferDisposalUntil: (promise: Promise<unknown>) => void;
dispose: () => Promise<void>;
};
//#endregion
//#region src/agents/harness/context-engine-turn-attempt.d.ts
type ContextEngineTurnAttemptFacts = {
boundary: TranscriptTurnBoundary;
sessionIdUsed: string;
sessionKey?: string;
sessionTarget?: ContextEngineSessionTarget;
promptError: boolean;
aborted: boolean;
yieldAborted: boolean;
isHeartbeat?: boolean;
};
//#endregion
//#region src/agents/harness/runtime-artifact.types.d.ts
/** Exact local implementation owned by one plugin agent harness process. */
type AgentHarnessRuntimeArtifactBinding = Readonly<{
id: string;
fingerprint: string;
}>;
/** Runtime artifact a verified continuation must keep using. */
type ExpectedAgentHarnessRuntimeArtifact = Readonly<{
harnessId: string;
artifact: AgentHarnessRuntimeArtifactBinding;
}>;
//#endregion
//#region src/agents/run-session-target.d.ts
/** Identifies a run transcript target without naming the current storage artifact. */
type AgentRunSessionTarget = {
agentId?: string;
sessionId?: string;
sessionKey?: string;
storePath?: string;
threadId?: string | number;
/** Internal admission fence paired with sessionId for run-owned transcript writes. */
expectedLifecycleRevision?: string;
/** Internal durable writer claim installed after session-lane admission. */
expectedWriterRunId?: string;
};
//#endregion
//#region src/agents/embedded-agent-runner/run/auth-profile-failure-policy.types.d.ts
/**
* Scope used when classifying auth-profile failures for retry/fallback decisions.
*/
type AuthProfileFailurePolicy = "shared" | "local" | "local_transient";
//#endregion
//#region src/agents/embedded-agent-runner/run/params.d.ts
type EmbeddedRunTrigger = "cron" | "heartbeat" | "manual" | "memory" | "overflow" | "user";
type ResolvedToolPromptFinalizer = (params: {
prompt: string;
messageToolAvailable: boolean;
}) => string;
type ReasoningStreamPayload = Pick<ReplyPayload, "text" | "mediaUrls" | "isReasoning" | "isReasoningSnapshot"> & {
requiresReasoningProgressOptIn?: boolean;
};
type CurrentInboundPromptContext = {
text: string;
resumableText?: string;
promptJoiner?: "\n\n" | "\n" | " ";
/** Generated goal blocks owned by inbound-context assembly, never user text. */
injectedGoalContexts?: string[];
};
type RunEmbeddedAgentParams = {
/** Already-admitted internal execution; mutually exclusive with preparedRunAdmission. */
admittedRunContext?: AdmittedRunContext;
/** Host-only post-prepare continuation, removed before plugin invocation. */
preparedRunAdmission?: PreparedAgentRunAdmission;
/** Caller-owned in-memory transcript for ephemeral helper runs. */
sessionManager?: SessionManager;
/** Detached runs may read session identity but never write its durable transcript or metadata. */
sessionPersistence?: "durable" | "detached";
sessionId: string;
sessionKey?: string;
/** Storage-neutral transcript/session target. Defaults to sessionId/sessionKey/agentId. */
sessionTarget?: AgentRunSessionTarget;
/** Immutable gateway lifecycle ownership captured when this execution was admitted. */
lifecycleGeneration?: string;
/** Provider prompt-cache affinity key; distinct from transcript/session identity. */
promptCacheKey?: string;
/** Session-like key for sandbox and tool-policy resolution. Defaults to sessionKey. */
sandboxSessionKey?: string;
/** Explicit sandbox and tool-policy owner when the policy session key is unscoped. */
sandboxAgentId?: string;
agentId?: string;
messageChannel?: string;
messageProvider?: string;
/** Capabilities declared by the gateway client that originated this run. */
clientCaps?: string[];
/** Out-of-band plugin bindings attached by the run initiator. */
toolBindings?: Readonly<Record<string, unknown>>;
chatType?: ChatType;
agentAccountId?: string;
/** Raw peer observed by the inbound routing owner, before identity linking. */
conversationRoutePeerId?: string;
/** What initiated this agent run: "user", "heartbeat", "cron", "memory", "overflow", or "manual". */
trigger?: EmbeddedRunTrigger;
/** Stable cron job identifier populated for cron-triggered runs. */
jobId?: string;
/** Store-private runtime authority forwarded only by the cron execution owner. */
scheduledRuntimeAuthority?: CronRuntimeAuthority;
/** A known runtime-specific authority envelope was explicitly cleared. */
scheduledRuntimeAuthorityRecoveryRequired?: boolean;
/** Relative workspace path that memory-triggered writes are allowed to append to. */
memoryFlushWritePath?: string;
/** Sticky source-turn taint inherited by an internal maintenance run. */
initialTurnTainted?: boolean;
/** Delivery target for topic/thread routing. */
messageTo?: string;
/** Thread/topic identifier for routing replies to the originating thread. */
messageThreadId?: string | number;
/** Trusted channel-configured policy for the admitted conversation turn. */
conversationToolPolicy?: GroupToolPolicyConfig;
/** Group id for channel-level tool policy resolution. */
groupId?: string | null;
/** Group channel label (e.g. #general) for channel-level tool policy resolution. */
groupChannel?: string | null;
/** Group space label (e.g. guild/team id) for channel-level tool policy resolution. */
groupSpace?: string | null;
/** Trusted provider role ids for the requester in this group turn. */
memberRoleIds?: string[];
/** Opaque host-issued capability for current-turn channel message actions. */
messageActionTurnCapability?: string;
/** Parent session key for subagent policy inheritance. */
spawnedBy?: string | null;
/** Whether workspaceDir points at the canonical agent workspace for bootstrap purposes. */
isCanonicalWorkspace?: boolean;
senderId?: string | null;
senderName?: string | null;
senderUsername?: string | null;
senderE164?: string | null;
/** Trusted sender identity bit for command/channel-action auth. */
senderIsOwner?: boolean;
/** Device-scoped operator session allowed to review approvals initiated by this run. */
approvalReviewerDeviceId?: string;
/** Current channel ID for auto-threading (Slack). */
currentChannelId?: string;
/** Transport-native chat/conversation ID for hook identity context. */
chatId?: string;
/** Channel-specific identity metadata surfaced to plugin hooks. */
channelContext?: PluginHookChannelContext;
/** Routable target for the current conversation when it differs from the native channel ID. */
currentMessagingTarget?: string;
/** Current thread timestamp for auto-threading (Slack). */
currentThreadTs?: string;
/** Current inbound message id for action fallbacks (e.g. Telegram react). */
currentMessageId?: string | number;
/** True when the current inbound turn carried audio media. */
currentInboundAudio?: boolean;
/** Reply-to mode for Slack auto-threading. */
replyToMode?: "off" | "first" | "all" | "batched";
/** Mutable ref to track if a reply was sent (for "first" mode). */
hasRepliedRef?: {
value: boolean;
};
/** Require explicit message tool targets (no implicit last-route sends). */
requireExplicitMessageTarget?: boolean;
/** If true, omit the message tool from the tool list. */
disableMessageTool?: boolean;
/** Host-prepared proof that the exact session can request Gateway publication. */
githubPublicationAvailable?: boolean;
swarmCollector?: boolean;
swarmOutputSchema?: Record<string, unknown>;
/** Restrict this reconstructed run to restart-safe tools. */
forceRestartSafeTools?: boolean;
/** Preserve Code Mode controls for a replay-safe restart recovery turn. */
forceCodeModeTools?: boolean;
/** Invocation-owned Code Mode activation; limits still come from config. */
codeModeOverride?: boolean | "auto";
/** Internal one-shot model probe mode: no tools, no workspace/chat prompt policy. */
modelRun?: boolean;
/** Disable trajectory persistence for auxiliary runs with no durable session owner. */
disableTrajectory?: boolean;
/** Restrict Skill Workshop to a bounded pending-proposal budget for an internal review run. */
skillWorkshopProposalOnly?: boolean;
/** Mark proposals created by this internal review as autonomous captures. */
skillWorkshopAutonomousCapture?: boolean;
skillWorkshopUpdateProposals?: boolean;
/** Preserve the foreground run as proposal provenance for an internal review run. */
skillWorkshopOrigin?: SkillProposalOrigin;
/** Run-scoped mutation budget shared across internal runner attempts. */
skillWorkshopProposalMutationBudget?: SkillWorkshopProposalMutationBudget;
/** Optional state environment for isolated Skill Workshop proposal persistence. */
skillWorkshopProposalEnv?: NodeJS.ProcessEnv;
/** Shared completion latch for proposal-only review runs that checkpoint their batch. */
skillWorkshopProposalReviewCompletion?: SkillWorkshopRunOptions["proposalReviewCompletion"];
/** Restrict Skill Workshop to one atomic collection reconciliation. */
skillWorkshopCollectionReconcile?: SkillWorkshopRunOptions["collectionReconcile"];
/** Bind an operator-requested revision turn to the exact proposal revision they reviewed. */
skillWorkshopProposalRevision?: SkillWorkshopRunOptions["proposalRevision"];
skillLibraryAuthoring?: SkillWorkshopRunOptions["libraryAuthoring"];
/** Explicit system prompt mode override for trusted callers. */
promptMode?: PromptMode;
/** Keep the message tool available even when a narrow profile would omit it. */
forceMessageTool?: boolean;
/** Include the heartbeat response tool for structured heartbeat outcomes. */
enableHeartbeatTool?: boolean;
/** Keep the heartbeat response tool available even when a narrow profile would omit it. */
forceHeartbeatTool?: boolean;
/** Allow runtime plugins for this run to late-bind the gateway subagent. */
allowGatewaySubagentBinding?: boolean;
/** @deprecated Use sessionTarget plus sessionId/sessionKey/agentId for runtime identity. */
sessionFile?: string;
workspaceDir: string;
/** Canonical agent workspace used for bootstrap files when execution runs elsewhere. */
bootstrapWorkspaceDir?: string;
/** Task working directory for tool/runtime execution. Defaults to workspaceDir. */
cwd?: string;
permissionMode?: SessionEntry$1["permissionMode"];
sessionRoot?: string;
agentDir?: string;
/**
* Run config consumed by core paths (model selection, tools, plugin
* activation). Plugin harnesses resolve `plugins.entries.<id>.config` from
* the live global config, NOT from this object — per-run plugin-config
* overrides are unsupported; use an explicit run param instead.
*/
config?: OpenClawConfig;
toolOverrides?: SessionToolOverrides;
skillsSnapshot?: SkillSnapshot;
prompt: string;
/** User-visible prompt body to submit and persist; runtime context travels separately. */
transcriptPrompt?: string;
/** Finalizes caller-owned guidance after the submitted tool surface is known. */
finalizePromptForResolvedTools?: ResolvedToolPromptFinalizer;
currentInboundEventKind?: InboundEventKind;
currentInboundContext?: CurrentInboundPromptContext;
explicitSkillSelections?: ExplicitSkillSelection[];
images?: ImageContent$1[];
imageOrder?: PromptImageOrderEntry[];
/** Ordered facts represented by attachment text in the current prompt. */
media?: MediaFact[];
/** Optional client-provided tools (OpenResponses hosted tools). */
clientTools?: ClientToolDefinition[];
/** Disable built-in tools for this run (LLM-only mode). */
disableTools?: boolean;
provider?: string;
model?: string;
/** Outer model-fallback owner facts for this admitted attempt. */
modelRoutingProvenance?: ModelFallbackAttemptProvenance;
/** Vision capability resolved by the run owner from its prepared model catalog. */
modelHasVision?: boolean;
/** Session-selected context-window option id carried by the run owner. */
contextWindow?: string;
/** Route-bound thinking capability resolved from the selected prepared catalog row. */
modelThinkingCapability?: PreparedModelThinkingCapability;
/** Effective model fallback chain for this session attempt. Undefined uses config defaults. */
modelFallbacksOverride?: string[];
/** Prepared fallback availability fact shared by selection and failure reporting. */
modelFallbackAvailability?: ModelFallbackAvailability;
/** Session-pinned embedded harness id. Prevents runtime hot-switching. */
agentHarnessId?: string;
/** Locks the selected model against hooks and fallbacks; does not imply native model ownership. */
modelSelectionLocked?: boolean;
/** Explicit runtime override selected for this turn. Unlike agentHarnessId, this may force OpenClaw. */
agentHarnessRuntimeOverride?: string;
/** Verified setup continuation: pin both the harness and its local implementation. */
expectedAgentHarnessRuntimeArtifact?: ExpectedAgentHarnessRuntimeArtifact;
authProfileId?: string;
authProfileIdSource?: "auto" | "user";
thinkLevel?: ThinkLevel;
fastMode?: FastMode;
/** Stable outer-run start time for auto fast-mode cutoff across retries/fallbacks. */
fastModeStartedAtMs?: number;
/** Effective auto fast-mode cutoff for this run, in seconds. */
fastModeAutoOnSeconds?: number;
/** Shared notification state for nested harnesses that can observe the same tool boundary. */
fastModeAutoProgressState?: FastModeAutoProgressState;
/** True when the outer model fallback loop has reached its final candidate. */
isFinalFallbackAttempt?: boolean;
verboseLevel?: VerboseLevel;
reasoningLevel?: ReasoningLevel;
toolResultFormat?: ToolResultFormat;
toolProgressDetail?: ToolProgressDetailMode;
/** Bootstrap context mode for workspace file injection. */
bootstrapContextMode?: "full" | "lightweight";
/** Run kind hint for context mode behavior. */
bootstrapContextRunKind?: BootstrapContextRunKind;
/** Optional tool allow-list; when set, only these tools are sent to the model. */
toolsAllow?: string[];
/** Preserve the visible tool schemas while allowing execution only for these names. */
toolExecutionAllow?: readonly string[];
/** Exact attempt authority attached to the active steering backend. */
toolAuthorityFingerprint?: string;
/** Owner-scoped plugin tool grant; normal policy and deny rules still apply. */
runtimePluginToolGrant?: RuntimePluginToolGrant;
/** Consumed in-process subagent-completion capability; never derived from public input. */
trustedInternalHandoff?: TrustedSubagentCompletionHandoff;
/** Trusted server-stamped authority for an explicitly capped scheduled run. */
scheduledToolPolicy?: ScheduledToolPolicyContext;
/** Host-stamped exact-run capability for late Codex creator-authority capture. */
cronCreatorAuthorityCapability?: CronCreatorAuthorityCapability;
/** Ephemeral reason fresh local-operator cron authority cannot survive this queued turn. */
cronCreatorAuthorityUnavailableReason?: "queued-local-operator";
/** Seen bootstrap truncation warning signatures for this session (once mode dedupe). */
bootstrapPromptWarningSignaturesSeen?: string[];
/** Last shown bootstrap truncation warning signature for this session. */
bootstrapPromptWarningSignature?: string;
execOverrides?: Pick<ExecToolDefaults, "host" | "mode" | "security" | "ask" | "node" | "nodeCwd" | "notifyOnExit" | "notifyOnExitEmptySuccess">;
bashElevated?: ExecElevatedDefaults;
/** Trusted approved-exec runtime prompt span awaiting the resolved attempt cap. */
execApprovalContinuationPromptRange?: ExecApprovalContinuationPromptRange;
/** Corresponding span in the undecorated transcript prompt. */
execApprovalContinuationTranscriptPromptRange?: ExecApprovalContinuationPromptRange;
timeoutMs: number;
/**
* Explicit per-run timeout override, in milliseconds, when the caller knows
* the run was launched with a deliberate per-run value (e.g. a cron payload's
* `timeoutSeconds`) rather than inheriting `agents.defaults.timeoutSeconds`.
* When set, the LLM idle watchdog honors this value directly instead of
* inferring "explicitness" from `timeoutMs !== agents.defaults.timeoutSeconds`,
* which fails when the explicit value happens to numerically equal the agent
* default.
*/
runTimeoutOverrideMs?: number;
runId: string;
/** Trusted runtime-only authorization for one bounded cross-conversation recall pass. */
conversationRecall?: ConversationRecallContext;
abortSignal?: AbortSignal;
onExecutionStarted?: (info?: {
lifecycleGeneration?: string;
}) => void;
onExecutionPhase?: (info: {
phase: EmbeddedAgentExecutionPhase;
provider?: string;
model?: string;
backend?: string;
source?: string;
tool?: string;
toolCallId?: string;
itemId?: string;
firstModelCallStarted?: boolean;
}) => void;
onLaneWait?: (info: {
waitMs: number;
queuedAhead: number;
waiting?: boolean;
}) => void;
onRunProgress?: (info: {
reason: string;
provider?: string;
model?: string;
backend?: string;
}) => void;
onSessionIdChanged?: (sessionId: string) => void;
replyOperation?: ReplyOperation;
shouldEmitToolResult?: () => boolean;
shouldEmitToolOutput?: () => boolean;
onPartialReply?: (payload: PartialReplyPayload) => boolean | void | Promise<boolean | void>;
onAssistantMessageStart?: () => void | Promise<void>;
prepareAssistantTranscriptMessage?: PrepareAssistantTranscriptMessage;
onBlockReply?: (payload: BlockReplyPayload, context?: BlockReplyContext) => void | Promise<void>;
onBlockReplyFlush?: (context: BlockReplyFlushContext) => void | Promise<void>;
blockReplyBreak?: "text_end" | "message_end";
blockReplyChunking?: BlockReplyChunking;
onReasoningStream?: (payload: ReasoningStreamPayload) => void | Promise<void>;
streamReasoningInNonStreamModes?: boolean;
onReasoningEnd?: () => void | Promise<void>;
onToolResult?: (payload: ReplyPayload) => void | Promise<void>;
/** Synchronous private observer for the sanitized per-tool result. */
onAgentToolResult?: (event: {
toolName: string;
result: unknown;
isError: boolean;
}) => void;
/** Reports a committed generic recovery compaction before its retry starts. */
onAutoCompactionSucceeded?: (count: number) => void;
onAgentEvent?: (evt: EmbeddedAgentEvent) => void | Promise<void>;
onToolStreamBoundary?: () => void | Promise<void>;
/**
* Emit lifecycle "finishing" when the attempt ends; the caller owns the
* final lifecycle "end" or "error" after fallback and post-turn work settle.
*/
deferTerminalLifecycle?: boolean;
/** @deprecated Use deferTerminalLifecycle. */
deferTerminalLifecycleEnd?: boolean;
lane?: string;
enqueue?: CommandQueueEnqueueFn;
extraSystemPrompt?: string;
sourceReplyDeliveryMode?: SourceReplyDeliveryMode;
taskSuggestionDeliveryMode?: TaskSuggestionDeliveryMode;
silentReplyPromptMode?: SilentReplyPromptMode;
internalEvents?: AgentInternalEvent[];
inputProvenance?: InputProvenance;
streamParams?: AgentStreamParams;
ownerNumbers?: string[];
enforceFinalTag?: boolean;
silentExpected?: boolean;
/** Skip per-chunk live visible-text parsing when no live stream consumer exists (e.g. subagents). */
suppressLiveStreamOutput?: boolean;
/**
* Treat a clean empty assistant stop as an intentional silent reply.
* Only set when the caller's prompt policy already allows an exact NO_REPLY
* final answer for silence.
*/
allowEmptyAssistantReplyAsSilent?: boolean;
/**
* Whether this run still owes a visible reply after settled non-reporting tools.
* Exact configured silence and committed delivery remain terminal outcomes.
*/
terminalReplyExpectation?: "required" | "optional";
authProfileFailurePolicy?: AuthProfileFailurePolicy;
/**
* One-shot helper runs may opt in to executing through the provider's CLI
* backend instead of the direct-API passthrough when the run targets a CLI
* runtime provider whose passthrough credentials are subscription-scoped.
* Anthropic routes direct anthropic-messages calls on subscription OAuth to
* metered extra-usage billing: without extra-usage balance the passthrough
* fails closed with a billing error, and with it the run silently draws
* paid usage instead of plan limits. The CLI backend is the plan-limits
* path for those credentials. CLI dispatch translates `toolsAllow` into the
* selectable-backend surface (no native tools, allowlisted loopback MCP
* tools); the same list bounds the loopback MCP grant server-side, so tools
* outside it — including the message tool, matching `disableMessageTool`
* intent — can be neither listed nor called. Leave unset to keep the
* direct-API passthrough.
*/
cliBackendDispatch?: "subscription-auth";
/**
* Allow a single run attempt even when all auth profiles are in cooldown,
* but only for inferred transient cooldowns like `rate_limit` or `overloaded`.
*
* This is used by model fallback when trying sibling models on providers
* where transient service pressure is often model-scoped.
*/
allowTransientCooldownProbe?: boolean;
suppressNextUserMessagePersistence?: boolean;
suppressTranscriptOnlyAssistantPersistence?: boolean;
suppressAssistantErrorPersistence?: boolean;
userTurnTranscriptRecorder?: UserTurnTranscriptRecorder;
/** Context engine resolved once by the outer logical-turn owner. */
contextEngineLogicalTurnLease?: ContextEngineLogicalTurnLease;
/** Emits immutable attempt facts for selection by the outer logical-turn owner. */
onContextEngineTurnCandidate?: (facts: ContextEngineTurnAttemptFacts) => void;
/** Keep an internal continuation prompt from being replaced by the original prepared turn. */
skipPreparedUserTurnMessage?: boolean;
onUserMessagePersisted?: (message: Extract<AgentMessage, {
role: "user";
}>) => void;
onUserMessagePersistenceInvalidated?: () => void;
onAssistantErrorMessagePersisted?: (message: Extract<AgentMessage, {
role: "assistant";
}>) => void;
/**
* Dispose bundled MCP runtimes when the overall run ends instead of preserving
* the session-scoped cache. Intended for one-shot local CLI runs that must
* exit promptly after emitting the final JSON result.
*/
cleanupBundleMcpOnRunEnd?: boolean;
/** Mark explicit one-shot local CLI runs so plugin tools can release resources promptly. */
oneShotCliRun?: boolean;
};
//#endregion
//#region src/agents/defaults.d.ts
declare const DEFAULT_PROVIDER = "openai";
declare const DEFAULT_MODEL = "gpt-5.6-sol";
//#endregion
//#region src/agents/identity.d.ts
/** Resolve the configured identity block for one agent. */
declare function resolveAgentIdentity(cfg: OpenClawConfig, agentId: string): IdentityConfig | undefined;
/** Resolve message and response prefix values together for channel delivery. */
declare function resolveEffectiveMessagesConfig(cfg: OpenClawConfig, agentId: string, opts?: {
hasAllowFrom?: boolean;
fallbackMessagePrefix?: string;
channel?: string;
accountId?: string;
}): {
messagePrefix: string;
responsePrefix?: string;
};
/** Resolve per-agent human-delay settings over global agent defaults. */
declare function resolveHumanDelayConfig(cfg: OpenClawConfig, agentId: string): HumanDelayConfig | undefined;
//#endregion
//#region src/plugins/runtime/runtime-agent-session-catalog.d.ts
type RuntimeSessionCatalogCreateTargetParams = {
config: OpenClawConfig;
requestedAgentId?: string;
provider: string;
modelIds: readonly string[];
agentRuntime: string;
};
/**
* Resolve a synchronous catalog create target through the same model/runtime
* policy used by agent turns, without making plugins import that policy graph.
*/
declare function resolveAgentCatalogCreateTarget(params: RuntimeSessionCatalogCreateTargetParams): SessionCatalogCreateTarget | undefined;
//#endregion
//#region src/agents/spawned-context.d.ts
type SpawnedRunMetadata = {
spawnedBy?: string | null;
groupId?: string | null;
groupChannel?: string | null;
groupSpace?: string | null;
workspaceDir?: string | null;
};
//#endregion
//#region src/agents/workspace.d.ts
declare function ensureAgentWorkspace(params?: {
dir?: string;
ensureBootstrapFiles?: boolean;
/** Guard each new mutation after async preparation; admitted effects may settle. */
beforePersistentApply?: () => void;
/**
* List of optional bootstrap filenames to skip writing.
* Applies only to SOUL.md, USER.md, IDENTITY.md.
* Required workspace setup such as AGENTS.md still runs.
*/
skipOptionalBootstrapFiles?: string[];
/**
* Workspace provisioning mode. "runtime-managed-implicit" marks a workspace
* owned by a runtime-managed (ACP) agent without an explicit workspace and
* with a distinct authoritative cwd: only the directory is provisioned, and
* bootstrap files, workspace setup state, and `git init` are skipped (#92015).
*/
provisioning?: "standard" | "runtime-managed-implicit";
}): Promise<{
dir: string;
agentsPath?: string;
soulPath?: string;
identityPath?: string;
userPath?: string;
bootstrapPath?: string;
bootstrapPending?: boolean;
identityPathCreated?: boolean;
}>;
//#endregion
//#region src/agents/cli-runner/types.d.ts
type CliSessionBindingFacts = {
extraSystemPromptStatic?: string;
sourceReplyDeliveryMode?: SourceReplyDeliveryMode;
requireExplicitMessageTarget?: boolean;
};
//#endregion
//#region src/agents/main-session-recovery/main-session-recovery-types.d.ts
type MainSessionRecoveryOwnerClaim = {
cycleId: string;
lifecycleGeneration: string;
claimId: string;
sessionId: string;
sessionKey: string;
runId?: string;
};
//#endregion
//#region src/agents/main-session-recovery/main-session-recovery-store.d.ts
type MainSessionRecoveryStoreTarget = {
sessionKey: string;
storePath: string;
};
type MainSessionRecoveryOwnerLease = MainSessionRecoveryOwnerClaim & MainSessionRecoveryStoreTarget;
//#endregion
//#region src/agents/command/types.d.ts
/** Image content block for Claude API multimodal messages. */
type ImageContent = {
type: "image";
data: string;
mimeType: string;
};
/** ACP turn source markers accepted by trusted command callsites. */
type AcpTurnSource = "manual_spawn";
/** Channel/account/thread context carried into an agent run. */
type AgentRunContext = {
messageChannel?: string;
accountId?: string;
groupId?: string | null;
groupChannel?: string | null;
groupSpace?: string | null;
currentChannelId?: string;
/** Transport-native chat/conversation ID for plugin hook identity context. */
chatId?: string;
/** Channel-specific sender/chat metadata for plugin hook identity context. */
channelContext?: PluginHookChannelContext;
currentThreadTs?: string;
currentInboundAudio?: boolean;
senderId?: string | null;
replyToMode?: "off" | "first" | "all" | "batched";
hasRepliedRef?: {
value: boolean;
};
};
/** Full trusted option surface for running an agent command. */
type AgentCommandOpts = {
message: string;
/** User-visible transcript body; defaults to message and excludes runtime-only context. */
transcriptMessage?: string;
/** Durable media metadata for the user-visible transcript turn. */
transcriptMedia?: UserTurnInput["media"];
/** Optional image attachments for multimodal messages. */
images?: ImageContent[];
/** Original inline/offloaded attachment order for inbound images. */
imageOrder?: PromptImageOrderEntry[];
/** Ordered facts represented by attachment text in this prompt. */
media?: MediaFact[];
/** Optional client-provided tools (OpenResponses hosted tools). */
clientTools?: ClientToolDefinition[];
/** Agent id override (must exist in config). */
agentId?: string;
/** Per-run provider override. */
provider?: string;
/** Per-run model override. */
model?: string;
/** Explicit ordered fallback chain for this run. Undefined uses normal selection policy. */
modelFallbacksOverride?: string[];
to?: string;
sessionId?: string;
sessionKey?: string;
thinking?: string;
thinkingOnce?: string;
verbose?: string;
json?: boolean;
timeout?: string;
deliver?: boolean;
/** Override delivery target (separate from session routing). */
replyTo?: string;
/** Override delivery channel (separate from session routing). */
replyChannel?: string;
/** Override delivery account id (separate from session routing). */
replyAccountId?: string;
/** Override delivery thread/topic id (separate from session routing). */
threadId?: string | number;
/** Message channel context. */
messageChannel?: string;
/** Tool-policy/output surface context. Defaults to messageChannel. */
messageProvider?: string;
/** Delivery channel. */
channel?: string;
/** Account ID for multi-account channel routing. */
accountId?: string;
/** Context for embedded run routing (channel/account/thread). */
runContext?: AgentRunContext;
/** Device-scoped operator session allowed to review approvals initiated by this run. */
approvalReviewerDeviceId?: string;
/** Internal trusted exec approval follow-up elevated defaults. */
bashElevated?: ExecElevatedDefaults;
/** Trusted span whose final cap is resolved with the selected model. */
execApprovalContinuationPromptRange?: ExecApprovalContinuationPromptRange;
/** Corresponding span in the undecorated transcript message. */
execApprovalContinuationTranscriptPromptRange?: ExecApprovalContinuationPromptRange;
/** Trusted sender identity bit for command/channel-action auth; defaults true for local CLI calls. */
senderIsOwner?: boolean;
/** Whether this caller is authorized to use provider/model per-run overrides. */
allowModelOverride?: boolean;
/** Optional runtime tool allow-list; when set, only these tools are exposed for this run. */
toolsAllow?: string[];
/** Trusted owner-scoped plugin tool grant; normal policy and deny rules still apply. */
runtimePluginToolGrant?: RuntimePluginToolGrant;
/** Consumed in-process subagent-completion capability; never accepted from public RPC params. */
trustedInternalHandoff?: TrustedSubagentCompletionHandoff;
/** Internal marker identifying a server-managed default cap. */
toolsAllowIsDefault?: boolean;
/** Trusted server-stamped authority for an explicitly capped scheduled run. */
scheduledToolPolicy?: ScheduledToolPolicyContext;
/** Preserve the originating run's message-tool policy across internal continuation turns. */
requireExplicitMessageTarget?: boolean;
cliSessionBindingFacts?: CliSessionBindingFacts;
/** Group/spawn metadata for subagent policy inheritance and routing context. */
groupId?: SpawnedRunMetadata["groupId"];
groupChannel?: SpawnedRunMetadata["groupChannel"];
groupSpace?: SpawnedRunMetadata["groupSpace"];
spawnedBy?: SpawnedRunMetadata["spawnedBy"];
deliveryTargetMode?: ChannelOutboundTargetMode;
bestEffortDeliver?: boolean;
abortSignal?: AbortSignal;
lane?: string;
runId?: string;
/** Immutable gateway lifecycle ownership captured when this run was admitted. */
lifecycleGeneration?: string;
/** Called once when the selected runtime actually admits the prompt for execution. */
onExecutionStarted?: () => void;
extraSystemPrompt?: string;
/** Frozen profile-backed human Git attribution prepared by trusted ingress. */
gitCoauthorAttribution?: string;
/** Bootstrap workspace context injection mode for this run. */
bootstrapContextMode?: "full" | "lightweight";
/** Run kind hint for bootstrap context behavior. */
bootstrapContextRunKind?: BootstrapContextRunKind;
internalEvents?: AgentInternalEvent[];
inputProvenance?: InputProvenance;
/** Internal runs can execute against a session without updating visible status/model/usage. */
sessionEffects?: "visible" | "internal";
/** Internal handoffs can write transcript turns without changing user-facing model/usage state. */
preserveUserFacingSessionModelState?: boolean;
/** Visible source replies must be sent through the message tool when set. */
sourceReplyDeliveryMode?: SourceReplyDeliveryMode;
/** Internal runs can omit the channel message tool entirely. */
disableMessageTool?: boolean;
/** Collector children fail closed instead of emitting operator approval requests. */
swarmCollector?: boolean;
/** Synthetic structured_output input schema for collector children. */
swarmOutputSchema?: Record<string, unknown>;
/** Restrict this reconstructed run to restart-safe tools. */
forceRestartSafeTools?: boolean;
forceCodeModeTools?: boolean;
/** Invocation-owned Code Mode activation; limits still come from config. */
codeModeOverride?: boolean | "auto";
/** Host-owned exact media set for a scoped automatic recovery delivery. */
internalDeliveryMediaUrls?: string[];
internalDeliverySuppressText?: boolean;
/** Gateway ingress that already persisted visible activity can skip the duplicate pre-run touch. */
skipInitialSessionTouch?: boolean;
/** Per-call stream param overrides (best-effort). */
streamParams?: AgentStreamParams;
/** Resolved per-run fast mode from channel/directive handling. */
fastMode?: FastMode;
/** Resolved per-run auto cutoff seconds for fast mode. */
fastModeAutoOnSeconds?: number;
/** Explicit workspace directory override (for subagents to inherit parent workspace). */
workspaceDir?: SpawnedRunMetadata["workspaceDir"];
/** Explicit task working directory for this run. Bootstrap still uses workspaceDir. */
cwd?: string;
/** Force bundled MCP teardown when a one-shot local run completes. */
cleanupBundleMcpOnRunEnd?: boolean;
/** Force long-lived CLI live session teardown when a one-shot local run completes. */
cleanupCliLiveSessionOnRunEnd?: boolean;
/** Mark explicit one-shot local CLI runs so plugin tools can release resources promptly. */
oneShotCliRun?: boolean;
/** Gateway-owned runs can late-bind plugin subagent and node runtime helpers. */
allowGatewaySubagentBinding?: boolean;
/** Opaque foreground fence transferred by Gateway after atomic session admission. */
mainRestartRecoveryOwnerLease?: MainSessionRecoveryOwnerLease;
/** Gateway already consumed this automatic recovery run's durable reservation. */
mainRestartRecoveryAdmitted?: boolean;
/** Exact durable recovery attempt allowed to bind post-admission execution identity. */
mainRestartRecoveryAttempt?: number;
/** Private recovery correlation; public ingress callers cannot author identity evidence. */
executionIdentityAdmission?: ReturnType<(typeof admitted_run_context_d_exports)["createExecutionIdentityRecoveryAdmission"]>;
/** Gateway-owned exact operational instance shared with its abort controller. */
operationalRunInstance?: OperationalRunInstanceRef;
skillLibraryAuthoring?: SkillLibraryAuthoringCapability;
/** Gateway-minted exact-run capability for late Codex creator-authority capture. */
cronCreatorAuthorityCapability?: CronCreatorAuthorityCapability;
/** Private exact-instance binding hook invoked after delegated authority admission. */
onAdmittedRunContext?: (context: AdmittedRunContext) => void | Promise<void>;
/** Private owner binding hook invoked only after exact admission has resolved. */
onPostAdmittedRunContext?: (context: AdmittedRunContext) => void;
/** Called when the actual run model is selected, including fallback retries. */
onActiveModelSelected?: (ctx: {
provider: string;
model: string;
}) => void | Promise<void>;
/** Called when every candidate in the run's model fallback chain failed. */
onModelFallbackExhausted?: () => void;
/** Called before delivery projection when the raw run contains an error payload. */
onResultErrorPayload?: (message?: string) => void;
/** Called when compaction rotates the active run onto a successor session. */
onSessionIdChanged?: (sessionId: string) => void;
/** Internal one-shot model probe mode: no tools, no workspace/chat prompt policy. */
modelRun?: boolean;
/** Internal prompt-mode override for trusted local/gateway callsites. */
promptMode?: PromptMode;
/** Internal ACP-ready session turn source. Manual spawn turns bypass only the dispatch gate. */
acpTurnSource?: AcpTurnSource;
/** Internal handoffs can feed the model without writing the synthetic prompt to transcript. */
suppressPromptPersistence?: boolean;
/** Gateway/channel ingress can provide a canonical user-turn persistence owner. */
userTurnTranscriptRecorder?: UserTurnTranscriptRecorder;
};
/** Restricted option surface for external ingress callsites. */
type AgentCommandIngressOpts = Omit<AgentCommandOpts, "senderIsOwner" | "allowModelOverride" | "mainRestartRecoveryOwnerLease" | "mainRestartRecoveryAdmitted" | "mainRestartRecoveryAttempt" | "executionIdentityAdmission" | "operationalRunInstance" | "skillLibraryAuthoring" | "cronCreatorAuthorityCapability" | "onAdmittedRunContext" | "onPostAdmittedRunContext"> & {
/** @deprecated Public ingress ignores owner claims; use the host-injected channel runtime. */
senderIsOwner?: boolean;
/** Ingress callsites must always pass explicit model-override authorization state. */
allowModelOverride: boolean;
};
//#endregion
//#region src/agents/embedded-agent-runner/compact.types.d.ts
type CompactEmbeddedAgentSessionParams = {
/** Explicit session owner captured before fallback agent resolution. */
contextEngineAgentId?: string;
sessionId: string;
runId?: string;
sessionKey?: string;
/** Storage-neutral transcript/session target. Defaults to sessionId/sessionKey/agentId. */
sessionTarget?: AgentRunSessionTarget;
/** Caller-resolved owner agent for global session aliases. */
agentId?: string;
/** Session key used only for runtime policy/sandbox resolution. Defaults to sessionKey. */
sandboxSessionKey?: string;
/** Owner captured with the sandbox policy before execution identity changes. */
sandboxAgentId?: string;
messageChannel?: string;
messageProvider?: string;
/** Capabilities declared by the gateway client that originated this run. */
clientCaps?: string[];
chatType?: ChatType;
agentAccountId?: string;
/** Raw peer observed by the inbound routing owner, before identity linking. */
conversationRoutePeerId?: string;
conversationToolPolicy?: GroupToolPolicyConfig;
currentChannelId?: string;
currentThreadTs?: string;
currentMessageId?: string | number;
/** Trusted sender id from inbound context for scoped message-tool discovery. */
senderId?: string;
senderName?: string;
senderUsername?: string;
senderE164?: string;
authProfileId?: string;
authProfileIdSource?: "auto" | "user";
/** Host-resolved provider credential for native harness compaction. */
resolvedApiKey?: string;
/** Group id for channel-level tool policy resolution. */
groupId?: string | null;
/** Group channel label (e.g. #general) for channel-level tool policy resolution. */
groupChannel?: string | null;
/** Group space label (e.g. guild/team id) for channel-level tool policy resolution. */
groupSpace?: string | null;
memberRoleIds?: string[];
/** Parent session key for subagent policy inheritance. */
spawnedBy?: string | null;
inputProvenance?: InputProvenance;
/** Consumed in-process subagent-completion capability; never derived from public input. */
trustedInternalHandoff?: TrustedSubagentCompletionHandoff;
toolsAllow?: string[];
disableTools?: boolean;
runtimePluginToolGrant?: RuntimePluginToolGrant;
scheduledToolPolicy?: ScheduledToolPolicyContext;
/** Host-resolved ambient native-tool boundary for this compaction operation. */
nativeToolSurface?: "unrestricted" | "host-isolated";
sessionFile: string;
/** Optional caller-observed live prompt tokens used for compaction diagnostics. */
currentTokenCount?: number;
workspaceDir: string;
/** Canonical agent workspace used for bootstrap files when execution runs elsewhere. */
bootstrapWorkspaceDir?: string;
/** Optional task working directory; workspaceDir remains the agent bootstrap workspace. */
cwd?: string;
permissionMode?: SessionEntry$1["permissionMode"];
sessionRoot?: string;
agentDir?: string;
config?: OpenClawConfig;
toolOverrides?: SessionToolOverrides;
skillsSnapshot?: SkillSnapshot;
senderIsOwner?: boolean;
provider?: string;
model?: string;
/** Caller-resolved model/provider shape used by native harness compactors. */
runtimeModel?: Model;
/** Effective model fallback chain for this session attempt. Undefined uses config defaults. */
modelFallbacksOverride?: string[];
/** Optional caller-resolved context engine for harness-owned compaction. */
contextEngine?: ContextEngine;
/** Optional caller-resolved token budget for harness-owned compaction. */
contextTokenBudget?: number;
/** Optional caller-resolved runtime context for harness-owned context-engine compaction. */
contextEngineRuntimeContext?: ContextEngineRuntimeContext;
/** Transcript/runtime hint; durable native ownership is resolved from the session entry. */
agentHarnessId?: string;
/** Resumable native CLI session targeted by an explicit manual compaction. */
cliSessionId?: string;
/** Complete persisted CLI binding targeted by an explicit manual compaction. */
cliSessionBinding?: CliSessionBinding;
/** Owning session facts required for placement and runtime preparation. */
sessionEntry?: SessionEntry$1;
/** Keep the concrete model fixed; native runtime ownership is a separate session fact. */
modelSelectionLocked?: boolean;
/** OpenClaw-owned runtime policy prepared for this compaction path. */
runtimePlan?: AgentRuntimePlan;
/** Host-prepared route and credential selection for native harness compaction. */
runtimeAuthPlan?: AgentRuntimeAuthPlan;
thinkLevel?: ThinkLevel;
reasoningLevel?: ReasoningLevel;
execOverrides?: Pick<ExecToolDefaults, "host" | "mode" | "security" | "ask" | "node" | "nodeCwd">;
bashElevated?: ExecElevatedDefaults;
customInstructions?: string;
tokenBudget?: number;
force?: boolean;
/** Force compaction because the caller already determined this turn must compact before prompt submission. */
forcePreflight?: boolean;
/** Alias for forcePreflight used by preflight budget gates. */
preflightRequired?: boolean;
/** Diagnostic trigger that made preflight compaction mandatory. */
preflightCompactionTrigger?: "tokens" | "transcript_bytes";
trigger?: "budget" | "overflow" | "manual";
/**
* Preflight callers can allow native/current-session harness compaction but
* move plugin-owned budget compaction onto background turn maintenance.
*/
deferOwningContextEngineCompaction?: boolean;
diagId?: string;
attempt?: number;
maxAttempts?: number;
lane?: string;
enqueue?: CommandQueueEnqueueFn;
extraSystemPrompt?: string;
sourceReplyDeliveryMode?: SourceReplyDeliveryMode;
ownerNumbers?: string[];
abortSignal?: AbortSignal;
/** @internal Refreshes the host watchdog when delegated native compaction makes progress. */
compactionTimeoutReset?: () => void;
onCompactionHookMessages?: (payload: {
phase: "before" | "after";
messages: string[];
sessionId: string;
sessionKey: string;
}) => void | Promise<void>;
/** Allow runtime plugins for this compaction to late-bind the gateway subagent. */
allowGatewaySubagentBinding?: boolean;
/** Mark explicit one-shot local CLI runs so plugin tools can release resources promptly. */
oneShotCliRun?: boolean;
};
//#endregion
//#region src/channels/message/send.d.ts
type DurableMessageSuppressionReason = OutboundPayloadDeliverySuppressionReason | "no_visible_result";
type DurableMessageFailureStage = "platform_send" | "queue" | "unknown";
type SerializedDurableMessagePayloadOutcome = {
index: number;
status: "sent";
resultCount: number;
} | {
index: number;
status: "suppressed";
reason: DurableMessageSuppressionReason;
hookEffect?: {
cancelReason?: string;
metadata?: Record<string, unknown>;
};
} | {
index: number;
status: "failed";
error: string;
sentBeforeError: boolean;
stage: DurableMessageFailureStage;
};
//#endregion
//#region src/agents/agent-command.d.ts
/** Runs an agent turn from an inbound channel/gateway ingress context. */
declare function agentCommandFromIngress(opts: AgentCommandIngressOpts, runtime?: RuntimeEnv, deps?: CliDeps): Promise<{
payloads: ReturnType<typeof projectOutboundPayloadPlanForJson>;
meta: EmbeddedAgentRunMeta;
didSendViaMessagingTool?: boolean;
messagingToolSentTexts?: string[];
messagingToolSentMediaUrls?: string[];
messagingToolSentTargets?: MessagingToolSend[];
didSendDeterministicApprovalPrompt?: true;
acceptedSessionSpawns?: NonNullable<AcceptedSessionSpawn[] | undefined>;
successfulCronAdds?: number;
deliverySucceeded?: boolean;
deliveryStatus?: {
requested: true;
attempted: boolean;
status: "sent" | "suppressed" | "partial_failed" | "failed";
succeeded: true | false | "partial";
error?: true;
errorMessage?: string;
reason?: string;
resultCount?: number;
sentBeforeError?: true;
payloadOutcomes?: SerializedDurableMessagePayloadOutcome[];
};
}>;
//#endregion
//#region src/agents/timeout.d.ts
declare function resolveAgentTimeoutMs(opts: {
cfg?: OpenClawConfig;
overrideMs?: number | null;
overrideSeconds?: number | null;
minMs?: number;
}): number;
//#endregion
//#region src/agents/embedded-agent-runner/cli-backend-dispatch-eligibility.d.ts
type EmbeddedCliBackendDispatchEligibilityParams = {
provider?: string;
model?: string;
agentId?: string;
/** Explicitly pinned auth profile for the run; decisive when it resolves. */
authProfileId?: string;
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
};
/**
* Decides whether an opted-in embedded run would execute through the CLI
* backend. Resolution stays on stored credential metadata — no credential
* materialization, refresh locks, or network calls on this per-turn path.
*/
declare function resolveEmbeddedCliBackendDispatchEligibility(params: EmbeddedCliBackendDispatchEligibilityParams): {
provider: string;
} | undefined;
//#endregion
//#region src/infra/system-events.d.ts
type SystemEventOptions = {
sessionKey: string;
contextKey?: string | null;
deliveryContext?: DeliveryContext;
/** Replace the pending event for this context and delivery route. Requires contextKey. */
replace?: boolean;
};
declare function enqueueSystemEvent(text: string, options: SystemEventOptions): boolean;
//#endregion
//#region src/plugins/runtime/native-deps.d.ts
/** Inputs used to format native dependency install/rebuild guidance. */
type NativeDependencyHintParams = {
packageName: string;
manager?: "pnpm" | "npm" | "yarn";
rebuildCommand?: string;
approveBuildsCommand?: string;
downloadCommand?: string;
};
/** Formats concise guidance for installing and rebuilding a native dependency. */
declare function formatNativeDependencyHint(params: NativeDependencyHintParams): string;
//#endregion
//#region src/media/image-ops.d.ts
/** JPEG resize request passed through the media-runtime/plugin SDK surface. */
type ResizeToJpegParams = {
buffer: Buffer;
maxSide: number;
quality: number;
withoutEnlargement?: boolean;
};
/** Fully probes display dimensions through Rastermill when header-only metadata is insufficient. */
declare function getImageMetadata(buffer: Buffer): Promise<ImageMetadata | null>;
/** Resizes or encodes image bytes as JPEG through the shared image processor. */
declare function resizeToJpeg(params: ResizeToJpegParams): Promise<Buffer>;
//#endregion
//#region src/media/web-media.d.ts
/** Loaded media bytes plus resolved MIME kind and filename metadata for outbound/plugin callers. */
type WebMediaResult = {
buffer: Buffer;
contentType?: string;
kind: MediaKind | undefined;
fileName?: string;
/** Source bytes came from a generated-HTML trust boundary. */
trustedGeneratedHtmlSource?: boolean;
};
type WebMediaOptions = {
maxBytes?: number;
optimizeImages?: boolean;
imageCompression?: ImageCompressionPolicy;
ssrfPolicy?: SsrFPolicy;
proxyUrl?: string;
fetchImpl?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
requestInit?: RequestInit;
readIdleTimeoutMs?: number;
trustExplicitProxyDns?: boolean;
workspaceDir?: string;
/** Allowed root directories for local path reads. "any" is deprecated; prefer sandboxValidated + readFile. */
localRoots?: readonly string[] | "any";
/** Channel inbound attachment root patterns checked with inbound path policy semantics. */
inboundRoots?: readonly string[];
/** Caller already validated the local path (sandbox/other guards); requires readFile override. */
sandboxValidated?: boolean;
readFile?: OutboundMediaReadFile;
/** Host-local fs-policy read piggyback; rejects plaintext-like document sends. */
hostReadCapability?: boolean;
};
/** Compression preference used to tune image size/quality search grids. */
type ImageQualityPreference = "auto" | "efficient" | "balanced" | "high";
/** Per-model image compression constraints merged into outbound media policy. */
type ImageCompressionModelPolicy = {
maxBytes?: number;
maxPixels?: number;
maxSidePx?: number;
preferredSidePx?: number;
};
/** Image compression policy for model/tool callers that need bounded media payloads. */
type ImageCompressionPolicy = {
quality?: ImageQualityPreference;
models?: ImageCompressionModelPolicy[];
imageCount?: number;
};
/** Loads local, remote, hosted, or media-store media and optimizes images by default. */
declare function loadWebMedia(mediaUrl: string, maxBytesOrOptions?: number | WebMediaOptions, options?: {
ssrfPolicy?: SsrFPolicy;
localRoots?: readonly string[] | "any";
}): Promise<WebMediaResult>;
//#endregion
//#region packages/media-core/src/mime.d.ts
/** Detects the best MIME type from bytes, file path, and header metadata. */
declare function detectMime(opts: {
buffer?: Buffer;
headerMime?: string | null;
additionalMimeHints?: readonly (string | null | undefined)[];
filePath?: string;
}): Promise<string | undefined>;
//#endregion
//#region src/media/audio.d.ts
/**
* Backward-compatible alias for voice-message audio compatibility checks.
*
* @deprecated Use isVoiceMessageCompatibleAudio.
*/
declare function isVoiceCompatibleAudio(opts: {
contentType?: string | null;
fileName?: string | null;
}): boolean;
//#endregion
//#region src/image-generation/runtime-types.d.ts
type GenerateImageParams = {
cfg: OpenClawConfig;
prompt: string;
agentDir?: string;
authStore?: AuthProfileStore;
modelOverride?: string;
count?: number;
size?: string;
aspectRatio?: string;
resolution?: ImageGenerationResolution;
/** Resolution inferred from reference images; omitted for incompatible fallback models. */
inferredResolution?: ImageGenerationResolution;
quality?: ImageGenerationQuality;
outputFormat?: ImageGenerationOutputFormat;
background?: ImageGenerationBackground;
inputImages?: ImageGenerationSourceImage[];
autoProviderFallback?: boolean;
/** Optional per-request provider timeout in milliseconds. */
timeoutMs?: number;
providerOptions?: ImageGenerationProviderOptions;
/** SSRF policy to propagate into image-generation provider HTTP calls. */
ssrfPolicy?: SsrFPolicy;
};
type GenerateImageRuntimeResult = {
images: GeneratedImageAsset[];
provider: string;
model: string;
attempts: FallbackAttempt[];
appliedResolution?: ImageGenerationResolution;
normalization?: ImageGenerationNormalization;
metadata?: Record<string, unknown>;
ignoredOverrides: ImageGenerationIgnoredOverride[];
};
//#endregion
//#region src/video-generation/runtime-types.d.ts
type GenerateVideoParams = {
cfg: OpenClawConfig;
prompt: string;
agentDir?: string;
authStore?: AuthProfileStore;
modelOverride?: string;
size?: string;
aspectRatio?: string;
resolution?: VideoGenerationResolution;
durationSeconds?: number;
audio?: boolean;
watermark?: boolean;
inputImages?: VideoGenerationSourceAsset[];
inputVideos?: VideoGenerationSourceAsset[];
inputAudios?: VideoGenerationSourceAsset[];
autoProviderFallback?: boolean;
/** Arbitrary provider-specific options forwarded as-is to provider.generateVideo. */
providerOptions?: Record<string, unknown>;
/** Optional per-request provider timeout in milliseconds. */
timeoutMs?: number;
};
type GenerateVideoRuntimeResult = {
videos: GeneratedVideoAsset[];
provider: string;
model: string;
attempts: FallbackAttempt[];
normalization?: VideoGenerationNormalization;
metadata?: Record<string, unknown>;
ignoredOverrides: VideoGenerationIgnoredOverride[];
};
//#endregion
//#region src/music-generation/runtime-types.d.ts
/**
* Runtime input/output contracts for music generation.
*
* These are separate from provider contracts because runtime results include
* fallback attempts, normalized metadata, and selected provider/model identity.
*/
/** Parameters accepted by the core music generation runtime. */
type GenerateMusicParams = {
cfg: OpenClawConfig;
prompt: string;
agentDir?: string;
authStore?: AuthProfileStore;
modelOverride?: string;
lyrics?: string;
instrumental?: boolean;
durationSeconds?: number;
format?: MusicGenerationOutputFormat;
inputImages?: MusicGenerationSourceImage[];
autoProviderFallback?: boolean;
/** Optional per-request provider timeout in milliseconds. */
timeoutMs?: number;
};
/** Result returned after a successful runtime provider attempt. */
type GenerateMusicRuntimeResult = {
tracks: GeneratedMusicAsset[];
provider: string;
model: string;
attempts: FallbackAttempt[];
lyrics?: string[];
normalization?: MusicGenerationNormalization;
metadata?: Record<string, unknown>;
ignoredOverrides: MusicGenerationIgnoredOverride[];
};
//#endregion
//#region src/web-search/runtime-types.d.ts
/** Provider/tool resolution inputs for web_search. */
type ResolveWebSearchDefinitionParams = {
config?: OpenClawConfig;
agentDir?: string;
sandboxed?: boolean;
runtimeWebSearch?: RuntimeWebSearchMetadata;
providerId?: string;
preferRuntimeProviders?: boolean;
preferInputConfig?: boolean;
};
/** Inputs for executing a web_search request through the selected provider. */
type RunWebSearchParams = ResolveWebSearchDefinitionParams & {
args: Record<string, unknown>;
signal?: AbortSignal;
};
/** Normalized execution result that records which provider answered. */
type RunWebSearchResult = {
provider: string;
result: Record<string, unknown>;
};
//#endregion
//#region src/globals.d.ts
declare function shouldLogVerbose(): boolean;
//#endregion
//#region src/plugin-state/plugin-blob-store.types.d.ts
type PluginBlobEntryInfo<TMetadata> = {
key: string;
metadata: TMetadata;
sizeBytes: number;
createdAt: number;
expiresAt?: number;
};
type PluginBlobEntry<TMetadata> = PluginBlobEntryInfo<TMetadata> & {
bytes: Uint8Array;
};
type PluginBlobStore<TMetadata> = {
register(key: string, bytes: Uint8Array, metadata: TMetadata, opts?: {
ttlMs?: number;
}): Promise<void>;
registerIfAbsent(key: string, bytes: Uint8Array, metadata: TMetadata, opts?: {
ttlMs?: number;
}): Promise<boolean>;
lookup(key: string): Promise<PluginBlobEntry<TMetadata> | undefined>;
entries(): Promise<PluginBlobEntryInfo<TMetadata>[]>;
delete(key: string): Promise<boolean>;
deleteExpiredKey(key: string): Promise<PluginBlobEntryInfo<TMetadata> | undefined>;
deleteExpired(): Promise<PluginBlobEntryInfo<TMetadata>[]>;
clear(): Promise<void>;
};
type PluginBlobOverflowPolicy = "evict-oldest" | "reject-new";
type OpenBlobStoreOptions = {
namespace: string;
maxEntries: number;
maxBytesPerEntry: number;
maxBytesPerNamespace: number;
overflowPolicy?: PluginBlobOverflowPolicy;
defaultTtlMs?: number;
};
//#endregion
//#region src/plugin-state/plugin-state-store.types.d.ts
type PluginStateEntry<T> = {
key: string;
value: T;
createdAt: number;
expiresAt?: number;
};
/** Async plugin state API exposed to plugin runtimes. */
type PluginStateKeyedStore<T> = {
register(key: string, value: T, opts?: {
ttlMs?: number;
}): Promise<void>;
registerIfAbsent(key: string, value: T, opts?: {
ttlMs?: number;
}): Promise<boolean>;
update?: (key: string, updateValue: (current: T | undefined) => T | undefined, opts?: {
ttlMs?: number;
}) => Promise<boolean>;
/** Atomically deletes an existing entry when its current value matches. */
deleteIf?: (key: string, predicate: (current: T) => boolean) => Promise<boolean>;
lookup(key: string): Promise<T | undefined>;
consume(key: string): Promise<T | undefined>;
delete(key: string): Promise<boolean>;
entries(): Promise<PluginStateEntry<T>[]>;
clear(): Promise<void>;
};
/** Sync plugin state API used by trusted core/plugin bootstrap paths. */
type PluginStateSyncKeyedStore<T> = {
register(key: string, value: T, opts?: {
ttlMs?: number;
}): void;
registerIfAbsent(key: string, value: T, opts?: {
ttlMs?: number;
}): boolean;
update?: (key: string, updateValue: (current: T | undefined) => T | undefined, opts?: {
ttlMs?: number;
}) => boolean;
/** Atomically deletes an existing entry when its current value matches. */
deleteIf?: (key: string, predicate: (current: T) => boolean) => boolean;
lookup(key: string): T | undefined;
consume(key: string): T | undefined;
delete(key: string): boolean;
entries(): PluginStateEntry<T>[];
clear(): void;
};
/** Options for opening a keyed plugin-state namespace. */
type PluginStateOverflowPolicy = "evict-oldest" | "reject-new";
type OpenKeyedStoreOptions = {
namespace: string;
maxEntries: number;
overflowPolicy?: PluginStateOverflowPolicy;
defaultTtlMs?: number;
env?: NodeJS.ProcessEnv;
};
//#endregion
//#region src/channels/message/ingress-queue.d.ts
/** Pending or retryable inbound channel event stored in the durable ingress queue. */
type ChannelIngressQueueRecord<TPayload, TMetadata = unknown> = {
id: string;
channelId: string;
accountId: string;
queueName: string;
payload: TPayload;
metadata?: TMetadata;
receivedAt: number;
updatedAt: number;
laneKey?: string;
attempts: number;
lastAttemptAt?: number;
lastError?: string;
};
/** Pending ingress event currently claimed by a worker. */
type ChannelIngressQueueClaim<TPayload, TMetadata = unknown> = ChannelIngressQueueRecord<TPayload, TMetadata> & {
claim: {
token: string;
ownerId: string;
claimedAt: number;
};
};
/** Minimal claim reference used to guard completion/release/failure with a claim token. */
type ChannelIngressQueueClaimRef = {
id: string;
claim: {
token: string;
};
};
/** Claim identity available when a stale row's payload cannot be decoded. */
type ChannelIngressQueueCorruptClaim = {
id: string;
channelId: string;
accountId: string;
queueName: string;
laneKey?: string;
reason: "corrupt_payload";
claim: {
token: string;
ownerId: string;
claimedAt: number;
};
};
/** Completed ingress event tombstone retained for duplicate detection. */
type ChannelIngressQueueCompletedRecord<TCompletedMetadata = unknown> = {
id: string;
channelId: string;
accountId: string;
queueName: string;
completedAt: number;
metadata?: TCompletedMetadata;
};
/** Failed ingress event tombstone retained for duplicate detection. */
type ChannelIngressQueueFailedRecord = {
id: string;
channelId: string;
accountId: string;
queueName: string;
failedAt: number;
reason: string;
message?: string;
};
/** Rich failed ingress event retained for diagnostics and operator recovery. */
type ChannelIngressQueueDeadLetterRecord<TPayload = unknown, TMetadata = unknown> = ChannelIngressQueueFailedRecord & {
payload?: TPayload;
metadata?: TMetadata;
receivedAt: number;
updatedAt: number;
laneKey?: string;
attempts: number;
lastAttemptAt?: number;
};
/** Outcome of asking a channel/account queue to re-enqueue one failed event. */
type ChannelIngressQueueResubmitResult<TPayload, TMetadata = unknown, TCompletedMetadata = unknown> = {
kind: "resubmitted";
record: ChannelIngressQueueRecord<TPayload, TMetadata>;
previous: ChannelIngressQueueDeadLetterRecord<TPayload, TMetadata>;
} | {
kind: "not-found";
} | {
kind: "completed";
record: ChannelIngressQueueCompletedRecord<TCompletedMetadata>;
} | {
kind: "active";
status: "pending" | "claimed";
} | {
kind: "unrecoverable";
record: ChannelIngressQueueDeadLetterRecord<TPayload, TMetadata>;
};
/** Retention options for pending, completed, and failed ingress queue rows. */
type ChannelIngressQueuePruneOptions = {
pendingTtlMs?: number;
completedTtlMs?: number;
failedTtlMs?: number;
pendingMaxEntries?: number;
completedMaxEntries?: number;
failedMaxEntries?: number;
protectIds?: Iterable<string>;
now?: number;
};
/** Result of enqueueing a possibly duplicate ingress event id. */
type ChannelIngressQueueEnqueueResult<TPayload, TMetadata, TCompletedMetadata> = {
kind: "accepted";
duplicate: false;
record: ChannelIngressQueueRecord<TPayload, TMetadata>;
} | {
kind: "pending";
duplicate: true;
record: ChannelIngressQueueRecord<TPayload, TMetadata>;
} | {
kind: "claimed";
duplicate: true;
record: ChannelIngressQueueClaim<TPayload, TMetadata>;
} | {
kind: "completed";
duplicate: true;
record: ChannelIngressQueueCompletedRecord<TCompletedMetadata>;
} | {
kind: "failed";
duplicate: true;
record: ChannelIngressQueueFailedRecord;
};
/** Durable FIFO-ish ingress queue with claims, duplicate detection, and retention pruning. */
type ChannelIngressQueue<TPayload, TMetadata = unknown, TCompletedMetadata = unknown> = {
enqueue(id: string, payload: TPayload, options?: {
metadata?: TMetadata;
receivedAt?: number;
laneKey?: string;
}): Promise<ChannelIngressQueueEnqueueResult<TPayload, TMetadata, TCompletedMetadata>>;
listPending(options?: {
limit?: number | "all";
orderBy?: "received" | "id";
}): Promise<Array<ChannelIngressQueueRecord<TPayload, TMetadata>>>;
listClaims(): Promise<Array<ChannelIngressQueueClaim<TPayload, TMetadata>>>;
/** Additive SDK seam; optional so existing external queue test doubles remain compatible. */
listFailed?(options?: {
limit?: number | "all";
}): Promise<Array<ChannelIngressQueueDeadLetterRecord<TPayload, TMetadata>>>;
claimNext(options?: {
ownerId?: string;
blockedLaneKeys?: Iterable<string>;
staleMs?: number;
orderBy?: "received" | "id";
scanLimit?: number;
candidateIds?: Iterable<string>;
deriveLaneKey?: (record: ChannelIngressQueueRecord<TPayload, TMetadata>) => string | undefined;
/** Authorize a changed durable lane before the atomic pending-to-claimed transition. */
reconcileStoredLaneKey?: (record: ChannelIngressQueueRecord<TPayload, TMetadata>, storedLaneKey: string, derivedLaneKey: string) => boolean;
}): Promise<ChannelIngressQueueClaim<TPayload, TMetadata> | null>;
claim(id: string, options?: {
ownerId?: string;
}): Promise<ChannelIngressQueueClaim<TPayload, TMetadata> | null>;
refreshClaim?(claim: ChannelIngressQueueClaimRef, options?: {
refreshedAt?: number;
}): Promise<boolean>;
complete(idOrClaim: string | ChannelIngressQueueClaimRef, options?: {
metadata?: TCompletedMetadata;
completedAt?: number;
}): Promise<boolean>;
release(idOrClaim: string | ChannelIngressQueueClaimRef, options?: {
lastError?: string;
releasedAt?: number;
recordAttempt?: boolean;
}): Promise<boolean>;
fail(idOrClaim: string | ChannelIngressQueueClaimRef, options: {
reason: string;
message?: string;
failedAt?: number;
}): Promise<boolean>;
/** Additive SDK seam; actual runtime queues support operator resubmission. */
resubmit?(id: string, options?: {
resubmittedAt?: number;
}): Promise<ChannelIngressQueueResubmitResult<TPayload, TMetadata, TCompletedMetadata>>;
delete(idOrClaim: string | ChannelIngressQueueRecord<TPayload, TMetadata> | ChannelIngressQueueClaimRef): Promise<boolean>;
recoverStaleClaims(options?: {
staleMs?: number;
now?: number;
shouldRecover?: (claim: ChannelIngressQueueClaim<TPayload, TMetadata>) => boolean | Promise<boolean>;
shouldRecoverCorrupt?: (claim: ChannelIngressQueueCorruptClaim) => boolean | Promise<boolean>;
}): Promise<number>;
prune(options?: ChannelIngressQueuePruneOptions): Promise<number>;
};
/** Construction options for a channel/account-scoped ingress queue. */
type CreateChannelIngressQueueOptions = {
channelId: string;
accountId?: string;
stateDir?: string;
now?: () => number;
/**
* `read-only` reads through the existing-database read-only opener, which never
* creates, migrates, chmods or configures the shared state file. Callers that must
* not touch durable state before they own it - Doctor detection runs before the
* exclusive maintenance lock - use it so listing cannot take a write path.
*/
access?: "read-write" | "read-only";
};
//#endregion
//#region src/channels/message/ingress-drain-lifecycle.d.ts
/** Full pre-adoption -> adoption ownership lifecycle for one claimed event. */
type ChannelIngressDispatchLifecycle = {
/** Pre-adoption only. After adopt the drain treats this signal as inert. */
abortSignal: AbortSignal;
/**
* Fires when recovery-relevant session/run state is durable.
* Drain completes (tombstones) the claim here -- never at settle.
*/
onAdopted: () => void | Promise<void>;
/**
* Turn ownership deferred to reply-lane admission (queued followup).
* Claim remains held until adopted or abandoned.
*/
onDeferred: () => void;
/** Deferred reply-lane admission is still waiting behind an active turn. */
onDeferredHeartbeat?: () => void;
/**
* Durable adoption finalization is in progress (e.g. settlement hold while
* committing dedupe). Clears the pre-adoption stall watchdog so a timeout
* settlement cannot race and dead-letter an about-to-complete claim.
* Claim stays held until onAdopted / onAbandoned / fail.
*/
onAdoptionFinalizing: () => void;
/** Deferred work terminally failed after dispatch returned. */
onFailed?: (error: unknown) => void | Promise<void>;
/** Explicit cancellation before adoption; releases without consuming retry budget. */
onCancelled?: () => void | Promise<void>;
/**
* Deferred turn finished without ever owning the reply lane.
* Drain releases the claim for retry.
*/
onAbandoned: () => void | Promise<void>;
};
//#endregion
//#region src/channels/message/ingress-drain-state.d.ts
type ChannelIngressDrainDispatchResult = {
kind: "completed";
} | {
kind: "deferred";
} | {
kind: "failed-retryable";
error: unknown;
};
//#endregion
//#region src/channels/message/ingress-retry-policy.d.ts
type IngressRetryPolicyConfig = {
maxAttempts?: number;
deadLetterMinAgeMs?: number;
baseMs?: number;
maxMs?: number;
};
type IngressNonRetryableFailure = {
reason: string;
message: string;
};
//#endregion
//#region src/channels/message/ingress-drain.d.ts
type DeferredLaneOccupancy = "hold" | "release";
type CreateChannelIngressDrainOptions<TPayload, TMetadata = unknown, TCompletedMetadata = unknown> = {
queue: ChannelIngressQueue<TPayload, TMetadata, TCompletedMetadata>;
/**
* Dispatch a claimed event. Wire lifecycle into reply options (see
* bindIngressLifecycleToReplyOptions). Return deferred when ownership will
* transfer at reply-lane admission; otherwise complete or throw.
*/
dispatchClaimedEvent: (event: ChannelIngressQueueClaim<TPayload, TMetadata>, lifecycle: ChannelIngressDispatchLifecycle) => Promise<ChannelIngressDrainDispatchResult | void> | ChannelIngressDrainDispatchResult | void;
resolveNonRetryableFailure?: (err: unknown) => IngressNonRetryableFailure | null;
shouldSupersedePending?: (newEvent: ChannelIngressQueueRecord<TPayload, TMetadata> | ChannelIngressQueueClaim<TPayload, TMetadata>, pendingEvent: ChannelIngressQueueClaim<TPayload, TMetadata>) => boolean | Promise<boolean>;
deriveLaneKey?: (record: ChannelIngressQueueRecord<TPayload, TMetadata>) => string | undefined;
reconcileStoredLaneKey?: (record: ChannelIngressQueueRecord<TPayload, TMetadata>, storedLaneKey: string, derivedLaneKey: string) => boolean;
ownerId?: string;
adoptionStallTimeoutMs?: number;
claimLeaseMs?: number;
/**
* Whether a claimed event keeps occupying its ingress serialization lane after
* dispatch hands ownership to deferred work. Default "hold" (current behavior).
*/
deferredLaneOccupancy?: DeferredLaneOccupancy;
retryPolicy?: IngressRetryPolicyConfig;
now?: () => number;
formatError?: (err: unknown) => string;
onLog?: (message: string) => void;
abortSignal?: AbortSignal;
orderBy?: "received" | "id";
scanLimit?: number;
startLimit?: number;
};
type ChannelIngressDrain = {
recoverStaleClaims: () => Promise<number>;
drainOnce: (options?: {
shouldStop?: () => boolean;
}) => Promise<{
started: number;
}>;
activeLaneKeys: () => ReadonlySet<string>;
waitForIdle: () => Promise<void>;
dispose: () => void;
};
//#endregion
//#region src/tasks/task-flow-registry.types.d.ts
type TaskFlowSyncMode = "task_mirrored" | "managed";
/** Lifecycle statuses for multi-step task flows. */
declare const TASK_FLOW_STATUSES: readonly ["queued", "running", "waiting", "blocked", "succeeded", "failed", "cancelled", "lost"];
type TaskFlowStatus = (typeof TASK_FLOW_STATUSES)[number];
type TaskFlowRecord = {
flowId: string;
syncMode: TaskFlowSyncMode;
ownerKey: string;
requesterOrigin?: DeliveryContext;
controllerId?: string;
revision: number;
status: TaskFlowStatus;
notifyPolicy: TaskNotifyPolicy;
goal: string;
currentStep?: string;
blockedTaskId?: string;
blockedSummary?: string;
stateJson?: JsonValue;
waitJson?: JsonValue;
cancelRequestedAt?: number;
createdAt: number;
updatedAt: number;
endedAt?: number;
};
//#endregion
//#region src/plugins/runtime/runtime-taskflow.types.d.ts
type ManagedTaskFlowRecord = TaskFlowRecord & {
syncMode: "managed";
controllerId: string;
};
type ManagedTaskFlowMutationErrorCode = "not_found" | "not_managed" | "revision_conflict" | "persist_failed";
type ManagedTaskFlowMutationResult = {
applied: true;
flow: ManagedTaskFlowRecord;
} | {
applied: false;
code: ManagedTaskFlowMutationErrorCode;
current?: TaskFlowRecord;
};
type ManagedTaskFlowCreateParams = {
controllerId: string;
goal: string;
status?: ManagedTaskFlowRecord["status"];
notifyPolicy?: TaskNotifyPolicy;
currentStep?: string | null;
stateJson?: JsonValue | null;
waitJson?: JsonValue | null;
cancelRequestedAt?: number | null;
createdAt?: number;
updatedAt?: number;
endedAt?: number | null;
};
type BoundTaskFlowTaskRunResult = {
created: true;
flow: ManagedTaskFlowRecord;
task: TaskRecord;
} | {
created: false;
reason: string;
found: boolean;
flow?: TaskFlowRecord;
};
type BoundTaskFlowCancelResult = {
found: boolean;
cancelled: boolean;
reason?: string;
flow?: TaskFlowRecord;
tasks?: TaskRecord[];
};
type BoundTaskFlowRuntime = {
readonly sessionKey: string;
readonly requesterOrigin?: TaskDeliveryState["requesterOrigin"];
createManaged: (params: ManagedTaskFlowCreateParams) => ManagedTaskFlowRecord;
tryCreateManaged: (params: ManagedTaskFlowCreateParams) => ManagedTaskFlowRecord | null;
get: (flowId: string) => TaskFlowRecord | undefined;
list: () => TaskFlowRecord[];
findLatest: () => TaskFlowRecord | undefined;
resolve: (token: string) => TaskFlowRecord | undefined;
getTaskSummary: (flowId: string) => TaskRegistrySummary | undefined;
setWaiting: (params: {
flowId: string;
expectedRevision: number;
currentStep?: string | null;
stateJson?: JsonValue | null;
waitJson?: JsonValue | null;
blockedTaskId?: string | null;
blockedSummary?: string | null;
updatedAt?: number;
}) => ManagedTaskFlowMutationResult;
resume: (params: {
flowId: string;
expectedRevision: number;
status?: Extract<ManagedTaskFlowRecord["status"], "queued" | "running">;
currentStep?: string | null;
stateJson?: JsonValue | null;
updatedAt?: number;
}) => ManagedTaskFlowMutationResult;
finish: (params: {
flowId: string;
expectedRevision: number;
stateJson?: JsonValue | null;
updatedAt?: number;
endedAt?: number;
}) => ManagedTaskFlowMutationResult;
fail: (params: {
flowId: string;
expectedRevision: number;
stateJson?: JsonValue | null;
blockedTaskId?: string | null;
blockedSummary?: string | null;
updatedAt?: number;
endedAt?: number;
}) => ManagedTaskFlowMutationResult;
requestCancel: (params: {
flowId: string;
expectedRevision: number;
cancelRequestedAt?: number;
}) => ManagedTaskFlowMutationResult;
cancel: (params: {
flowId: string;
cfg: OpenClawConfig;
}) => Promise<BoundTaskFlowCancelResult>;
runTask: (params: {
flowId: string;
runtime: TaskRuntime;
sourceId?: string;
childSessionKey?: string;
parentTaskId?: string;
agentId?: string;
runId?: string;
label?: string;
task: string;
preferMetadata?: boolean;
notifyPolicy?: TaskNotifyPolicy;
deliveryStatus?: TaskDeliveryStatus;
status?: "queued" | "running";
startedAt?: number;
lastEventAt?: number;
progressSummary?: string | null;
}) => BoundTaskFlowTaskRunResult;
};
type PluginRuntimeTaskFlow = {
bindSession: (params: {
sessionKey: string;
requesterOrigin?: TaskDeliveryState["requesterOrigin"];
}) => BoundTaskFlowRuntime;
fromToolContext: (ctx: Pick<OpenClawPluginToolContext, "sessionKey" | "deliveryContext">) => BoundTaskFlowRuntime;
};
//#endregion
//#region src/plugins/runtime/model-auth-types.d.ts
/**
* Runtime-ready auth result exposed to native plugins and context engines.
*
* `source`, `mode`, and `profileId` describe how the original credential was
* resolved. `apiKey` is the request-ready credential after any provider-owned
* runtime exchange, so it may differ from the stored/raw credential.
*/
type ResolvedProviderRuntimeAuth = Omit<ResolvedProviderAuth, "apiKey"> & {
apiKey?: string;
baseUrl?: string;
request?: ModelProviderRequestTransportOverrides$1;
expiresAt?: number;
};
//#endregion
//#region packages/media-understanding-common/src/active-model.d.ts
/** Provider/model pair selected for one media-understanding request. */
type ActiveMediaModel = {
provider: string;
model?: string;
};
//#endregion
//#region src/media-understanding/runtime-types.d.ts
type RunMediaUnderstandingFileParams = {
capability: "image" | "audio" | "video";
filePath: string;
mediaUrl?: string;
cfg: OpenClawConfig;
agentId?: string;
agentDir?: string;
workspaceDir?: string;
mime?: string;
activeModel?: ActiveMediaModel;
prompt?: string;
timeoutMs?: number;
scopeContext?: MediaUnderstandingScopeContext;
};
type MediaUnderstandingScopeContext = {
sessionKey?: string;
channel?: string;
chatType?: string;
};
type RunMediaUnderstandingFileResult = {
text: string | undefined;
provider?: string;
model?: string;
output?: MediaUnderstandingOutput;
decision?: MediaUnderstandingDecision;
};
type DescribeImageFileParams = {
filePath: string;
mediaUrl?: string;
cfg: OpenClawConfig;
agentId?: string;
agentDir?: string;
workspaceDir?: string;
mime?: string;
activeModel?: ActiveMediaModel;
prompt?: string;
timeoutMs?: number;
scopeContext?: MediaUnderstandingScopeContext;
};
type DescribeImageFileWithModelParams = {
filePath: string;
mediaUrl?: string;
cfg: OpenClawConfig;
agentId?: string;
agentDir?: string;
workspaceDir?: string;
mime?: string;
provider: string;
model: string;
prompt: string;
maxTokens?: number;
timeoutMs?: number;
};
type PreparedImageDescriptionInput = {
buffer: Buffer;
fileName: string;
mime?: string;
};
type PrepareImageDescriptionInputParams = Pick<DescribeImageFileWithModelParams, "filePath" | "mediaUrl" | "mime" | "cfg" | "timeoutMs">;
type DescribePreparedImageWithModelParams = Omit<DescribeImageFileWithModelParams, "filePath" | "mediaUrl" | "mime"> & {
image: PreparedImageDescriptionInput;
};
type DescribeImageFileWithModelResult = Awaited<ReturnType<NonNullable<MediaUnderstandingProvider["describeImage"]>>>;
type ExtractStructuredWithModelParams = {
/** At least one image input is required; text inputs provide supplemental context. */
input: StructuredExtractionInput[];
instructions: string;
schemaName?: string;
jsonSchema?: unknown;
jsonMode?: boolean;
cfg: OpenClawConfig;
agentDir?: string;
provider: string;
model: string;
profile?: string;
preferredProfile?: string;
authStore?: AuthProfileStore;
timeoutMs?: number;
};
type ExtractStructuredWithModelResult = Awaited<ReturnType<NonNullable<MediaUnderstandingProvider["extractStructured"]>>>;
type DescribeVideoFileParams = {
filePath: string;
cfg: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
mime?: string;
activeModel?: ActiveMediaModel;
};
type TranscribeAudioFileParams = {
filePath: string;
cfg: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
mime?: string;
activeModel?: ActiveMediaModel;
language?: string;
prompt?: string;
};
type MediaUnderstandingRuntime = {
resolveAudioInputBudget: (params: {
cfg: OpenClawConfig;
}) => Promise<{
enabled: false;
} | {
enabled: true;
maxBytes: number;
}>;
runMediaUnderstandingFile: (params: RunMediaUnderstandingFileParams) => Promise<RunMediaUnderstandingFileResult>;
describeImageFile: (params: DescribeImageFileParams) => Promise<RunMediaUnderstandingFileResult>;
prepareImageDescriptionInput: (params: PrepareImageDescriptionInputParams) => Promise<PreparedImageDescriptionInput>;
describePreparedImageWithModel: (params: DescribePreparedImageWithModelParams) => Promise<DescribeImageFileWithModelResult>;
describeImageFileWithModel: (params: DescribeImageFileWithModelParams) => Promise<DescribeImageFileWithModelResult>;
extractStructuredWithModel: (params: ExtractStructuredWithModelParams) => Promise<ExtractStructuredWithModelResult>;
describeVideoFile: (params: DescribeVideoFileParams) => Promise<RunMediaUnderstandingFileResult>;
transcribeAudioFile: (params: TranscribeAudioFileParams) => Promise<RunMediaUnderstandingFileResult>;
};
//#endregion
//#region src/plugins/runtime/task-domain-types.d.ts
/** Aggregate task-run counts exposed to plugin task views. */
type TaskRunAggregateSummary = {
total: number;
active: number;
terminal: number;
failures: number;
byStatus: TaskStatusCounts;
byRuntime: TaskRuntimeCounts;
};
/** Public task run summary exposed through plugin runtime task APIs. */
type TaskRunView = {
id: string;
runtime: TaskRuntime;
sourceId?: string;
sessionKey: string;
ownerKey: string;
scope: TaskScopeKind;
childSessionKey?: string;
flowId?: string;
parentTaskId?: string;
agentId?: string;
runId?: string;
label?: string;
title: string;
status: TaskStatus;
deliveryStatus: TaskDeliveryStatus;
notifyPolicy: TaskNotifyPolicy;
createdAt: number;
startedAt?: number;
endedAt?: number;
lastEventAt?: number;
cleanupAfter?: number;
error?: string;
progressSummary?: string;
terminalSummary?: string;
terminalOutcome?: TaskTerminalOutcome;
};
/** Detailed task run view; currently equal to the summary view. */
type TaskRunDetail = TaskRunView;
/** Result returned when cancelling a task run. */
type TaskRunCancelResult = {
found: boolean;
cancelled: boolean;
reason?: string;
task?: TaskRunDetail;
};
/** Public task flow summary exposed through plugin runtime task APIs. */
type TaskFlowView = {
id: string;
ownerKey: string;
requesterOrigin?: DeliveryContext;
status: TaskFlowStatus;
notifyPolicy: TaskNotifyPolicy;
goal: string;
currentStep?: string;
cancelRequestedAt?: number;
createdAt: number;
updatedAt: number;
endedAt?: number;
};
/** Detailed task flow view with state, wait, blocked, and task summary data. */
type TaskFlowDetail = TaskFlowView & {
state?: JsonValue;
wait?: JsonValue;
blocked?: {
taskId?: string;
summary?: string;
};
tasks: TaskRunView[];
taskSummary: TaskRunAggregateSummary;
};
//#endregion
//#region src/plugins/runtime/runtime-tasks.types.d.ts
type BoundTaskRunsRuntime = {
readonly sessionKey: string;
readonly requesterOrigin?: TaskDeliveryState["requesterOrigin"];
get: (taskId: string) => TaskRunDetail | undefined;
list: () => TaskRunView[];
findLatest: () => TaskRunDetail | undefined;
resolve: (token: string) => TaskRunDetail | undefined;
cancel: (params: {
taskId: string;
cfg: OpenClawConfig;
}) => Promise<TaskRunCancelResult>;
};
type PluginRuntimeTaskRuns = {
bindSession: (params: {
sessionKey: string;
agentId?: string;
requesterOrigin?: TaskDeliveryState["requesterOrigin"];
}) => BoundTaskRunsRuntime;
fromToolContext: (ctx: Pick<OpenClawPluginToolContext, "sessionKey" | "agentId" | "deliveryContext">) => BoundTaskRunsRuntime;
};
type BoundTaskFlowsRuntime = {
readonly sessionKey: string;
readonly requesterOrigin?: TaskDeliveryState["requesterOrigin"];
get: (flowId: string) => TaskFlowDetail | undefined;
list: () => TaskFlowView[];
findLatest: () => TaskFlowDetail | undefined;
resolve: (token: string) => TaskFlowDetail | undefined;
getTaskSummary: (flowId: string) => TaskRunAggregateSummary | undefined;
};
type PluginRuntimeTaskFlows = {
bindSession: (params: {
sessionKey: string;
requesterOrigin?: TaskDeliveryState["requesterOrigin"];
}) => BoundTaskFlowsRuntime;
fromToolContext: (ctx: Pick<OpenClawPluginToolContext, "sessionKey" | "deliveryContext">) => BoundTaskFlowsRuntime;
};
//#endregion
//#region src/plugins/runtime/types-core.d.ts
type TtsRuntimeApi = typeof runtime_api_d_exports;
type ListSpeechVoices = TtsRuntimeApi["listSpeechVoices"];
type PrepareTtsRequest = (...args: Parameters<TtsRuntimeApi["prepareTtsRequest"]>) => Promise<ReturnType<TtsRuntimeApi["prepareTtsRequest"]>>;
type TextToSpeech = typeof textToSpeech;
type TextToSpeechStream = TtsRuntimeApi["textToSpeechStream"];
type TextToSpeechTelephony = TtsRuntimeApi["textToSpeechTelephony"];
type RuntimeRequestHeartbeatOptions = Parameters<typeof requestHeartbeat>[0];
type RuntimeRequestHeartbeatNowOptions = Omit<RuntimeRequestHeartbeatOptions, "source" | "intent"> & Partial<Pick<RuntimeRequestHeartbeatOptions, "source" | "intent">>;
type RuntimeWriteConfigOptions = {
envSnapshotForRestore?: Record<string, string | undefined>;
expectedConfigPath?: string;
unsetPaths?: string[][];
};
type DeepReadonly<T> = T extends ((...args: never[]) => unknown) ? T : T extends readonly (infer U)[] ? ReadonlyArray<DeepReadonly<U>> : T extends object ? { readonly [K in keyof T]: DeepReadonly<T[K]>; } : T;
type RuntimeConfigAfterWrite = ConfigWriteAfterWrite;
type RuntimeConfigReplaceResult = ConfigReplaceResult;
type RuntimeProviderListParams = {
config?: OpenClawConfig;
};
type RuntimeConfigMutationContext = {
snapshot: ConfigFileSnapshot;
previousHash: string | null;
};
type RuntimeMutateConfigFileParams<T = void> = {
base?: ConfigMutationBase;
baseHash?: string;
afterWrite: RuntimeConfigAfterWrite;
writeOptions?: RuntimeWriteConfigOptions;
mutate: (draft: OpenClawConfig, context: RuntimeConfigMutationContext) => Promise<T | void> | T | void;
};
type RuntimeReplaceConfigFileParams = {
nextConfig: OpenClawConfig;
baseHash?: string;
afterWrite: RuntimeConfigAfterWrite;
writeOptions?: RuntimeWriteConfigOptions;
};
type RuntimeSessionEntry = SessionEntry$1;
type RuntimeSessionPluginExtensions = Record<string, Record<string, SessionPluginJsonValue>> | undefined;
type RuntimeSessionStoreReadParams = {
agentId?: string;
env?: NodeJS.ProcessEnv;
hydrateSkillPromptRefs?: boolean;
sessionKey: string;
readConsistency?: "latest";
storePath?: string;
};
type RuntimeSessionStoreListParams = Partial<Omit<RuntimeSessionStoreReadParams, "sessionKey">> & {
readOnly?: boolean;
};
type RuntimeSessionStoreEntrySummary = {
sessionKey: string;
entry: RuntimeSessionEntry;
};
type RuntimeCreateSessionEntryResult = {
key: string;
agentId: string;
sessionId: string;
entry: RuntimeSessionEntry;
};
type RuntimeCreateSessionEntryContext = RuntimeCreateSessionEntryResult & {
/** Host creation authority; runtimes that cannot supply it must leave it absent. */
initialization?: SessionInitialization;
};
type RuntimeCreateSessionEntryFinalPatch = {
pluginExtensions: RuntimeSessionPluginExtensions;
};
type RuntimeCreateSessionEntryBaseParams = {
cfg: OpenClawConfig;
key: string;
agentId?: string;
label?: string;
/** Create-only title snapshot: trimmed, capped at 500 UTF-16 units without splitting pairs; not a unique label. */
displayName?: string;
spawnedCwd?: string;
sessionRoot?: string;
permissionMode?: RuntimeSessionEntry["permissionMode"];
/** Bind the created session's CLI execution to this paired node. */
execNode?: string;
/** Working directory interpreted only by execNode. */
execCwd?: string;
initialEntry: {
agentHarnessId: string;
color?: string;
modelSelectionLocked?: true;
pluginExtensions?: RuntimeSessionPluginExtensions;
} | {
cliBackendId: string;
color?: string;
model: string;
cliSessionBinding: CliSessionBinding;
modelSelectionLocked: true;
pluginExtensions?: RuntimeSessionPluginExtensions;
/** Registry-injected owner; plugin callers cannot select another owner. */
pluginOwnerId?: string;
} | {
acpBackendId: string;
color?: string;
acpSessionBinding: {
acpAgentId: string;
agentSessionId: string;
};
modelSelectionLocked?: true;
pluginExtensions?: RuntimeSessionPluginExtensions;
/** Registry-injected owner; plugin callers cannot select another owner. */
pluginOwnerId?: string;
};
};
type RuntimeCreateSessionEntryParams = RuntimeCreateSessionEntryBaseParams & ({
/** Retry an interrupted initializer only when persisted trusted state matches exactly. */
recoverMatchingInitialEntry: true;
afterCreate: (created: RuntimeCreateSessionEntryContext) => Promise<RuntimeCreateSessionEntryFinalPatch>;
} | {
recoverMatchingInitialEntry?: never;
afterCreate?: (created: RuntimeCreateSessionEntryContext) => Promise<RuntimeCreateSessionEntryFinalPatch | void>;
});
type RuntimeSessionStoreEntryPatchParams = RuntimeSessionStoreReadParams & {
/** Synchronous final ownership check executed inside the commit transaction. */
assertCommitAllowed?: () => void;
fallbackEntry?: RuntimeSessionEntry;
maintenanceConfig?: ResolvedSessionMaintenanceConfigInput;
preserveActivity?: boolean;
replaceEntry?: boolean;
update: (entry: RuntimeSessionEntry, context: {
existingEntry?: RuntimeSessionEntry;
}) => Promise<Partial<RuntimeSessionEntry> | null> | Partial<RuntimeSessionEntry> | null;
};
type RuntimeUpsertSessionEntryParams = RuntimeSessionStoreReadParams & {
entry: RuntimeSessionEntry;
};
type RuntimeSessionWorkAdmissionParams = {
storePath: string;
sessionKey: string;
signal?: AbortSignal;
};
type RuntimeSessionStoreEntryUpdateParams = {
storePath: string;
sessionKey: string;
update: (entry: RuntimeSessionEntry) => Promise<Partial<RuntimeSessionEntry> | null> | Partial<RuntimeSessionEntry> | null;
skipMaintenance?: boolean;
takeCacheOwnership?: boolean;
requireWriteSuccess?: boolean;
};
/** @public Part of the PluginRuntime declaration contract. */
type PluginRuntimeThinkingPolicyRequest = {
provider?: string | null;
model?: string | null;
catalog?: ThinkingCatalogEntry[];
agentRuntime?: string | null;
};
/** @public Part of the PluginRuntime declaration contract. */
type PluginRuntimeThinkingPolicyLevel = {
id: ThinkLevel;
label: string;
};
/** @public Part of the PluginRuntime declaration contract. */
type PluginRuntimeThinkingPolicy = {
levels: PluginRuntimeThinkingPolicyLevel[];
defaultLevel?: ThinkLevel | null;
};
/** Structured logger surface injected into runtime-backed plugin helpers. */
type RuntimeLogger = {
debug?: (message: string, meta?: Record<string, unknown>) => void;
info: (message: string, meta?: Record<string, unknown>) => void;
warn: (message: string, meta?: Record<string, unknown>) => void;
error: (message: string, meta?: Record<string, unknown>) => void;
};
type RunHeartbeatOnceOptions = {
reason?: string;
agentId?: string;
sessionKey?: string;
/** Override heartbeat config (e.g. `{ target: "last" }` to deliver to the last active channel). */
heartbeat?: {
target?: string;
};
};
type LlmCompleteMessage = {
role: "system" | "user" | "assistant";
content: string;
};
type LlmCompleteCaller = {
kind: "plugin" | "context-engine" | "host" | "unknown";
id?: string;
name?: string;
};
type LlmCompleteUsage = {
inputTokens?: number;
outputTokens?: number;
cacheReadTokens?: number;
cacheWriteTokens?: number;
totalTokens?: number;
costUsd?: number;
};
type LlmCompleteCommonParams = {
/** Model ref (e.g. "anthropic/claude-sonnet-4-6"); defaults to the target agent's configured model. */
model?: string;
/** Advisory output limit; runtime owners without an equivalent control may ignore it. */
maxTokens?: number;
/** Advisory sampling hint; runtime owners without an equivalent control may ignore it. */
temperature?: number;
/** Requested reasoning effort; the host normalizes it for the selected model. */
reasoning?: ThinkLevel;
systemPrompt?: string;
signal?: AbortSignal;
/** Human-readable reason for audit/debug output. */
purpose?: string;
/** Agent whose model/credentials to use. Session-bound capabilities may disallow overrides. */
agentId?: string;
};
type LlmDirectCompleteParams = LlmCompleteCommonParams & {
messages: LlmCompleteMessage[];
execution?: undefined;
};
type LlmIsolatedAgentRuntimeCompleteParams = LlmCompleteCommonParams & {
/** Isolated runtimes currently accept one fresh user prompt, not a replayed chat history. */
messages: [{
role: "user";
content: string;
}];
execution: {
/** Fresh, literal-zero-tool completion through the configured agent runtime. */
mode: "isolated-agent-runtime";
/** Exact credential owner. Requires host-granted plugin policy. */
authProfileId?: string;
timeoutMs?: number;
};
};
type LlmCompleteParams = LlmDirectCompleteParams | LlmIsolatedAgentRuntimeCompleteParams;
type LlmCompleteExecution = {
mode: "direct-provider";
owner: {
kind: "provider";
id: string;
};
} | {
mode: "isolated-agent-runtime";
owner: {
kind: "cli" | "harness";
id: string;
};
};
type LlmCompleteResult = {
text: string;
provider: string;
model: string;
agentId: string;
usage: LlmCompleteUsage;
execution: LlmCompleteExecution;
audit: {
caller: LlmCompleteCaller;
purpose?: string;
sessionKey?: string;
};
};
type RuntimeRunEmbeddedAgentParams = Omit<RunEmbeddedAgentParams, "admittedRunContext" | "preparedRunAdmission" | "skillWorkshopCollectionReconcile">;
type RuntimeRunEmbeddedAgent = (params: RuntimeRunEmbeddedAgentParams) => Promise<EmbeddedAgentRunResult>;
/** Core runtime helpers exposed to trusted native plugins. */
type PluginRuntimeCore = {
version: string;
config: {
/** Current process runtime config snapshot. Prefer config passed into the active call path. */
current: () => DeepReadonly<OpenClawConfig>;
/**
* Persist a focused config mutation. Callers must choose the post-write
* behavior explicitly so the gateway can hot-reload, restart, or defer.
*/
mutateConfigFile: <T = void>(params: RuntimeMutateConfigFileParams<T>) => Promise<RuntimeConfigReplaceResult & {
result: T | undefined;
}>;
/**
* Persist a full config replacement. Callers must choose the post-write
* behavior explicitly so the gateway can hot-reload, restart, or defer.
*/
replaceConfigFile: (params: RuntimeReplaceConfigFileParams) => Promise<RuntimeConfigReplaceResult>;
};
agent: {
defaults: {
model: typeof DEFAULT_MODEL;
provider: typeof DEFAULT_PROVIDER;
};
resolveAgentDir: typeof resolveAgentDir;
resolveAgentWorkspaceDir: typeof resolveAgentWorkspaceDir;
resolveAgentIdentity: typeof resolveAgentIdentity;
/** Resolve an allowed catalog create target through canonical agent model/runtime policy. */
resolveSessionCatalogCreateTarget: typeof resolveAgentCatalogCreateTarget;
resolveThinkingDefault: (params: {
cfg: OpenClawConfig;
provider: string;
model: string;
catalog?: ModelCatalogEntry[];
}) => ThinkLevel;
normalizeThinkingLevel: (raw?: string | null) => ThinkLevel | undefined;
resolveThinkingPolicy: (params: PluginRuntimeThinkingPolicyRequest) => PluginRuntimeThinkingPolicy;
/** Admit a turn for this exact trusted channel plugin and its authenticated sender. */
runCommandFromIngress: (opts: AgentCommandIngressOpts, runtime: RuntimeEnv) => ReturnType<typeof agentCommandFromIngress>;
runEmbeddedAgent: RuntimeRunEmbeddedAgent;
resolveAgentTimeoutMs: typeof resolveAgentTimeoutMs;
/**
* Shares the embedded runner's CLI-backend dispatch eligibility (route,
* registered backend, stored credential mode) so opted-in callers can
* budget timeouts for the run that will actually execute.
*/
resolveCliBackendDispatchEligibility: typeof resolveEmbeddedCliBackendDispatchEligibility;
ensureAgentWorkspace: typeof ensureAgentWorkspace;
session: {
resolveStorePath: typeof resolveSessionStorePathCore;
createSessionEntry: (params: RuntimeCreateSessionEntryParams) => Promise<RuntimeCreateSessionEntryResult>;
getSessionEntry: (params: RuntimeSessionStoreReadParams) => RuntimeSessionEntry | undefined;
listSessionEntries: (params?: RuntimeSessionStoreListParams) => RuntimeSessionStoreEntrySummary[];
patchSessionEntry: (params: RuntimeSessionStoreEntryPatchParams) => Promise<RuntimeSessionEntry | null>;
upsertSessionEntry: (params: RuntimeUpsertSessionEntryParams) => Promise<void>;
runWithWorkAdmission: <T>(params: RuntimeSessionWorkAdmissionParams, run: (signal: AbortSignal) => Promise<T>) => Promise<T>;
updateSessionStoreEntry: (params: RuntimeSessionStoreEntryUpdateParams) => Promise<RuntimeSessionEntry | null>;
};
};
hooks: {
/** Dispatch untrusted external content through an isolated, contained hook agent turn. */
dispatchHookAgentTurn: (params: {
name: string;
agentId: string;
sessionKey: string;
message: string;
externalContentSource: "email";
deliver: boolean;
model?: string;
thinking?: ThinkLevel;
timeoutSeconds?: number;
idempotencyKey?: string;
}) => Promise<{
ok: true;
runId: string;
} | {
ok: false;
reason: string;
}>;
};
system: {
enqueueSystemEvent: typeof enqueueSystemEvent;
requestHeartbeat: typeof requestHeartbeat;
/**
* @deprecated Use `requestHeartbeat({ source, intent, reason })` so wake producers declare
* scheduler intent explicitly.
*/
requestHeartbeatNow: (opts?: RuntimeRequestHeartbeatNowOptions) => void;
/**
* Run a single heartbeat cycle immediately (bypassing the coalesce timer).
* Accepts an optional `heartbeat` config override so callers can choose
* an explicit destination or opt into internal-only `target: "none"` runs.
*/
runHeartbeatOnce: (opts?: RunHeartbeatOnceOptions) => Promise<HeartbeatRunResult>;
runCommandWithTimeout: typeof runCommandWithTimeout;
formatNativeDependencyHint: typeof formatNativeDependencyHint;
};
media: {
loadWebMedia: typeof loadWebMedia;
detectMime: typeof detectMime;
mediaKindFromMime: typeof mediaKindFromMime;
isVoiceCompatibleAudio: typeof isVoiceCompatibleAudio;
getImageMetadata: typeof getImageMetadata;
resizeToJpeg: typeof resizeToJpeg;
};
tts: {
prepareTtsRequest: PrepareTtsRequest;
textToSpeech: TextToSpeech;
textToSpeechStream: TextToSpeechStream;
textToSpeechTelephony: TextToSpeechTelephony;
listVoices: ListSpeechVoices;
};
mediaUnderstanding: {
resolveAudioInputBudget: MediaUnderstandingRuntime["resolveAudioInputBudget"];
runFile: MediaUnderstandingRuntime["runMediaUnderstandingFile"];
describeImageFile: MediaUnderstandingRuntime["describeImageFile"];
describeImageFileWithModel: MediaUnderstandingRuntime["describeImageFileWithModel"];
extractStructuredWithModel: MediaUnderstandingRuntime["extractStructuredWithModel"];
describeVideoFile: MediaUnderstandingRuntime["describeVideoFile"];
transcribeAudioFile: MediaUnderstandingRuntime["transcribeAudioFile"];
};
imageGeneration: {
generate: (params: GenerateImageParams) => Promise<GenerateImageRuntimeResult>;
listProviders: (params?: RuntimeProviderListParams) => ImageGenerationProvider[];
};
videoGeneration: {
generate: (params: GenerateVideoParams) => Promise<GenerateVideoRuntimeResult>;
listProviders: (params?: RuntimeProviderListParams) => VideoGenerationProvider[];
};
musicGeneration: {
generate: (params: GenerateMusicParams) => Promise<GenerateMusicRuntimeResult>;
listProviders: (params?: RuntimeProviderListParams) => MusicGenerationProvider[];
};
webSearch: {
listProviders: (params?: RuntimeProviderListParams) => PluginWebSearchProviderEntry[];
search: (params: RunWebSearchParams) => Promise<RunWebSearchResult>;
};
events: {
onAgentEvent: typeof onAgentEvent;
onSessionTranscriptUpdate: typeof onSessionTranscriptUpdate;
};
logging: {
shouldLogVerbose: typeof shouldLogVerbose;
getChildLogger: (bindings?: Record<string, unknown>, opts?: {
level?: LogLevel;
}) => RuntimeLogger;
};
state: {
resolveStateDir: typeof resolveStateDir;
openBlobStore: <TMetadata>(options: OpenBlobStoreOptions) => PluginBlobStore<TMetadata>;
openKeyedStore: <T>(options: OpenKeyedStoreOptions) => PluginStateKeyedStore<T>;
openSyncKeyedStore: <T>(options: OpenKeyedStoreOptions) => PluginStateSyncKeyedStore<T>;
openChannelIngressQueue: <TPayload, TMetadata = unknown, TCompletedMetadata = unknown>(options?: Omit<CreateChannelIngressQueueOptions, "channelId">) => ChannelIngressQueue<TPayload, TMetadata, TCompletedMetadata>;
openChannelIngressDrain: <TPayload, TMetadata = unknown, TCompletedMetadata = unknown>(options: Omit<CreateChannelIngressDrainOptions<TPayload, TMetadata, TCompletedMetadata>, "queue"> & {
queue?: ChannelIngressQueue<TPayload, TMetadata, TCompletedMetadata>;
accountId?: string;
stateDir?: string;
}) => ChannelIngressDrain;
};
tasks: {
runs: PluginRuntimeTaskRuns;
flows: PluginRuntimeTaskFlows;
managedFlows: PluginRuntimeTaskFlow;
};
llm: {
complete: (params: LlmCompleteParams) => Promise<LlmCompleteResult>;
acquireLocalService: (target: {
providerId: string;
baseUrl: string;
headers?: HeadersInit;
}, signal?: AbortSignal | null) => Promise<{
release: () => void;
} | undefined>;
};
modelAuth: {
/** Resolve auth for a model. Only provider/model, optional cfg, and workspaceDir are used. */
getApiKeyForModel: (params: {
model: Model<Api>;
cfg?: OpenClawConfig;
workspaceDir?: string;
}) => Promise<ResolvedProviderAuth>;
/** Resolve request-ready auth for a model, including provider runtime exchanges. */
getRuntimeAuthForModel: (params: {
model: Model<Api>;
cfg?: OpenClawConfig;
workspaceDir?: string;
}) => Promise<ResolvedProviderRuntimeAuth>;
/** Resolve auth for a provider by name. Only provider, optional cfg, and workspaceDir are used. */
resolveApiKeyForProvider: (params: {
provider: string;
cfg?: OpenClawConfig;
workspaceDir?: string;
}) => Promise<ResolvedProviderAuth>;
};
};
//#endregion
//#region src/context-engine/types.d.ts
type AssembleResult = {
/** Ordered messages to use as model context */
messages: AgentMessage[];
/** Estimated total tokens in assembled context */
estimatedTokens: number;
/**
* Controls which token estimate the runner treats as authoritative for
* preemptive overflow prechecks. The returned `messages` are always the
* prompt sent to the model; this only affects the precheck's token comparison.
*
* - "assembled": the generic precheck uses only the assembled prompt's estimate
* unless the engine owns compaction; owning engines manage prompt admission.
* - "preassembly_may_overflow": the precheck takes the maximum of the
* assembled estimate and the pre-assembly (unwindowed) session-history
* estimate. Engines opt into this when their assembled view can hide an
* overflow that would still affect the underlying transcript. This opt-in
* keeps the generic precheck active even for engines that own compaction.
*
* Defaults to "assembled".
*/
promptAuthority?: "assembled" | "preassembly_may_overflow";
/** Optional context-engine-provided instructions prepended to the runtime system prompt */
systemPromptAddition?: string;
/**
* Optional projection lifecycle for hosts with persistent backend threads.
*
* Context engines that return `thread_bootstrap` ask the host to inject the
* assembled context once for the supplied epoch, then reuse the backend
* thread until the epoch changes. Engines that omit this field retain the
* legacy per-turn projection behavior.
*/
contextProjection?: ContextEngineProjection;
};
type ContextEngineProjection = {
/** How the assembled context should be projected into the backend runtime. */
mode: "per_turn" | "thread_bootstrap";
/** Stable context epoch. Changing this tells persistent backends to rotate. */
epoch?: string;
/** Optional diagnostic fingerprint for the projected context payload. */
fingerprint?: string;
};
type ContextEngineOperation = "agent-run" | "manual-compact" | "subagent-spawn";
type ContextEngineRuntimeMode = "normal" | "fallback" | "degraded";
type ContextEngineSelectionSource = "configured" | "default" | "unknown";
type ContextEngineRuntimeReasonCode = "provider_timeout" | "provider_unavailable" | "rate_limited" | "context_overflow" | "runtime_unavailable" | "unknown";
type ContextEngineHostCapability = "bootstrap" | "assemble-before-prompt" | "after-turn" | "maintain" | "compact" | "runtime-llm-complete" | "thread-bootstrap-projection";
type ContextEngineHostRequirements = {
/** Host capabilities required before the engine can safely serve this operation. */
requiredCapabilities: ContextEngineHostCapability[];
/** Optional engine-authored guidance appended to the host compatibility error. */
unsupportedMessage?: string;
};
type ContextEngineRuntimeSettings = {
schemaVersion: 1;
runtime: {
host: "openclaw";
mode: ContextEngineRuntimeMode;
harnessId: string | null;
runtimeId: string | null;
};
model: {
requested: string | null;
resolved: string | null;
provider: string | null;
family: string | null;
};
contextEngineSelection: {
selectedId: string | null;
source: ContextEngineSelectionSource;
};
executionHost: {
id: string | null;
label: string | null;
};
limits: {
promptTokenBudget: number | null;
maxOutputTokens: number | null;
};
diagnostics: {
fallbackReason: ContextEngineRuntimeReasonCode | null;
degradedReason: ContextEngineRuntimeReasonCode | null;
};
};
type CompactResult = {
ok: boolean;
compacted: boolean;
reason?: string;
result?: {
summary?: string;
firstKeptEntryId?: string;
tokensBefore: number;
tokensAfter?: number;
details?: unknown;
/** Session id after compaction, when the runtime rotated transcripts. */
sessionId?: string;
/** Typed post-compaction live session target; successor when the runtime rotated transcripts. */
sessionTarget?: ContextEngineSessionTarget;
/**
* Raw session file path after compaction.
*
* @deprecated Use `sessionTarget`. Shipped plugin-sdk contract: released
* third-party context engines (v2026.6.x and earlier) report rotated
* transcripts through this field. Remove once typed session targets are
* the only successor contract.
*/
sessionFile?: string;
};
};
type IngestResult = {
/** Whether the message was ingested (false if duplicate or no-op) */
ingested: boolean;
};
type IngestBatchResult = {
/** Number of messages ingested from the supplied batch */
ingestedCount: number;
};
type BootstrapResult = {
/** Whether bootstrap ran and initialized the engine's store */
bootstrapped: boolean;
/** Number of historical messages imported (if applicable) */
importedMessages?: number;
/** Optional reason when bootstrap was skipped */
reason?: string;
};
type ContextEngineInfo = {
id: string;
name: string;
version?: string;
acceptedHostParams?: string[];
transcriptSemantics?: {
currentTurnFence?: "before-current-turn-entry-v1";
turnAdvancementIdempotency?: "atomic-idempotent-v1";
};
/** True when the engine manages its own compaction lifecycle. */
ownsCompaction?: boolean;
/**
* Controls how turn-triggered maintenance should be executed.
*
* Engines remain compatible by default unless the host explicitly opts into
* background turn maintenance.
*/
turnMaintenanceMode?: "foreground" | "background";
/**
* Host capability requirements for operations where using an unsupported
* runtime would silently degrade or corrupt the engine's behavior.
*/
hostRequirements?: Partial<Record<ContextEngineOperation, ContextEngineHostRequirements>>;
};
type SubagentSpawnPreparation = {
/** Roll back pre-spawn setup when subagent launch fails. */
rollback: () => void | Promise<void>;
};
type SubagentEndReason = "deleted" | "completed" | "swept" | "released";
type TranscriptRewriteReplacement = {
/** Existing transcript entry id to replace on the active branch. */
entryId: string;
/** Replacement message content for that entry. */
message: AgentMessage;
};
type TranscriptRewriteRequest = {
/** Message entry replacements to apply in one branch-and-reappend pass. */
replacements: TranscriptRewriteReplacement[];
/** Optional entry-id set that must cover every active-branch entry from the first replacement onward. */
allowedRewriteSuffixEntryIds?: string[];
};
type TranscriptRewriteResult = {
/** Whether the active branch changed. */
changed: boolean;
/** Estimated bytes removed from the active branch message payloads. */
bytesFreed: number;
/** Number of transcript message entries rewritten. */
rewrittenEntries: number;
/** Optional reason when no rewrite occurred. */
reason?: string;
};
type ContextEngineMaintenanceResult = TranscriptRewriteResult;
type ContextEnginePromptCacheRetention = "none" | "short" | "long" | "in_memory" | "24h";
type ContextEnginePromptCacheUsage = {
input?: number;
output?: number;
cacheRead?: number;
cacheWrite?: number;
contextUsage?: {
state: "available";
promptTokens: number;
totalTokens: number;
} | {
state: "unavailable";
};
total?: number;
};
type ContextEnginePromptCacheObservationChangeCode = "aggregateToolResultTruncation" | "cacheRetention" | "model" | "streamStrategy" | "systemPrompt" | "tools" | "transport";
type ContextEnginePromptCacheObservationChange = {
code: ContextEnginePromptCacheObservationChangeCode;
detail: string;
};
type ContextEnginePromptCacheObservation = {
broke: boolean;
previousCacheRead?: number;
cacheRead?: number;
changes?: ContextEnginePromptCacheObservationChange[];
};
type ContextEnginePromptCacheInfo = {
/** Runtime-resolved retention for the actual provider/model/request path. */
retention?: ContextEnginePromptCacheRetention;
/** Usage from the most recent API call, not accumulated retry/tool-loop totals. */
lastCallUsage?: ContextEnginePromptCacheUsage;
/** Result from the runtime's prompt-cache observability heuristic. */
observation?: ContextEnginePromptCacheObservation;
/** Last known cache-touch timestamp from runtime-managed cache-TTL bookkeeping. */
lastCacheTouchAt?: number;
/** Known cache expiry time when the runtime can source it confidently. */
expiresAt?: number;
};
type ContextEngineTranscriptStorageInfo = {
/**
* Authoritative transcript backend for this runtime turn.
*
* Hosts may still pass legacy locator fields such as `sessionFile` for older
* plugin contracts, but context engines should use this field to decide
* whether that locator is a live transcript source.
*/
kind: "sqlite";
};
type ContextEngineSessionTarget = {
/** Agent that owns the session in the runtime store. */
agentId?: string;
/** Runtime session id to compact. */
sessionId?: string;
/** Stable session key used for aliases, policy, and store resolution. */
sessionKey?: string;
/** Session store path that scopes the SQLite-backed runtime session. */
storePath?: string;
/** Optional transport thread identity for session target resolution. */
threadId?: string | number;
};
type ContextEngineRuntimeContext = Record<string, unknown> & {
/** Runtime task working directory; workspaceDir remains the agent bootstrap workspace. */
cwd?: string;
/**
* True when the host has explicitly opted this maintenance run into
* consuming deferred compaction debt.
*/
allowDeferredCompactionExecution?: boolean;
/** Runtime-resolved context window budget for the active model call. */
tokenBudget?: number;
/** Selected agent harness id when compaction delegates back to the runtime. */
agentHarnessId?: string;
/** Best-effort current prompt/context token estimate for this turn. */
currentTokenCount?: number;
/** Optional prompt-cache telemetry for cache-aware engines. */
promptCache?: ContextEnginePromptCacheInfo;
/** Authoritative transcript backend for this turn. */
transcriptStorage?: ContextEngineTranscriptStorageInfo;
/** Storage-neutral runtime session target for compaction delegation. */
sessionTarget?: ContextEngineSessionTarget;
/**
* Safe transcript rewrite helper implemented by the runtime.
*
* Engines decide what is safe to rewrite; the runtime owns how the session
* DAG is updated on disk.
*/
rewriteTranscriptEntries?: (request: TranscriptRewriteRequest) => Promise<TranscriptRewriteResult>;
/** LLM completion capability for engines that need model inference. */
llm?: {
complete: (params: LlmCompleteParams) => Promise<LlmCompleteResult>;
};
};
/**
* ContextEngine defines the pluggable contract for context management.
*
* Required methods define a generic lifecycle; optional methods allow engines
* to provide additional capabilities (retrieval, lineage, etc.).
*/
interface ContextEngine {
/** Engine identifier and metadata */
readonly info: ContextEngineInfo;
/**
* Initialize engine state for a session, optionally importing historical context.
*/
bootstrap?(params: {
sessionId: string;
sessionKey?: string;
/** Storage-neutral runtime session target for transcript/session SDK helpers. */
sessionTarget?: ContextEngineSessionTarget;
sessionFile: string;
runtimeSettings?: ContextEngineRuntimeSettings;
runtimeContext?: ContextEngineRuntimeContext;
}): Promise<BootstrapResult>;
/**
* Run transcript maintenance after bootstrap, successful turns, or compaction.
*
* Engines can use runtimeContext.rewriteTranscriptEntries() to request safe
* branch-and-reappend transcript rewrites without depending on runner internals.
*/
maintain?(params: {
sessionId: string;
sessionKey?: string;
/** Storage-neutral runtime session target for transcript/session SDK helpers. */
sessionTarget?: ContextEngineSessionTarget;
sessionFile: string;
runtimeSettings?: ContextEngineRuntimeSettings;
runtimeContext?: ContextEngineRuntimeContext;
/**
* Optional caller cancellation for maintenance work that may block.
* Engines should reject promptly when this signal aborts.
*/
abortSignal?: AbortSignal;
}): Promise<ContextEngineMaintenanceResult>;
/**
* Ingest a single message into the engine's store.
*/
ingest(params: {
sessionId: string;
sessionKey?: string;
message: AgentMessage;
/** True when the message belongs to a heartbeat run. */
isHeartbeat?: boolean;
}): Promise<IngestResult>;
/**
* Ingest a completed turn batch as a single unit.
*/
ingestBatch?(params: {
sessionId: string;
sessionKey?: string;
messages: AgentMessage[];
/** True when the batch belongs to a heartbeat run. */
isHeartbeat?: boolean;
}): Promise<IngestBatchResult>;
/**
* Execute optional post-turn lifecycle work after a run attempt completes.
* Engines can use this to persist canonical context and trigger background
* compaction decisions.
*/
afterTurn?(params: {
sessionId: string;
sessionKey?: string;
/** Storage-neutral runtime session target for transcript/session SDK helpers. */
sessionTarget?: ContextEngineSessionTarget;
sessionFile: string;
messages: AgentMessage[];
/** Number of messages that existed before the prompt was sent. */
prePromptMessageCount: number;
/** Optional auto-compaction summary emitted by the runtime. */
autoCompactionSummary?: string;
/** True when this turn belongs to a heartbeat run. */
isHeartbeat?: boolean;
/** Optional model context token budget for proactive compaction. */
tokenBudget?: number;
/** Optional runtime-owned context for engines that need caller state. */
runtimeSettings?: ContextEngineRuntimeSettings;
runtimeContext?: ContextEngineRuntimeContext;
}): Promise<void>;
/**
* Atomically and idempotently commit one accepted durable transcript turn.
* Messages span the admitted user entry through the accepted terminal entry.
* Hosts may retry the same advancement key after process or plugin failure.
*/
commitTurn?(params: {
advancementKey: string;
admission: TranscriptTurnAdmission;
terminal: TranscriptEntryAnchor;
messages: AgentMessage[];
sessionId: string;
sessionKey?: string;
sessionTarget?: ContextEngineSessionTarget;
runtimeSettings?: ContextEngineRuntimeSettings;
runtimeContext?: ContextEngineRuntimeContext;
isHeartbeat?: boolean;
}): Promise<{
status: "committed" | "duplicate";
}>;
/**
* Assemble model context under a token budget.
* Returns an ordered set of messages ready for the model.
*/
assemble(params: {
sessionId: string;
sessionKey?: string;
messages: AgentMessage[];
tokenBudget?: number;
/** Tool names available for this run so engines can align prompt guidance with runtime tool access. */
availableTools?: Set<string>;
/** Active memory citation mode when engines want to mirror memory prompt guidance. */
citationsMode?: MemoryCitationsMode;
/** Current model identifier (e.g. "claude-opus-4", "gpt-4o", "qwen2.5-7b").
* Allows context engine plugins to adapt formatting per model. */
model?: string;
/** The incoming user prompt for this turn (useful for retrieval-oriented engines). */
prompt?: string;
runtimeSettings?: ContextEngineRuntimeSettings;
runtimeContext?: ContextEngineRuntimeContext;
}): Promise<AssembleResult>;
/**
* Compact context to reduce token usage.
* May create summaries, prune old turns, etc.
*
* The host always bounds this call with a finite safety timeout (the same
* one that protects native runtime compaction). Engines that run long
* operations SHOULD additionally honor `abortSignal` so an in-flight
* compaction can be canceled promptly on run abort or host timeout instead
* of running to completion in the background.
*/
compact(params: {
sessionId: string;
sessionKey: string;
/** Caller-resolved owner agent for global session aliases. */
agentId?: string;
/** Storage-neutral runtime session target for delegated compaction. */
sessionTarget?: ContextEngineSessionTarget;
tokenBudget?: number;
/** Force compaction even below the default trigger threshold. */
force?: boolean;
/** Optional live token estimate from the caller's active context. */
currentTokenCount?: number;
/** Controls convergence target; defaults to budget. */
compactionTarget?: "budget" | "threshold";
customInstructions?: string;
/** Optional runtime-owned context for engines that need caller state. */
runtimeSettings?: ContextEngineRuntimeSettings;
runtimeContext?: ContextEngineRuntimeContext;
/**
* Optional abort signal honored before and during compaction. The host
* aborts it on run-level abort or when its compaction safety timeout
* fires; engines should stop work and reject promptly when it aborts.
*/
abortSignal?: AbortSignal;
}): Promise<CompactResult>;
/**
* Prepare context-engine-managed subagent state before the child run starts.
*
* Implementations can return a rollback handle that is invoked when spawn
* fails after preparation succeeds.
*/
prepareSubagentSpawn?(params: {
parentSessionKey: string;
childSessionKey: string;
contextMode?: "isolated" | "fork";
parentSessionId?: string;
parentSessionFile?: string;
childSessionId?: string;
childSessionFile?: string;
ttlMs?: number;
}): Promise<SubagentSpawnPreparation | undefined>;
/**
* Notify the context engine that a subagent lifecycle ended.
*/
onSubagentEnded?(params: {
childSessionKey: string;
reason: SubagentEndReason;
}): Promise<void>;
/**
* Dispose of any resources held by the engine.
*/
dispose?(): Promise<void>;
}
//#endregion
//#region src/plugins/cli-backend.types.d.ts
/** Static command adapter owned by a CLI backend plugin registration. */
type CliBackendConfig = {
/** CLI command to execute (absolute path or on PATH). */
command: string;
/** Base args applied to every invocation. */
args?: string[];
/** Output parsing mode (default: json). */
output?: "json" | "text" | "jsonl";
/** Output parsing mode when resuming a CLI session. */
resumeOutput?: "json" | "text" | "jsonl";
/** JSONL event dialect for CLIs with provider-specific stream formats. */
jsonlDialect?: "claude-stream-json" | "gemini-stream-json";
/** Long-lived CLI process mode. */
liveSession?: "claude-stdio";
/** Prompt input mode (default: arg). */
input?: "arg" | "stdin";
/** Max prompt length for arg mode (if exceeded, stdin is used). */
maxPromptArgChars?: number;
/** Extra env vars injected for this CLI. */
env?: Record<string, string>;
/** Env vars to remove before launching this CLI. */
clearEnv?: string[];
/** Flag used to pass model id (e.g. --model). */
modelArg?: string;
/** Model aliases mapping (OpenClaw model id → CLI model id). */
modelAliases?: Record<string, string>;
/** Args used to pass a session id (use {sessionId} placeholder). */
sessionArgs?: string[];
/** Alternate args to use when resuming a session (use {sessionId} placeholder). */
resumeArgs?: string[];
/** Argument appended to one explicitly forked resume invocation. */
forkArg?: string;
/** Argument followed by an assistant checkpoint id to bound one resumed fork. */
resumeAtArg?: string;
/** When to pass session ids. */
sessionMode?: "always" | "existing" | "none";
/** JSON fields to read session id from (in order). */
sessionIdFields?: string[];
/** Flag used to pass system prompt. */
systemPromptArg?: string;
/** Flag used to pass a system prompt file. */
systemPromptFileArg?: string;
/** Config override flag used to pass a system prompt file (e.g. -c). */
systemPromptFileConfigArg?: string;
/** Config override key used to pass a system prompt file. */
systemPromptFileConfigKey?: string;
/** System prompt behavior (append vs replace). */
systemPromptMode?: "append" | "replace";
/** When to send system prompt. */
systemPromptWhen?: "first" | "always" | "never";
/** Flag used to pass image paths. */
imageArg?: string;
/** How to pass multiple images. */
imageMode?: "repeat" | "list";
/** Where staged image files should live before handing them to the CLI. */
imagePathScope?: "temp" | "workspace";
/** Serialize runs for this CLI. */
serialize?: boolean;
/** Opt in to bounded raw transcript reseed before compaction for safe session resets. */
reseedFromRawTranscriptWhenUncompacted?: boolean;
/**
* Controls fresh recovery after a recoverable resumed-session failure.
*
* Undefined and `replace-binding` preserve the legacy clear-and-reseed behavior.
* `invalidated-only` retries fresh only when the failure proves the binding expired.
*/
freshSessionRecovery?: "replace-binding" | "invalidated-only";
/** Runtime reliability tuning for this backend's process lifecycle. */
reliability?: {
/** No-output watchdog tuning (fresh vs resumed runs). */
watchdog?: {
/** Fresh/new sessions (non-resume). */
fresh?: {
/** Fraction of overall timeout used when fixed timeout is not set. */
noOutputTimeoutRatio?: number;
/** Lower bound for computed watchdog timeout. */
minMs?: number;
/** Upper bound for computed watchdog timeout. */
maxMs?: number;
};
/** Resume sessions. */
resume?: {
/** Fraction of overall timeout used when fixed timeout is not set. */
noOutputTimeoutRatio?: number;
/** Lower bound for computed watchdog timeout. */
minMs?: number;
/** Upper bound for computed watchdog timeout. */
maxMs?: number;
};
};
};
};
type PluginTextReplacement = {
from: string | RegExp;
to: string;
};
type PluginTextTransforms = {
/** Rewrites applied to outbound prompt text before provider/CLI transport. */
input?: PluginTextReplacement[];
/** Rewrites applied to inbound assistant text before OpenClaw consumes it. */
output?: PluginTextReplacement[];
};
type CliBundleMcpMode = "claude-config-file" | "codex-config-overrides" | "gemini-system-settings";
type CliBackendPrepareExecutionContext = {
config?: OpenClawConfig;
workspaceDir: string;
agentDir?: string;
provider: string;
modelId: string;
/** Effective catalog context-window option selected for this run. */
contextWindow?: string;
/** Effective OpenClaw context budget selected for this run. */
contextTokenBudget?: number;
/** Effective OpenClaw thinking level selected for this run. */
thinkingLevel?: CliBackendThinkingLevel;
authProfileId?: string;
executionMode?: CliBackendExecutionMode;
/** Exact runtime tool surface the backend must enforce for this run. */
toolAvailability?: CliBackendToolAvailability;
/** Core-prepared environment, including any bundled MCP settings path. */
env?: Readonly<Record<string, string>>;
};
type CliBackendPreparedExecution = {
env?: Record<string, string>;
clearEnv?: string[];
/**
* Backend-owned staging that must run after the core CLI queue admits the turn.
* Use this for mutable per-profile CLI homes that the launched process also owns.
*/
beforeExecution?: () => Promise<void>;
cleanup?: () => Promise<void>;
/** Positive acknowledgement for `prepare-execution` tool enforcement. */
toolAvailabilityEnforced?: true;
/** Optional plugin-owned execution transport for this prepared local run. */
execute?: CliBackendExecute;
};
type CliBackendThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive" | "max";
type CliBackendExecutionMode = "agent" | "side-question";
/** Exact backend-native plus canonical OpenClaw tool surface for one CLI run. */
type CliBackendToolAvailability = {
native: readonly string[];
/** Canonical OpenClaw tool names served through the host-isolated transport. */
openClaw: readonly string[];
};
/** Native action a plugin-owned runtime asks the admitted host run to authorize. */
type CliBackendToolPermissionRequest = {
toolName: string;
toolInput: Record<string, unknown>;
toolCallId?: string;
abortSignal?: AbortSignal;
};
/** Host-owned native action decision; plugins never acquire approval authority. */
type CliBackendToolPermissionResult = {
behavior: "allow";
updatedInput: Record<string, unknown>;
} | {
behavior: "deny";
message: string;
};
type CliBackendUserInputOption = {
label: string;
description?: string;
};
type CliBackendUserInputQuestion = {
id: string;
header: string;
question: string;
multiSelect?: boolean;
isOther?: boolean;
options?: readonly CliBackendUserInputOption[] | null;
};
/** Structured operator input requested by a plugin-owned native runtime. */
type CliBackendUserInputRequest = {
toolName: string;
questions: readonly CliBackendUserInputQuestion[];
intro?: string;
toolCallId?: string;
abortSignal?: AbortSignal;
};
type CliBackendUserInputResult = {
status: "answered";
answers: Record<string, string[]>;
} | {
status: "cancelled";
message: string;
};
/** Lifecycle reasons accepted by a plugin-owned reusable execution process. */
type CliBackendLiveSessionCloseReason = "idle" | "restart" | "abort" | "mcp-capture-rotation";
/** Plugin-owned process lifecycle registered with the generic host owner. */
type CliBackendLiveSessionHandle = {
generation: string;
fingerprint: string;
isIdle(): boolean;
close(reason: CliBackendLiveSessionCloseReason, error?: unknown): void;
waitForExit(): Promise<void>;
};
/** Closure-bound host capability for one admitted reusable-runtime turn. */
type CliBackendLiveSessionCapability = {
fingerprint: string;
current(): CliBackendLiveSessionHandle | undefined;
register(handle: CliBackendLiveSessionHandle): void;
/** Rebinds this exact admitted turn to the registered process's stable capture. */
activate(handle: CliBackendLiveSessionHandle): void;
remove(handle: CliBackendLiveSessionHandle): void;
};
/** Turn-only context that must not become an operator-authored native transcript row. */
type CliBackendPromptContext = {
prependContext?: string;
appendContext?: string;
};
/** Exact prepared local process facts consumed by a plugin-owned execution transport. */
type CliBackendExecuteContext = {
command: string;
/** Preserve a verified invocation name when command resolves through a PATH shim. */
argv0?: string;
args: readonly string[];
cwd: string;
env: Record<string, string>;
prompt: string;
promptContext?: CliBackendPromptContext;
modelId: string;
systemPrompt: string;
sessionId?: string;
useResume: boolean;
abortSignal?: AbortSignal;
/** Revalidate the host-owned run and caller before deferred credential use or dispatch. */
assertCurrent?: () => void;
timeoutMs: number;
executionMode?: CliBackendExecutionMode;
toolAvailability?: CliBackendToolAvailability;
/** Exact host-owned reusable process lifecycle and current-turn admission. */
liveSession?: CliBackendLiveSessionCapability;
/** Closure-bound approval capability; retained copies fail after the run closes. */
requestToolPermission: (request: CliBackendToolPermissionRequest) => Promise<CliBackendToolPermissionResult>;
/** Closure-bound structured-input capability; retained copies fail after the run closes. */
requestUserInput: (request: CliBackendUserInputRequest) => Promise<CliBackendUserInputResult>;
};
/** Plugin-owned runtime yielding the backend's existing structured stream records. */
type CliBackendExecute = (context: CliBackendExecuteContext) => AsyncIterable<Record<string, unknown>>;
type CliBackendResolveExecutionArgsContext = {
config?: OpenClawConfig;
workspaceDir: string;
provider: string;
modelId: string;
authProfileId?: string;
thinkingLevel?: CliBackendThinkingLevel;
executionMode?: CliBackendExecutionMode;
toolAvailability?: CliBackendToolAvailability;
useResume: boolean;
baseArgs: readonly string[];
};
type CliBackendResolveExecutionArgs = (ctx: CliBackendResolveExecutionArgsContext) => readonly string[] | null | undefined;
type CliBackendResolveModelIdContext = {
modelId: string;
contextWindow?: string;
};
type CliBackendJsonlUsage = {
input?: number;
output?: number;
cacheRead?: number;
cacheWrite?: number;
total?: number;
};
type CliBackendParsedJsonlEvent = {
kind: "text";
text: string;
} | {
kind: "thinking";
text: string;
} | {
kind: "toolStart";
toolCallId: string;
name: string;
args?: Record<string, unknown>;
} | {
kind: "toolResult";
toolCallId: string;
name?: string;
isError?: boolean;
result?: unknown;
} | {
kind: "result";
text?: string;
sessionId?: string;
usage?: CliBackendJsonlUsage;
errorText?: string;
} | {
kind: "sessionId";
sessionId: string;
};
type CliBackendParseJsonlEventContext = {
backendId: string;
backend: Readonly<CliBackendConfig>;
};
type CliBackendParseJsonlEvent = (line: string, ctx: CliBackendParseJsonlEventContext) => CliBackendParsedJsonlEvent | readonly CliBackendParsedJsonlEvent[] | null | undefined;
type CliBackendParsedJsonlLifecycleEvent = {
kind: "compaction";
phase: "start";
} | {
kind: "compaction";
phase: "end";
completed: boolean;
};
type CliBackendParseJsonlLifecycleEvent = (line: string, ctx: CliBackendParseJsonlEventContext) => CliBackendParsedJsonlLifecycleEvent | readonly CliBackendParsedJsonlLifecycleEvent[] | null | undefined;
type CliBackendAuthEpochMode = "combined" | "profile-only";
type CliBackendNativeToolMode = "none" | "always-on" | "selectable";
/** Backend-owned mechanism that enforces exact per-run tool availability. */
type CliBackendToolAvailabilityEnforcement = "execution-args" | "prepare-execution";
type CliBackendSideQuestionToolMode = "disabled";
type CliBackendExactToolAvailabilityVersionPolicy = Readonly<{
/** Inclusive floor for stable package releases. */
stableMinimum: string;
/** Inclusive floors keyed by the first SemVer prerelease identifier. */
prereleaseMinimums?: Readonly<Record<string, string>>;
}>;
type CliBackendNormalizeConfigContext = {
config?: OpenClawConfig;
backendId: string;
agentId?: string;
};
/** Backend-owned implementation boundary for script-backed CLI executables. */
type CliBackendRuntimeArtifactPolicy = Readonly<{
kind: "bundled-package-tree";
/** Exact package.json name whose complete installed tree owns inference. */
packageName: string;
/** Only the command itself may be the package entrypoint. */
entrypoint: "command";
/** Supported package release lines when a run requests exact tool availability. */
exactToolAvailabilityVersionPolicy?: CliBackendExactToolAvailabilityVersionPolicy;
/** Canonical basenames allowed when this backend ships a self-contained native build. */
nativeExecutableNames?: readonly string[];
}>;
/** Complete backend-owned contract for in-place native session compaction. */
type CliBackendManualCompaction = Readonly<{
/** Builds the exact backend command for the resumed native session. */
buildPrompt: (customInstructions?: string) => string;
/** Prompt transport required by the backend control command. */
input: "arg" | "stdin";
/** Positively confirms that a successful process exit performed compaction. */
validateOutput: (rawOutput: string) => {
ok: true;
} | {
ok: false;
reason: string;
};
}>;
/** Plugin-owned CLI backend defaults used by the text-only CLI runner. */
type CliBackendPluginBase = {
/** Provider id used in model refs, for example `claude-cli/opus`. */
id: string;
/** Canonical model provider whose models this CLI backend can execute. */
modelProvider?: string;
/** Static command adapter owned by this plugin. */
config: CliBackendConfig;
/**
* Context-engine host capabilities provided by this backend when it is
* driven through the generic CLI runner.
*/
contextEngineHostCapabilities?: readonly ContextEngineHostCapability[];
/**
* Whether embedded runs opted into `cliBackendDispatch: "subscription-auth"`
* execute through this backend when the selected credential is
* subscription-scoped (oauth/token) or unresolvable.
*
* Set only when this backend's model provider rejects or meters direct API
* calls on subscription tokens, so the passthrough would fail or silently
* bill outside plan limits. API-key credentials always keep the passthrough.
*/
subscriptionAuthDispatch?: boolean;
/**
* Optional live-smoke metadata owned by the backend plugin.
*
* Keep provider-specific test wiring here instead of scattering it across
* Docker wrappers, docs, and gateway live tests.
*/
liveTest?: {
defaultModelRef?: string;
defaultImageProbe?: boolean;
defaultMcpProbe?: boolean;
docker?: {
npmPackage?: string;
binaryName?: string;
};
};
/** Required whenever this backend can become a verified inference owner. */
runtimeArtifact?: CliBackendRuntimeArtifactPolicy;
/**
* Whether OpenClaw should inject bundle MCP config for this backend.
*
* Keep this opt-in. Only backends that explicitly consume OpenClaw's bundle
* MCP bridge should enable it.
*/
bundleMcp?: boolean;
/**
* Provider-owned bundle MCP integration strategy.
*
* Different CLIs wire MCP through different surfaces:
* - Claude: `--strict-mcp-config --mcp-config`
* - Codex: `-c mcp_servers=...`
* - Gemini: system-level `settings.json`
*/
bundleMcpMode?: CliBundleMcpMode;
/**
* Optional config normalizer applied to the registered adapter.
*/
normalizeConfig?: (config: CliBackendConfig, context?: CliBackendNormalizeConfigContext) => CliBackendConfig;
/**
* Backend-owned final system-prompt transform.
*
* Use this for tiny CLI-specific compatibility rewrites without replacing
* the generic CLI runner or prompt builder.
*/
transformSystemPrompt?: (ctx: {
config?: OpenClawConfig;
workspaceDir?: string;
provider: string;
modelId: string;
modelDisplay: string;
agentId?: string;
systemPrompt: string;
}) => string | null | undefined;
/**
* Backend-owned bidirectional text replacements.
*
* `input` applies to the system prompt and user prompt passed to the CLI.
* `output` applies to parsed/streamed assistant text from the CLI.
*/
textTransforms?: PluginTextTransforms;
/**
* Preferred auth-profile id when the caller did not explicitly lock one.
*
* Use this when the backend should consume a canonical OpenClaw auth profile
* rather than ambient host auth by default.
*/
defaultAuthProfileId?: string;
/**
* Session/auth epoch source policy.
*
* `combined` keeps the legacy "host credential + auth profile" fingerprint.
* `profile-only` treats the selected OpenClaw auth profile as the sole auth
* owner for session invalidation when one is present.
*/
authEpochMode?: CliBackendAuthEpochMode;
/**
* Whether `prepareExecution` may auto-select a configured auth profile.
*
* Defaults to true for auth bridges. Set false for environment/config-only
* hooks that do not consume OpenClaw auth profiles.
*/
autoSelectAuthProfile?: boolean;
/**
* Backend-owned execution bridge.
*
* Use this on async run paths when the backend needs a generated auth/config
* bridge (for example a private CLI home directory) without teaching the core
* runner about provider-specific file formats.
*/
prepareExecution?: (ctx: CliBackendPrepareExecutionContext) => Promise<CliBackendPreparedExecution | null | undefined> | CliBackendPreparedExecution | null | undefined;
/**
* Backend-owned per-run argv rewrite.
*
* Use this for request-scoped CLI dialect flags that should not be modeled
* as static config, such as mapping OpenClaw thinking levels to a backend's
* native effort flag.
*/
resolveExecutionArgs?: CliBackendResolveExecutionArgs;
/** Backend-owned native model id selected from validated session metadata. */
resolveModelId?: (ctx: CliBackendResolveModelIdContext) => string;
/** How this backend enforces an exact per-run `toolAvailability` contract. */
toolAvailabilityEnforcement?: CliBackendToolAvailabilityEnforcement;
/**
* Maps the observed native list, intersected with the host selection, to equivalent
* cron capabilities: read/write/edit/apply_patch/exec/process/web_search/web_fetch.
* Never infer capabilities decided by unobserved model or sandbox settings.
* Core rejects other names before grant/capture and excludes node/tool-disabled runs.
*/
projectNativeToolAuthority?: (nativeTools: readonly string[]) => readonly string[];
/**
* Backend-owned JSONL line parser for provider-specific stream formats.
*
* Tool events report execution already performed by the backend. OpenClaw
* renders them but does not treat them as host tool execution or delivery evidence.
*/
parseJsonlEvent?: CliBackendParseJsonlEvent;
/**
* Optional lifecycle parser kept separate from the legacy JSONL event union.
* Existing plugins can continue exhaustively matching `parseJsonlEvent` results.
*/
parseJsonlLifecycleEvent?: CliBackendParseJsonlLifecycleEvent;
/**
* Whether this CLI backend can expose native tools outside OpenClaw's tool
* catalog. Exact restricted runs require `selectable` plus a declared
* `toolAvailabilityEnforcement`; `always-on` backends fail closed.
*/
nativeToolMode?: CliBackendNativeToolMode;
/**
* Side-question native tool behavior.
*
* Set to `disabled` only when `executionMode: "side-question"` reliably
* launches the CLI without native tools, even if normal agent turns expose
* backend-owned tools.
*/
sideQuestionToolMode?: CliBackendSideQuestionToolMode;
};
type CliBackendNativeCompactionContract = {
/** Backend-owned compaction for a persisted resumable CLI transcript. */
ownsNativeCompaction: true;
/** Optional control operation for explicit manual compaction. */
manualCompaction?: CliBackendManualCompaction;
} | {
/** Boolean-compatible ownership for existing plugins without manual compaction. */
ownsNativeCompaction?: boolean;
manualCompaction?: never;
};
/** Plugin-owned CLI backend defaults used by the text-only CLI runner. */
type CliBackendPlugin = CliBackendPluginBase & CliBackendNativeCompactionContract;
//#endregion
//#region src/system-agent/operator-approval.d.ts
type SystemAgentProposalRef = {
current?: string;
operation?: SystemAgentOperation;
};
//#endregion
//#region src/agents/tools/system-agent-tool.d.ts
type SystemAgentToolOptions = {
/** Verified inference owner, distinct from the internal OpenClaw execution agent. */
agentId?: string;
/** Where setup side effects run; the gateway surface never manages its own daemon. */
surface: "cli" | "gateway";
/** The host resolves delegated proposals under session policy, never a chat reply. */
operatorApprovalOnly?: boolean;
/**
* Host-verified consent for THIS turn: true only when the host judged the
* user's actual message to be an explicit approval. The model-supplied
* `approved` argument alone must never authorize a mutation (prompt
* injection, model error).
*/
approvalArmed?: boolean;
/**
* Approval is scoped to one exact operation: a denied mutating call records
* its canonical hash here (host-owned, survives turns), and an armed turn
* may execute only a call matching that hash. Cleared after use.
*/
proposalRef?: SystemAgentProposalRef;
/**
* Host handoff channel for actions the tool cannot perform itself
* (interactive channel setup, external onboarding guidance, opening the
* agent TUI). The engine reads it after the turn; CLI MCP hosts mirror it
* from tool events.
*/
directiveRef?: {
current?: SystemAgentToolDirective;
};
};
/** Host directives the hosting chat engine handles after the turn. */
type SystemAgentToolDirective = SystemAgentNavigationOperation | {
kind: "approved-operation";
operation: SystemAgentOperation;
};
//#endregion
//#region src/agents/agent-tools.before-tool-call.types.d.ts
type ToolOutcomeObservation = {
toolName: string;
argsHash: string;
resultHash: string;
resultContentSource?: AgentTool["resultContentSource"];
/** Monotonic model-call order within the owning embedded run. */
toolCallOrdinal?: number;
terminalPresentation?: string;
presentationOnly?: boolean;
};
type ToolOutcomeObserver = (observation: ToolOutcomeObservation) => void;
type HookContext = {
agentId?: string;
config?: OpenClawConfig;
/** Tool execution cwd for host-derived path facts. */
cwd?: string;
/** Host workspace used to resolve relative tool params for diagnostics only. */
workspaceDir?: string;
sessionKey?: string;
/** Ephemeral session UUID — regenerated on /new and /reset. */
sessionId?: string;
runId?: string;
/** What initiated this run, used to reject approvals on unattended surfaces. */
trigger?: string;
/** Device-scoped operator session allowed to review approvals initiated by this run. */
approvalReviewerDeviceId?: string;
trace?: DiagnosticTraceContext;
channelId?: string;
/** Host-derived message requester for sender-aware tool hooks. */
requester?: PluginHookToolRequesterContext;
/** Originating channel for approval delivery routing; mirrors exec approval turn-source fields. */
turnSourceChannel?: string;
turnSourceTo?: string;
turnSourceAccountId?: string;
turnSourceThreadId?: string | number;
loopDetection?: ToolLoopDetectionConfig;
onToolOutcome?: ToolOutcomeObserver;
allocateToolOutcomeOrdinal?: (toolCallId?: string) => number;
skillsSnapshot?: SkillSnapshot;
skillUsagePaths?: SkillUsagePath[];
skillCommand?: {
commandName: string;
skillFile?: string;
skillName: string;
skillSource?: SkillTelemetrySource;
toolName?: string;
};
sandbox?: {
root: string;
bridge: SandboxFsBridge;
};
};
type BeforeToolCallFailureDisposition = "blocked" | DiagnosticToolTerminalReason;
type PluginApprovalRequest = NonNullable<PluginHookBeforeToolCallResult["requireApproval"]>;
type DeferredPluginToolApproval = {
approval: PluginApprovalRequest;
toolName: string;
toolCallId?: string;
ctx?: HookContext;
baseParams: unknown;
overrideParams?: unknown;
};
type BeforeToolCallPolicyDiagnosticState = {
hasBeforeToolCallHook: boolean;
trustedToolPolicies: Array<{
id: string;
pluginId: string;
pluginName?: string;
}>;
};
type HookBlockedReason = "client-voice-confirmation" | "plugin-before-tool-call" | "plugin-approval" | "plugin-approval-unavailable" | "tool-loop";
type HookBlockedOutcome = {
blocked: true;
deniedReason?: HookBlockedReason;
reason: string;
params?: unknown;
};
type HookOutcome = (HookBlockedOutcome & {
kind: "veto";
genericDecision?: true;
}) | (HookBlockedOutcome & {
kind: "failure";
disposition: BeforeToolCallFailureDisposition;
}) | {
blocked: false;
params: unknown;
ownerDecision?: true;
approvalResolution?: PluginApprovalResolution;
deferredApproval?: DeferredPluginToolApproval;
loopWarning?: ToolLoopWarning;
};
//#endregion
//#region src/agents/agent-tools.before-tool-call.state.d.ts
/** Consume and remove hook-adjusted params for a completed tool call. */
declare function consumeAdjustedParamsForToolCall(toolCallId: string, runId?: string): unknown;
/** Snapshot hook-adjusted params without consuming later outcome bookkeeping. */
declare function peekAdjustedParamsForToolCall(toolCallId: string, runId?: string): unknown;
/** Consume whether policy prevented the target tool from starting. */
declare function consumePreExecutionBlockedToolCall(toolCallId: string, runId?: string): boolean;
//#endregion
//#region src/agents/before-tool-call-metadata.d.ts
type BeforeToolCallDiagnosticOptions = {
emitDiagnostics: boolean;
protectNetworkErrors?: boolean;
approvalMode?: "request" | "report" | "deny";
};
/** Return true when a tool already carries the before_tool_call wrapper marker. */
declare function isToolWrappedWithBeforeToolCallHook(tool: AnyAgentTool): boolean;
/** Toggle diagnostic event emission on an existing before_tool_call wrapper. */
declare function setBeforeToolCallDiagnosticsEnabled(tool: AnyAgentTool, enabled: boolean): void;
//#endregion
//#region src/agents/agent-tools.before-tool-call.diagnostics.d.ts
/** Finalizes a trusted terminal summary after harness result middleware. */
declare function finalizeToolTerminalPresentation(params: {
toolCallId: string;
runId?: string;
result: Awaited<ReturnType<AnyAgentTool["execute"]>>;
isError: boolean;
observer?: ToolOutcomeObserver;
toolName?: string;
toolCallOrdinal?: number;
}): void;
//#endregion
//#region src/agents/agent-tools.before-tool-call.approval.d.ts
/** Resolve a deferred plugin approval request at the later execution boundary. */
declare function requestDeferredPluginToolApproval(params: {
deferredApproval: DeferredPluginToolApproval;
signal?: AbortSignal;
}): Promise<HookOutcome>;
/** Notify plugin approval callbacks that a deferred approval was cancelled. */
declare function cancelDeferredPluginToolApproval(deferredApproval: DeferredPluginToolApproval): void;
//#endregion
//#region src/agents/agent-tools.before-tool-call.policy.d.ts
declare function getBeforeToolCallPolicyDiagnosticState(): BeforeToolCallPolicyDiagnosticState;
/** Return true when any before_tool_call policy could affect tool execution. */
declare function hasBeforeToolCallPolicy(): boolean;
declare function runBeforeToolCallHook(args: {
toolName: string;
params: unknown;
toolKind?: PluginHookToolKind;
toolInputKind?: PluginHookToolInputKind;
toolCallId?: string;
ctx?: HookContext;
signal?: AbortSignal;
approvalMode?: "request" | "report" | "deny" | "defer";
}): Promise<HookOutcome>;
//#endregion
//#region src/agents/agent-tools.before-tool-call.wrapper.d.ts
declare class BeforeToolCallBlockedError extends Error {
readonly reason: string;
constructor(reason: string);
}
/** Return the closed terminal disposition carried by a before-tool failure. */
declare function getBeforeToolCallFailureDisposition(error: unknown): BeforeToolCallFailureDisposition | undefined;
/** Remember hook-adjusted params for later adapter-side execution. */
declare function recordAdjustedParamsForToolCall(toolCallId: string | undefined, params: unknown, runId?: string): void;
/** Record that one concrete core-owned tool call may use structured replay classification. */
declare function recordStructuredReplayTrustForToolCall(toolCallId: string | undefined, tool: AnyAgentTool, runId?: string): void;
/**
* Returns true when an error represents an intentional before_tool_call veto.
*/
declare function isBeforeToolCallBlockedError(err: unknown): err is BeforeToolCallBlockedError;
declare function isPreExecutionBlockedToolResult(result: unknown): boolean;
/** Build the standard terminal result for vetoed tool calls. */
declare function buildBlockedToolResult(params: {
reason: string;
deniedReason?: HookBlockedReason;
toolCallId?: string;
runId?: string;
}): {
content: {
type: "text";
text: string;
}[];
details: {
status: string;
deniedReason: HookBlockedReason;
reason: string;
};
};
declare function wrapToolWithBeforeToolCallHook(tool: AnyAgentTool, ctx?: HookContext, options?: Partial<BeforeToolCallDiagnosticOptions>): AnyAgentTool;
/** Rebuild a before_tool_call wrapper while preserving the original source tool. */
declare function rewrapToolWithBeforeToolCallHook(tool: AnyAgentTool, ctx?: HookContext, options?: Partial<BeforeToolCallDiagnosticOptions>): AnyAgentTool;
declare namespace agent_tools_before_tool_call_d_exports {
export { BeforeToolCallFailureDisposition, BeforeToolCallPolicyDiagnosticState, DeferredPluginToolApproval, HookContext, ToolOutcomeObservation, ToolOutcomeObserver, buildBlockedToolResult, cancelDeferredPluginToolApproval, consumeAdjustedParamsForToolCall, consumePreExecutionBlockedToolCall, finalizeToolTerminalPresentation, getBeforeToolCallFailureDisposition, getBeforeToolCallPolicyDiagnosticState, hasBeforeToolCallPolicy, isBeforeToolCallBlockedError, isPreExecutionBlockedToolResult, isToolWrappedWithBeforeToolCallHook, peekAdjustedParamsForToolCall, recordAdjustedParamsForToolCall, recordStructuredReplayTrustForToolCall, requestDeferredPluginToolApproval, rewrapToolWithBeforeToolCallHook, runBeforeToolCallHook, setBeforeToolCallDiagnosticsEnabled, wrapToolWithBeforeToolCallHook };
}
//#endregion
//#region src/agents/agent-tools.read.d.ts
type SkillInstructionDeliveryCache = Map<string, Promise<boolean>>;
//#endregion
//#region src/agents/bash-tools.process.d.ts
/** Defaults injected by tests, agent scopes, and scoped process registries. */
type ProcessToolDefaults = {
cleanupMs?: number;
hasCronTool?: boolean;
inputWaitIdleMs?: number;
scopeKey?: string;
};
//#endregion
//#region src/agents/sandbox/types.docker.d.ts
type RequiredDockerConfigKeys = "image" | "containerPrefix" | "workdir" | "readOnlyRoot" | "tmpfs" | "network" | "capDrop";
type SandboxDockerConfig = Omit<SandboxDockerSettings, RequiredDockerConfigKeys> & Required<Pick<SandboxDockerSettings, RequiredDockerConfigKeys>>;
//#endregion
//#region src/agents/sandbox/types.d.ts
type SandboxToolPolicy = {
allow?: string[];
deny?: string[];
};
type SandboxWorkspaceAccess = "none" | "ro" | "rw";
type SandboxBrowserContext = {
bridgeUrl: string;
noVncUrl?: string;
containerName: string;
};
type SandboxContext = {
enabled: boolean;
/** Immutable creator policy: this session may never escape to a host execution target. */
required?: true;
backendId: SandboxBackendId;
sessionKey: string;
workspaceDir: string;
agentWorkspaceDir: string;
skillsWorkspaceDir?: string;
skillsEligibility?: SkillEligibilityContext;
skillUsagePaths?: SkillUsagePath[];
readOnlyResourceMounts?: Array<{
hostPath: string;
containerPath: string;
}>;
workspaceAccess: SandboxWorkspaceAccess;
runtimeId: string;
runtimeLabel: string;
containerName: string;
containerWorkdir: string;
docker: SandboxDockerConfig;
tools: SandboxToolPolicy;
browserAllowHostControl: boolean;
browser?: SandboxBrowserContext;
fsBridge?: SandboxFsBridge;
backend?: SandboxBackendHandle;
};
//#endregion
//#region src/agents/requester-tool-policy.d.ts
type RequesterToolPolicySource = "current-request" | "persisted-child" | "completion-handoff";
//#endregion
//#region src/agents/sandbox-tool-policy.d.ts
/** Provenance marker for wildcard allowlists created from `alsoAllow`. */
declare const IMPLICIT_ALLOW_ALL_FROM_ALSO_ALLOW: unique symbol;
//#endregion
//#region src/agents/tool-policy.d.ts
/** Tool allow/deny policy shape accepted by agent and sandbox config. */
type ToolPolicyLike = {
allow?: string[];
deny?: string[];
[IMPLICIT_ALLOW_ALL_FROM_ALSO_ALLOW]?: true;
};
//#endregion
//#region src/agents/conversation-capability-profile.d.ts
type ConversationCapabilityScope = "direct" | "shared" | "unknown";
type ResolvedConversationCapabilityProfile = {
agentId?: string;
serviceIdentity: {
agentId?: string;
agentDir?: string;
accountId?: string | null;
runId?: string;
sessionId?: string;
};
model: {
provider?: string;
id?: string;
api?: string;
contextWindowTokens?: number;
hasVision?: boolean;
};
conversation: {
scope: ConversationCapabilityScope;
chatType?: ChatType;
sessionKey?: string;
policySessionKey?: string;
runSessionKey?: string;
sessionId?: string;
messageProvider?: string | null;
messageChannel?: string | null;
messageTo?: string | null;
messageThreadId?: string | number | null;
currentChannelId?: string | null;
currentMessagingTarget?: string | null;
currentThreadTs?: string | null;
currentMessageId?: string | number | null;
groupId?: string | null;
groupChannel?: string | null;
groupSpace?: string | null;
memberRoleIds?: readonly string[];
spawnedBy?: string | null;
};
sender: {
id?: string | null;
name?: string | null;
username?: string | null;
e164?: string | null;
isOwner?: boolean;
};
workspace: {
workspaceDir?: string;
cwd?: string;
spawnWorkspaceDir?: string;
workspaceRoot: string;
runtimeRoot: string;
spawnWorkspaceRoot?: string;
instructionRoot?: string;
isCanonicalWorkspace?: boolean;
};
instructions: {
agentDir?: string;
workspaceDir?: string;
promptMode?: PromptMode;
isCanonicalWorkspace?: boolean;
};
skills: {
snapshot?: SkillSnapshot;
};
policy: {
agentId?: string;
sessionKey?: string;
subagentSessionKey?: string;
trustedGroup: {
groupId: string | null | undefined;
dropped: boolean;
};
profile?: string;
providerProfile?: string;
profilePolicy?: ToolPolicyLike;
providerProfilePolicy?: ToolPolicyLike;
profileAlsoAllow?: string[];
providerProfileAlsoAllow?: string[];
globalPolicy?: SandboxToolPolicy;
globalProviderPolicy?: SandboxToolPolicy;
agentPolicy?: SandboxToolPolicy;
agentProviderPolicy?: SandboxToolPolicy;
groupPolicy?: SandboxToolPolicy;
senderPolicy?: SandboxToolPolicy;
sandboxPolicy?: SandboxToolPolicy;
subagentPolicy?: SandboxToolPolicy;
inheritedToolPolicy?: SandboxToolPolicy;
delegated: boolean;
requesterPolicySource: RequesterToolPolicySource;
runtimeToolPolicyForInheritance?: ToolPolicyLike;
inheritancePolicies: Array<ToolPolicyLike | undefined>;
explicitToolAllowlist: string[];
/** Explicit config/runtime grants only; excludes built-in profile expansion. */
explicitToolOverrideAllowlist: string[];
explicitToolDenylist: string[];
runtimePluginToolGrant?: RuntimePluginToolGrant;
};
};
//#endregion
//#region src/agents/core-tool-factory-descriptors.d.ts
type OpenClawCodingToolConstructionPlan = {
includeBaseCodingTools: boolean;
includeShellTools: boolean;
includeChannelTools: boolean;
includeOpenClawTools: boolean;
includePluginTools: boolean;
};
//#endregion
//#region src/agents/delegation-capability.d.ts
type DelegationCapability = "full" | "report_only";
//#endregion
//#region src/plugins/tool-metadata.d.ts
/** MCP bridge metadata attached to plugin tools surfaced through agent tool lists. */
type PluginToolMcpMeta = {
serverName: string;
safeServerName: string;
toolName: string;
operation: "tool" | "resources_list" | "resources_read" | "prompts_list" | "prompts_get";
excludedFromOpenClawCatalog?: true;
deniedBySession?: true;
codexApproval?: {
mode?: McpCodexToolApprovalMode;
annotations?: McpCodexToolAnnotations;
};
node?: {
id: string;
displayName?: string;
};
};
//#endregion
//#region src/agents/tool-search-types.d.ts
type CatalogSource = "openclaw" | "mcp" | "client";
type CatalogTool = AnyAgentTool | ToolDefinition;
type ToolSearchCatalogToolExecutor = (params: {
tool: CatalogTool;
toolName: string;
source: CatalogSource;
sourceName?: string;
toolCallId: string;
parentToolCallId?: string;
/** Exact registered-instance classification resolved by the catalog owner. */
replaySafe?: boolean;
input: unknown;
signal?: AbortSignal;
onUpdate?: AgentToolUpdateCallback;
acceptResultBeforeProjection: (result: AgentToolResult<unknown>) => Promise<AgentToolResult<unknown>>;
}) => Promise<AgentToolResult<unknown>>;
/** Catalog entry retained behind compacted Tool Search control tools. */
type ToolSearchCatalogEntry = {
id: string;
source: CatalogSource;
sourceName?: string;
mcp?: PluginToolMcpMeta;
name: string;
label?: string;
description: string;
parameters?: unknown;
outputSchema?: TSchema;
tool: CatalogTool;
};
type ToolSearchCatalogSession = {
entries: ToolSearchCatalogEntry[];
counterScope: string;
searchCount: number;
describeCount: number;
callCount: number;
};
type ToolSearchCatalogTelemetry = Omit<ToolSearchCatalogSession, "entries"> & {
catalogSize: number;
sources: Record<CatalogSource, number>;
};
type ToolSearchCatalogRef = {
current?: ToolSearchCatalogSession;
closedTelemetry?: ToolSearchCatalogTelemetry;
onChange?: () => void;
disposeObserver?: () => void;
onDispose?: Set<() => void>;
};
//#endregion
//#region src/agents/tools/question-prompt-send.d.ts
/** Publishes one prompt into the originating conversation. */
type QuestionPromptSend = (payload: ReplyPayload) => void | Promise<void>;
/** A run's own way to show a question prompt, plus the channel it would appear in. */
type QuestionPromptDelivery = {
send: QuestionPromptSend;
messageChannel?: string;
};
//#endregion
//#region src/agents/tool-loop-detection-config.d.ts
/** Resolves effective tool loop-detection config by overlaying agent settings on globals. */
declare function resolveToolLoopDetectionConfig(params: {
cfg?: OpenClawConfig;
agentId?: string;
}): ToolLoopDetectionConfig | undefined;
declare namespace agent_tools_d_exports {
export { createOpenClawCodingTools, resolveToolLoopDetectionConfig };
}
/** Public options for building one plugin-owned agent tool surface. */
type OpenClawCodingToolsOptions = {
agentId?: string;
/** Retained policy owner; execution identity remains agentId/runSessionKey. */
policyAgentId?: string;
exec?: ExecToolDefaults & ProcessToolDefaults;
messageProvider?: string;
/** Canonical transport channel when tool-policy provider differs from delivery channel. */
messageChannel?: string;
/**
* How this run shows a blocking question tool's prompt. Left unset by harnesses
* whose tool lifecycle reserves the prompt for them.
*/
questionPrompt?: QuestionPromptDelivery;
/** Capabilities declared by the gateway client that originated this run. */
clientCaps?: string[];
/** Out-of-band plugin bindings attached by the run initiator. */
toolBindings?: Readonly<Record<string, unknown>>;
/** Trusted runtime-only authorization for one bounded cross-conversation recall pass. */
conversationRecall?: ConversationRecallContext;
/** Normalized conversation kind when the caller already has channel metadata. */
chatType?: ChatType;
/** Specific ingress provider used only for transport tool availability. */
toolPolicyMessageProvider?: string;
agentAccountId?: string;
messageTo?: string;
messageThreadId?: string | number;
/** Trusted platform-native conversation id for the active inbound turn. */
nativeChannelId?: string;
/** Opaque host-issued capability for current-turn channel message actions. */
messageActionTurnCapability?: string;
sandbox?: SandboxContext | null;
stagedMediaPaths?: ReadonlyMap<string, string>;
sessionKey?: string;
/**
* The durable store session key for the live run when it differs from the
* sandbox/policy session key used to construct the tool set.
*/
runSessionKey?: string;
/** Ephemeral session UUID — regenerated on /new and /reset. */
sessionId?: string;
/**
* Explicit one-shot local CLI runs should not keep plugin-owned process
* resources alive after emitting their result.
*/
oneShotCliRun?: boolean;
/** Stable run identifier for this agent invocation. */
runId?: string;
requesterThinkingLevel?: ThinkLevel;
/** Exact admitted run instance for lifecycle-bound subprocess capabilities. */
operationalRunInstance?: OperationalRunInstanceRef;
/** Device-scoped operator session allowed to review approvals initiated by this run. */
approvalReviewerDeviceId?: string;
/** Diagnostic trace context for hook/log correlation during this run. */
trace?: DiagnosticTraceContext;
/** What initiated this run (for trigger-specific tool restrictions). */
trigger?: string;
/** Stable cron job identifier populated for cron-triggered runs. */
jobId?: string;
/** Relative workspace path that memory-triggered writes may append to. */
memoryFlushWritePath?: string;
agentDir?: string;
preparedModelRuntime?: PreparedModelRuntimeSnapshot;
/** Task working directory for coding tools. Defaults to workspaceDir. */
cwd?: string;
workspaceDir?: string;
sessionPermissionPolicy?: PreparedSessionPermissionPolicy;
/**
* Workspace directory that spawned subagents should inherit.
* When sandboxing uses a copied workspace (`ro` or `none`), workspaceDir is the
* sandbox copy but subagents should inherit the real agent workspace instead.
* Defaults to workspaceDir when not set.
*/
spawnWorkspaceDir?: string;
config?: OpenClawConfig;
/** Explicitly distinguishes live Gateway session policy from a pinned run override. */
sessionConfigSource?: "runtime" | "pinned";
abortSignal?: AbortSignal;
/** Disable hook-owned diagnostics when an outer runtime owns tool diagnostics. */
emitBeforeToolCallDiagnostics?: boolean;
/** Skip hook wrapping when an outer tool-call boundary owns hook execution. */
wrapBeforeToolCallHook?: boolean;
/**
* Provider of the currently selected model (used for provider-specific tool quirks).
* Example: "anthropic", "openai", "google", "openai".
*/
modelProvider?: string;
/** Model id for the current provider (used for model-specific tool gating). */
modelId?: string;
/** Internal review-run restrictions and proposal provenance. */
skillWorkshop?: SkillWorkshopRunOptions;
/** Attempt-local authority to start or redirect delegated work. */
delegationCapability?: DelegationCapability;
/** Model API for the current provider (used for provider-native tool arbitration). */
modelApi?: string;
/** Model context window in tokens (used to scale read-tool output budget). */
modelContextWindowTokens?: number;
/** Resolved runtime model compatibility hints. */
modelCompat?: ModelCompatConfig;
/** If false, keep OpenClaw web_search even when a provider-native search tool is active. */
suppressManagedWebSearch?: boolean;
webFetchHostnameAllowlistRef?: {
value?: string[];
};
webSearchEnabled?: boolean;
/**
* Auth mode for the current provider. We only need this for Anthropic OAuth
* tool-name blocking quirks.
*/
modelAuthMode?: ModelAuthMode;
/** Current channel ID for auto-threading (Slack). */
currentChannelId?: string;
/** Routable target for the current conversation when it differs from the native channel ID. */
currentMessagingTarget?: string;
/** Normalized conversation id exposed to tool hooks. Defaults to currentChannelId. */
hookChannelId?: string;
/** Channel-owned sender/chat metadata exposed to subprocess environments. */
channelContext?: PluginHookChannelContext;
/** Current thread timestamp for auto-threading (Slack). */
currentThreadTs?: string;
/** Current inbound message id for action fallbacks (e.g. Telegram react). */
currentMessageId?: string | number;
/** True when the current inbound turn carried audio media. */
currentInboundAudio?: boolean;
/** Dynamic audio state for runs that can accept steered input after tool creation. */
hasCurrentInboundAudio?: () => boolean;
/** Group id for channel-level tool policy resolution. */
groupId?: string | null;
/** Group channel label (e.g. #general) for channel-level tool policy resolution. */
groupChannel?: string | null;
/** Group space label (e.g. guild/team id) for channel-level tool policy resolution. */
groupSpace?: string | null;
/** Trusted provider role ids for the requester in this group turn. */
memberRoleIds?: string[];
/** Parent session key for subagent group policy inheritance. */
spawnedBy?: string | null;
senderId?: string | null;
senderName?: string | null;
senderUsername?: string | null;
senderE164?: string | null;
/** Reply-to mode for Slack auto-threading. */
replyToMode?: "off" | "first" | "all" | "batched";
/** Mutable ref to track if a reply was sent (for "first" mode). */
hasRepliedRef?: {
value: boolean;
};
/** Allow plugin tools for this run to late-bind the gateway subagent. */
allowGatewaySubagentBinding?: boolean;
/** Runtime-scoped explicit allowlist used to materialize matching plugin tools. */
runtimeToolAllowlist?: string[];
/** Host-prepared proof that this exact session can request Gateway publication. */
githubPublicationAvailable?: boolean;
/** True when runtimeToolAllowlist is real parent authority that child sessions inherit. */
inheritRuntimeToolAllowlist?: boolean;
/** Mutable spawn capability snapshot refreshed after late-bound runtime tools are authorized. */
inheritedToolAllowlistRef?: string[];
/** Mutable cron creator cap ref for callers that append final runtime tools later. */
cronCreatorToolAllowlistRef?: CronCreatorToolAllowlistEntry[];
/** Mutable proof that the cron cap reached the final executable surface. */
cronCreatorToolAllowlistCaptureRef?: CronToolsAllowCaptureRef;
/** Visible fail-closed reason for queued Codex configured-MCP cron mutations. */
cronCreatorAuthorityUnavailableReason?: CronToolOptions["creatorAuthorityUnavailableReason"];
/** If true, the model has native vision capability */
modelHasVision?: boolean;
/** Mutable model-context generation used to expire screenshot coordinate frames. */
computerContextEpoch?: {
value: number;
};
/** Attempt-local full skill reads that remain visible in the model context. */
skillInstructionDeliveryCache?: SkillInstructionDeliveryCache;
/** Registers run-owned cleanup for tools that hold node resources. */
registerRunCleanup?: (cleanup: (reason: string) => Promise<void>) => void;
/** Require explicit message targets (no implicit last-route sends). */
requireExplicitMessageTarget?: boolean;
/** Visible source replies must be sent through the message tool when set to message_tool_only. */
sourceReplyDeliveryMode?: SourceReplyDeliveryMode;
/** Action sink available for model-proposed follow-up tasks. */
taskSuggestionDeliveryMode?: TaskSuggestionDeliveryMode;
inboundEventKind?: InboundEventKind;
/** If true, omit the message tool from the tool list. */
disableMessageTool?: boolean;
/** Collector runs never open operator approval flows. */
swarmCollector?: boolean;
/** Synthetic structured_output schema for collector runs. */
swarmOutputSchema?: Record<string, unknown>;
/** Keep the message tool available even when the selected profile omits it. */
forceMessageTool?: boolean;
/** Include the heartbeat response tool for structured heartbeat outcomes. */
enableHeartbeatTool?: boolean;
/** Keep the heartbeat response tool available even when the selected profile omits it. */
forceHeartbeatTool?: boolean;
/** If false, build plugin tools only while preserving the shared policy pipeline. */
includeCoreTools?: boolean;
/** Include Tool Search control tools when enabled for this run. */
includeToolSearchControls?: boolean;
/** Executes cataloged tools through the active agent run lifecycle. */
toolSearchCatalogExecutor?: ToolSearchCatalogToolExecutor;
/** Runtime-local Tool Search catalog ref shared with attempt compaction. */
toolSearchCatalogRef?: ToolSearchCatalogRef;
/** Limits which tool families are materialized before the shared policy pipeline runs. */
toolConstructionPlan?: OpenClawCodingToolConstructionPlan;
/** Ring-zero OpenClaw tool; set only by the OpenClaw agent runner. */
systemAgentTool?: SystemAgentToolOptions;
/** Trusted sender identity bit for command/channel-action auth and owner-gated plugin tools. */
senderIsOwner?: boolean;
/** Auth profiles already loaded for this run; used for prompt-time tool availability. */
authProfileStore?: AuthProfileStore;
/** Callback invoked when sessions_yield tool is called. */
onYield?: (message: string, acknowledgment?: string) => Promise<void> | void;
/** Side-effect-free runtime completion claimant composed with the durable subagent claim. */
claimYieldCompletion?: () => boolean | Promise<boolean>;
/** Optional instrumentation callback for tool preparation stage timing. */
recordToolPrepStage?: (name: string) => void;
/** Live observer called after wrapped tool outcomes are recorded. */
onToolOutcome?: ToolOutcomeObserver;
/** Reads the sticky untrusted-content flag for the current user turn. */
isTurnTainted?: () => boolean;
/** Supplies run-global model-call ordering for parallel tool outcomes. */
allocateToolOutcomeOrdinal?: (toolCallId?: string) => number;
/** Runtime-only resolved skill paths that the read tool may load under workspaceOnly. */
skillsSnapshot?: SkillSnapshot;
/** Original identities for sandbox-materialized skill instruction paths. */
skillUsagePaths?: SkillUsagePath[];
/** Prepared conversation-scoped facts for callers that already resolved this run context. */
conversationCapabilityProfile?: ResolvedConversationCapabilityProfile;
/** Trusted conversation policy prepared at channel ingress. */
conversationToolPolicy?: GroupToolPolicyConfig;
inputProvenance?: InputProvenance;
/** Consumed in-process completion capability; never derived from model-facing input. */
trustedInternalHandoff?: TrustedSubagentCompletionHandoff;
/** Trusted server-stamped authority for an explicitly capped scheduled run. */
scheduledToolPolicy?: ScheduledToolPolicyContext;
};
/** Build the runtime tool list exposed through the public agent harness SDK. */
declare function createOpenClawCodingTools(options?: OpenClawCodingToolsOptions): AnyAgentTool[];
//#endregion
//#region src/agents/harness/host-capability-types.d.ts
type AgentHarnessHostApprovalDecision = "allow-once" | "allow-always" | "deny";
type AgentHarnessHostApprovalTerminalReason = "user" | "timeout" | "malformed-verdict" | "no-route" | "run-aborted" | "gateway-restart" | "storage-corrupt";
type AgentHarnessHostApprovalResult = Readonly<{
decision: AgentHarnessHostApprovalDecision | null | undefined;
terminalReason: AgentHarnessHostApprovalTerminalReason | null | undefined;
}>;
type AgentHarnessPreparedEnvironment = Readonly<{
credentialScrubEnv: Readonly<Record<string, string>>;
localIdentityEnv: Readonly<Record<string, string>>;
/** Local child destination facts; must not be projected into a remote or sandbox process. */
localProcessEnv?: Readonly<Record<string, string>>;
/** Non-secret fact used to select the local GitHub identity overlay. */
managedLocalIdentity: boolean;
}>;
type AgentHarnessToolSurfaceOptions = Omit<NonNullable<Parameters<(typeof agent_tools_d_exports)["createOpenClawCodingTools"]>[0]>, "operationalRunInstance">;
type AgentHarnessHostCapabilities = Readonly<{
kind: "agent-harness-host-capability";
version: 1;
/** Fails closed unless this exact admitted run capability remains active. */
assertActive: () => void;
/** Reports one completed model call's output tokens to this admitted run's live total. */
reportOutputTokens?: (outputTokens: number) => void;
/** Adds native provenance only to this host's exact current admitted prompt. */
annotateCurrentUserTurn?: (annotation: UserTurnTranscriptAnnotation) => Promise<void>;
/** Closure-bound event sink backed by the host-owned trajectory recorder. */
trajectory?: Readonly<{
recordEvent: (type: string, data?: Record<string, unknown>) => void;
flush: () => Promise<void>;
}>;
/** Closure-bound non-secret maps prepared before harness placement. */
preparedEnvironment?: () => AgentHarnessPreparedEnvironment;
/** Applies the exact host caller binding to a plugin-built tool surface. */
bindToolSurface: (tools: AnyAgentTool[], options?: Readonly<{
cwd?: string;
}>) => AnyAgentTool[];
/** Creates and binds core tools without exposing admitted-run correlation to the plugin. */
createToolSurface?: (options: AgentHarnessToolSurfaceOptions, bindingOptions?: Readonly<{
cwd?: string;
}>) => AnyAgentTool[];
/** Core-owned byte binding for a native command approval, scoped to this admitted run. */
prepareMutableFileApproval?: (request: {
command: string;
cwd?: string;
}) => Promise<{
ok: true;
requiresOneShot: boolean;
revalidate: () => Promise<{
ok: true;
} | {
ok: false;
message: string;
}>;
} | {
ok: false;
message: string;
}>;
/** Runs policy with host-fixed HookContext; callers provide only the native action tuple. */
runBeforeToolCall: (request: Omit<Parameters<(typeof agent_tools_before_tool_call_d_exports)["runBeforeToolCallHook"]>[0], "approvalMode" | "ctx"> & {
/** Native relays may defer approval for a correlated app-server callback. */
approvalMode?: "request" | "defer";
/** Action-local facts from the native runtime; host authority remains closure-bound. */
nativeOperation?: Readonly<{
cwd?: string;
}>;
}) => ReturnType<(typeof agent_tools_before_tool_call_d_exports)["runBeforeToolCallHook"]>;
requestApproval: (request: {
signal?: AbortSignal;
title: string;
description: string;
severity: "info" | "warning";
toolName: string;
toolCallId?: string;
mcpTool?: {
server: string;
tool: string;
};
/** Persistence-only proof; loss of correlation does not cancel a one-shot approval. */
isMcpToolApprovalActive?: () => boolean;
allowedDecisions?: AgentHarnessHostApprovalDecision[];
timeoutMs: number;
transportTimeoutMs?: number;
}) => Promise<{
id?: string;
decision?: AgentHarnessHostApprovalDecision | null;
} | undefined>;
waitForApproval: (request: {
approvalId: string;
timeoutMs: number;
transportTimeoutMs?: number;
signal?: AbortSignal;
}) => Promise<AgentHarnessHostApprovalResult | undefined>;
}>;
//#endregion
//#region src/tasks/agent-harness-task-runtime-scope.d.ts
type AgentHarnessTaskRuntimeScope = {
readonly requesterSessionKey: string;
readonly requesterOrigin?: DeliveryContext;
};
//#endregion
//#region src/agents/tool-effect-receipt.d.ts
/** Host-owned effect provenance for one completed tool lifecycle. */
type ToolEffectReceipt = Readonly<{
state: "not_started" | "read_completed" | "failed_no_effect" | "mutation_committed" | "uncertain";
}>;
//#endregion
//#region src/agents/tool-error-summary.d.ts
type ProcessTerminalDiagnostic = {
kind: "process";
sessionId: string;
reason: {
kind: "exit";
exitCode: number;
} | {
kind: "signal";
signal: string | number;
} | {
kind: "timeout";
timeoutKind?: "overall-timeout" | "no-output-timeout";
};
};
type ToolErrorSummary = {
toolName: string;
executionStarted?: boolean;
meta?: string;
errorCode?: string;
error?: string;
validationErrorSummary?: string;
timedOut?: boolean;
middlewareError?: boolean;
mutatingAction?: boolean;
terminalDiagnostic?: ProcessTerminalDiagnostic;
};
//#endregion
//#region src/agents/embedded-agent-runner/replay-state.d.ts
/**
* Tracks whether an embedded run can be replayed after compaction or retry.
*/
type EmbeddedRunReplayState = {
replayInvalid: boolean;
hadPotentialSideEffects: boolean;
};
/** Serializable replay metadata stored with run results. */
type EmbeddedRunReplayMetadata = {
hadPotentialSideEffects: boolean;
replaySafe: boolean;
};
//#endregion
//#region src/agents/embedded-agent-runner/run/deferred-lifecycle-owner.d.ts
type DeferredEmbeddedRunLifecycleOwner = {
complete: () => Promise<void>;
discard: () => void;
};
//#endregion
//#region src/agents/embedded-agent-runner/run/preemptive-compaction.types.d.ts
/**
* Route chosen before a model call when context pressure may require compaction or truncation.
*/
type PreemptiveCompactionRoute = "fits" | "compact_only" | "truncate_tool_results_only" | "compact_then_truncate";
//#endregion
//#region src/agents/embedded-agent-runner/run/types.d.ts
type EmbeddedRunAttemptBase = Omit<RunEmbeddedAgentParams, "provider" | "model" | "authProfileId" | "authProfileIdSource" | "thinkLevel" | "fastMode" | "lane" | "enqueue" | "sessionFile" | "preparedRunAdmission" | "admittedRunContext">;
type EmbeddedRunContextWindowInfo = {
tokens: number;
referenceTokens?: number;
source: "model" | "modelsConfig" | "agentContextTokens" | "default";
};
type EmbeddedRunFastModeParam = boolean | (() => boolean | undefined);
type EmbeddedRunAttemptOperation = "attempt" | "settled-tool-finalization";
type EmbeddedRunAttemptToolTerminalObservation = {
toolCallId?: string;
toolName: string;
arguments?: unknown;
meta?: string;
executionStarted?: boolean;
/** Exact-instance replay classification resolved by the host tool catalog. */
replaySafe?: boolean;
outcome: "success" | "failure";
failure?: Omit<ToolErrorSummary, "toolName" | "meta" | "mutatingAction">;
/** Protocol-owned mutation facts for native tools that do not use OpenClaw definitions. */
nativeMutation?: {
mutatingAction: boolean;
replaySafe: boolean;
};
/** Concrete plugin owner; the terminal observer derives mutation facts from executed args. */
ownerMutation?: {
ownerKey: string;
};
};
type EmbeddedRunAttemptToolTerminalResolution = {
lastToolError?: ToolErrorSummary;
executionStarted: boolean;
executedArguments?: Record<string, unknown>;
sideEffectEvidence: boolean;
effectReceipt: ToolEffectReceipt;
};
type EmbeddedRunAttemptToolTerminalObserver = (observation: EmbeddedRunAttemptToolTerminalObservation) => EmbeddedRunAttemptToolTerminalResolution;
/** Host-owned trajectory recorder supplied to plugin harnesses for attempt-local runtime events. */
type EmbeddedRunAttemptTrajectoryRecorder = {
recordEvent: (type: string, data?: Record<string, unknown>) => void;
flush: () => Promise<void>;
};
type EmbeddedRunAttemptParams = EmbeddedRunAttemptBase & {
admittedRunContext: NonNullable<RunEmbeddedAgentParams["admittedRunContext"]>;
/**
* Run-owned start timestamp captured by the embedded-run orchestrator before
* admission. Flows onto the queue handle so recovery can project the active
* run's authoritative start time instead of the session's subagent first-run.
*/
startedAtMs?: number;
/** Explicit session owner captured before fallback agent resolution. */
contextEngineAgentId?: string;
/** Host-resolved sandbox snapshot for plugin harness tool construction. */
sandbox?: SandboxContext | null;
/** Host-created authority available only after harness selection. */
hostCapabilities?: AgentHarnessHostCapabilities;
/** Sticky operation identity used to suppress ordinary retry and hook policy. */
operation?: EmbeddedRunAttemptOperation;
/** Core-prepared fact that explicit requester/config policy restricts plugin-native tools. */
pluginHarnessToolPolicyRestricted?: boolean;
/** Audited exact denies that the plugin harness must enforce against native equivalents. */
pluginHarnessToolPolicySafeDeniedTools?: readonly string[];
preparedModelRuntime?: PreparedModelRuntimeSnapshot;
/** Active file-backed artifact target resolved by the run/session target seam. */
sessionFile: string;
initialReplayState?: EmbeddedRunReplayState;
/** Pluggable context engine for ingest/assemble/compact lifecycle. */
contextEngine?: ContextEngine;
/** Resolved model context window in tokens for assemble/compact budgeting. */
contextTokenBudget?: number;
/** Per-model contextTokens cap authored by the operator; absent when none was authored. */
authoredContextTokenCap?: number;
/** Source metadata for the resolved model context budget. */
contextWindowInfo?: EmbeddedRunContextWindowInfo;
/** Resolved API key for this run when runtime auth did not replace it. */
resolvedApiKey?: string;
/** Auth profile resolved for this attempt's provider/model call. */
authProfileId?: string;
/** Source for the resolved auth profile (user-locked or automatic). */
authProfileIdSource?: "auto" | "user";
provider: string;
modelId: string;
/** Operator-requested or initial model id before any fallback resolution. */
requestedModelId?: string | null;
/** True when this attempt is running after a model fallback decision. */
fallbackActive?: boolean;
/** Concrete fallback reason that selected this attempt, when known. */
fallbackReason?: string | null;
/** Whether this attempt may start or redirect work to another agent/task. */
delegationCapability?: DelegationCapability;
/** Concrete degraded-runtime reason for this attempt, when known. */
degradedReason?: string | null;
/** Final prepared harness for this attempt; not evidence of native session/model ownership. */
agentHarnessId?: string;
/** Non-authorizing expectation; the harness must verify its current private binding. */
expectedSessionRuntimeOwnership?: {
model: "native";
auth: "native" | "host";
/** Host-prepared credentials must still target this exact native tuple at inference. */
modelRef?: ModelRef;
};
/** Capture a local harness implementation only for setup/verified continuations. */
captureRuntimeArtifact?: boolean;
/** Exact implementation that must own the attempt before it creates a native thread. */
expectedRuntimeArtifact?: AgentHarnessRuntimeArtifactBinding;
/** OpenClaw-owned runtime policy prepared by the orchestrator for this attempt. */
runtimePlan?: AgentRuntimePlan;
/** Reports terminal tool facts to the host-owned attempt outcome accumulator. */
observeToolTerminal?: EmbeddedRunAttemptToolTerminalObserver;
/** Host-issued scope for harnesses that mirror native child runs into task state. */
agentHarnessTaskRuntimeScope?: AgentHarnessTaskRuntimeScope;
/** Storage-aware trajectory recorder owned by the OpenClaw host. */
trajectoryRecorder?: EmbeddedRunAttemptTrajectoryRecorder | null;
/** Live observer called after wrapped tool outcomes are recorded. */
onToolOutcome?: ToolOutcomeObserver;
/** Reads the sticky untrusted-content flag for the current user turn. */
isTurnTainted?: () => boolean;
/** Shipped harness notification; core uses onAttemptDeadlineChanged for queue ownership. */
onAttemptTimeoutArmed?: () => void;
/** Hands the lane an authoritative deadline, never a progress-idle estimate. */
onAttemptDeadlineChanged?: (deadline: CommandQueueTaskDeadline) => void;
/** Signals that this attempt's timeout has fired and must unwind promptly. */
onAttemptTimeout?: (reason: Error) => void;
/** Signals an explicit cancellation through the active native run handle. */
onAttemptAbort?: () => void;
onDeferredLifecycleOwner?: (owner: DeferredEmbeddedRunLifecycleOwner) => void;
onDeferredLifecycleAbort?: (reason?: "user_abort" | "restart" | "superseded") => void;
/** Run-owned permission changes survive native attempt replacement, never user cancellation. */
permissionChange?: {
readonly owner: object;
readonly baseExecOverrides: Readonly<NonNullable<RunEmbeddedAgentParams["execOverrides"]>>;
readonly notice?: string;
request: (mode: NonNullable<RunEmbeddedAgentParams["permissionMode"]> | null) => Promise<boolean>;
/** False means a newer permission request superseded this prepared attempt. */
applied: () => boolean;
recordApplied: (mode: NonNullable<RunEmbeddedAgentParams["permissionMode"]> | null) => void;
};
/** Supplies run-global model-call ordering for parallel tool outcomes. */
allocateToolOutcomeOrdinal?: (toolCallId?: string) => number;
model: Model;
authStorage: AuthStorage;
/** Auth profile store already resolved during startup for this attempt. */
authProfileStore: AuthProfileStore;
/**
* Full auth profile store for OpenClaw tool availability.
* Plugin-owned harnesses may scope `authProfileStore` to model transport credentials.
*/
toolAuthProfileStore?: AuthProfileStore;
modelRegistry: ModelRegistry;
thinkLevel: ThinkLevel;
fastMode?: EmbeddedRunFastModeParam;
/** True when this attempt is running the auto fast-mode policy. */
fastModeAuto?: boolean;
beforeAgentFinalizeRevisionAttempts?: number;
maxBeforeAgentFinalizeRevisions?: number;
};
type EmbeddedRunAttemptResult = {
terminal: AgentRunAttemptTerminal;
/** True when the runtime made the authoritative final-assistant transcript decision. */
assistantTranscriptOwned?: boolean;
/** Exact idempotency key for the runtime-owned final-assistant transcript row. */
assistantTranscriptIdempotencyKey?: string;
/** Host-private terminal identity used to close the accepted transcript turn. */
contextEngineTerminalAnchor?: TranscriptEntryAnchor;
preflightRecovery?: {
route: Exclude<PreemptiveCompactionRoute, "fits">;
source?: "mid-turn";
estimatedPromptTokens?: number;
promptBudgetBeforeReserve?: number;
overflowTokens?: number;
handled: true;
truncatedCount?: number;
} | {
route: Exclude<PreemptiveCompactionRoute, "fits">;
source?: "mid-turn";
estimatedPromptTokens?: number;
promptBudgetBeforeReserve?: number;
overflowTokens?: number;
handled?: false;
};
sessionIdUsed: string;
sessionFileUsed?: string;
diagnosticTrace?: DiagnosticTraceContext;
agentHarnessId?: string;
/** Current physical model attempt; replaced from the prepared runtime plan at the boundary. */
modelAttempt?: AgentRuntimeModelAttempt;
/** Native owner's selected tuple, distinct from response/billing model attribution. */
runtimeModelSelection?: ModelRef;
/** Exact credential material fingerprint reported by a harness-owned auth boundary. */
authBindingFingerprint?: string;
/** Exact local implementation used by a plugin-owned harness attempt. */
runtimeArtifact?: AgentHarnessRuntimeArtifactBinding;
agentHarnessResultClassification?: "empty" | "reasoning-only" | "planning-only";
promptTimeoutOutcome?: {
message?: string;
replayInvalid?: boolean;
livenessState?: EmbeddedRunLivenessState;
timeoutPhase?: AgentRunTimeoutPhase;
providerStarted?: boolean;
};
codexAppServerFailure?: {
kind: "client_closed_before_turn_completed" | "turn_settlement_timeout" | "turn_completion_idle_timeout";
turnWatchTimeoutKind?: "progress" | "completion" | "terminal";
transport: "stdio" | "unix" | "websocket";
threadId?: string;
turnId?: string;
replaySafe: boolean;
replayBlockedReason?: "assistant_output" | "tool_activity" | "potential_side_effect" | "active_item";
diagnostics?: {
transportError?: string;
idleMs?: number;
timeoutMs?: number;
lastActivityReason?: string;
lastNotificationMethod?: string;
lastNotificationItemId?: string;
lastNotificationItemType?: string;
lastNotificationItemRole?: string;
lastAssistantTextPreview?: string;
activeAppServerTurnRequests?: number;
activeTurnItemCount?: number;
terminalTurnNotificationQueued?: boolean;
completionIdleWatchArmed?: boolean;
assistantCompletionIdleWatchArmed?: boolean;
terminalIdleWatchArmed?: boolean;
};
};
bootstrapPromptWarningSignaturesSeen?: string[];
bootstrapPromptWarningSignature?: string;
systemPromptReport?: SessionSystemPromptReport;
finalPromptText?: string;
/** Exact provider-response count when the harness can observe model iterations directly. */
modelIterations?: number;
/** Saved provider retry setting resolved by the prepared session owner. */
providerRetryMaxRetries?: number;
messagesSnapshot: AgentMessage[];
/** Owner-eligible settled finalization, with frozen evidence or an unavailable projection. */
settledTurnFinalizationContext?: {
readonly source: "openclaw-transcript";
readonly messages: readonly AgentMessage[];
} | {
readonly source: "harness";
readonly data: unknown;
} | {
readonly source: "unavailable";
};
beforeAgentFinalizeRevisionReason?: string;
assistantTexts: string[];
latestMcpAppChannelView?: McpAppChannelView;
latestMcpConnectAction?: McpConnectAction;
lastAssistantTextMessageIndex?: number;
toolMetas: Array<{
toolName: string;
toolCallId?: string;
meta?: string;
replaySafe?: boolean;
isError?: boolean;
terminate?: boolean;
asyncStarted?: boolean;
asyncTaskRunId?: string;
asyncTaskId?: string;
/** Producer-recorded: this exec result parked a Code Mode run (status "waiting"). */
codeModeSuspended?: boolean;
}>;
acceptedSessionSpawns?: AcceptedSessionSpawn[];
/** This attempt accepted work whose future output has a runtime-owned delivery path. */
runtimeContinuationStarted?: boolean;
lastAssistant: AssistantMessage | undefined;
/**
* Omission preserves the legacy `lastAssistant` fallback; explicit `undefined`
* means this attempt produced no assistant response.
*/
currentAttemptAssistant?: AssistantMessage | undefined;
/** Completed message_end snapshot owned by this model attempt. */
currentAttemptCompletedAssistant?: AssistantMessage | undefined;
lastToolError?: ToolErrorSummary;
didSendViaMessagingTool: boolean;
didDeliverSourceReplyViaMessageTool?: boolean;
sourceReplyDelivered?: true;
didSendDeterministicApprovalPrompt?: boolean;
messagingToolSentTexts: string[];
messagingToolSentMediaUrls: string[];
messagingToolSentTargets: MessagingToolSend[];
messagingToolSourceReplyPayloads?: MessagingToolSourceReplyPayload[];
heartbeatToolResponse?: HeartbeatToolResponse;
toolMediaUrls?: string[];
/**
* Native artifacts produced and owned by the harness, never model-selected
* dynamic-tool output. Core validates this as a subset of toolMediaUrls.
*/
hostOwnedToolMediaUrls?: string[];
toolAudioAsVoice?: boolean;
toolTrustedLocalMedia?: boolean;
hasToolMediaBlockReply?: boolean;
successfulCronAdds?: number;
cloudCodeAssistFormatError: boolean;
/** Effective context window reported by the harness during this attempt. */
contextTokens?: number;
/** Whether the harness observed the window or carried prepared resolution forward. */
contextTokensSource?: "runtime" | "runtime-configured" | "resolved";
attemptUsage?: NormalizedUsage;
promptCache?: ContextEnginePromptCacheInfo;
contextBudgetStatus?: SessionContextBudgetStatus;
compactionCount?: number;
compactionTokensAfter?: number;
/**
* Client tool calls detected during this attempt (OpenResponses hosted
* tools), in the order the underlying LLM emitted them. Field is
* `undefined` when no client tools were called so existing truthiness
* checks across the runner pipeline (`attempt.clientToolCalls ? ...`)
* keep their meaning. When set, the array always has at least one entry.
*/
clientToolCalls?: Array<{
name: string;
params: Record<string, unknown>;
}>;
/** True when sessions_yield tool was called during this attempt. */
yieldDetected?: boolean;
/** Explicit user-facing waiting status supplied to sessions_yield. */
yieldAcknowledgment?: string;
/**
* True when code mode owned this attempt's model tool surface. Absent means
* the harness did not report engagement (treated as not engaged), which is
* how config-enabled code mode stays visible as a no-op on harness routes.
*/
codeModeEngaged?: boolean;
/** Completed assistant round trips observed during this attempt. */
assistantTurns?: number;
/** Inner bridge call counts from this attempt's tool-search/code-mode catalog. */
bridgeCalls?: {
search: number;
describe: number;
call: number;
};
replayMetadata: EmbeddedRunReplayMetadata;
/**
* Replay metadata for this attempt before prior session state is accumulated.
* Older harnesses may omit it and retain conservative cumulative retry gating.
*/
currentAttemptReplayMetadata?: EmbeddedRunReplayMetadata;
itemLifecycle: {
startedCount: number;
completedCount: number;
activeCount: number;
};
setTerminalLifecycleMeta?: (meta: {
replayInvalid?: boolean;
livenessState?: EmbeddedRunLivenessState;
stopReason?: string;
yielded?: boolean;
timeoutPhase?: AgentRunTimeoutPhase;
providerStarted?: boolean;
aborted?: boolean;
}) => void;
};
//#endregion
//#region src/agents/harness/types.d.ts
/** Private native ownership, not execution authority or credential readiness. */
type AgentHarnessSessionRuntimeOwnership = {
model: "native";
auth: "native" | "host";
/** Actual native selection, only when both facts are known from the same binding. */
modelRef?: ModelRef;
};
type AgentHarnessPreparedAuthSupport = {
source: "profile" | "direct" | "harness" | "none";
mode?: string;
requirement?: ProviderModelRouteAuthRequirement;
};
type AgentHarnessSupportContext = {
provider: string;
modelId?: string;
modelProvider?: {
api?: string;
baseUrl?: string;
azureApiVersion?: string;
/** Secret-free projection of request behavior a native harness must reproduce. */
requestTransportOverrides?: ProviderRouteOverridePresence;
/** Provider-owned native-runtime compatibility for the prepared route. */
runtimePolicy?: ProviderModelRouteRuntimePolicy;
/** Secret-free auth source the native runtime must reproduce for this attempt. */
preparedAuth?: AgentHarnessPreparedAuthSupport;
request?: {
auth?: {
mode?: unknown;
};
proxy?: unknown;
tls?: unknown;
allowPrivateNetwork?: unknown;
};
};
requestedRuntime: EmbeddedAgentRuntime;
providerOwnerStatus?: "unowned" | "owned" | "ambiguous";
providerOwnerPluginIds?: readonly string[];
};
type AgentHarnessSupport = {
supported: true;
priority?: number;
reason?: string;
} | {
supported: false;
reason?: string;
/** Lossless host fallback when this harness cannot reproduce the prepared request. */
fallbackRuntime?: "openclaw";
};
type InternalEmbeddedRunAttemptParams = EmbeddedRunAttemptParams;
/** @deprecated Read `terminal` instead. Remove no earlier than the 2026.9 stable release. */
type AgentHarnessDeprecatedAttemptTerminalFields = {
aborted?: boolean;
externalAbort?: boolean;
timedOut?: boolean;
idleTimedOut?: boolean;
timedOutDuringCompaction?: boolean;
timedOutDuringToolExecution?: boolean;
timedOutByRunBudget?: boolean;
promptError?: unknown;
promptErrorSource?: AgentRunAttemptFailureSource | null;
};
type AgentHarnessCanonicalAttemptResult = Omit<EmbeddedRunAttemptResult, "contextEngineTerminalAnchor"> & AgentHarnessDeprecatedAttemptTerminalFields;
/** @deprecated Return `terminal` instead. Remove no earlier than the 2026.9 stable release. */
type AgentHarnessLegacyAttemptResult = Omit<EmbeddedRunAttemptResult, "contextEngineTerminalAnchor" | "terminal"> & AgentHarnessDeprecatedAttemptTerminalFields & {
aborted: boolean;
externalAbort: boolean;
timedOut: boolean;
idleTimedOut: boolean;
timedOutDuringCompaction: boolean;
timedOutDuringToolExecution?: boolean;
timedOutByRunBudget?: boolean;
promptError: unknown;
promptErrorSource: AgentRunAttemptFailureSource | null;
};
type AgentHarnessAttemptParamsBase = Omit<InternalEmbeddedRunAttemptParams, "admittedRunContext" | "contextEngineLogicalTurnLease" | "onContextEngineTurnCandidate" | "trajectoryRecorder">;
/**
* @deprecated Use AgentHarnessAttemptParamsV2. The optional capability keeps
* existing harness source compatible through 2026-10-12.
*/
type AgentHarnessAttemptParams = AgentHarnessAttemptParamsBase & {
hostCapabilities?: AgentHarnessHostCapabilities;
};
type AgentHarnessAttemptResult = AgentHarnessCanonicalAttemptResult | AgentHarnessLegacyAttemptResult;
type AgentHarnessSettledTurnFinalizationAttemptParams<TAttemptParams extends AgentHarnessAttemptParams = AgentHarnessAttemptParams> = Omit<TAttemptParams, "hostCapabilities"> & {
hostCapabilities?: never;
};
type AgentHarnessSettledTurnFinalizationParams<TAttemptParams extends AgentHarnessAttemptParams = AgentHarnessAttemptParams> = {
/** Fully prepared attempt context for the isolated finalization operation. */
attempt: AgentHarnessSettledTurnFinalizationAttemptParams<TAttemptParams>;
/** Settled result whose completed tool transcript needs a final visible answer. */
settledAttempt: AgentHarnessCanonicalAttemptResult;
};
type AgentHarnessSettledTurnFinalizationResult = {
/** The single completed assistant answer produced by the isolated operation. */
assistant: AssistantMessage;
/** Normalized usage for the finalization model call only. */
usage?: NormalizedUsage;
/** True when the harness already persisted the assistant into the application transcript. */
assistantTranscriptOwned?: boolean;
/** Exact idempotency key for the harness-owned assistant transcript row. */
assistantTranscriptIdempotencyKey?: string;
/** Assistant stream generation index used to correlate final reply delivery. */
assistantMessageIndex?: number;
diagnosticTrace?: DiagnosticTraceContext;
};
/** @deprecated Use AgentHarnessIsolatedCompletionParamsV2. Remove after 2026-10-12. */
type AgentHarnessIsolatedCompletionParams = {
/** Logical provider selected by the caller before harness dispatch. */
provider: string;
/** Logical model id selected by the caller before harness dispatch. */
modelId: string;
/** Exact prepared transport model; harnesses must not resolve another route. */
model: Model;
/** Exact prepared credential; harnesses must not rotate or substitute it. */
auth: ResolvedProviderAuth;
/** Non-reversible proof of the prepared credential owner when available. */
sourceAuthFingerprint?: string;
config: OpenClawConfig;
agentId: string;
agentDir: string;
workspaceDir: string;
systemPrompt: string;
prompt: string;
timeoutMs: number;
abortSignal?: AbortSignal;
/** Revalidate after preparation and before credential or inference I/O, including retries. */
assertCurrent?: () => void;
thinkLevel?: ThinkLevel;
/** Do not recover ambiguous reasoning as visible text; an empty visible result is valid. */
outputTextPolicy?: "strict-visible";
streamParams?: {
maxTokens?: number;
temperature?: number;
};
};
type AgentHarnessIsolatedCompletionAuthorization = {
/** OpenClaw resolved the exact transport model and credential before handoff. */
owner: "host";
model: Model;
auth: ResolvedProviderAuth;
/** Non-reversible proof of the prepared credential owner when available. */
sourceAuthFingerprint?: string;
} | {
/** The selected harness owns credential resolution for this prepared route. */
owner: "harness";
plan: AgentRuntimeAuthPlan;
/** Credential snapshot restricted to the single profile selected for this call. */
authProfileStore: AuthProfileStore;
};
type AgentHarnessIsolatedCompletionParamsV2 = Omit<AgentHarnessIsolatedCompletionParams, "model" | "auth" | "sourceAuthFingerprint"> & {
authorization: AgentHarnessIsolatedCompletionAuthorization;
};
type AgentHarnessIsolatedCompletionResult = {
/** The single assistant completion. Core rejects tool-shaped or failed results. */
assistant: AssistantMessage;
};
type AgentHarnessAuthBindingFingerprintParams = {
authProfileId: string;
authProfileStore: AuthProfileStore;
agentDir: string;
config?: OpenClawConfig;
};
/**
* @deprecated Use {@link AgentHarnessSideQuestionParamsV2}. This compatibility
* contract is retained through 2026-10-12.
*/
type AgentHarnessSideQuestionParams = {
/** Host-bound authority for this admitted side execution; contains no public token fields. */
hostCapabilities?: AgentHarnessHostCapabilities;
/** Host-resolved sandbox snapshot for this side execution. */
sandbox?: SandboxContext | null;
/** Prepared plugin/model generation that owns this side execution. */
preparedModelRuntime?: PreparedModelRuntimeSnapshot;
cfg: OpenClawConfig;
agentDir: string;
provider: string;
model: string;
runtimeModel?: Model<Api>;
/** One atomic route/profile/store snapshot prepared before native dispatch. */
preparedRuntimeAuth: {
plan: AgentRuntimeAuthPlan;
authProfileStore: AuthProfileStore;
authStorage: AuthStorage;
modelRegistry: ModelRegistry;
/** Resolved host credential for an immutable API-key route only. */
resolvedApiKey?: string;
};
question: string;
sessionEntry: SessionEntry$1;
sessionStore?: Record<string, SessionEntry$1>;
sessionKey?: string;
storePath?: string;
resolvedThinkLevel?: ThinkLevel;
resolvedReasoningLevel: ReasoningLevel;
blockReplyChunking?: BlockReplyChunking;
resolvedBlockStreamingBreak?: "text_end" | "message_end";
opts?: GetReplyOptions;
isNewSession: boolean;
sessionId: string;
sessionFile: string;
sandboxSessionKey?: string;
agentId?: string;
workspaceDir?: string;
messageChannel?: string;
messageProvider?: string;
chatType?: ChatType;
agentAccountId?: string;
messageTo?: string;
messageThreadId?: string | number;
chatId?: string;
messageActionTurnCapability?: string;
groupId?: string | null;
groupChannel?: string | null;
groupSpace?: string | null;
memberRoleIds?: string[];
spawnedBy?: string | null;
senderId?: string | null;
senderName?: string | null;
senderUsername?: string | null;
senderE164?: string | null;
senderIsOwner?: boolean;
currentChannelId?: string;
toolsAllow?: string[];
authProfileId?: string;
authProfileIdSource?: "auto" | "user";
};
type AgentHarnessSideQuestionResult = {
text: string;
};
type AgentHarnessCompactParams = CompactEmbeddedAgentSessionParams;
type AgentHarnessCompactResult = EmbeddedAgentCompactResult;
type AgentHarnessNativeCompactionRequest = "after_context_engine" | "required_preflight";
type AgentHarnessNativeCompactionParams = AgentHarnessCompactParams & {
nativeCompactionRequest: AgentHarnessNativeCompactionRequest;
};
type AgentHarnessNativeCompaction = (params: AgentHarnessNativeCompactionParams) => Promise<AgentHarnessCompactResult | undefined>;
type AgentHarnessRegistrationOptions = {
/**
* Registers the Codex-only native preflight bridge in host-owned registry
* metadata. Arbitrary properties on the public harness never grant it.
*/
nativeCompaction?: AgentHarnessNativeCompaction;
};
type AgentHarnessResetParams = {
agentId?: string;
sessionId?: string;
sessionKey?: string;
sessionFile?: string;
reason?: "new" | "reset" | "idle" | "daily" | "compaction" | "deleted" | "unknown";
};
type AgentHarnessSessionForkFailureCode = "steer-message" | "in-progress-turn" | "drift-mismatch" | "upstream-unavailable";
type AgentHarnessSessionForkParams = {
targetKey: string;
/** Creator-owned isolation floor resolved by the trusted Gateway request. */
sandbox?: "required";
source: {
agentId: string;
sessionId: string;
sessionKey: string;
storePath: string;
entryId: string;
};
upstream: {
catalogId: string;
hostId: string;
kind: SessionUpstreamKind;
threadId: string;
ref: SessionUpstreamJsonValue;
};
};
type AgentHarnessSessionForkResult = {
status: "created";
key: string;
editorText?: string;
} | {
status: "failed";
code: AgentHarnessSessionForkFailureCode;
message: string;
};
type AgentHarnessResultClassification = "ok" | NonNullable<AgentHarnessAttemptResult["agentHarnessResultClassification"]>;
type AgentHarnessDeliveryDefaults = {
/** Default visible-reply policy when config does not override the harness. */
visibleReplies?: "automatic" | "message_tool";
/**
* @deprecated Use visibleReplies. Kept for existing harness plugins.
*/
sourceVisibleReplies?: "automatic" | "message_tool";
};
/** Exact node authority and worker capacity required by one paired-device runtime. */
type DevicePlacementRequirement = {
requiredNodeCommands: readonly string[];
consumesWorkerSlot: boolean;
};
type AgentHarnessRunCapability<TAttemptParams extends AgentHarnessAttemptParams = AgentHarnessAttemptParams> = {
id: string;
label: string;
pluginId?: string;
/**
* Exhaustive provider ids eligible for automatic selection. Omitting this hint preserves
* dynamic probing; an empty list marks an explicit-only harness.
*/
autoSelection?: {
providerIds: readonly string[];
};
/** Declares host-owned remote execution and its exact paired-device requirements. */
cloudPlacement?: {
mode: "remote-exec";
devicePlacement?: DevicePlacementRequirement;
};
/**
* Plugin ids this harness owner permits to execute its locked sessions.
* Delegates receive work admission and execution only; session mutation stays owner-only.
*/
delegatedExecutionPluginIds?: readonly string[];
/**
* Context-engine host capabilities provided by this harness during agent
* runs. Harnesses that omit this are unsupported for engines that declare
* host requirements.
*/
contextEngineHostCapabilities?: readonly ContextEngineHostCapability[];
deliveryDefaults?: AgentHarnessDeliveryDefaults;
/** Certifies exact runAttempt enforcement; direct-policy-restricted channel side questions fail in core. */
conversationToolPolicySupport?: "exact";
/**
* Canonical OpenClaw tool names whose exact denies the harness can also enforce
* against native equivalents. Every other deny remains fail-closed.
*/
conversationToolPolicySafeDenyTools?: readonly string[];
supports(ctx: AgentHarnessSupportContext): AgentHarnessSupport;
/** Synchronous private ownership read; no discovery, auth loading, or native connection setup. */
resolveSessionRuntimeOwnership?(params: {
config?: OpenClawConfig;
agentId?: string;
sessionId: string;
sessionKey?: string;
storePath?: string;
assertCurrent: () => void;
}): AgentHarnessSessionRuntimeOwnership | undefined;
/** Lets this harness resolve forwarded profiles or its own native credentials. */
authBootstrap?: "harness";
runAttempt(params: TAttemptParams): Promise<AgentHarnessAttemptResult>;
/**
* Produces one final answer from a settled tool transcript without exposing
* capabilities that can repeat or extend the completed work.
*/
finalizeSettledTurn?(params: AgentHarnessSettledTurnFinalizationParams<TAttemptParams>): Promise<AgentHarnessSettledTurnFinalizationResult>;
/** @deprecated Implement runIsolatedCompletionV2. Remove after 2026-10-12. */
runIsolatedCompletion?(params: AgentHarnessIsolatedCompletionParams): Promise<AgentHarnessIsolatedCompletionResult>;
/**
* Runs one fresh prompt-only completion with a literal zero-tool model surface.
* The harness must fail closed when it cannot enforce that native boundary.
*/
runIsolatedCompletionV2?(params: AgentHarnessIsolatedCompletionParamsV2): Promise<AgentHarnessIsolatedCompletionResult>;
};
type AgentHarnessSideQuestionCapability<TSideQuestionParams extends AgentHarnessSideQuestionParams = AgentHarnessSideQuestionParams> = {
runSideQuestion?(params: TSideQuestionParams): Promise<AgentHarnessSideQuestionResult>;
};
type AgentHarnessClassificationCapability<TAttemptParams extends AgentHarnessAttemptParams = AgentHarnessAttemptParams> = {
classify?(result: AgentHarnessAttemptResult, ctx: TAttemptParams): AgentHarnessResultClassification | undefined;
};
type AgentHarnessCompactionCapability = {
compact?(params: AgentHarnessCompactParams): Promise<AgentHarnessCompactResult | undefined>;
};
type AgentHarnessSessionDeletionParams = {
/** Present only during the exact host initializer's guarded rollback. */
initialization?: SessionInitialization;
agentId: string;
sessionKey: string;
sessionId: string;
lifecycleRevision?: string;
/** Revalidate the captured registry, harness, and operation before each side effect. */
assertCurrent: () => void;
};
type AgentHarnessSessionDeletionMutation = {
/** Synchronously remove only the prepared owner's state at the session commit edge. */
commit: () => void;
/** Restore only that removal when the authoritative session transaction rolls back. */
rollback: () => void;
};
type AgentHarnessSessionLifecycleCapability = {
reset?(params: AgentHarnessResetParams): Promise<void> | void;
/** Prepare outside the session writer; release native resources after its commit completes. */
withSessionDeletion?<T>(this: void, params: AgentHarnessSessionDeletionParams, run: (mutation: AgentHarnessSessionDeletionMutation) => Promise<T>): Promise<T>;
dispose?(): Promise<void> | void;
};
type AgentHarnessSessionForkCapability = {
sessionFork?: {
upstreamKinds: readonly SessionUpstreamKind[];
fork(params: AgentHarnessSessionForkParams): Promise<AgentHarnessSessionForkResult>;
};
};
type AgentHarnessRuntimeArtifactCapability = {
/** Revalidate an artifact only at setup and persistent-operation boundaries. */
runtimeArtifact?: {
validate(binding: AgentHarnessRuntimeArtifactBinding): Promise<boolean>;
};
};
type AgentHarnessAuthBindingCapability = {
/** Recomputes the exact credential fingerprint at persistent trust boundaries. */
authBinding?: {
fingerprint(params: AgentHarnessAuthBindingFingerprintParams): Promise<string | undefined>;
};
};
type AgentHarnessProviderUsageCapability = {
/**
* Contributes runtime-owned quota data without registering a text provider.
* Provider usage hooks remain authoritative when both surfaces exist.
*/
fetchUsageSnapshot?: (ctx: ProviderFetchUsageSnapshotContext) => Promise<ProviderUsageSnapshot | null | undefined> | ProviderUsageSnapshot | null | undefined;
};
type AgentHarnessMcpCatalogParams = {
config: OpenClawConfig;
agentId: string;
sessionId: string;
sessionKey: string;
workspaceDir: string;
/** OpenClaw-configured servers whose session policy this harness can enforce. */
mcpServerNames: readonly string[];
toolOverrides?: Pick<SessionToolOverrides, "mcpServers" | "mcpToolsDeny">;
};
type AgentHarnessMcpCatalogCapability = {
/** Lists the MCP tools owned by this session's native runtime, if it is already bound. */
loadMcpToolCatalog?(params: AgentHarnessMcpCatalogParams): Promise<McpToolCatalog | undefined>;
};
type AgentHarnessModelCatalogParams = {
config: OpenClawConfig;
agentId: string;
agentDir: string;
workspaceDir: string;
configuredModelRefs?: readonly ModelRef[];
};
type AgentHarnessModelCatalogCapability = {
/** Lists account-scoped models owned by this native runtime. */
loadModelCatalog?(params: AgentHarnessModelCatalogParams): Promise<readonly ModelCatalogEntry[]>;
/**
* Reads current, secret-free native account evidence for this exact catalog scope/model.
* No I/O or discovery here. Missing/stale/disposed evidence returns undefined; this is
* picker metadata only, never execution authorization or a host-route credential.
*/
readModelCatalogReadiness?(params: AgentHarnessModelCatalogParams & {
provider: string;
modelId: string;
}): {
accountType: string;
} | undefined;
};
/**
* @deprecated Implement AgentHarnessV2. This registration contract remains
* source-compatible for existing plugins through 2026-10-12.
*/
type AgentHarness = AgentHarnessRunCapability & AgentHarnessSideQuestionCapability & AgentHarnessClassificationCapability & AgentHarnessCompactionCapability & AgentHarnessRuntimeArtifactCapability & AgentHarnessAuthBindingCapability & AgentHarnessProviderUsageCapability & AgentHarnessModelCatalogCapability & AgentHarnessMcpCatalogCapability & AgentHarnessSessionForkCapability & AgentHarnessSessionLifecycleCapability;
//#endregion
//#region packages/gateway-protocol/src/schema/skill-resources.d.ts
/** Portable, bounded skill resources; paths are relative to a worker-owned resource directory. */
declare const SkillResourceDeliverySchema: Type.TObject<{
version: Type.TLiteral<1>;
skills: Type.TArray<Type.TObject<{
sourcePath: Type.TOptional<Type.TString>;
modelVisible: Type.TOptional<Type.TBoolean>;
name: Type.TString;
displayName: Type.TOptional<Type.TString>;
description: Type.TString;
revision: Type.TString;
files: Type.TArray<Type.TObject<{
path: Type.TString;
content: Type.TString;
encoding: Type.TOptional<Type.TUnion<[Type.TLiteral<"utf8">, Type.TLiteral<"base64">]>>;
executable: Type.TOptional<Type.TBoolean>;
}>>;
}>>;
}>;
type SkillResourceDelivery = Static<typeof SkillResourceDeliverySchema>;
//#endregion
//#region packages/gateway-protocol/src/schema/worker-skill-workshop.d.ts
declare const WorkerSkillWorkshopBindingSchema: Type.TObject<{
multipleProfiles: Type.TBoolean;
}>;
type WorkerSkillWorkshopBinding = Static<typeof WorkerSkillWorkshopBindingSchema>;
//#endregion
//#region src/worker/tool-authority.d.ts
declare const WORKER_TOOL_NAMES: readonly ["read", "write", "edit", "apply_patch", "exec", "process", "browser", "computer", "skill_workshop", "sessions_spawn", "sessions_send", "portal"];
type WorkerToolName = (typeof WORKER_TOOL_NAMES)[number];
type WorkerToolAuthority = {
allowedToolNames: WorkerToolName[];
};
//#endregion
//#region src/worker/launch-descriptor.d.ts
type WorkerBrowserLaunchDescriptor = {
cdpUrl: string;
launcherPath: string;
};
type WorkerComputerLaunchDescriptor = {
nodeId: string;
computerUse: ComputerUseCapabilityDescriptor;
};
type WorkerGitHubLaunchBinding = {
token: string;
login: string;
branch: string;
remoteUrl?: string;
gitAuthor?: {
name?: string;
email?: string;
};
};
type WorkerLaunchPermissionContext = {
permissionMode: SessionPermissionMode;
workerContainmentRoot: string;
} | {
permissionMode?: never;
workerContainmentRoot?: never;
};
type WorkerLaunchAssignment = WorkerLaunchPermissionContext & {
skillAuthoring?: WorkerSkillWorkshopBinding;
skillResources?: SkillResourceDelivery;
/** Host placement namespace used for worker-local policy, hooks, and audit attribution. */
agentId: string;
operationalRunInstance: OperationalRunInstanceRef;
/** Opaque host-signed runtime envelope; worker code never parses private identity. */
agentRuntimeIdentityToken: string;
runId: string;
turnId: string;
prompt: string | Extract<WorkerTranscriptMessage, {
role: "user";
}>["content"];
suppressPromptTranscript: boolean;
workspaceDir: string;
modelRef: WorkerInferenceModelRef;
inferenceOptions: WorkerInferenceOptions;
systemPrompt?: string;
initialMessages: WorkerTranscriptMessage[];
transcript: {
baseLeafId: WorkerTranscriptCommitParams["baseLeafId"];
nextSeq: number;
};
liveEvents: {
ackedSeq: number;
nextSeq: number;
};
toolAuthority: WorkerToolAuthority;
browser?: WorkerBrowserLaunchDescriptor;
computer?: WorkerComputerLaunchDescriptor;
github?: WorkerGitHubLaunchBinding;
};
type WorkerLaunchAdmission = Omit<WorkerConnectParams["admission"], "runId"> & {
sessionId: string;
};
type WorkerLaunchPlan = {
version: 4;
admission: WorkerLaunchAdmission;
assignment: WorkerLaunchAssignment;
};
//#endregion
//#region src/worker/node-workspace-transfer-protocol.d.ts
type NodeWorkerWorkspaceTransferInput = {
direction: "download";
token: string;
manifestRef: string;
/** Reuse this prepared project's immutable Git objects before downloading a pack. */
seedKey?: string;
/** Install attachment files only; never replace or delete workspace entries. */
attachments?: true;
} | {
direction: "upload";
token: string;
baseManifestRef: string;
};
//#endregion
//#region src/worker/node-workspace-protocol.d.ts
type NodeWorkerWorkspaceSeedInput = {
action: "apply";
key: string;
} | {
action: "store";
key: string;
maxAgeMs: number;
};
//#endregion
//#region src/gateway/worker-environments/workspace-reconcile-core.d.ts
type WorkerWorkspaceApplyResult = {
manifestRef: string;
manifest: WorkerWorkspaceManifest;
conflictPaths: string[];
verifyLocalStable(): Promise<void>;
};
//#endregion
//#region src/gateway/worker-environments/tunnel-contract.d.ts
type WorkerTunnelRequest = {
environmentId: string;
ownerEpoch: number;
};
type WorkerWorkspaceCommand = {
argv: readonly string[];
transportRetry: "idempotent" | "never";
/** Local owner guard revalidated after transport awaits, immediately before dispatch. */
assertCurrent?: () => void;
onDispatchReady?: () => void;
input?: string;
timeoutMs?: number;
signal?: AbortSignal;
transfer?: NodeWorkerWorkspaceTransferInput;
seed?: NodeWorkerWorkspaceSeedInput;
};
type WorkerWorkspaceSyncRequest = {
localPath: string;
sessionId: string;
generation: number;
gitAuthor?: {
name?: string;
email?: string;
};
/** Immutable project identity from the owning environment's provisioning snapshot. */
projectKey?: string;
};
type WorkerWorkspaceSyncResult = {
mode: "git" | "plain";
remoteWorkspaceDir: string;
manifestRef: string;
};
type WorkerWorkspaceReconcileRequest = {
localPath: string;
remoteWorkspaceDir: string;
baseManifestRef: string;
journal: WorkerWorkspaceReconciliationJournalAdapter;
stagedResult?: {
ref: string;
record(ref: string): void;
};
};
type WorkerWorkspaceReconcileResult = {
manifestRef: string;
changed: boolean;
/** Re-read the remote workspace after local acceptance, immediately before teardown. */
verifyStable(): Promise<void>;
/** Re-read the accepted local result after the remote stability fence. */
verifyLocalStable(): Promise<void>;
/** Apply the prepared candidate locally without making it restart-authoritative. */
applyPreparedStagedResult?(): Promise<void>;
/** Return the accepted local manifest and any keep-local conflicts after apply. */
getAppliedWorkspaceResult?(): WorkerWorkspaceApplyResult | undefined;
/** Publish the verified candidate for restart recovery. */
publishStagedResult?(): Promise<void>;
discardPreparedStagedResult?(): Promise<void>;
};
type WorkerWorkspaceQuiescence = {
/** Prove the watchdog lease still owns stopped processes and extend it through teardown. */
assertActive(): Promise<void>;
/** Resume only the remote processes stopped by this quiescence owner. */
resume(): Promise<void>;
};
type WorkerTurnLaunchRequest = {
plan: WorkerLaunchPlan;
turnClaim: WorkerSessionTurnClaim;
timeoutMs?: number;
credentialExpiresAtMs?: number;
signal?: AbortSignal;
onDispatchReady?: () => void;
};
type WorkerWorkspaceTunnelHandle = {
environmentId: string;
ownerEpoch: number;
launchTurn?: never;
measureLaunchTurn?: never;
runWorkspaceCommand(command: WorkerWorkspaceCommand): Promise<SpawnResult>;
stageAttachments?(request: {
localPath: string;
isAuthorized: () => boolean;
signal: AbortSignal;
}): Promise<void>;
quiesceWorkspace(remoteWorkspaceDir: string): Promise<WorkerWorkspaceQuiescence>;
syncWorkspace(request: WorkerWorkspaceSyncRequest): Promise<WorkerWorkspaceSyncResult>;
reconcileWorkspace(request: WorkerWorkspaceReconcileRequest): Promise<WorkerWorkspaceReconcileResult>;
stop(): Promise<void>;
};
type WorkerTurnTunnelHandle = Omit<WorkerWorkspaceTunnelHandle, "launchTurn" | "measureLaunchTurn"> & {
measureLaunchTurn(plan: WorkerLaunchPlan, claim: WorkerSessionTurnClaim): number;
launchTurn(request: WorkerTurnLaunchRequest): Promise<SpawnResult>;
};
type WorkerTunnelHandle = WorkerWorkspaceTunnelHandle | WorkerTurnTunnelHandle;
//#endregion
//#region src/gateway/worker-environments/service-contract.d.ts
/** Non-secret worker projection available to Gateway request handlers. */
type WorkerEnvironmentServiceRecord = {
environmentId: string;
providerId: string;
profileId: string;
leaseId: string | null;
nodeDeviceId?: string | null;
sharedHost: boolean | null;
state: WorkerEnvironmentState;
ownerEpoch: number;
createdAtMs: number;
idleSinceAtMs: number | null;
attachedSessionIds: readonly string[];
desktopAvailable: boolean;
desktopApps: readonly WorkerDesktopApp["id"][];
tunnelStatus: WorkerTunnelStatus;
error?: string;
};
type WorkerDesktopObserveResult = {
transport: "rfb";
wsPath: string;
expiresAtMs: number;
control: boolean;
vncPassword?: string;
};
type WorkerDesktopLaunchResult = {
app: WorkerDesktopApp["id"];
status: "ready";
};
/** Request-facing lifecycle methods, kept separate from persistence and provider internals. */
type WorkerEnvironmentServiceContract = {
list(): WorkerEnvironmentServiceRecord[];
get(environmentId: string): WorkerEnvironmentServiceRecord | undefined;
inventoryVersion(): number;
supportsExecutionMode(profileId: string, mode: WorkerPlacementExecutionMode): boolean;
listMachineOptions(profileId: string): Promise<readonly WorkerMachineOption[] | undefined>;
create(profileId: string, idempotencyKey: string, machineClass?: string, executionMode?: WorkerPlacementExecutionMode): Promise<WorkerEnvironmentServiceRecord>;
destroy(environmentId: string): Promise<WorkerEnvironmentServiceRecord>;
destroyUnattached(environmentId: string): Promise<WorkerEnvironmentServiceRecord>;
observeDesktop(request: {
environmentId: string;
control: boolean;
}): Promise<WorkerDesktopObserveResult>;
launchDesktopApp(request: {
environmentId: string;
app: WorkerDesktopApp["id"];
}): Promise<WorkerDesktopLaunchResult>;
startTunnel(request: WorkerTunnelRequest): Promise<WorkerTunnelHandle>;
stopTunnel(environmentId: string, ownerEpoch?: number): Promise<void>;
};
type WorkerPlacementDispatchRequest = {
sessionId: string;
sessionKey: string;
agentId: string;
profileId: string;
executionMode: WorkerPlacementExecutionMode;
devicePlacement?: DevicePlacementRequirement;
idempotencyKey?: string;
deviceId?: string;
machineClass?: string;
inheritedProfile?: {
providerId: string;
profileSnapshot: WorkerProfile;
};
};
type WorkerPlacementReclaimRequest = {
sessionId: string;
sessionKey: string;
agentId: string;
};
type WorkerPlacementMoveRequest = WorkerPlacementReclaimRequest & {
source: WorkerPlacementMoveSource;
target: WorkerPlacementMoveTarget;
abandonSource?: true;
};
/** Closure-bound request authority; in-process only and never part of durable placement intent. */
type WorkerPlacementAuthorization = () => void;
type WorkerPlacementDispatchContract = {
dispatch(request: WorkerPlacementDispatchRequest, onTransition?: (placement: WorkerSessionPlacementRecord) => void, authorize?: WorkerPlacementAuthorization): Promise<Extract<WorkerSessionPlacementRecord, {
state: "active";
}>>;
move?(request: WorkerPlacementMoveRequest, onTransition?: (placement: WorkerSessionPlacementRecord) => void, authorize?: WorkerPlacementAuthorization): Promise<Extract<WorkerSessionPlacementRecord, {
state: "local" | "active";
}>>;
reclaim?(request: WorkerPlacementReclaimRequest, authorize?: WorkerPlacementAuthorization, beforeDrain?: WorkerPlacementAuthorization): Promise<Extract<WorkerSessionPlacementRecord, {
state: "local" | "reclaimed";
}>>;
forceDestroyEnvironment?(environmentId: string, onCleanupError?: (error: unknown) => void): Promise<WorkerEnvironmentServiceRecord>;
reconcileActive?(environmentId?: string): Promise<void>;
};
//#endregion
//#region src/gateway/worker-environments/session-placement-lifecycle.d.ts
type SessionWorkerPlacementContext = {
workerEnvironmentService?: Pick<WorkerEnvironmentServiceContract, "get">;
workerPlacementDispatchService?: Pick<WorkerPlacementDispatchContract, "reclaim">;
workerSessionPlacementService?: Pick<WorkerSessionPlacementStore, "getMany"> & Partial<Pick<WorkerSessionPlacementStore, "retireSessionPlacement" | "listForReconcile">>;
};
//#endregion
//#region src/auto-reply/reply/abort.runtime-types.d.ts
/** Result from the fast abort path before normal reply dispatch starts. */
type FastAbortResult = {
handled: boolean;
aborted: boolean;
rejectionReason?: "finalizing";
stoppedSubagents?: number;
failedSubagents?: number;
};
/** Runtime hook that may convert a message into an immediate abort action. */
type TryFastAbortFromMessage = (params: {
ctx: FinalizedRuntimeMsgContext;
cfg: OpenClawConfig;
isCommandTargetCurrent?: () => boolean;
}) => Promise<FastAbortResult>;
/** Formats the user-visible abort acknowledgement text. */
type FormatAbortReplyText = (stoppedSubagents?: number, rejectionReason?: FastAbortResult["rejectionReason"], failedSubagents?: number) => string;
//#endregion
//#region src/config/implicit-mentions.d.ts
type ResolvedChannelImplicitMentions = Required<ChannelImplicitMentionsConfig>;
//#endregion
//#region src/channels/mention-gating.d.ts
type InboundImplicitMentionKind = "reply_to_bot" | "quoted_bot" | "bot_thread_participant" | "native";
type InboundMentionFacts = {
canDetectMention: boolean;
wasMentioned: boolean;
hasAnyMention?: boolean;
implicitMentionKinds?: readonly InboundImplicitMentionKind[];
};
type InboundMentionPolicy = {
isGroup: boolean;
requireMention: boolean;
implicitMentions?: ChannelImplicitMentionsConfig;
allowedImplicitMentionKinds?: readonly InboundImplicitMentionKind[];
allowTextCommands: boolean;
hasControlCommand: boolean;
commandAuthorized: boolean;
};
/** @deprecated Prefer the nested `{ facts, policy }` call shape for new code. */
type ResolveInboundMentionDecisionFlatParams = InboundMentionFacts & InboundMentionPolicy;
type ResolveInboundMentionDecisionNestedParams = {
facts: InboundMentionFacts;
policy: InboundMentionPolicy;
};
type ResolveInboundMentionDecisionParams = ResolveInboundMentionDecisionFlatParams | ResolveInboundMentionDecisionNestedParams;
type InboundMentionDecision = {
effectiveWasMentioned: boolean;
shouldSkip: boolean;
implicitMention: boolean;
matchedImplicitMentionKinds: InboundImplicitMentionKind[];
shouldBypassMention: boolean;
};
declare function implicitMentionKindWhen(kind: InboundImplicitMentionKind, enabled: boolean): InboundImplicitMentionKind[];
declare function resolveInboundMentionDecision(params: ResolveInboundMentionDecisionParams): InboundMentionDecision;
//#endregion
//#region src/channels/message-access/types.d.ts
/** Channel identifier used in ingress diagnostics and config lookups. */
type ChannelIngressChannelId = ChatChannelId;
/** Redacted identifier category used by allowlist normalization and matching. */
type ChannelIngressIdentifierKind = "stable-id" | "username" | "email" | "phone" | "role" | `plugin:${string}`;
/** Public, redacted identifier material that can participate in allowlist matching. */
type MatchableIdentifier = {
opaqueId: string;
kind: ChannelIngressIdentifierKind;
authentication?: IdentifierAuthentication;
/** @deprecated Use `authentication: "mutable"`. Remove in the next Plugin SDK major. */
dangerous?: boolean;
sensitivity?: "normal" | "pii";
};
/** Internal identifier material with the raw comparable value retained. */
type InternalMatchMaterial = MatchableIdentifier & {
value: string;
};
/** Internal subject representation used by the shared ingress kernel. */
type InternalChannelIngressSubject = {
identifiers: InternalMatchMaterial[];
};
/** Public, redacted form of a normalized allowlist entry. */
type ChannelIngressNormalizedEntry = {
opaqueEntryId: string;
kind: ChannelIngressIdentifierKind;
wildcard?: boolean;
authentication?: IdentifierAuthentication;
/** @deprecated Use `authentication: "mutable"`. Remove in the next Plugin SDK major. */
dangerous?: boolean;
sensitivity?: "normal" | "pii";
};
/** Redacted diagnostic for an invalid, disabled, or unsupported allowlist entry. */
type RedactedIngressEntryDiagnostic = {
opaqueEntryId?: string;
reasonCode: IngressReasonCode;
};
/** Redacted allowlist match result exposed to callers and access facts. */
type RedactedIngressMatch = {
matched: boolean;
matchedEntryIds: string[];
/** Exact redacted entry-to-subject edges retained for authentication policy. */
matchedPairs?: RedactedIngressMatchedPair[];
};
type RedactedIngressMatchedPair = {
opaqueEntryId: string;
opaqueSubjectId: string;
subjectAuthentication: IdentifierAuthentication;
};
/** Fully normalized allowlist facts for one ingress gate. */
type ResolvedIngressAllowlist = {
rawEntryCount: number;
normalizedEntries: ChannelIngressNormalizedEntry[];
invalidEntries: RedactedIngressEntryDiagnostic[];
disabledEntries: RedactedIngressEntryDiagnostic[];
matchedEntryIds: string[];
hasConfiguredEntries: boolean;
hasMatchableEntries: boolean;
hasWildcard: boolean;
accessGroups: {
referenced: string[];
matched: string[];
missing: string[];
unsupported: string[];
failed: string[];
};
match: RedactedIngressMatch;
authentication?: RedactedIdentifierAuthenticationResult;
};
type RedactedIdentifierAuthenticationResult = {
evaluated: boolean;
threshold: IdentifierAuthentication;
affectedMatch: boolean;
rejectedEntryIds: string[];
};
type RedactedIdentifierAuthenticationDecision = {
evaluated: boolean;
affectedMatch: boolean;
};
/** Redacted allowlist facts safe to expose in the access graph. */
type RedactedIngressAllowlistFacts = {
configured: boolean;
matched: boolean;
reasonCode: IngressReasonCode;
matchedEntryIds: string[];
invalidEntryCount: number;
disabledEntryCount: number;
accessGroups: ResolvedIngressAllowlist["accessGroups"];
};
/** Route lookup state projected into the ingress access graph. */
type RouteGateState = "not-configured" | "matched" | "not-matched" | "disabled" | "lookup-failed";
/** How a matched route affects sender allowlist evaluation. */
type RouteSenderPolicy = "inherit" | "replace" | "deny-when-empty";
/** Source list used when a route sender policy contributes sender entries. */
type RouteSenderAllowlistSource = "effective-dm" | "effective-group";
/** Raw route gate facts supplied by a channel-specific router. */
type RouteGateFacts = {
id: string;
kind: "route" | "routeSender" | "membership" | "ownerAllowlist" | "nestedAllowlist";
gate: RouteGateState;
effect: "allow" | "block-dispatch" | "ignore";
precedence: number;
senderPolicy: RouteSenderPolicy;
senderAllowFrom?: Array<string | number>;
senderAllowFromSource?: RouteSenderAllowlistSource;
match?: RedactedIngressMatch;
};
/** Route gate facts after any route-specific sender allowlist is normalized. */
type ResolvedRouteGateFacts = Omit<RouteGateFacts, "senderAllowFrom" | "senderAllowFromSource"> & {
senderAllowlist?: ResolvedIngressAllowlist;
};
/** Inbound event facts used to choose command, pairing, and origin-subject rules. */
type ChannelIngressEventInput = {
kind: "message" | "reaction" | "button" | "postback" | "native-command" | "slash-command" | "system";
authMode: "inbound" | "command" | "origin-subject" | "route-only" | "none";
mayPair: boolean;
originSubject?: InternalChannelIngressSubject;
};
/** Redacted event facts exposed in decisions and access facts. */
type RedactedChannelIngressEvent = Omit<ChannelIngressEventInput, "originSubject"> & {
hasOriginSubject: boolean;
originSubjectMatched: boolean;
originSubjectAuthentication?: IdentifierAuthentication;
};
/** Policy knobs that decide how the ingress graph is evaluated. */
type ChannelIngressPolicyInput = {
dmPolicy: "pairing" | "allowlist" | "open" | "disabled";
groupPolicy: "allowlist" | "open" | "disabled";
groupAllowFromFallbackToAllowFrom?: boolean;
minIdentifierAuthentication?: IdentifierAuthentication;
/** @deprecated `enabled` maps to minimum `mutable`; otherwise minimum `asserted`. Remove in the next Plugin SDK major. */
mutableIdentifierMatching?: "disabled" | "enabled";
activation?: {
requireMention: boolean;
allowTextCommands: boolean;
implicitMentions?: ResolvedChannelImplicitMentions;
allowedImplicitMentionKinds?: readonly InboundImplicitMentionKind[];
order?: "before-sender" | "after-command";
};
command?: {
useAccessGroups?: boolean;
allowTextCommands: boolean;
hasControlCommand: boolean;
modeWhenAccessGroupsOff?: "allow" | "deny" | "configured";
};
};
/** Ordered phase for a gate in the ingress graph. */
type IngressGatePhase = "route" | "sender" | "command" | "event" | "activation";
/** Gate kind used in the ingress graph and projected access facts. */
type IngressGateKind = "route" | "routeSender" | "dmSender" | "groupSender" | "membership" | "ownerAllowlist" | "nestedAllowlist" | "command" | "event" | "mention";
/** Effect produced by a gate when computing final ingress admission. */
type IngressGateEffect = "allow" | "block-dispatch" | "block-command" | "skip" | "observe" | "ignore";
/** Stable machine-readable reason code for ingress diagnostics. */
type IngressReasonCode = "allowed" | "route_blocked" | "route_sender_empty" | "dm_policy_disabled" | "dm_policy_open" | "dm_policy_allowlisted" | "dm_policy_pairing_required" | "dm_policy_not_allowlisted" | "group_policy_disabled" | "group_policy_open" | "group_policy_allowed" | "group_policy_empty_allowlist" | "group_policy_not_allowlisted" | "command_authorized" | "control_command_unauthorized" | "event_authorized" | "event_unauthorized" | "event_pairing_not_allowed" | "sender_not_required" | "origin_subject_missing" | "origin_subject_not_matched" | "activation_allowed" | "activation_skipped" | "access_group_missing" | "access_group_unsupported" | "access_group_failed" | "mutable_identifier_disabled" | "identifier_authentication_too_weak" | "no_policy_match";
/** One evaluated gate in the ordered ingress access graph. */
type AccessGraphGate = {
id: string;
phase: IngressGatePhase;
kind: IngressGateKind;
effect: IngressGateEffect;
allowed: boolean;
reasonCode: IngressReasonCode;
match?: RedactedIngressMatch;
allowlist?: RedactedIngressAllowlistFacts;
identifierAuthentication?: RedactedIdentifierAuthenticationDecision;
sender?: {
policy: ChannelIngressPolicyInput["dmPolicy"] | ChannelIngressPolicyInput["groupPolicy"];
};
command?: {
useAccessGroups: boolean;
allowTextCommands: boolean;
modeWhenAccessGroupsOff?: "allow" | "deny" | "configured";
shouldBlockControlCommand: boolean;
};
event?: RedactedChannelIngressEvent;
activation?: {
hasMentionFacts: boolean;
requireMention: boolean;
allowTextCommands: boolean;
allowedImplicitMentionKinds?: readonly InboundImplicitMentionKind[];
order?: "before-sender" | "after-command";
shouldSkip: boolean;
canDetectMention?: boolean;
wasMentioned?: boolean;
hasAnyMention?: boolean;
implicitMentionKinds?: readonly InboundImplicitMentionKind[];
effectiveWasMentioned?: boolean;
shouldBypassMention?: boolean;
};
};
/** Ordered graph of all evaluated ingress gates. */
type AccessGraph = {
gates: AccessGraphGate[];
};
/** Normalized ingress state before policy gates are reduced into a decision. */
type ChannelIngressState = {
channelId: ChannelIngressChannelId;
accountId: string;
conversationKind: "direct" | "group" | "channel";
event: RedactedChannelIngressEvent;
mentionFacts?: InboundMentionFacts;
routeFacts: ResolvedRouteGateFacts[];
allowlists: {
dm: ResolvedIngressAllowlist;
pairingStore: ResolvedIngressAllowlist;
group: ResolvedIngressAllowlist;
commandOwner: ResolvedIngressAllowlist;
commandGroup: ResolvedIngressAllowlist;
};
};
/** Final runtime admission action for the inbound event. */
type ChannelIngressAdmission = "dispatch" | "observe" | "skip" | "drop" | "pairing-required";
/** Final decision and graph for a resolved channel ingress event. */
type ChannelIngressDecision = {
admission: ChannelIngressAdmission;
decision: "allow" | "block" | "pairing";
decisiveGateId: string;
reasonCode: IngressReasonCode;
graph: AccessGraph;
};
//#endregion
//#region src/channels/message-access/runtime-types.d.ts
/** Sender/conversation projection consumed by channel handlers. */
type ChannelIngressSenderAccess = {
/** True when the sender gate admits the event. */
allowed: boolean;
/** Final ingress decision after all gates, not just the sender gate. */
decision: ChannelIngressDecision["decision"];
/** Sender gate reason when present, otherwise decisive ingress reason. */
reasonCode: IngressReasonCode;
/** Sender gate from the access graph, when one ran. */
gate?: AccessGraphGate;
/** Effective DM allowlist entries after store and access-group processing. */
effectiveAllowFrom: string[];
/** Effective group allowlist entries after fallback and access-group processing. */
effectiveGroupAllowFrom: string[];
/** Whether provider-specific fallback behavior was applied. */
providerMissingFallbackApplied: boolean;
};
/** Command projection consumed by channel command/control handlers. */
type ChannelIngressCommandAccess = {
/** True when a command gate was requested for this event. */
requested: boolean;
/** True when the command gate authorizes this sender. */
authorized: boolean;
/** True when an unauthorized control command should be blocked. */
shouldBlockControlCommand: boolean;
/** Command gate reason when present, otherwise decisive ingress reason. */
reasonCode: IngressReasonCode;
/** Command gate from the access graph, when one ran. */
gate?: AccessGraphGate;
};
/** Route projection consumed by room/thread/topic handlers. */
type ChannelIngressRouteAccess = {
/** True when all configured route gates admit the event. */
allowed: boolean;
/** Route gate reason when a route gate decided. */
reasonCode?: IngressReasonCode;
/** Optional route-specific reason text. */
reason?: string;
/** Route gate from the access graph, when one ran. */
gate?: AccessGraphGate;
};
/** Activation/mention projection consumed by group handlers. */
type ChannelIngressActivationAccess = {
/** True when an activation gate ran. */
ran: boolean;
/** True when activation admits the event. */
allowed: boolean;
/** True when the event should be skipped instead of dispatched. */
shouldSkip: boolean;
/** Activation gate reason when present, otherwise decisive ingress reason. */
reasonCode: IngressReasonCode;
/** Effective mention match after command bypass and activation policy. */
effectiveWasMentioned?: boolean;
/** True when mention gating was bypassed by policy or command facts. */
shouldBypassMention?: boolean;
/** Activation gate from the access graph, when one ran. */
gate?: AccessGraphGate;
};
/** Full ingress result returned by runtime resolvers. */
type ResolvedChannelMessageIngress = {
/** Redacted normalized state used as input to the decision engine. */
state: ChannelIngressState;
/** Ordered access graph plus final admission decision. */
ingress: ChannelIngressDecision;
/** Sender/conversation projection. */
senderAccess: ChannelIngressSenderAccess;
/** Route projection. */
routeAccess: ChannelIngressRouteAccess;
/** Command projection. */
commandAccess: ChannelIngressCommandAccess;
/** Activation/mention projection. */
activationAccess: ChannelIngressActivationAccess;
};
//#endregion
//#region src/auto-reply/reply/agent-runner-execution-status.d.ts
/** Projects closed execution independently of later reply delivery. */
declare function resolveAgentTurnExecutionStatus(outcome?: {
kind: "aborted" | "rejected";
} | {
kind: "settled";
status: "ok" | "failed";
}): "cancelled" | "failed" | "ok";
//#endregion
//#region src/auto-reply/reply/reply-operation-run-state.d.ts
type ReplyOperationAdmissionSnapshot = {
status: "owned";
} | {
status: "accepted";
mode: "steer" | "followup";
} | {
status: "skipped";
reason: "active-run" | "aborted" | "lifecycle-invalidated" | "queue-cap" | "question-response-indeterminate" | "question-response-refused";
};
type ReplyOperationRunState = {
admission?: ReplyOperationAdmissionSnapshot;
messageInjectionAborted?: true;
agentTurn?: ReturnType<typeof resolveAgentTurnExecutionStatus>;
agentTurnOwner?: ReplyOperation;
};
declare const REPLY_OPERATION_RUN_STATE: unique symbol;
type ReplyOptionsWithOperationRunState = {
[REPLY_OPERATION_RUN_STATE]?: ReplyOperationRunState;
};
//#endregion
//#region src/auto-reply/reply/queue/types.d.ts
type FollowupQueueDisposition = "queue-cap" | "queue-cap-old" | "queue-cap-new";
type QueuedFollowupReplyBatch = {
kind: "queued-followup";
runId: string;
originatingChannel: string | undefined;
payloads: ReplyPayload[];
};
//#endregion
//#region src/auto-reply/reply/prompt-session-context.d.ts
type ReplyConversationFields = Pick<TemplateContext, "Provider" | "Surface" | "ChatType" | "OriginatingChannel" | "OriginatingTo" | "AccountId" | "MessageThreadId" | "GroupSubject" | "GroupChannel" | "GroupSpace">;
type PreparedReplyConversation = {
fields: ReplyConversationFields;
group: {
channel?: string;
groupId?: string;
groupChannel?: string;
groupSpace?: string;
accountId?: string;
};
activation?: SessionEntry$1["groupActivation"];
};
//#endregion
//#region src/shared/keyed-fifo-lease.d.ts
type KeyedFifoLease = {
wait(signal?: AbortSignal): Promise<boolean>;
release(): void;
};
//#endregion
//#region src/auto-reply/reply/reply-admission-ticket.d.ts
declare const REPLY_ADMISSION_TICKET: unique symbol;
type ReplyAdmissionTicket = KeyedFifoLease;
type ReplyOptionsWithAdmissionTicket = {
[REPLY_ADMISSION_TICKET]?: ReplyAdmissionTicket;
};
//#endregion
//#region src/auto-reply/reply/get-reply.types.d.ts
type ReplySessionBinding = {
sessionKey?: string;
sessionId: string;
storePath?: string;
};
type PendingContinuationSettlement = {
settle: (statusDelivered: boolean) => Promise<void>;
};
type ReplyRunVerbosity = {
verboseLevelOverride?: VerboseLevel;
resolvedVerboseLevel: VerboseLevel;
};
type InternalReplySessionOptions = {
/** Invocation-owned conversation facts; never execution or sender authority. */
replyConversation?: PreparedReplyConversation;
prepareAssistantTranscriptMessage?: PrepareAssistantTranscriptMessage;
/** Exact authority-bearing settings captured by Gateway chat admission. */
admittedSessionSettings?: Readonly<Pick<SessionEntry$1, "permissionMode" | "toolOverrides">>;
/** Host-stamped exact-run capability for late Codex creator-authority capture. */
cronCreatorAuthorityCapability?: CronCreatorAuthorityCapability;
expectedExistingSessionId?: string;
/** First dispatch only: admission created this exact pinned session before reply initialization. */
newlyCreatedSessionId?: string;
onDeliberateSilentTerminalReply?: () => void;
/** Defers the child-completion wake until the visible waiting status is delivered. */
onPendingContinuation?: (settlement?: PendingContinuationSettlement) => void;
onSessionPrepared?: (binding: ReplySessionBinding) => void;
/** Publishes each executing turn's preferences without persisting them to its session. */
onRunVerbosityResolved?: (settings: ReplyRunVerbosity) => void;
/** Prevent implicit rollover after a caller has durably admitted this exact session. */
pinExpectedExistingSession?: boolean;
requestedSessionId?: string;
resumeRequestedSession?: boolean;
sessionPromptSourceReplyDeliveryMode?: GetReplyOptions["sourceReplyDeliveryMode"];
/** Receives terminal queue-cap outcomes without widening the public reply API. */
onFollowupQueueDisposition?: (disposition: FollowupQueueDisposition) => void;
/** Delivers queued replies only through their originating Gateway admission. */
onQueuedFollowupReplyBatch?: (batch: QueuedFollowupReplyBatch) => Promise<void> | void;
/** Overrides persisted queue mode for this reply only. */
queueModeOverride?: QueueMode;
/** Dispatch-owned operation used to defer hooks until durable run admission. */
replyOperation?: ReplyOperation;
skillOverrides?: SessionToolOverrides["skills"];
/** Gateway-private optimistic-concurrency constraint for an operator-requested proposal revision. */
skillWorkshopProposalRevision?: SkillWorkshopProposalRevisionConstraint;
skillLibraryAuthoring?: SkillLibraryAuthoringCapability;
};
type InternalGetReplyOptions = GetReplyOptions & PluginCommandReplyOptions & InternalReplySessionOptions & ReplyOptionsWithOperationRunState & ReplyOptionsWithAdmissionTicket;
/** Reply resolver signature used by dispatchers and tests for dependency injection. */
type GetReplyFromConfig = (ctx: MsgContext, opts?: GetReplyOptions, configOverride?: OpenClawConfig) => Promise<ReplyPayload | ReplyPayload[] | undefined>;
type InternalGetReplyFromConfig = (ctx: MsgContext, opts?: InternalGetReplyOptions, configOverride?: OpenClawConfig) => Promise<ReplyPayload | ReplyPayload[] | undefined>;
//#endregion
//#region src/auto-reply/reply/command-session-metadata.d.ts
type CommandSessionMetadataChange = {
sessionKey: string;
agentId?: string;
reason: "command-metadata";
};
//#endregion
//#region src/auto-reply/reply/dispatch-from-config.types.d.ts
type DispatchFromConfigResult = {
queuedFinal: boolean;
counts: Record<ReplyDispatchKind, number>;
failedCounts?: Partial<Record<ReplyDispatchKind, number>>;
settledReceipt?: ReplyDispatchReceipt;
sourceReplyDeliveryMode?: SourceReplyDeliveryMode;
sendPolicyDenied?: boolean;
observedReplyDelivery?: boolean;
deferredToActiveRun?: "steer" | "followup";
noVisibleReplyFallbackEligible?: boolean;
noVisibleReplyFallbackDelivered?: boolean;
deliberateSilentTerminalReply?: true;
beforeAgentRunBlocked?: boolean;
sessionMetadataChanges?: CommandSessionMetadataChange[];
};
type DispatchFromConfigParams = {
ctx: FinalizedMsgContext;
/** Full runtime config captured by the channel; reply resolution refreshes it per turn. */
cfg: OpenClawConfig;
dispatcher: ReplyDispatcher;
replyOptions?: Omit<InternalGetReplyOptions, "onBlockReply">;
replyResolver?: InternalGetReplyFromConfig;
onSessionMetadataChanges?: (changes: CommandSessionMetadataChange[]) => void;
fastAbortResolver?: TryFastAbortFromMessage;
formatAbortReplyTextResolver?: FormatAbortReplyText;
/** Optional patch applied to the current runtime config before reply resolution. */
configOverride?: OpenClawConfig;
/** Gateway-owned worker services for archive recovery outside a request scope. */
sessionWorkerPlacementContext?: SessionWorkerPlacementContext;
/**
* Channel turns consume the Gateway's committed model-runtime owner even when the global
* config snapshot is unavailable during startup or durable ingress replay.
*/
usePublishedModelRuntime?: boolean;
};
type DispatchReplyFromConfig = (params: DispatchFromConfigParams) => Promise<DispatchFromConfigResult>;
//#endregion
//#region src/channels/typing.d.ts
type TypingCallbacks = {
onReplyStart: () => Promise<void>;
onIdle?: () => void;
/** Called when the typing controller is cleaned up (e.g. on NO_REPLY). */
onCleanup?: () => void;
};
type CreateTypingCallbacksParams = {
start: () => Promise<void>;
stop?: () => Promise<void>;
onStartError: (err: unknown) => void;
onStopError?: (err: unknown) => void;
keepaliveIntervalMs?: number;
/** Stop keepalive after this many consecutive start() failures. Default: 2 */
maxConsecutiveFailures?: number;
/** Maximum duration for typing indicator before auto-cleanup (safety TTL). Default: 60s */
maxDurationMs?: number;
};
//#endregion
//#region src/auto-reply/reply/response-prefix-template.d.ts
/**
* Template interpolation for response prefix.
*
* Supports variables like `{model}`, `{provider}`, `{thinkingLevel}`, etc.
* Variables are case-insensitive and unresolved ones remain as literal text.
*/
type ResponsePrefixContext = {
/** Short model name (e.g., "gpt-5.4", "claude-opus-4-6") */
model?: string;
/** Full model ID including provider (e.g., "openai/gpt-5.6-sol") */
modelFull?: string;
/** Provider name (e.g., "openai", "anthropic") */
provider?: string;
/** Current thinking level (e.g., "high", "low", "off") */
thinkingLevel?: string;
/** Agent identity name */
identityName?: string;
};
//#endregion
//#region src/auto-reply/reply/reply-dispatcher.d.ts
type ReplyDispatchErrorHandler = (err: unknown, info: ReplyDispatchRuntimeInfo) => Promise<void> | void;
type ReplyDispatchSkipHandler = (payload: ReplyPayload, info: ReplyDispatchRuntimeInfo & {
reason: NormalizeReplySkipReason;
}) => void;
type ReplyDispatchCancelHandler = (payload: ReplyPayload, info: ReplyDispatchRuntimeInfo) => Promise<void> | void;
type ReplyDispatchDeliverer = (payload: ReplyPayload, info: ReplyDispatchRuntimeInfo) => Promise<unknown>;
type ReplyDispatcherOptions = {
deliver: ReplyDispatchDeliverer;
silentReplyContext?: {
cfg?: OpenClawConfig;
sessionKey?: string;
surface?: string;
conversationType?: SilentReplyConversationType;
};
responsePrefix?: string;
transformReplyPayload?: (payload: ReplyPayload) => ReplyPayload | null;
/** Static context for response prefix template interpolation. */
responsePrefixContext?: ResponsePrefixContext;
/** Dynamic context provider for response prefix template interpolation.
* Called at normalization time, after model selection is complete. */
responsePrefixContextProvider?: () => ResponsePrefixContext;
onHeartbeatStrip?: () => void;
onIdle?: () => Promise<void> | void;
onError?: ReplyDispatchErrorHandler;
/** Let a durable ingress owner retry when every attempted send proves no recipient visibility. */
propagateRetryableNoSendFailure?: boolean;
onSkip?: ReplyDispatchSkipHandler;
/** Human-like delay between block replies for natural rhythm. */
humanDelay?: HumanDelayConfig;
beforeDeliver?: ReplyDispatchBeforeDeliver;
/** Owner-declared deadline for the constructor before-delivery callback. */
beforeDeliverOptions?: ReplyDispatchBeforeDeliverOptions;
onBeforeDeliverCancelled?: ReplyDispatchCancelHandler;
/** Observe each queued payload settling, including cancellation and delivery failure. */
onDeliverySettled?: (info: ReplyDispatchRuntimeInfo) => void;
/** Resolve an owner activity policy for holding queued follow-ups behind delivery. */
resolveFollowupAdmissionBarrierTimeoutPolicy?: (context: {
queuedCounts: Readonly<Record<ReplyDispatchKind, number>>;
humanDelayBudgetMs: number;
}) => ReplyFollowupAdmissionBarrierTimeoutPolicy | undefined;
};
type ReplyDispatcherWithTypingOptions = Omit<ReplyDispatcherOptions, "onIdle"> & {
typingCallbacks?: TypingCallbacks;
onReplyStart?: () => Promise<void> | void;
onIdle?: () => Promise<void> | void;
onSettled?: () => unknown;
onFreshSettledDelivery?: () => unknown;
/** Called when the typing controller is cleaned up (e.g., on NO_REPLY). */
onCleanup?: () => void;
};
type ReplyDispatcherWithTypingResult = {
dispatcher: ReplyDispatcher;
replyOptions: Pick<GetReplyOptions, "onReplyStart" | "onTypingController" | "onTypingCleanup">;
markDispatchIdle: () => void;
/** Signal that the model run is complete so the typing controller can stop. */
markRunComplete: () => void;
};
declare function createReplyDispatcherWithTyping(options: ReplyDispatcherWithTypingOptions): ReplyDispatcherWithTypingResult;
//#endregion
//#region src/auto-reply/reply/provider-dispatcher.types.d.ts
type DispatchReplyContext = MsgContext | FinalizedMsgContext;
type DispatchReplyOptions = Omit<GetReplyOptions, "onBlockReply"> & PluginCommandReplyOptions;
/** Buffered block dispatcher entry point used by provider reply flows. */
type DispatchReplyWithBufferedBlockDispatcher$1 = (params: {
ctx: DispatchReplyContext;
cfg: OpenClawConfig;
dispatcherOptions: ReplyDispatcherWithTypingOptions;
toolsAllow?: string[];
replyOptions?: DispatchReplyOptions;
replyResolver?: GetReplyFromConfig;
dispatchReplyFromConfig?: DispatchReplyFromConfig;
}) => Promise<DispatchFromConfigResult>;
//#endregion
//#region src/channels/session.types.d.ts
type InboundLastRouteUpdate = {
sessionKey: string;
channel: string;
to: string;
accountId?: string;
threadId?: string | number;
route?: ChannelRouteRef;
mainDmOwnerPin?: {
ownerRecipient: string;
senderRecipient: string;
onSkip?: (params: {
ownerRecipient: string;
senderRecipient: string;
}) => void;
};
};
/** Function contract for recording inbound channel session state. */
type RecordInboundSession$1 = (params: {
storePath: string;
sessionKey: string;
ctx: MsgContext;
groupResolution?: GroupKeyResolution | null;
createIfMissing?: boolean;
updateLastRoute?: InboundLastRouteUpdate;
onRecordError: (err: unknown) => void;
trackSessionMetaTask?: (task: Promise<unknown>) => void;
}) => Promise<void>;
//#endregion
//#region src/auto-reply/commands-registry.types.d.ts
/** Extra context used when normalizing slash command text. */
type CommandNormalizeOptions = {
botUsername?: string;
/** Keeps complete directive/task arguments, including whitespace and later lines. */
preserveArguments?: boolean;
/** Strip an explicit command target only while channel bot identity is unavailable. */
targetedCommandMode?: "pre-identity";
};
/** Inputs for deciding whether text slash commands should run on a surface. */
type ShouldHandleTextCommandsParams = {
cfg: OpenClawConfig;
surface: string;
commandSource?: "text" | "native";
};
//#endregion
//#region src/auto-reply/command-detection.d.ts
/** Returns true when text starts with a configured control command alias. */
declare function hasControlCommand(text?: string, cfg?: OpenClawConfig, options?: CommandNormalizeOptions): boolean;
//#endregion
//#region packages/markdown-core/src/types.d.ts
/** Table rendering modes used when markdown tables need plaintext-safe output. */
type MarkdownTableMode = "off" | "bullets" | "code" | "block";
//#endregion
//#region packages/markdown-core/src/tables.d.ts
/** Converts markdown tables into the configured plaintext/code rendering mode. */
declare function convertMarkdownTables(markdown: string, mode: MarkdownTableMode): string;
//#endregion
//#region src/auto-reply/dispatch-dispatcher.d.ts
/** Mark a dispatcher complete, wait for pending work, then run optional cleanup. */
declare function settleReplyDispatcher(params: {
dispatcher: ReplyDispatcher;
onSettled?: () => void | Promise<void>;
}): Promise<ReplyDispatchReceipt | undefined>;
/** Run work with a dispatcher and always drain it before returning or throwing. */
declare function withReplyDispatcher<T>(params: {
dispatcher: ReplyDispatcher;
run: () => Promise<T>;
onSettled?: () => void | Promise<void>;
onSettledReceipt?: (receipt: ReplyDispatchReceipt | undefined) => void;
}): Promise<T>;
//#endregion
//#region src/auto-reply/reply/inbound-context.d.ts
type FinalizeInboundContextOptions = {
forceBodyForAgent?: boolean;
forceBodyForCommands?: boolean;
forceChatType?: boolean;
};
declare function finalizeInboundContext<T extends Record<string, unknown>>(ctx: T, opts?: FinalizeInboundContextOptions): Omit<T, LegacyMediaContextKey> & FinalizedRuntimeMsgContext;
//#endregion
//#region src/auto-reply/envelope.d.ts
type AgentEnvelopeParams = {
channel: string;
from?: string;
timestamp?: number | Date;
host?: string;
ip?: string;
body: string;
previousTimestamp?: number | Date;
envelope?: EnvelopeFormatOptions;
};
/** User/config-facing controls for timestamp rendering in prompt envelopes. */
type EnvelopeFormatOptions = {
/**
* "local" (default), "utc", "user", or an explicit IANA timezone string.
*/
timezone?: string;
/**
* Include absolute timestamps in the envelope (default: true).
*/
includeTimestamp?: boolean;
/**
* Include elapsed time suffix when previousTimestamp is provided (default: true).
*/
includeElapsed?: boolean;
/**
* Optional user timezone used when timezone="user".
*/
userTimezone?: string;
};
/** Resolves envelope formatting defaults from agent config. */
declare function resolveEnvelopeFormatOptions(cfg?: OpenClawConfig): EnvelopeFormatOptions;
/** Formats the generic bracketed envelope prepended to agent-visible messages. */
declare function formatAgentEnvelope(params: AgentEnvelopeParams): string;
//#endregion
//#region src/pairing/pairing-store.types.d.ts
type PairingChannel = ChannelId$1;
/** Reads approved ids from a channel/account allowFrom store. */
type ReadChannelAllowFromStoreForAccount = (params: {
channel: PairingChannel;
accountId: string;
env?: NodeJS.ProcessEnv;
}) => Promise<string[]>;
/** Deletes one approved id from a channel/account allowFrom store. */
type RemoveChannelAllowFromStoreEntryForAccount = (params: {
channel: PairingChannel;
entry: string | number;
accountId: string;
env?: NodeJS.ProcessEnv;
pairingAdapter?: ChannelPairingAdapter;
}) => Promise<{
changed: boolean;
allowFrom: string[];
}>;
/** Creates or reuses a pending pairing request for one channel account. */
type UpsertChannelPairingRequestForAccount = (params: {
channel: PairingChannel;
id: string | number;
accountId: string;
meta?: Record<string, string | undefined | null>;
env?: NodeJS.ProcessEnv;
pairingAdapter?: ChannelPairingAdapter;
}) => Promise<{
code: string;
created: boolean;
}>;
//#endregion
//#region src/pairing/pairing-messages.d.ts
declare function buildPairingReply(params: {
channel: PairingChannel;
idLine: string;
code: string;
}): string;
//#endregion
//#region src/media/store.d.ts
/** Media-store file metadata returned after bytes are persisted under a safe media ID. */
type SavedMedia = {
id: string;
path: string;
size: number;
contentType?: string;
};
/** Saves an in-memory media buffer under a UUID-backed media ID. */
declare function saveMediaBuffer(buffer: Buffer, contentType?: string, subdir?: string, maxBytes?: number, originalFilename?: string, detectionFilePathHint?: string): Promise<SavedMedia>;
//#endregion
//#region src/media/fetch.d.ts
/** Remote media bytes plus metadata before they are persisted to the media store. */
type FetchMediaResult = {
buffer: Buffer;
contentType?: string;
fileName?: string;
};
/** Saved media record enriched with the best remote filename candidate. */
type SavedRemoteMedia = SavedMedia & {
fileName?: string;
};
/** Retry policy applied around the complete guarded fetch and body read/save operation. */
type MediaFetchRetryOptions = RetryOptions;
/** Fetch-compatible injection point used by tests and guarded network callers. */
type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
/** Alternate dispatcher/lookup pair tried inside a single guarded fetch attempt. */
type FetchDispatcherAttempt = {
dispatcherPolicy?: PinnedDispatcherPolicy;
lookupFn?: LookupFn;
};
type FetchMediaOptions = {
url: string;
fetchImpl?: FetchLike;
/** Final synchronous check repeated for every media attempt and redirect. */
beforeRequest?: GuardedFetchOptions["beforeRequest"];
requestInit?: RequestInit;
filePathHint?: string;
maxBytes?: number;
maxRedirects?: number;
/** Require HTTPS for the initial URL and every redirect target. */
requireHttps?: boolean;
/** Abort the complete guarded fetch and body operation after this deadline (ms). */
timeoutMs?: number;
/** Abort if final response headers have not arrived by this deadline (ms). */
responseHeaderTimeoutMs?: number;
/** Abort if the response body stops yielding data for this long (ms). */
readIdleTimeoutMs?: number;
ssrfPolicy?: SsrFPolicy;
lookupFn?: LookupFn;
dispatcherPolicy?: PinnedDispatcherPolicy;
dispatcherAttempts?: FetchDispatcherAttempt[];
shouldRetryFetchError?: (error: unknown) => boolean;
/**
* Retries the complete guarded fetch/read-or-save operation. Dispatcher
* attempts still run inside each retry attempt.
*/
retry?: MediaFetchRetryOptions;
/**
* Allow an operator-configured explicit proxy to resolve target DNS after
* hostname-policy checks instead of forcing local pinned-DNS first.
*/
trustExplicitProxyDns?: boolean;
};
/** Options for validating and saving an existing Response body into the media store. */
type SaveResponseMediaOptions = {
sourceUrl?: string;
filePathHint?: string;
maxBytes?: number;
readIdleTimeoutMs?: number;
fallbackContentType?: string;
subdir?: string;
originalFilename?: string;
};
/** Options for guarded URL fetches that are saved directly into the media store. */
type SaveRemoteMediaOptions = FetchMediaOptions & {
fallbackContentType?: string;
subdir?: string;
originalFilename?: string;
};
/** Validates and saves a caller-provided response without performing a new fetch. */
declare function saveResponseMedia(res: Response, options?: SaveResponseMediaOptions): Promise<SavedRemoteMedia>;
/** Fetches media through SSRF guards and saves the body into the media store. */
declare function saveRemoteMedia(options: SaveRemoteMediaOptions): Promise<SavedRemoteMedia>;
/** Fetches media through SSRF guards and returns the bounded response body as a buffer. */
declare function readRemoteMediaBuffer(options: FetchMediaOptions): Promise<FetchMediaResult>;
/** @deprecated Use `readRemoteMediaBuffer` for buffer reads or `saveRemoteMedia` for URL-to-store. */
declare const fetchRemoteMedia: typeof readRemoteMediaBuffer;
//#endregion
//#region src/infra/channel-activity.d.ts
/** Direction of the last observed activity for a channel/account pair. */
type ChannelDirection = "inbound" | "outbound";
type ActivityEntry = {
inboundAt: number | null;
outboundAt: number | null;
};
/** Records the latest inbound or outbound activity timestamp for a channel/account. */
declare function recordChannelActivity(params: {
channel: ChannelId$1;
accountId?: string | null;
direction: ChannelDirection;
at?: number;
}): void;
/** Returns the latest known inbound/outbound activity timestamps for a channel/account. */
declare function getChannelActivity(params: {
channel: ChannelId$1;
accountId?: string | null;
}): ActivityEntry;
//#endregion
//#region src/channels/ack-reactions.d.ts
type AckReactionScope = "all" | "direct" | "group-all" | "group-mentions" | "off" | "none";
/** Sent ack reaction state plus the cleanup hook callers can run after reply delivery. */
type AckReactionHandle = {
ackReactionPromise: Promise<boolean>;
ackReactionValue: string;
remove: () => Promise<void>;
};
/**
* Inputs for the reusable direct/group/mention gate shared by channel plugins.
*
* `effectiveWasMentioned` should already include any channel-specific mention
* normalization. `shouldBypassMention` is only for an earlier channel gate that
* proved the active conversation, such as a group activation state.
*/
type AckReactionGateParams = {
scope: AckReactionScope | undefined;
inboundEventKind?: "user_request" | "room_event";
isDirect: boolean;
isGroup: boolean;
isMentionableGroup: boolean;
canDetectMention: boolean;
effectiveWasMentioned: boolean;
shouldBypassMention?: boolean;
};
/** Resolves the generic ack reaction gate without sending or removing reactions. */
declare function shouldAckReaction(params: AckReactionGateParams): boolean;
/** Starts sending an ack reaction and returns the success-tracking cleanup handle. */
declare function createAckReactionHandle(params: {
ackReactionValue: string;
send: () => Promise<void>;
remove: () => Promise<void>;
onSendError?: (err: unknown) => void;
}): AckReactionHandle | null;
/** Schedules removal of a previously sent ack reaction after reply delivery. */
declare function removeAckReactionAfterReply(params: {
removeAfterReply: boolean;
ackReactionPromise: Promise<boolean> | null;
ackReactionValue: string | null;
remove: () => Promise<void>;
onError?: (err: unknown) => void;
}): void;
/** Convenience wrapper that removes an ack reaction handle after reply delivery. */
declare function removeAckReactionHandleAfterReply(params: {
removeAfterReply: boolean;
ackReaction: AckReactionHandle | null | undefined;
onError?: (err: unknown) => void;
}): void;
//#endregion
//#region src/auto-reply/inbound-debounce.d.ts
/** Resolve effective inbound debounce milliseconds from explicit, channel, and global config. */
declare function resolveInboundDebounceMs(params: {
cfg: OpenClawConfig;
channel: string;
overrideMs?: number;
}): number;
/** A flush releases its debounce lane at admission while completion remains drainable. */
type InboundDebounceFlush = {
admission: Promise<void>;
completion: Promise<void>;
};
type InboundDebounceAdmissionLifecycleInput = {
abortSignal?: AbortSignal;
onAdopted?: () => void | Promise<void>;
onDeferred?: () => boolean | void;
onDeferredHeartbeat?: () => void;
onAdoptionFinalizing?: () => void;
onFailed?: (error: unknown) => void | Promise<void>;
onAbandoned?: () => void | Promise<void>;
};
/** Lifecycle shape passed to a channel dispatch so it can signal session-lane admission. */
type InboundDebounceAdmissionLifecycle = {
abortSignal: AbortSignal;
onAdopted: () => Promise<void>;
onDeferred: () => boolean | void;
onDeferredHeartbeat?: () => void;
onAdoptionFinalizing: () => void;
onFailed?: (error: unknown) => Promise<void>;
onAbandoned: () => Promise<void>;
};
/**
* Start one flush and bind its admission signal to the turn lifecycle.
* Completion also releases admission for gated work that never enters a session lane.
*/
declare function createInboundDebounceFlush(params: {
lifecycle?: InboundDebounceAdmissionLifecycleInput;
dispatch: (lifecycle: InboundDebounceAdmissionLifecycle) => Promise<void>;
}): InboundDebounceFlush;
/** Options for creating a keyed inbound debouncer. */
type InboundDebounceCreateParams<T> = {
debounceMs: number;
maxTrackedKeys?: number;
buildKey: (item: T) => string | null | undefined;
shouldDebounce?: (item: T) => boolean;
resolveDebounceMs?: (item: T) => number | undefined;
serializeImmediate?: boolean;
onFlush: (items: T[], createFlush: typeof createInboundDebounceFlush) => InboundDebounceFlush;
onError?: (err: unknown, items: T[]) => void;
onCancel?: (items: T[]) => void;
};
/** Create a keyed debouncer with flush/cancel controls and same-key serialization. */
declare function createInboundDebouncer<T>(params: InboundDebounceCreateParams<T>): {
enqueue: (item: T) => Promise<void>;
flushKey: (key: string) => Promise<void>;
cancelKey: (key: string) => boolean;
drain: () => Promise<void>;
};
//#endregion
//#region src/channels/command-gating.d.ts
/**
* Shared text-control command authorization policy for channel runtimes.
*
* These helpers are re-exported through the plugin SDK so built-in and external
* channels make the same access-groups decisions for native command text.
*/
/** One channel-specific authorization source for text control commands. */
type CommandAuthorizer = {
/** True when this channel/user identity has an access-group rule configured. */
configured: boolean;
/** True when the configured rule permits the command. Ignored when unconfigured. */
allowed: boolean;
};
/** Fallback policy for channels that have access groups globally disabled. */
type CommandGatingModeWhenAccessGroupsOff = "allow" | "deny" | "configured";
/** Resolves whether any configured authorizer permits a control command. */
declare function resolveCommandAuthorizedFromAuthorizers(params: {
/** Global access-group switch for the channel/runtime. */
useAccessGroups: boolean;
/** Independent authorization sources, such as sender id and actor id. */
authorizers: CommandAuthorizer[];
/** Policy used only when `useAccessGroups` is false. Defaults to open. */
modeWhenAccessGroupsOff?: CommandGatingModeWhenAccessGroupsOff;
}): boolean;
//#endregion
//#region src/channels/reply-prefix.d.ts
type ModelSelectionContext = Parameters<NonNullable<GetReplyOptions["onModelSelected"]>>[0];
/**
* Mutable response-prefix state shared between reply setup and model selection callbacks.
*/
type ReplyPrefixContextBundle = {
prefixContext: ResponsePrefixContext;
responsePrefix?: string;
responsePrefixContextProvider: () => ResponsePrefixContext;
onModelSelected: (ctx: ModelSelectionContext) => void;
};
/**
* Reply option subset consumed by channel reply dispatchers.
*/
type ReplyPrefixOptions = Pick<ReplyPrefixContextBundle, "responsePrefix" | "responsePrefixContextProvider" | "onModelSelected">;
/**
* Creates the reply-prefix options object expected by `getReply` call sites.
*/
declare function createReplyPrefixOptions(params: {
cfg: OpenClawConfig;
agentId: string;
channel?: string;
accountId?: string;
}): ReplyPrefixOptions;
//#endregion
//#region src/channels/message/reply-pipeline.d.ts
/** Parameters for building a channel reply pipeline with prefix, typing, and payload transforms. */
type CreateChannelReplyPipelineParams = {
/** Full config used for reply prefix and channel plugin transform resolution. */
cfg: Parameters<typeof createReplyPrefixOptions>[0]["cfg"];
/** Agent id used in reply prefix context. */
agentId: string;
/** Optional channel id for prefix context and plugin transform lookup. */
channel?: string;
/** Optional channel account id for prefix context and plugin transform lookup. */
accountId?: string;
/** Typing callback factory input. */
typing?: CreateTypingCallbacksParams;
/** Prebuilt typing callbacks that take precedence over `typing`. */
typingCallbacks?: TypingCallbacks;
/** Explicit payload transform; avoids channel plugin lookup when provided. */
transformReplyPayload?: (payload: ReplyPayload) => ReplyPayload | null;
};
//#endregion
//#region src/plugin-sdk/pair-loop-guard-runtime.d.ts
/** User-facing pair-loop guard config accepted by channel plugins. */
type PairLoopGuardConfig = {
/** Enables or disables loop protection for the channel/account scope. */
enabled?: boolean;
/** Number of pair events allowed before cooldown starts. */
maxEventsPerWindow?: number;
/** Rolling event window size in seconds for config files. */
windowSeconds?: number;
/** Suppression duration in seconds for config files. */
cooldownSeconds?: number;
};
//#endregion
//#region src/channels/turn/bot-loop-protection.d.ts
/** Facts used to detect repeated bot-to-bot channel reply loops. */
type ChannelBotLoopProtectionFacts = {
scopeId: string;
conversationId: string;
senderId: string;
receiverId: string;
eventId?: string;
config?: PairLoopGuardConfig;
defaultsConfig?: PairLoopGuardConfig;
defaultEnabled: boolean;
nowMs?: number;
};
//#endregion
//#region src/channels/turn/types.d.ts
/** Admission decision for an inbound channel event before agent dispatch. */
type ChannelTurnAdmission = {
kind: "dispatch";
reason?: string;
} | {
kind: "observeOnly";
reason: string;
} | {
kind: "handled";
reason: string;
} | {
kind: "drop";
reason: string;
recordHistory?: boolean;
};
/** Coarse event classification used to decide whether an event can start an agent turn. */
type ChannelEventClass = {
kind: "message" | "command" | "interaction" | "reaction" | "lifecycle" | "unknown";
canStartAgentTurn: boolean;
requiresImmediateAck?: boolean;
};
/** Normalized inbound event text and raw payload after channel-specific ingestion. */
type NormalizedTurnInput = {
id: string;
timestamp?: number;
rawText: string;
textForAgent?: string;
textForCommands?: string;
raw?: unknown;
};
/** Sender identity facts projected into channel access, routing, and prompt context. */
type SenderFacts = {
id?: string;
name?: string;
username?: string;
tag?: string;
roles?: string[];
isBot?: boolean;
isSelf?: boolean;
displayLabel?: string;
};
/** Conversation identity and threading facts for a channel turn. */
type ConversationFacts = {
kind: "direct" | "group" | "channel";
id: string;
label?: string;
spaceId?: string;
parentId?: string;
threadId?: string;
nativeChannelId?: string;
avatar?: string;
routePeer?: {
kind: "direct" | "group" | "channel";
id: string;
};
};
/** Session routing facts derived before dispatch. */
type RouteFacts = {
agentId: string;
dmScope?: DmScope;
accountId?: string;
routeSessionKey: string;
dispatchSessionKey?: string;
persistedSessionKey?: string;
parentSessionKey?: string;
modelParentSessionKey?: string;
mainSessionKey?: string;
createIfMissing?: boolean;
};
/** Reply target and source-delivery facts for a channel turn. */
type ReplyPlanFacts = {
to: string;
originatingTo?: string;
nativeChannelId?: string;
replyTarget?: string;
deliveryTarget?: string;
replyToId?: string;
replyToIdFull?: string;
messageThreadId?: string | number;
threadParentId?: string;
sourceReplyDeliveryMode?: "thread" | "reply" | "channel" | "direct" | "none";
};
/** Message text/history facts passed into templating and dispatch. */
type MessageFacts = {
inboundEventKind?: InboundEventKind;
body?: string;
rawBody: string;
bodyForAgent?: string;
commandBody?: string;
envelopeFrom?: string;
senderLabel?: string;
preview?: string;
inboundHistory?: HistoryEntry[];
sourceModality?: InboundSourceModality;
};
/** Parsed command facts for command-like channel turns. */
type CommandFacts = {
kind: CommandTurnKind;
body?: string;
name?: string;
authorized?: boolean;
};
/** Inbound media facts supplied to the agent context. */
type InboundMediaFacts = Omit<MediaFact, "staged" | "workspaceDir">;
type MaybePromise$1<T> = T | Promise<T>;
/** Adapter preflight output assembled before turn resolution. */
type PreflightFacts = {
admission?: ChannelTurnAdmission;
command?: CommandFacts;
message?: Partial<MessageFacts>;
media?: readonly InboundMediaFacts[] | (() => MaybePromise$1<readonly InboundMediaFacts[] | readonly HistoryMediaEntry[] | null | undefined>);
supplemental?: SupplementalContextFacts;
history?: ChannelTurnDroppedHistoryOptions;
};
/** Delivery metadata for one reply payload dispatch. */
type ChannelDeliveryInfo = ReplyDispatchRuntimeInfo;
type ChannelCoreManagedDeliveryInfo = Omit<ChannelDeliveryInfo, "assertPlatformSendAuthorized" | "bindPendingFinalDelivery" | "onPlatformSendDispatch">;
type ChannelProviderOwnedDeliveryInfo = ChannelDeliveryInfo & {
assertPlatformSendAuthorized: () => void;
onPlatformSendDispatch: () => Promise<void>;
};
/** Durable delivery queue intent recorded when a reply is deferred. */
type ChannelDeliveryIntent = {
id: string;
kind: "outbound_queue";
queuePolicy: OutboundDeliveryQueuePolicy;
};
/** Provider-accepted outcome for one logical channel reply payload. */
type ChannelDeliveryOutcome = {
messageIds?: string[];
receipt?: MessageReceipt;
threadId?: string;
replyToId?: string;
visibleReplySent?: boolean;
/** Final provider-visible text used for this logical payload's terminal observation. */
content?: string;
};
/** Result returned after delivering one channel reply payload. */
type ChannelDeliveryResult = ChannelDeliveryOutcome & {
deliveryIntent?: ChannelDeliveryIntent;
/** Intentional no-send outcome after payload policy or modifying hooks settle. */
suppression?: {
reason: OutboundPayloadDeliverySuppressionReason | "channel_transform" | "no_visible_result";
cancelReason?: string;
metadata?: Record<string, unknown>;
};
/** Same-payload native settlement; resolved fields override this result before observation. */
finalization?: Promise<ChannelDeliveryOutcome>;
};
/** Durable outbound delivery options available to channel turn delivery adapters. */
type ChannelTurnDurableDeliveryOptions = Pick<DeliverOutboundPayloadsParams, "deps" | "formatting" | "identity" | "mediaAccess" | "replyToMode" | "silent" | "threadId"> & {
to?: string | null;
replyToId?: string | null;
requiredCapabilities?: DurableFinalDeliveryRequirements;
};
type ChannelDeliveryAdapterBase = {
/** Return null when channel policy intentionally suppresses this logical payload. */
preparePayload?: (payload: ReplyPayload, info: ChannelDeliveryInfo) => MaybePromise$1<ReplyPayload | null>;
onDelivered?: (payload: ReplyPayload, info: ChannelDeliveryInfo, result: ChannelDeliveryResult | void) => Promise<void> | void;
/** Let core emit the one canonical `message_sent` after non-durable provider settlement. */
observeMessageSent?: true;
onError?: (err: unknown, info: {
kind: string;
}) => void;
};
type ChannelCoreManagedTurnDeliveryAdapter = ChannelDeliveryAdapterBase & {
deliver: (payload: ReplyPayload, info: ChannelCoreManagedDeliveryInfo) => Promise<ChannelDeliveryResult | void>;
durable?: false | ChannelTurnDurableDeliveryOptions | ((payload: ReplyPayload, info: ChannelDeliveryInfo) => false | ChannelTurnDurableDeliveryOptions | Promise<false | ChannelTurnDurableDeliveryOptions>);
};
/** Delivery adapter used by legacy caller-assembled channel turns. */
type ChannelEventDeliveryAdapter = ChannelCoreManagedTurnDeliveryAdapter;
type ChannelProviderOwnedMessageSendingDeliveryAdapter = ChannelDeliveryAdapterBase & {
/**
* Provider funnel that owns `message_sending` after its native payload preparation.
* Use only when delivery cannot declare its durable/direct branch before entering the
* provider funnel; core still owns `reply_payload_sending` for this routed turn.
*/
deliverWithProviderMessageSending: (payload: ReplyPayload, info: ChannelProviderOwnedDeliveryInfo) => Promise<ChannelDeliveryResult | void>;
deliver?: never;
durable?: never;
};
/** Delivery adapter used by modern routed channel turns. */
type ChannelTurnDeliveryAdapter = (ChannelCoreManagedTurnDeliveryAdapter & {
deliverWithProviderMessageSending?: never;
}) | ChannelProviderOwnedMessageSendingDeliveryAdapter;
/** Options for recording inbound session route state around a turn. */
type ChannelTurnRecordOptions = {
/**
* Override the session used for metadata and transcript context.
* Must be non-empty and contain no surrounding whitespace.
*/
sessionKey?: string;
groupResolution?: GroupKeyResolution | null;
createIfMissing?: boolean;
updateLastRoute?: InboundLastRouteUpdate;
onRecordError?: (err: unknown) => void;
trackSessionMetaTask?: (task: Promise<unknown>) => void;
};
/** Options for finalizing visible conversation history after dispatch. */
type ChannelTurnHistoryFinalizeOptions = {
isGroup?: boolean;
historyKey?: string;
historyMap?: Map<string, HistoryEntry[]>;
limit?: number;
};
/** Options for recording history when an inbound event is dropped before dispatch. */
type ChannelTurnDroppedHistoryOptions = {
key: string;
limit: number;
historyMap: Map<string, HistoryEntry[]>;
recordOnDrop?: boolean;
mediaLimit?: number;
shouldRecord?: () => boolean;
};
/** Dispatcher options excluding delivery hooks owned by the channel turn adapter. */
type ChannelTurnDispatcherOptions = Omit<ReplyDispatcherWithTypingOptions, "deliver" | "onError">;
/** Reply options plus the opaque native command ownership decision carried by channel turns. */
type ChannelTurnReplyOptions = Omit<GetReplyOptions, "onBlockReply"> & PluginCommandReplyOptions;
/** Reply pipeline options excluding cfg/agent/channel identity supplied by the turn. */
type ChannelTurnReplyPipelineOptions = Omit<CreateChannelReplyPipelineParams, "cfg" | "agentId" | "channel" | "accountId">;
/** Fully assembled channel turn ready to build the dispatch runner. */
type AssembledChannelTurn = {
cfg: OpenClawConfig;
channel: string;
accountId?: string;
agentId: string;
routeSessionKey: string;
storePath: string;
ctxPayload: FinalizedMsgContext;
recordInboundSession: RecordInboundSession$1;
afterRecord?: () => void | Promise<void>;
dispatchReplyWithBufferedBlockDispatcher: DispatchReplyWithBufferedBlockDispatcher$1;
delivery: ChannelEventDeliveryAdapter;
replyPipeline?: ChannelTurnReplyPipelineOptions;
dispatcherOptions?: ChannelTurnDispatcherOptions;
toolsAllow?: string[];
replyOptions?: ChannelTurnReplyOptions;
replyResolver?: GetReplyFromConfig;
/** Instance-bound reply dispatcher supplied by the owning plugin runtime. */
dispatchReplyFromConfig?: DispatchReplyFromConfig;
sessionInitRetry?: {
delaysMs: readonly number[];
signal?: AbortSignal;
sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
};
record?: ChannelTurnRecordOptions;
history?: ChannelTurnHistoryFinalizeOptions;
admission?: Extract<ChannelTurnAdmission, {
kind: "dispatch" | "observeOnly";
}>;
botLoopProtection?: ChannelBotLoopProtectionFacts;
/** Transport-defined outbound source identity, such as a webhook id. */
outboundEchoSourceId?: string;
log?: (event: ChannelTurnLogEvent) => void;
messageId?: string;
/** Canonical adoption lifecycle threaded into replyOptions. */
turnAdoptionLifecycle?: TurnAdoptionLifecycle;
};
type PreparedChannelTurnDispatchSkipReason = "botLoopProtection" | "observeOnly" | "outboundEcho";
/** Lifecycle ownership declared alongside an already-prepared dispatch runner. */
type PreparedChannelTurnDispatchLifecycle = {
/** Exact adoption lifecycle captured by runDispatch, or undefined for non-durable turns. */
turnAdoptionLifecycle: TurnAdoptionLifecycle | undefined;
/** Releases resources that runDispatch would otherwise settle when dispatch is skipped. */
onDispatchSkipped: (reason: PreparedChannelTurnDispatchSkipReason) => void | Promise<void>;
};
/** Channel turn with dispatch runner already prepared. */
type PreparedChannelTurn<TDispatchResult = DispatchFromConfigResult> = {
channel: string;
accountId?: string;
routeSessionKey: string;
storePath: string;
ctxPayload: FinalizedMsgContext;
recordInboundSession: RecordInboundSession$1;
afterRecord?: () => void | Promise<void>;
record?: ChannelTurnRecordOptions;
history?: ChannelTurnHistoryFinalizeOptions;
onPreDispatchFailure?: (err: unknown) => void | Promise<void>;
runDispatch: () => Promise<TDispatchResult>;
/** Optional for the legacy direct prepared runner; inbound adapters use the stricter type. */
runDispatchLifecycle?: PreparedChannelTurnDispatchLifecycle;
observeOnlyDispatchResult?: TDispatchResult;
admission?: Extract<ChannelTurnAdmission, {
kind: "dispatch" | "observeOnly";
}>;
botLoopProtection?: ChannelBotLoopProtectionFacts;
/** Transport-defined outbound source identity, such as a webhook id. */
outboundEchoSourceId?: string;
log?: (event: ChannelTurnLogEvent) => void;
messageId?: string;
};
type ChannelTurnRoute = {
agentId: string;
dmScope?: DmScope;
sessionKey: string;
};
type RoutedChannelTurn<T> = Omit<T, "routeSessionKey" | "storePath" | "recordInboundSession"> & {
route: ChannelTurnRoute;
};
type InboundPreparedChannelTurn<TDispatchResult = DispatchFromConfigResult> = PreparedChannelTurn<TDispatchResult> & {
runDispatchLifecycle: PreparedChannelTurnDispatchLifecycle;
};
type ChannelTurnPlan<TDelivery extends ChannelTurnDeliveryAdapter = ChannelCoreManagedTurnDeliveryAdapter> = RoutedChannelTurn<Omit<AssembledChannelTurn, "agentId" | "delivery" | "dispatchReplyWithBufferedBlockDispatcher"> & {
delivery: TDelivery;
}>;
type PreparedChannelTurnPlan<TDispatchResult = DispatchFromConfigResult> = RoutedChannelTurn<InboundPreparedChannelTurn<TDispatchResult>> & {
cfg: OpenClawConfig;
};
/** Resolved turn shape returned by adapters before final run/dispatch handling. */
type ChannelTurnResolved<TDispatchResult = DispatchFromConfigResult, TDelivery extends ChannelTurnDeliveryAdapter = ChannelCoreManagedTurnDeliveryAdapter> = ChannelTurnPlan<TDelivery> | PreparedChannelTurnPlan<TDispatchResult> | (AssembledChannelTurn & {
admission?: Extract<ChannelTurnAdmission, {
kind: "dispatch" | "observeOnly";
}>;
}) | (InboundPreparedChannelTurn<TDispatchResult> & {
admission?: Extract<ChannelTurnAdmission, {
kind: "dispatch" | "observeOnly";
}>;
});
/** Ordered lifecycle stage names emitted to channel turn log hooks. */
type ChannelTurnStage = "ingest" | "classify" | "preflight" | "resolve" | "authorize" | "assemble" | "record" | "dispatch" | "finalize";
/** Structured channel turn log event. */
type ChannelTurnLogEvent = {
stage: ChannelTurnStage;
event: "start" | "done" | "drop" | "handled" | "error" | "warning";
channel: string;
accountId?: string;
messageId?: string;
sessionKey?: string;
admission?: ChannelTurnAdmission["kind"];
reason?: string;
error?: unknown;
};
/** Final result for a channel turn, dispatched or admitted without dispatch. */
type ChannelTurnResult<TDispatchResult = DispatchFromConfigResult> = DispatchedChannelTurnResult<TDispatchResult> | {
admission: ChannelTurnAdmission;
dispatched: false;
ctxPayload?: MsgContext;
routeSessionKey?: string;
};
/** Successful dispatch result for a channel turn. */
type DispatchedChannelTurnResult<TDispatchResult = DispatchFromConfigResult> = {
admission: Extract<ChannelTurnAdmission, {
kind: "dispatch" | "observeOnly";
}>;
dispatched: true;
ctxPayload: MsgContext;
routeSessionKey: string;
dispatchResult: TDispatchResult;
};
/** Adapter contract for ingesting, classifying, resolving, and finalizing raw channel events. */
type ChannelTurnAdapter<TRaw, TDispatchResult = DispatchFromConfigResult, TDelivery extends ChannelTurnDeliveryAdapter = ChannelCoreManagedTurnDeliveryAdapter> = {
ingest: (raw: TRaw) => Promise<NormalizedTurnInput | null> | NormalizedTurnInput | null;
classify?: (input: NormalizedTurnInput) => Promise<ChannelEventClass> | ChannelEventClass;
preflight?: (input: NormalizedTurnInput, eventClass: ChannelEventClass) => Promise<PreflightFacts | ChannelTurnAdmission | null | undefined> | PreflightFacts | ChannelTurnAdmission | null | undefined;
resolveTurn: (input: NormalizedTurnInput, eventClass: ChannelEventClass, preflight: PreflightFacts) => Promise<ChannelTurnResolved<TDispatchResult, TDelivery>> | ChannelTurnResolved<TDispatchResult, TDelivery>;
onFinalize?: (result: ChannelTurnResult<TDispatchResult>) => Promise<void> | void;
};
/** Parameters for running one raw channel event through the turn kernel. */
type RunChannelTurnParams<TRaw, TDispatchResult = DispatchFromConfigResult, TDelivery extends ChannelTurnDeliveryAdapter = ChannelCoreManagedTurnDeliveryAdapter> = {
channel: string;
accountId?: string;
raw: TRaw;
adapter: ChannelTurnAdapter<TRaw, TDispatchResult, TDelivery>;
log?: (event: ChannelTurnLogEvent) => void;
/** Canonical adoption lifecycle for this turn. */
turnAdoptionLifecycle?: TurnAdoptionLifecycle;
};
//#endregion
//#region src/channels/inbound-event/context.d.ts
type MaybePromise<T> = T | Promise<T>;
type ChannelInboundSupplementalMediaResolver = () => MaybePromise<readonly InboundMediaFacts[] | null | undefined>;
type ChannelInboundSupplementalQuoteFacts = NonNullable<SupplementalContextFacts["quote"]> & {
isSelf?: boolean;
media?: readonly InboundMediaFacts[] | ChannelInboundSupplementalMediaResolver;
};
type ChannelInboundSupplementalFacts = Omit<SupplementalContextFacts, "quote"> & {
quote?: ChannelInboundSupplementalQuoteFacts;
};
/**
* @deprecated Prefer passing `resolveSupplementalMedia: true` directly to
* `buildChannelInboundEventContext` without naming this compatibility type.
*/
type ChannelInboundSupplementalResolutionOptions = {
resolveSupplementalMedia: true;
suppressSelfQuoteBody?: boolean;
suppressSelfQuoteMedia?: boolean;
};
type BuildChannelInboundEventAccess = {
commands?: Pick<ChannelIngressCommandAccess, "authorized">;
/** Channel-configured policy resolved at the trusted ingress boundary. */
toolPolicy?: GroupToolPolicyConfig;
mentions?: {
canDetectMention: boolean;
wasMentioned: boolean;
hasAnyMention?: boolean;
explicitlyMentionedBot?: boolean;
mentionedUserIds?: string[];
mentionedSubteamIds?: string[];
mentionSource?: MentionSource;
implicitMentionKinds?: InboundImplicitMentionKind[];
requireMention?: boolean;
effectiveWasMentioned?: boolean;
};
};
type BuildChannelInboundEventContextParams = {
channel: string;
accountId?: string;
provider?: string;
surface?: string;
messageId?: string;
messageIdFull?: string;
timestamp?: number;
from: string;
sender: SenderFacts;
conversation: ConversationFacts;
route: RouteFacts;
reply: ReplyPlanFacts;
message: MessageFacts;
sessionTranscript?: SessionTranscriptContext;
access?: BuildChannelInboundEventAccess;
command?: CommandFacts;
commandTurn?: CommandTurnContext;
media?: InboundMediaFacts[];
supplemental?: ChannelInboundSupplementalFacts;
channelContext?: PluginHookChannelContext;
contextVisibility?: ContextVisibilityMode;
finalize?: FinalizeInboundContextFn;
finalizeOptions?: FinalizeInboundContextOptions;
extra?: Record<string, unknown>;
/** Exact host-resolved ingress result, or an explicit unsupported adapter marker. */
channelIngress?: ResolvedChannelMessageIngress | readonly ResolvedChannelMessageIngress[] | "unsupported";
};
/**
* @deprecated Prefer `BuildChannelInboundEventContextParams` with
* `resolveSupplementalMedia: true` at call sites that need lazy quote media.
*/
type BuildChannelInboundEventContextAsyncParams = BuildChannelInboundEventContextParams & ChannelInboundSupplementalResolutionOptions;
type BuiltChannelInboundEventContext = FinalizedMsgContext & {
Body: string;
BodyForAgent: string;
BodyForCommands: string;
ChatType: ConversationFacts["kind"];
CommandAuthorized: boolean;
CommandBody: string;
From: string;
RawBody: string;
SessionKey: string;
To: string;
InboundEventKind: InboundEventKind;
};
type FinalizeInboundContextFn = (ctx: Record<string, unknown>, opts?: FinalizeInboundContextOptions) => unknown;
declare function buildChannelInboundEventContext(params: BuildChannelInboundEventContextAsyncParams): Promise<BuiltChannelInboundEventContext>;
declare function buildChannelInboundEventContext(params: BuildChannelInboundEventContextParams): BuiltChannelInboundEventContext;
//#endregion
//#region src/channels/turn/run-channel-turn.d.ts
declare function runChannelTurn<TRaw, TDispatchResult = DispatchedChannelTurnResult["dispatchResult"]>(params: RunChannelTurnParams<TRaw, TDispatchResult, ChannelProviderOwnedMessageSendingDeliveryAdapter>): Promise<ChannelTurnResult<TDispatchResult>>;
declare function runChannelTurn<TRaw, TDispatchResult = DispatchedChannelTurnResult["dispatchResult"]>(params: RunChannelTurnParams<TRaw, TDispatchResult>): Promise<ChannelTurnResult<TDispatchResult>>;
//#endregion
//#region src/channels/turn/execution.d.ts
declare function runPreparedChannelTurn<TDispatchResult = DispatchedChannelTurnResult["dispatchResult"]>(params: PreparedChannelTurn<TDispatchResult>): Promise<ChannelTurnResult<TDispatchResult>>;
//#endregion
//#region src/channels/turn/lifecycle.d.ts
declare function dispatchAssembledChannelTurn(params: AssembledChannelTurn): Promise<ChannelTurnResult>;
declare function dispatchRoutedChannelTurn(params: ChannelTurnPlan<ChannelTurnDeliveryAdapter>): Promise<ChannelTurnResult>;
declare function dispatchRoutedChannelTurn(params: ChannelTurnPlan<ChannelProviderOwnedMessageSendingDeliveryAdapter>): Promise<ChannelTurnResult>;
declare function dispatchRoutedChannelTurn(params: ChannelTurnPlan): Promise<ChannelTurnResult>;
//#endregion
//#region src/auto-reply/command-detection.runtime-types.d.ts
/** Runtime-injected predicate for deciding whether visible text is an OpenClaw command. */
type IsControlCommandMessage = (text?: string, cfg?: OpenClawConfig, options?: CommandNormalizeOptions) => boolean;
/** Runtime-injected predicate for deciding whether command authorization must be computed. */
type ShouldComputeCommandAuthorized = (text?: string, cfg?: OpenClawConfig, options?: CommandNormalizeOptions) => boolean;
//#endregion
//#region src/auto-reply/commands-registry.runtime-types.d.ts
/** Runtime-injected policy hook for whether text slash commands should be honored. */
type ShouldHandleTextCommands = (params: ShouldHandleTextCommandsParams) => boolean;
//#endregion
//#region src/channels/mention-pattern-policy.d.ts
/**
* Inputs for resolving whether mention-pattern matching is enabled in a conversation.
*/
type ResolveMentionPatternPolicyParams = {
cfg?: OpenClawConfig;
provider?: string;
conversationId?: string | null;
providerPolicy?: MentionPatternsPolicyConfig;
agentId?: string;
};
//#endregion
//#region src/auto-reply/reply/mentions.types.d.ts
/** Options for building mention regexes without binding config/agent id. */
type BuildMentionRegexesOptions = Omit<ResolveMentionPatternPolicyParams, "cfg" | "agentId">;
/** Builds mention regexes for the current config and agent. */
type BuildMentionRegexes = (cfg: OpenClawConfig | undefined, agentId?: string, options?: BuildMentionRegexesOptions) => RegExp[];
/** Tests plain text against mention regexes. */
type MatchesMentionPatterns = (text: string, mentionRegexes: RegExp[]) => boolean;
/** Explicit mention metadata supplied by channel adapters. */
type ExplicitMentionSignal = {
hasAnyMention: boolean;
isExplicitlyMentioned: boolean;
canResolveExplicit: boolean;
};
/** Tests mention state using regexes plus explicit channel mention metadata. */
type MatchesMentionWithExplicit = (params: {
text: string;
mentionRegexes: RegExp[];
explicit?: ExplicitMentionSignal;
transcript?: string;
}) => boolean;
//#endregion
//#region src/auto-reply/reply/reply-dispatcher.runtime-types.d.ts
/** Type of the lazy reply dispatcher factory used by runtime dispatch paths. */
type CreateReplyDispatcherWithTyping = typeof createReplyDispatcherWithTyping;
//#endregion
//#region src/channels/plugins/outbound/load.types.d.ts
/**
* Lazy loader contract for channel outbound adapters.
*/
type LoadChannelOutboundAdapter = (id: ChannelId$1) => Promise<ChannelOutboundAdapter | undefined>;
//#endregion
//#region src/config/markdown-tables.types.d.ts
/** Parameters for resolving markdown table rendering per config and channel. */
type ResolveMarkdownTableModeParams = {
cfg?: Partial<OpenClawConfig>;
channel?: string | null;
accountId?: string | null;
supportsBlockTables?: boolean;
};
type ResolveMarkdownTableMode = (params: ResolveMarkdownTableModeParams) => MarkdownTableMode$1;
//#endregion
//#region src/config/sessions/runtime-types.d.ts
/** Runtime hook for reading a session store entry timestamp. */
type ReadSessionUpdatedAt = (params: {
storePath: string;
sessionKey: string;
}) => number | undefined;
type RecordSessionMetaFromInbound = (params: {
storePath: string;
sessionKey: string;
ctx: MsgContext;
groupResolution?: GroupKeyResolution | null;
createIfMissing?: boolean;
}) => Promise<SessionEntry$1 | null>;
type UpdateLastRoute = (params: {
storePath: string;
sessionKey: string;
channel?: string;
to?: string;
accountId?: string;
threadId?: string | number;
route?: ChannelRouteRef;
deliveryContext?: DeliveryContext;
ctx?: MsgContext;
groupResolution?: GroupKeyResolution | null;
createIfMissing?: boolean;
}) => Promise<SessionEntry$1 | null>;
//#endregion
//#region src/plugins/runtime/types-channel.d.ts
type DispatchReplyWithBufferedBlockDispatcher = DispatchReplyWithBufferedBlockDispatcher$1;
type RecordInboundSession = RecordInboundSession$1;
type RuntimeThreadBindingLifecycleRecord = SessionBindingRecord | {
boundAt: number;
lastActivityAt: number;
idleTimeoutMs?: number;
maxAgeMs?: number;
};
type PluginRuntimeChannelContextKey = {
channelId: string;
accountId?: string | null;
capability: string;
};
type PluginRuntimeChannelContextEvent = {
type: "registered" | "unregistered";
key: {
channelId: string;
accountId?: string;
capability: string;
};
context?: unknown;
};
type PluginRuntimeChannelContextRegistry = {
register: (params: PluginRuntimeChannelContextKey & {
context: unknown;
abortSignal?: AbortSignal;
}) => {
dispose: () => void;
};
get: <T = unknown>(params: PluginRuntimeChannelContextKey) => T | undefined;
watch: (params: {
channelId?: string;
accountId?: string | null;
capability?: string;
onEvent: (event: PluginRuntimeChannelContextEvent) => void;
}) => () => void;
};
type PluginRuntimeChannel$1 = {
text: {
chunkByNewline: typeof chunkByNewline;
chunkMarkdownText: typeof chunkMarkdownText;
chunkMarkdownTextWithMode: typeof chunkMarkdownTextWithMode;
chunkText: typeof chunkText;
chunkTextWithMode: typeof chunkTextWithMode;
resolveChunkMode: typeof resolveChunkMode;
resolveTextChunkLimit: typeof resolveTextChunkLimit;
hasControlCommand: typeof hasControlCommand;
resolveMarkdownTableMode: ResolveMarkdownTableMode;
convertMarkdownTables: typeof convertMarkdownTables;
};
reply: {
dispatchReplyWithBufferedBlockDispatcher: DispatchReplyWithBufferedBlockDispatcher;
/**
* @deprecated Prefer `openclaw/plugin-sdk/channel-outbound` adapters plus
* `dispatchReplyWithBufferedBlockDispatcher` or channel turn helpers.
* This is a low-level legacy dispatcher escape hatch.
*/
createReplyDispatcherWithTyping: CreateReplyDispatcherWithTyping;
resolveEffectiveMessagesConfig: typeof resolveEffectiveMessagesConfig;
/**
* @deprecated Prefer the channel-message reply pipeline helpers. This is
* tied to the low-level legacy dispatcher path.
*/
resolveHumanDelayConfig: typeof resolveHumanDelayConfig;
/**
* @deprecated Prefer `dispatchReplyWithBufferedBlockDispatcher` with a
* channel-message adapter or the channel turn helpers. Direct use must
* manually preserve source reply delivery metadata such as
* `sourceReplyDeliveryMode`.
*/
dispatchReplyFromConfig: DispatchReplyFromConfig;
withReplyDispatcher: typeof withReplyDispatcher;
settleReplyDispatcher: typeof settleReplyDispatcher;
/**
* @deprecated Prefer `buildChannelInboundEventContext` from
* `openclaw/plugin-sdk/channel-inbound` so inbound event metadata is
* carried into reply dispatch.
*/
finalizeInboundContext: typeof finalizeInboundContext;
formatAgentEnvelope: typeof formatAgentEnvelope;
resolveEnvelopeFormatOptions: typeof resolveEnvelopeFormatOptions;
};
routing: {
buildAgentSessionKey: typeof buildAgentSessionKey;
resolveAgentRoute: typeof resolveAgentRoute;
};
pairing: {
buildPairingReply: typeof buildPairingReply;
readAllowFromStore: ReadChannelAllowFromStoreForAccount;
removeAllowFromStoreEntry: RemoveChannelAllowFromStoreEntryForAccount;
upsertPairingRequest: UpsertChannelPairingRequestForAccount;
};
media: {
readRemoteMediaBuffer: typeof readRemoteMediaBuffer;
/** @deprecated Use `readRemoteMediaBuffer`. */
fetchRemoteMedia: typeof fetchRemoteMedia;
saveRemoteMedia: typeof saveRemoteMedia;
saveResponseMedia: typeof saveResponseMedia;
saveMediaBuffer: typeof saveMediaBuffer;
};
activity: {
record: typeof recordChannelActivity;
get: typeof getChannelActivity;
};
session: {
/** @deprecated Prefer channel turn helpers that record inbound sessions as part of dispatch. */
resolveStorePath: typeof resolveSessionStorePathCore;
readSessionUpdatedAt: ReadSessionUpdatedAt;
recordSessionMetaFromInbound: RecordSessionMetaFromInbound;
/** @deprecated Prefer channel turn helpers that record inbound sessions as part of dispatch. */
recordInboundSession: RecordInboundSession;
updateLastRoute: UpdateLastRoute;
};
mentions: {
buildMentionRegexes: BuildMentionRegexes;
matchesMentionPatterns: MatchesMentionPatterns;
matchesMentionWithExplicit: MatchesMentionWithExplicit;
implicitMentionKindWhen: typeof implicitMentionKindWhen;
resolveInboundMentionDecision: typeof resolveInboundMentionDecision;
};
reactions: {
createAckReactionHandle: typeof createAckReactionHandle;
shouldAckReaction: typeof shouldAckReaction;
removeAckReactionAfterReply: typeof removeAckReactionAfterReply;
removeAckReactionHandleAfterReply: typeof removeAckReactionHandleAfterReply;
};
groups: {
resolveGroupPolicy: typeof resolveChannelGroupPolicy;
resolveRequireMention: typeof resolveChannelGroupRequireMention;
};
debounce: {
createInboundDebouncer: typeof createInboundDebouncer;
resolveInboundDebounceMs: typeof resolveInboundDebounceMs;
};
commands: {
resolveCommandAuthorizedFromAuthorizers: typeof resolveCommandAuthorizedFromAuthorizers;
isControlCommandMessage: IsControlCommandMessage;
shouldComputeCommandAuthorized: ShouldComputeCommandAuthorized;
shouldHandleTextCommands: ShouldHandleTextCommands;
};
outbound: {
loadAdapter: LoadChannelOutboundAdapter;
};
inbound: {
buildContext: typeof buildChannelInboundEventContext;
run: typeof runChannelTurn;
/** @deprecated Prefer `run` for raw inbound events or `dispatchReply` for assembled contexts. */
runPreparedReply: typeof runPreparedChannelTurn;
dispatch: typeof dispatchRoutedChannelTurn;
/** Compatibility escape hatch; prefer `dispatch`, which keeps session wiring in core. */
dispatchReply: typeof dispatchAssembledChannelTurn;
};
threadBindings: {
setIdleTimeoutBySessionKey: (params: {
channelId: string;
targetSessionKey: string;
accountId?: string;
idleTimeoutMs: number;
}) => RuntimeThreadBindingLifecycleRecord[];
setMaxAgeBySessionKey: (params: {
channelId: string;
targetSessionKey: string;
accountId?: string;
maxAgeMs: number;
}) => RuntimeThreadBindingLifecycleRecord[];
};
runtimeContexts: PluginRuntimeChannelContextRegistry;
};
//#endregion
//#region src/agents/run-wait.types.d.ts
/** Normalized terminal or pending state returned by `agent.wait`. */
type AgentWaitResult = {
status: "ok" | "timeout" | "error" | "pending";
error?: string;
/** Set locally when the wait RPC fails; terminal run text is never retry evidence. */
retryableTransportError?: true;
startedAt?: number;
endedAt?: number;
stopReason?: string;
livenessState?: string;
yielded?: boolean;
pendingError?: boolean;
timeoutPhase?: AgentRunTimeoutPhase;
providerStarted?: boolean;
terminalReply?: AgentRunTerminalReplySnapshot;
sourceReplyDelivered?: true;
};
//#endregion
//#region src/plugins/runtime/types.d.ts
type PluginRuntimeChannel = PluginRuntimeChannel$1;
type SubagentRunParams = {
sessionKey: string;
message: string;
/** Run with an exact empty tool surface. */
disableTools?: boolean;
/** Add exact tools registered by the calling plugin to the worker's normal tool surface. */
toolsAlsoAllow?: string[];
provider?: string;
model?: string;
extraSystemPrompt?: string;
/** Use the bounded subagent prompt instead of the full conversation prompt. */
promptMode?: "minimal";
lane?: string;
lightContext?: boolean;
deliver?: boolean;
/** Deliver the completion to the authenticated requester of the current hook invocation. */
completionDelivery?: "current-requester";
idempotencyKey?: string;
cwd?: string;
};
type SubagentCompleteParams = {
agentId: string;
message: string;
extraSystemPrompt?: string;
model?: string;
timeoutMs?: number;
signal?: AbortSignal;
};
type PluginManagedWorktree = {
id: string;
path: string;
branch: string;
};
type SubagentRunResult = {
runId: string;
/** Canonical accepted session identity. Optional for explicit/custom runtimes. */
sessionKey?: string;
runtime?: {
harness: string;
provider: string;
model: string;
};
};
type SubagentWaitParams = {
runId: string;
timeoutMs?: number;
};
type SubagentGetSessionMessagesParams = {
sessionKey: string;
limit?: number;
};
type SubagentGetSessionMessagesResult = {
messages: unknown[];
};
type SubagentDeleteSessionParams = {
sessionKey: string;
deleteTranscript?: boolean;
};
type RuntimeNodeListParams = {
connected?: boolean;
};
type RuntimeNodeListResult = {
nodes: Array<{
nodeId: string;
displayName?: string;
platform?: string;
clientId?: string;
remoteIp?: string;
connected?: boolean;
connectedAtMs?: number;
lastSeenAtMs?: number;
caps?: string[];
commands?: string[];
/** True only for the node host installed alongside this Gateway. */
gatewayLocal?: boolean;
/** Advertised commands currently permitted by Gateway node-command policy. */
invocableCommands?: string[];
nodePluginTools?: NodePluginToolDescriptor[];
}>;
};
type RuntimeNodeInvokeParams = {
nodeId: string;
command: string;
params?: unknown;
timeoutMs?: number;
idempotencyKey?: string;
sessionKey?: string;
/** Cancel the invocation and any work already dispatched to a first-party node. */
signal?: AbortSignal;
/** Requested Gateway scopes. Honored only for bundled or trusted official plugins. */
scopes?: OperatorScope[];
};
/** A lifecycle-bound, complete-message binary channel for one node invocation. */
type RuntimeNodeDuplexChannel = {
send: (message: Uint8Array) => Promise<void>;
onMessage: (listener: (message: Uint8Array) => void | Promise<void>) => () => void;
closed: Promise<unknown>;
close: () => void;
};
type RuntimeGatewayRequestOptions = {
timeoutMs?: number;
/** Requested Gateway scopes. Honored only for bundled or trusted official plugins. */
scopes?: OperatorScope[];
};
/** Trusted in-process runtime surface injected into native plugins. */
type PluginRuntime = PluginRuntimeCore & {
gateway: {
/** Whether this process owns an active Gateway request context. */
isAvailable: () => Promise<boolean>;
/** Dispatch a Gateway method as the current trusted plugin. */
request: <T = unknown>(method: string, params?: Record<string, unknown>, options?: RuntimeGatewayRequestOptions) => Promise<T>;
};
subagent: {
/** Fresh, tool-free background inference under the existing subagent model policy. */
complete: (params: SubagentCompleteParams) => Promise<{
text: string;
}>;
run: (params: SubagentRunParams) => Promise<SubagentRunResult>;
waitForRun: (params: SubagentWaitParams) => Promise<AgentWaitResult>;
getSessionMessages: (params: SubagentGetSessionMessagesParams) => Promise<SubagentGetSessionMessagesResult>;
deleteSession: (params: SubagentDeleteSessionParams) => Promise<void>;
};
nodes: {
list: (params?: RuntimeNodeListParams) => Promise<RuntimeNodeListResult>;
invoke: (params: RuntimeNodeInvokeParams) => Promise<unknown>;
/** Open a connection-scoped binary node command inside the trusted Gateway runtime. */
openDuplex: (params: RuntimeNodeInvokeParams & {
maxMessageBytes?: number;
maxOutstandingDeliveryBytes?: number;
}) => Promise<RuntimeNodeDuplexChannel>;
};
sandbox: {
resolveWorkspaceAuthority: (params: {
config: OpenClawConfig;
agentId?: string;
confinedToolNames?: readonly string[];
requiredToolNames?: readonly string[];
modelProvider?: string;
modelId?: string;
sessionKey: string;
}) => {
sandboxed: boolean;
workspaceAccess: "none" | "ro" | "rw";
confinementError?: string;
};
prepareWorkspaceAuthority: (params: {
config: OpenClawConfig;
agentId?: string;
confinedToolNames?: readonly string[];
requiredToolNames?: readonly string[];
modelProvider?: string;
modelId?: string;
sessionKey: string;
workspaceDir: string;
}) => Promise<{
sandboxed: boolean;
workspaceAccess: "none" | "ro" | "rw";
confinementError?: string;
}>;
};
worktrees: {
resolveCheckoutRoot: (params: {
path: string;
}) => Promise<string | undefined>;
hasSelfContainedCheckoutMetadata?: (params: {
path: string;
}) => Promise<boolean>;
create: (params: {
repoRoot: string;
name: string;
baseRef?: string;
ownerKind: "workboard";
ownerId: string;
}) => Promise<PluginManagedWorktree>;
release: (params: {
path: string;
}) => Promise<void>;
removeIfLossless: (params: {
path: string;
ownerKind: "workboard";
ownerId: string;
}) => Promise<boolean>;
};
channel: PluginRuntimeChannel;
};
//#endregion
//#region src/plugin-sdk/plugin-entry.d.ts
/** Options for a plugin entry that registers providers, tools, commands, or services. */
type DefinePluginEntryOptions = {
id: string;
name: string;
description: string;
/**
* @deprecated Declare exclusive plugin kind in `openclaw.plugin.json` via
* manifest `kind`. Runtime-entry `kind` remains only as a compatibility
* fallback for older plugins.
*/
kind?: OpenClawPluginDefinition["kind"];
configSchema?: OpenClawPluginConfigSchema | (() => OpenClawPluginConfigSchema);
reload?: OpenClawPluginDefinition["reload"];
nodeHostCommands?: OpenClawPluginDefinition["nodeHostCommands"];
securityAuditCollectors?: OpenClawPluginDefinition["securityAuditCollectors"];
register: NonNullable<OpenClawPluginDefinition["register"]>;
};
/** Normalized object shape that OpenClaw loads from a plugin entry module. */
type DefinedPluginEntry = Omit<DefinePluginEntryOptions, "configSchema"> & {
configSchema: OpenClawPluginConfigSchema;
};
/**
* Canonical entry helper for non-channel plugins.
*
* Use this for provider, tool, command, service, memory, and context-engine
* plugins. Channel plugins should use `defineChannelPluginEntry(...)` from
* `openclaw/plugin-sdk/core` so they inherit the channel capability wiring.
*
* @experimental Pin and test OpenClaw host versions; existing compatibility windows still apply.
*/
declare function definePluginEntry({ id, name, description, kind, configSchema, reload, nodeHostCommands, securityAuditCollectors, register }: DefinePluginEntryOptions): DefinedPluginEntry;
//#endregion
export { MusicGenerationProvider as a, AnyAgentTool as c, ChannelPlugin$3 as d, ChannelGatewayContext as f, ModelProviderDeclarationConfig as g, OpenClawConfig as h, SpeechProviderPlugin$1 as i, getA2aChannelRuntime as l, ChannelConfigSchema as m, PluginRuntime as n, ImageGenerationProvider as o, ChannelOutboundAdapter as p, OpenClawPluginApi as r, PluginLogger as s, definePluginEntry as t, setA2aChannelRuntime as u };