Files
openclaw/src/plugins/command-registry-state.ts
pashpashpash 6ce1058296 Wire diagnostics through the core chat command (#72936)
* feat: wire codex diagnostics feedback

* fix: harden codex diagnostics hints

* fix: neutralize codex diagnostics output

* fix: tighten codex diagnostics safeguards

* fix: bound codex diagnostics feedback output

* fix: tighten codex diagnostics throttling

* fix: confirm codex diagnostics uploads

* docs: clarify codex diagnostics add-on

* fix: route diagnostics through core command

* fix: tighten diagnostics authorization

* fix: pin diagnostics to bundled codex command

* fix: limit owner status in plugin commands

* fix: scope diagnostics confirmations

* fix: scope codex diagnostics cooldowns

* fix: harden codex diagnostics ownership scopes

* fix: harden diagnostics command trust and display

* fix: keep diagnostics command trust internal

* fix: clarify diagnostics exec boundary

* fix: consume codex diagnostics confirmations atomically

* test: include codex diagnostics binding metadata

* test: use string codex binding timestamps

* fix: keep reserved command trust host-only

* fix: harden diagnostics trust and resume hints

* wire diagnostics through exec approval

* fix: keep diagnostics tests aligned with bundled root trust

* fix telegram diagnostics owner auth

* route trajectory exports through exec approval

* fix trajectory exec command encoding

* fix telegram group owner auth

* fix export trajectory approval hardening

* fix pairing command owner bootstrap

* fix telegram owner exec approvals

* fix: make diagnostics approval flow pasteable

* fix: route native sensitive command followups

* fix: invoke diagnostics exports with current cli

* fix: refresh exec approval protocol models

* fix: list codex diagnostics from thread bindings

* fix: fold codex diagnostics into exec approval

* fix: preserve diagnostics approval line breaks

* docs: clarify diagnostics codex workflow
2026-04-29 07:40:37 +09:00

87 lines
2.5 KiB
TypeScript

import { resolveGlobalSingleton } from "../shared/global-singleton.js";
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
import type { OpenClawPluginCommandDefinition } from "./types.js";
export type RegisteredPluginCommand = OpenClawPluginCommandDefinition & {
pluginId: string;
pluginName?: string;
pluginRoot?: string;
};
type PluginCommandState = {
pluginCommands: Map<string, RegisteredPluginCommand>;
registryLocked: boolean;
};
const PLUGIN_COMMAND_STATE_KEY = Symbol.for("openclaw.pluginCommandsState");
const getState = () =>
resolveGlobalSingleton<PluginCommandState>(PLUGIN_COMMAND_STATE_KEY, () => ({
pluginCommands: new Map<string, RegisteredPluginCommand>(),
registryLocked: false,
}));
const getPluginCommandMap = () => getState().pluginCommands;
export const pluginCommands = new Proxy(new Map<string, RegisteredPluginCommand>(), {
get(_target, property) {
const value = Reflect.get(getPluginCommandMap(), property, getPluginCommandMap());
return typeof value === "function" ? value.bind(getPluginCommandMap()) : value;
},
});
export function isPluginCommandRegistryLocked(): boolean {
return getState().registryLocked;
}
export function setPluginCommandRegistryLocked(locked: boolean): void {
getState().registryLocked = locked;
}
export function clearPluginCommands(): void {
pluginCommands.clear();
}
export function clearPluginCommandsForPlugin(pluginId: string): void {
for (const [key, cmd] of pluginCommands.entries()) {
if (cmd.pluginId === pluginId) {
pluginCommands.delete(key);
}
}
}
export function isTrustedReservedCommandOwner(command: RegisteredPluginCommand): boolean {
return command.ownership === "reserved";
}
export function listRegisteredPluginCommands(): RegisteredPluginCommand[] {
return Array.from(pluginCommands.values());
}
export function listRegisteredPluginAgentPromptGuidance(): string[] {
const lines: string[] = [];
const seen = new Set<string>();
for (const command of pluginCommands.values()) {
for (const line of command.agentPromptGuidance ?? []) {
const trimmed = line.trim();
if (!trimmed || seen.has(trimmed)) {
continue;
}
seen.add(trimmed);
lines.push(trimmed);
}
}
return lines;
}
export function restorePluginCommands(commands: readonly RegisteredPluginCommand[]): void {
pluginCommands.clear();
for (const command of commands) {
const name = normalizeOptionalLowercaseString(command.name);
if (!name) {
continue;
}
pluginCommands.set(`/${name}`, command);
}
}