From ce1ef04efe1233259beb2f3bc94284e72a30a68d Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 4 Jun 2026 01:04:21 -0400 Subject: [PATCH] docs: document schema media planning helpers --- .../models-config.providers.source-managed.ts | 9 +++++++++ src/agents/openai-tool-schema.ts | 13 +++++++++++++ src/agents/openclaw-tools.media-factory-plan.ts | 9 +++++++++ src/agents/prompt-surface.ts | 6 ++++++ 4 files changed, 37 insertions(+) diff --git a/src/agents/models-config.providers.source-managed.ts b/src/agents/models-config.providers.source-managed.ts index 69a085c0346a..ff63131412e7 100644 --- a/src/agents/models-config.providers.source-managed.ts +++ b/src/agents/models-config.providers.source-managed.ts @@ -8,6 +8,12 @@ import { } from "./model-auth-markers.js"; import type { ProviderConfig, SecretDefaults } from "./models-config.providers.secrets.js"; +/** + * Reapplies source-managed secret markers to normalized provider config. + * + * This keeps runtime snapshots from materializing secret refs as plain values after config + * normalization rewrites provider entries. + */ type ModelsConfig = NonNullable; function normalizeSourceProviderLookup( @@ -70,6 +76,7 @@ function resolveSourceManagedHeaderMarkers(params: { return markers; } +/** Preserves source-managed apiKey/header markers from the original provider config. */ export function enforceSourceManagedProviderSecrets(params: { providers: ModelsConfig["providers"]; sourceProviders: ModelsConfig["providers"] | undefined; @@ -120,6 +127,8 @@ export function enforceSourceManagedProviderSecrets(params: { const currentHeaders = isRecord(nextProvider.headers) ? (nextProvider.headers as Record) : undefined; + // Merge marker headers over normalized headers so auth metadata remains managed while + // unrelated provider headers survive normalization. const nextHeaders = { ...(currentHeaders as Record[string]>), }; diff --git a/src/agents/openai-tool-schema.ts b/src/agents/openai-tool-schema.ts index fde537c9dad0..e8a42bef480f 100644 --- a/src/agents/openai-tool-schema.ts +++ b/src/agents/openai-tool-schema.ts @@ -2,6 +2,12 @@ import type { ModelCompatConfig } from "../config/types.models.js"; import { shouldOmitEmptyArrayItems } from "../plugins/provider-model-compat.js"; import { normalizeToolParameterSchema } from "./agent-tools-parameter-schema.js"; +/** + * OpenAI strict-tool-schema normalization and diagnostics. + * + * Strict schemas need all object properties required and `additionalProperties: false`; model + * compatibility settings can also remove unsupported schema constructs before strict checks run. + */ type ToolSchemaCompatInput = { unsupportedToolSchemaKeywords?: unknown; omitEmptyArrayItems?: unknown; @@ -65,6 +71,7 @@ export function clearOpenAIToolSchemaCacheForTest(): void { strictOpenAISchemaCache = new WeakMap(); } +/** Normalizes a tool parameter schema into the OpenAI strict JSON-schema subset. */ export function normalizeStrictOpenAIJsonSchema( schema: unknown, modelCompat?: ToolSchemaCompatInput | null, @@ -86,6 +93,8 @@ export function normalizeStrictOpenAIJsonSchema( return rememberStrictOpenAISchema( schemaInput, cacheKey, + // Cache by input object and compatibility key so repeated inventory generation preserves object + // identity without mixing schemas normalized for different provider limitations. normalizeStrictOpenAIJsonSchemaRecursive( normalizeToolParameterSchema(schemaInput, { modelCompat: resolveToolSchemaModelCompat(modelCompat), @@ -141,6 +150,7 @@ function normalizeStrictOpenAIJsonSchemaRecursive(schema: unknown, depth: number return changed ? normalized : schema; } +/** Normalizes tool parameters using strict OpenAI rules only when strict mode is active. */ export function normalizeOpenAIStrictToolParameters( schema: T, strict: boolean, @@ -153,6 +163,7 @@ export function normalizeOpenAIStrictToolParameters( return normalizeStrictOpenAIJsonSchema(schema, toolSchemaCompat) as T; } +/** Returns whether a schema already satisfies OpenAI strict tool-schema constraints. */ export function isStrictOpenAIJsonSchemaCompatible(schema: unknown): boolean { return isStrictOpenAIJsonSchemaCompatibleRecursive(normalizeStrictOpenAIJsonSchema(schema)); } @@ -163,6 +174,7 @@ type OpenAIStrictToolSchemaDiagnostic = { violations: string[]; }; +/** Returns strict-schema violation paths for each incompatible tool definition. */ export function findOpenAIStrictToolSchemaDiagnostics( tools: readonly ToolWithParameters[], ): OpenAIStrictToolSchemaDiagnostic[] { @@ -297,6 +309,7 @@ function findStrictOpenAIJsonSchemaViolations(schema: unknown, path: string): st return violations; } +/** Resolves the strict flag to advertise for a tool inventory after compatibility checks. */ export function resolveOpenAIStrictToolFlagForInventory( tools: readonly ToolWithParameters[], strict: boolean | null | undefined, diff --git a/src/agents/openclaw-tools.media-factory-plan.ts b/src/agents/openclaw-tools.media-factory-plan.ts index 88a30c537c1c..00c5acc3d98e 100644 --- a/src/agents/openclaw-tools.media-factory-plan.ts +++ b/src/agents/openclaw-tools.media-factory-plan.ts @@ -16,6 +16,9 @@ import { loadCapabilityMetadataSnapshot, } from "./tools/manifest-capability-availability.js"; +/** + * Plans optional media-tool factory registration from config, policy, capabilities, and auth. + */ export type OptionalMediaToolFactoryPlan = { imageGenerate: boolean; videoGenerate: boolean; @@ -66,6 +69,7 @@ function isToolAllowedByFactoryPolicy(params: { }); } +/** Returns true only when an allowlist explicitly enables the requested tool. */ export function isToolExplicitlyAllowedByFactoryPolicy(params: { toolName: string; allowlist?: string[]; @@ -77,6 +81,7 @@ export function isToolExplicitlyAllowedByFactoryPolicy(params: { return isToolAllowedByFactoryPolicy(params); } +/** Merges factory policy lists while preserving stable unique entries. */ export function mergeFactoryPolicyList( ...lists: Array ): string[] | undefined { @@ -99,6 +104,7 @@ function mergeBuiltInFactoryAllowlist(...lists: Array): st return uniqueStrings(["*", ...withoutDefaultPluginMarker]); } +/** Returns whether the image understanding tool can be constructed for this agent context. */ export function resolveImageToolFactoryAvailable(params: { config?: OpenClawConfig; agentDir?: string; @@ -164,6 +170,7 @@ function hasConfiguredVisionModelAuthSignal(params: { return false; } +/** Resolves which optional media tools should be created for the current tool factory call. */ export function resolveOptionalMediaToolFactoryPlan(params: { config?: OpenClawConfig; workspaceDir?: string; @@ -202,6 +209,8 @@ export function resolveOptionalMediaToolFactoryPlan(params: { const explicitMusicGeneration = hasExplicitToolModelConfig(defaults?.musicGenerationModel); const explicitPdf = hasExplicitPdfModelConfig(params.config); if (params.config?.plugins?.enabled === false) { + // Optional media tools are plugin/capability backed. Disabling plugins shuts them off even when + // stale defaults or env availability would otherwise appear to make a tool available. return { imageGenerate: false, videoGenerate: false, diff --git a/src/agents/prompt-surface.ts b/src/agents/prompt-surface.ts index 84df3ce0154a..42d29cffcfd9 100644 --- a/src/agents/prompt-surface.ts +++ b/src/agents/prompt-surface.ts @@ -2,6 +2,10 @@ import { isOpenClawMainPromptSurface } from "../plugins/agent-prompt-surface-kin import type { AgentPromptSurfaceKind } from "../plugins/types.js"; import { isAcpSessionKey, isSubagentSessionKey } from "../routing/session-key.js"; +/** + * Prompt-surface helpers for deciding which OpenClaw tool guidance belongs in a session prompt. + */ +/** Builds fallback tool guidance when a runtime cannot render the structured tool list. */ export function buildOpenClawToolFallbackText(params: { surface: AgentPromptSurfaceKind; execToolName: string; @@ -33,6 +37,7 @@ export function buildOpenClawToolFallbackText(params: { return "No OpenClaw tool list is injected for this runtime prompt surface. Use only tools exposed directly by the active backend."; } +/** Returns whether the main OpenClaw prompt should include workflow hints around the tool list. */ export function shouldRenderOpenClawToolWorkflowHints(params: { surface: AgentPromptSurfaceKind; hasToolList: boolean; @@ -40,6 +45,7 @@ export function shouldRenderOpenClawToolWorkflowHints(params: { return isOpenClawMainPromptSurface(params.surface); } +/** Maps a session key to the prompt surface used for tool guidance and runtime behavior. */ export function resolveAgentPromptSurfaceForSessionKey( sessionKey?: string, ): AgentPromptSurfaceKind {