docs: document schema media planning helpers

This commit is contained in:
Peter Steinberger
2026-06-04 01:04:21 -04:00
parent 79f6c5a8ad
commit ce1ef04efe
4 changed files with 37 additions and 0 deletions
@@ -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<OpenClawConfig["models"]>;
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<string, unknown>)
: undefined;
// Merge marker headers over normalized headers so auth metadata remains managed while
// unrelated provider headers survive normalization.
const nextHeaders = {
...(currentHeaders as Record<string, NonNullable<ProviderConfig["headers"]>[string]>),
};
+13
View File
@@ -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<T>(
schema: T,
strict: boolean,
@@ -153,6 +163,7 @@ export function normalizeOpenAIStrictToolParameters<T>(
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,
@@ -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>
): string[] | undefined {
@@ -99,6 +104,7 @@ function mergeBuiltInFactoryAllowlist(...lists: Array<string[] | undefined>): 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,
+6
View File
@@ -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 {