Files
openclaw/src/plugins/plugin-registration.types.ts
Peter Steinberger edecdbd05e refactor(config): config-surface reduction tranche 3 — product consolidations (review request) (#111527)
* refactor(config): consolidate media model lists

* refactor(config): unify memory configuration

* refactor(config): consolidate TTS ownership

* refactor(config): move typing policy to agents

* refactor(config): retire product-level config surfaces

* refactor(config): share scoped tool policy type

* chore(config): refresh generated baselines

* fix(config): honor agent typing overrides

* fix(config): migrate sibling config consumers

* refactor(infra): keep base64url decoder private

* fix(config): strip invalid legacy TTS values

* chore(config): refresh rebased baseline hash

* fix(doctor): route legacy messages.tts.realtime voice to talk during tts move

* refactor(config): polish final layout names

* refactor(config): freeze retired tuning defaults

* feat(config): add fast mode default symmetry

* refactor(config): key agent entries by id

* docs(config): update final layout reference

* test(config): cover final layout migrations

* chore(config): refresh final layout baselines

* fix(config): align final layout runtime readers

* fix(config): align remaining readers

* fix(config): stabilize final layout migrations

* fix(config): finalize config projection proof

* fix(config): address final layout review

* docs(release): preserve historical config names

* fix(config): complete keyed agent migration

* fix(config): close final migration gaps

* fix(config): finish full-branch review

* fix(config): complete runtime secret detection

* fix(config): close final review findings

* fix(config): finish canonical docs and heartbeat migration

* fix(config): integrate latest main after rebase

* refactor(env): isolate test-only controls

* refactor(env): isolate build and development controls

* refactor(env): collapse process identity indirection

* refactor(env): remove duplicate config and temp aliases

* docs(env): define the operator-facing allowlist

* ci(env): ratchet production variable count

* fix(env): remove stale provider helper import

* fix(env): make ratchet sorting explicit

* test(env): keep test seam in dead-code audit

* test(env): cover ratchet growth and boundary; document surface budgets

* docs(config): document tier-eval consolidations

* docs(config): clarify speech preference ownership

* test(memory): align retired tuning fixtures

* refactor(memory): freeze engine heuristics

* refactor(config): apply tier-eval tranche

* refactor(tts): move persona shaping to providers

* refactor(compaction): move prompt policy to providers

* test(config): align hookified prompt fixtures

* chore(deadcode): classify test-only exports

* chore(github): remove unused spawn helper

* chore(deadcode): classify queue diagnostics

* chore(deadcode): remove unused lane snapshot export

* chore(plugin-sdk): ratchet consolidated surface

* fix(config): integrate latest main after rebase
2026-07-21 20:28:43 -07:00

300 lines
8.9 KiB
TypeScript

import type { IncomingMessage, ServerResponse } from "node:http";
import type { Duplex } from "node:stream";
import type { Command } from "commander";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type {
DiagnosticEventPrivateData,
DiagnosticEventInput,
DiagnosticEventMetadata,
DiagnosticEventPayload,
} from "../infra/diagnostic-events.js";
import type { SecurityAuditFinding } from "../security/audit.types.js";
import type { PluginLogger } from "./logger-types.js";
type ChannelPlugin = import("../channels/plugins/types.plugin.js").ChannelPlugin;
type PluginInteractiveHandlerResult = {
handled?: boolean;
} | void;
export type PluginInteractiveRegistration<
TContext = unknown,
TChannel extends string = string,
TResult = PluginInteractiveHandlerResult,
> = {
channel: TChannel;
namespace: string;
handler: (ctx: TContext) => Promise<TResult> | TResult;
};
export type PluginInteractiveHandlerRegistration = PluginInteractiveRegistration;
export type OpenClawPluginHttpRouteAuth = "gateway" | "plugin";
export type OpenClawPluginHttpRouteMatch = "exact" | "prefix";
export type OpenClawPluginGatewayRuntimeScopeSurface = "write-default" | "trusted-operator";
export type OpenClawPluginHttpRouteHandler = (
req: IncomingMessage,
res: ServerResponse,
) => Promise<boolean | void> | boolean | void;
export type OpenClawPluginHttpRouteUpgradeHandler = (
req: IncomingMessage,
socket: Duplex,
head: Buffer,
) => Promise<boolean | void> | boolean | void;
export type OpenClawPluginHttpRouteParams = {
path: string;
handler: OpenClawPluginHttpRouteHandler;
handleUpgrade?: OpenClawPluginHttpRouteUpgradeHandler;
auth: OpenClawPluginHttpRouteAuth;
match?: OpenClawPluginHttpRouteMatch;
gatewayRuntimeScopeSurface?: OpenClawPluginGatewayRuntimeScopeSurface;
nodeCapability?: {
surface: string;
ttlMs?: number;
};
replaceExisting?: boolean;
};
export type OpenClawPluginHostedMediaResolver = (
mediaUrl: string,
) => string | null | undefined | Promise<string | null | undefined>;
export 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;
};
export type OpenClawPluginCliRegistrar = (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.
*/
export type OpenClawPluginCliCommandDescriptor = {
name: string;
description: string;
hasSubcommands: boolean;
};
export 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[];
};
export type OpenClawPluginReloadRegistration = {
restartPrefixes?: string[];
hotPrefixes?: string[];
noopPrefixes?: string[];
};
export type {
OpenClawPluginNodeHostCommand,
OpenClawPluginNodeHostCommandAvailabilityContext,
OpenClawPluginNodeHostCommandIo,
} from "./types.node-host.js";
export 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;
severity?: "info" | "warning" | "critical";
toolName?: string;
toolCallId?: string;
agentId?: string;
sessionKey?: string;
timeoutMs?: number;
}) => Promise<{
id?: string;
decision?: OpenClawPluginNodeInvokeApprovalDecision | null;
}>;
};
export 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;
approvals?: OpenClawPluginNodeInvokePolicyApprovalRuntime;
invokeNode: (input?: {
params?: unknown;
timeoutMs?: number;
idempotencyKey?: string;
}) => Promise<OpenClawPluginNodeInvokeTransportResult>;
};
export type OpenClawPluginNodeInvokePolicyResult =
| {
ok: true;
payload?: unknown;
payloadJSON?: string | null;
}
| {
ok: false;
message: string;
code?: string;
details?: Record<string, unknown>;
unavailable?: boolean;
};
export 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;
/**
* iOS foreground-restricted commands should be queued for foreground delivery
* when an iOS node reports BACKGROUND_UNAVAILABLE.
*/
foregroundRestrictedOnIos?: boolean;
handle: (
ctx: OpenClawPluginNodeInvokePolicyContext,
) => Promise<OpenClawPluginNodeInvokePolicyResult> | OpenClawPluginNodeInvokePolicyResult;
};
export type OpenClawPluginSecurityAuditContext = {
config: OpenClawConfig;
sourceConfig: OpenClawConfig;
env: NodeJS.ProcessEnv;
stateDir: string;
configPath: string;
};
export type OpenClawPluginSecurityAuditCollector = (
ctx: OpenClawPluginSecurityAuditContext,
) => SecurityAuditFinding[] | Promise<SecurityAuditFinding[]>;
export type OpenClawGatewayDiscoveryAdvertiseContext = {
machineDisplayName: string;
gatewayPort: number;
gatewayTlsEnabled: boolean;
gatewayTlsFingerprintSha256?: string;
gatewayDirectReachable: boolean;
canvasPort?: number;
tailnetDns?: string;
sshPort?: number;
cliPath?: string;
minimal: boolean;
};
export type OpenClawGatewayDiscoveryService = {
id: string;
advertise: (
ctx: OpenClawGatewayDiscoveryAdvertiseContext,
) => void | Promise<void | { stop?: () => void | Promise<void> }>;
};
/** Context passed to long-lived plugin services. */
export type OpenClawPluginServiceContext = {
config: OpenClawConfig;
workspaceDir?: string;
stateDir: string;
logger: PluginLogger;
gatewayEvents?: import("./gateway-events.js").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,
) => () => void;
};
};
/** Background service registered by a plugin during `register(api)`. */
export type OpenClawPluginService = {
id: string;
start: (ctx: OpenClawPluginServiceContext) => void | Promise<void>;
stop?: (ctx: OpenClawPluginServiceContext) => void | Promise<void>;
};
export type OpenClawPluginChannelRegistration = {
plugin: ChannelPlugin;
};
/**
* 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.
*/
export type PluginRegistrationMode =
| "full"
| "discovery"
| "tool-discovery"
| "setup-only"
| "setup-runtime"
| "cli-metadata";