diff --git a/src/agents/agent-tool-definition-adapter.after-tool-call.test.ts b/src/agents/agent-tool-definition-adapter.after-tool-call.test.ts index 2d5c9db16153..e250b66f7b2d 100644 --- a/src/agents/agent-tool-definition-adapter.after-tool-call.test.ts +++ b/src/agents/agent-tool-definition-adapter.after-tool-call.test.ts @@ -1,3 +1,8 @@ +/** + * Regression tests for adapter interaction with after_tool_call hooks. + * Ensures embedded run subscription handling remains the single after-hook + * execution path. + */ import type { AgentTool } from "openclaw/plugin-sdk/agent-core"; import { Type } from "typebox"; import { beforeEach, describe, expect, it, vi } from "vitest"; diff --git a/src/agents/agent-tool-definition-adapter.logging.test.ts b/src/agents/agent-tool-definition-adapter.logging.test.ts index 646865942ef9..48881768b2c6 100644 --- a/src/agents/agent-tool-definition-adapter.logging.test.ts +++ b/src/agents/agent-tool-definition-adapter.logging.test.ts @@ -1,3 +1,8 @@ +/** + * Logging tests for tool adapter failures. + * Verifies retryable parameter errors expose useful context while intentional + * hook blocks and exec secrets stay out of raw logs. + */ import type { AgentTool } from "openclaw/plugin-sdk/agent-core"; import { Type } from "typebox"; import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; diff --git a/src/agents/agent-tool-definition-adapter.test.ts b/src/agents/agent-tool-definition-adapter.test.ts index 21b3829e544a..761fbb044963 100644 --- a/src/agents/agent-tool-definition-adapter.test.ts +++ b/src/agents/agent-tool-definition-adapter.test.ts @@ -1,3 +1,8 @@ +/** + * Unit coverage for adapting runtime and client-hosted tools. + * Exercises result coercion, error wrapping, client delegation, and conflict + * detection at the ToolDefinition boundary. + */ import type { AgentTool } from "openclaw/plugin-sdk/agent-core"; import { Type } from "typebox"; import { describe, expect, it } from "vitest"; diff --git a/src/agents/agent-tool-definition-adapter.ts b/src/agents/agent-tool-definition-adapter.ts index 06d4599f724e..2fadc2bf414a 100644 --- a/src/agents/agent-tool-definition-adapter.ts +++ b/src/agents/agent-tool-definition-adapter.ts @@ -1,3 +1,8 @@ +/** + * Adapts runtime AgentTool objects into session ToolDefinition entries. + * Owns hook execution, client-tool delegation, result coercion, and safe + * logging for failed tool calls. + */ import { createHash } from "node:crypto"; import { logDebug, logError } from "../logger.js"; import { redactToolDetail } from "../logging/redact.js"; @@ -304,6 +309,7 @@ function finalizeToolParamsBeforeExecute(params: { export const CLIENT_TOOL_NAME_CONFLICT_PREFIX = "client tool name conflict:"; +/** Find client-hosted tool names that collide with runtime or sibling tools. */ export function findClientToolNameConflicts(params: { tools: ClientToolDefinition[]; existingToolNames?: Iterable; @@ -338,14 +344,17 @@ export function findClientToolNameConflicts(params: { return Array.from(conflicts); } +/** Build a recognizable error for rejecting conflicting client tool names. */ export function createClientToolNameConflictError(conflicts: string[]): Error { return new Error(`${CLIENT_TOOL_NAME_CONFLICT_PREFIX} ${conflicts.join(", ")}`); } +/** Detect client tool conflict errors without depending on object identity. */ export function isClientToolNameConflictError(err: unknown): err is Error { return err instanceof Error && err.message.startsWith(CLIENT_TOOL_NAME_CONFLICT_PREFIX); } +/** Convert executable agent tools into session definitions with hook handling. */ export function toToolDefinitions( tools: AnyAgentTool[], hookContext?: HookContext, @@ -477,8 +486,7 @@ function coerceParamsRecord(value: unknown): Record { return {}; } -// Convert client tools (OpenResponses hosted tools) to ToolDefinition format -// These tools are intercepted to return a "pending" result instead of executing +/** Convert client-hosted tools into pending session definitions. */ export function toClientToolDefinitions( tools: ClientToolDefinition[], onClientToolCall?: ClientToolCallRecorder, diff --git a/src/agents/agent-tool-handler-state.test-helpers.ts b/src/agents/agent-tool-handler-state.test-helpers.ts index 31b2dfa75b05..0be91b1756b8 100644 --- a/src/agents/agent-tool-handler-state.test-helpers.ts +++ b/src/agents/agent-tool-handler-state.test-helpers.ts @@ -1,6 +1,10 @@ +/** + * Fixtures for embedded agent tool-handler state tests. + * Keeps large mutable handler state construction centralized so assertions can + * focus on the field under test. + */ import { createEmbeddedRunReplayState } from "./embedded-agent-runner/replay-state.js"; -// Shared fixture for tests that exercise embedded agent tool handler state. /** Build the minimal mutable state object expected by tool handler tests. */ export function createBaseToolHandlerState() { return { diff --git a/src/agents/agent-tools-parameter-schema.ts b/src/agents/agent-tools-parameter-schema.ts index 038b4f0a9d91..1815b3e155e9 100644 --- a/src/agents/agent-tools-parameter-schema.ts +++ b/src/agents/agent-tools-parameter-schema.ts @@ -1,3 +1,8 @@ +/** + * Normalizes model-facing tool parameter schemas across provider quirks. + * Handles local JSON Schema refs, OpenAPI nullable syntax, top-level unions, + * and provider-specific unsupported keyword stripping. + */ import { isRecord as isSchemaRecord } from "@openclaw/normalization-core/record-coerce"; import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce"; import { uniqueValues } from "@openclaw/normalization-core/string-normalization"; @@ -589,6 +594,7 @@ function inlineLocalSchemaRefsWithDefs( return result; } +/** Inline local $ref pointers so providers receive self-contained tool schemas. */ export function inlineLocalToolSchemaRefs(schema: unknown): TSchema { if (!schema || typeof schema !== "object") { return schema as TSchema; @@ -881,6 +887,7 @@ function normalizeToolParameterSchemaUncached( return applyProviderCleaning(flattenedSchema); } +/** Return a provider-compatible JSON schema for a model-facing tool. */ export function normalizeToolParameterSchema( schema: unknown, options?: ToolParameterSchemaOptions, diff --git a/src/agents/agent-tools.deferred-followup-guidance.test.ts b/src/agents/agent-tools.deferred-followup-guidance.test.ts index 60ccdb5e9fd7..baac2889d512 100644 --- a/src/agents/agent-tools.deferred-followup-guidance.test.ts +++ b/src/agents/agent-tools.deferred-followup-guidance.test.ts @@ -1,3 +1,7 @@ +/** + * Tests cron-aware deferred follow-up guidance in exec/process descriptions. + * Protects the model-facing text selected after tool filtering. + */ import { describe, expect, it } from "vitest"; import { applyDeferredFollowupToolDescriptions } from "./agent-tools.deferred-followup.js"; import type { AnyAgentTool } from "./agent-tools.types.js"; diff --git a/src/agents/agent-tools.deferred-followup.ts b/src/agents/agent-tools.deferred-followup.ts index e17e0a8b30f6..77f3dbda7a42 100644 --- a/src/agents/agent-tools.deferred-followup.ts +++ b/src/agents/agent-tools.deferred-followup.ts @@ -1,8 +1,11 @@ +/** + * Adjusts exec/process tool descriptions for long-running follow-up behavior. + * Cron-aware runs can point models at scheduled follow-ups; cronless runs keep + * guidance constrained to process polling and wake handling. + */ import type { AnyAgentTool } from "./agent-tools.types.js"; import { describeExecTool, describeProcessTool } from "./bash-tools.descriptions.js"; -// Updates exec/process tool descriptions with deferred-followup guidance based -// on the tools available in the current run. /** Return tools with exec/process descriptions adjusted for cron availability. */ export function applyDeferredFollowupToolDescriptions( tools: AnyAgentTool[], diff --git a/src/agents/agent-tools.message-provider-policy.test.ts b/src/agents/agent-tools.message-provider-policy.test.ts index 3ccb21dfa591..265b910e52ab 100644 --- a/src/agents/agent-tools.message-provider-policy.test.ts +++ b/src/agents/agent-tools.message-provider-policy.test.ts @@ -1,3 +1,8 @@ +/** + * Tests message-provider tool filtering. + * Voice-like transports should not expose text-to-speech when that surface is + * unsafe or redundant for the active channel. + */ import { describe, expect, it } from "vitest"; import { filterToolNamesByMessageProvider } from "./agent-tools.message-provider-policy.js"; diff --git a/src/agents/agent-tools.message-provider-policy.ts b/src/agents/agent-tools.message-provider-policy.ts index 03849528dea2..5be579475b99 100644 --- a/src/agents/agent-tools.message-provider-policy.ts +++ b/src/agents/agent-tools.message-provider-policy.ts @@ -1,8 +1,10 @@ +/** + * Message-provider tool filtering. + * Channels can restrict tool names after runtime assembly when the active + * transport cannot safely render or execute a class of tools. + */ import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce"; -// Message providers can narrow the tool surface when a channel cannot safely -// render or execute a tool class. The policy is name-based because channel -// delivery happens after tools are already assembled. const TOOL_DENY_BY_MESSAGE_PROVIDER: Readonly> = { "discord-voice": ["tts"], voice: ["tts"], diff --git a/src/agents/agent-tools.params.test.ts b/src/agents/agent-tools.params.test.ts index 1ff887473e67..4928d9619f3f 100644 --- a/src/agents/agent-tools.params.test.ts +++ b/src/agents/agent-tools.params.test.ts @@ -1,3 +1,7 @@ +/** + * Tests required parameter validation for model-facing tools. + * Covers retry guidance and path-only XML suffix cleanup for file operations. + */ import { describe, expect, it, vi } from "vitest"; import { assertRequiredParams, diff --git a/src/agents/agent-tools.params.ts b/src/agents/agent-tools.params.ts index 8cf4f5f14145..52af799e3cbb 100644 --- a/src/agents/agent-tools.params.ts +++ b/src/agents/agent-tools.params.ts @@ -1,7 +1,10 @@ +/** + * Shared validation for model-supplied tool parameters. + * Converts malformed file-tool arguments into retryable errors and fixes the + * specific XML suffix corruption seen in path arguments. + */ import type { AnyAgentTool } from "./agent-tools.types.js"; -// Shared tool parameter validation helpers for file-edit style tools. They turn -// model-facing malformed arguments into actionable retry guidance. export type RequiredParamGroup = { keys: readonly string[]; allowEmpty?: boolean; @@ -84,6 +87,7 @@ function hasValidEditReplacements(record: Record): boolean { ); } +/** Required parameter groups for file-style tools that need retry guidance. */ export const REQUIRED_PARAM_GROUPS = { read: [{ keys: ["path"], label: "path" }], write: [ @@ -140,6 +144,7 @@ function resolveMalformedXmlArgValuePathKeys( return [...keys]; } +/** Throw actionable retry guidance when required tool params are missing. */ export function assertRequiredParams( record: Record | undefined, groups: readonly RequiredParamGroup[], diff --git a/src/agents/agent-tools.policy.test.ts b/src/agents/agent-tools.policy.test.ts index 31f28f367874..9aba78981e61 100644 --- a/src/agents/agent-tools.policy.test.ts +++ b/src/agents/agent-tools.policy.test.ts @@ -1,3 +1,8 @@ +/** + * Tests layered tool policy resolution. + * Covers wildcard matching, sub-agent inheritance, provider overrides, and + * trusted group context checks. + */ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; diff --git a/src/agents/agent-tools.policy.ts b/src/agents/agent-tools.policy.ts index 578c6256520e..4a4b5749ed71 100644 --- a/src/agents/agent-tools.policy.ts +++ b/src/agents/agent-tools.policy.ts @@ -1,3 +1,8 @@ +/** + * Resolves sandbox tool policies for agents, providers, sub-agents, and group + * sessions. Keeps runtime tool filtering tied to canonical config, session + * provenance, and inherited sub-agent capabilities. + */ import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id"; import { normalizeLowercaseStringOrEmpty, @@ -97,6 +102,7 @@ function mergeConfiguredSubagentAllow( return allow && alsoAllow ? uniqueStrings([...allow, ...alsoAllow]) : allow; } +/** Resolve depth-based default deny rules plus configured sub-agent overrides. */ export function resolveSubagentToolPolicy(cfg?: OpenClawConfig, depth?: number): SandboxToolPolicy { const configured = cfg?.tools?.subagents?.tools; const maxSpawnDepth = @@ -116,6 +122,7 @@ export function resolveSubagentToolPolicy(cfg?: OpenClawConfig, depth?: number): return { allow: mergedAllow, deny }; } +/** Resolve sub-agent tool policy from stored session capabilities. */ export function resolveSubagentToolPolicyForSession( cfg: OpenClawConfig | undefined, sessionKey: string, @@ -147,6 +154,7 @@ export function resolveSubagentToolPolicyForSession( return { allow: mergedAllow, deny }; } +/** Resolve the tool policy inherited from a parent sub-agent session. */ export function resolveInheritedToolPolicyForSession( cfg: OpenClawConfig | undefined, sessionKey: string | undefined | null, @@ -171,6 +179,7 @@ export function resolveInheritedToolPolicyForSession( }; } +/** Filter runtime tools by sandbox allow/deny policy. */ export function filterToolsByPolicy(tools: AnyAgentTool[], policy?: SandboxToolPolicy) { if (!policy) { return tools; @@ -339,6 +348,7 @@ function resolveTrustedGroupIdFromContexts(params: { return { groupId: null, dropped: true }; } +/** Validate caller-supplied group ids against server-derived session context. */ export function resolveTrustedGroupId(params: { groupId?: string | null; sessionKey?: string | null; @@ -354,6 +364,7 @@ export function resolveTrustedGroupId(params: { }); } +/** Resolve model/provider-scoped tool policy from canonical provider keys. */ export function resolveProviderToolPolicy(params: { byProvider?: Record; modelProvider?: string; @@ -435,6 +446,7 @@ function formatToolListForWarning(toolNames: string[]): string { return toolNames.map((toolName) => `"${toolName}"`).join(", "); } +/** Resolve the layered global, provider, agent, and profile tool policies. */ export function resolveEffectiveToolPolicy(params: { config?: OpenClawConfig; sessionKey?: string; @@ -523,6 +535,7 @@ export function resolveEffectiveToolPolicy(params: { }; } +/** Resolve group-scoped tool policy after validating session provenance. */ export function resolveGroupToolPolicy(params: { config?: OpenClawConfig; sessionKey?: string;