diff --git a/src/agents/tools/heartbeat-response-tool.test.ts b/src/agents/tools/heartbeat-response-tool.test.ts index eb244d91030f..db04635480e2 100644 --- a/src/agents/tools/heartbeat-response-tool.test.ts +++ b/src/agents/tools/heartbeat-response-tool.test.ts @@ -1,3 +1,5 @@ +// Heartbeat response tool tests cover the one-shot heartbeat contract and +// provider-portable schema shape. import { describe, expect, it } from "vitest"; import { HEARTBEAT_RESPONSE_TOOL_NAME } from "../../auto-reply/heartbeat-tool-response.js"; import { createHeartbeatResponseTool } from "./heartbeat-response-tool.js"; @@ -23,6 +25,8 @@ type HeartbeatResponseDetails = { describe("createHeartbeatResponseTool", () => { it("uses flat enum schemas for provider portability", () => { + // Some providers reject anyOf literal unions in tool schemas; flat enums are + // the portable contract for heartbeat status fields. const tool = createHeartbeatResponseTool(); const outcome = readSchemaProperty(tool.parameters, "outcome"); @@ -54,6 +58,8 @@ describe("createHeartbeatResponseTool", () => { }); it("rejects repeated heartbeat responses from the same tool instance", async () => { + // A heartbeat turn has one final outcome; accepting multiple writes would + // make notification delivery ambiguous. const tool = createHeartbeatResponseTool(); await tool.execute("call-1", { diff --git a/src/agents/tools/model-config.helpers.test.ts b/src/agents/tools/model-config.helpers.test.ts index 7e013db6509d..4e0c9c56b23d 100644 --- a/src/agents/tools/model-config.helpers.test.ts +++ b/src/agents/tools/model-config.helpers.test.ts @@ -1,3 +1,5 @@ +// Model config helper tests cover provider auth detection across config and +// stored agent auth profiles for reusable media tools. import { afterEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../../config/config.js"; import { hasProviderAuthForTool } from "./model-config.helpers.js"; @@ -24,6 +26,8 @@ describe("hasProviderAuthForTool", () => { }); it("keeps auth-store profiles as valid tool auth", () => { + // Tool-specific model selection should honor the same stored profile shape + // used by agent sessions, not only process env/config keys. expect( hasProviderAuthForTool({ provider: "hatchery", diff --git a/src/agents/tools/pdf-native-providers.test.ts b/src/agents/tools/pdf-native-providers.test.ts index 0663d9fe1ac2..10b7614d9b79 100644 --- a/src/agents/tools/pdf-native-providers.test.ts +++ b/src/agents/tools/pdf-native-providers.test.ts @@ -1,3 +1,5 @@ +// Native PDF provider tests cover direct Anthropic and Gemini request shapes, +// base URL handling, and bounded API error reporting. import { afterEach, describe, expect, it, vi } from "vitest"; import * as pdfNativeProviders from "./pdf-native-providers.js"; @@ -129,6 +131,8 @@ describe("native PDF provider API calls", () => { }); it("bounds large Anthropic API error bodies", async () => { + // Provider errors can contain large or sensitive payloads; surface a compact + // diagnostic and cancel the stream once the cap is reached. let canceled = false; const body = new ReadableStream({ start(controller) { @@ -205,6 +209,8 @@ describe("native PDF provider API calls", () => { }); it("geminiAnalyzePdf sends correct request shape", async () => { + // Gemini API keys belong in headers here, not query strings that are more + // likely to leak through logs and URL diagnostics. const fetchMock = mockFetchResponse({ ok: true, json: async () => ({ diff --git a/src/agents/tools/pdf-tool.helpers.test.ts b/src/agents/tools/pdf-tool.helpers.test.ts index dd45fcc6f8a7..c462b2de6a59 100644 --- a/src/agents/tools/pdf-tool.helpers.test.ts +++ b/src/agents/tools/pdf-tool.helpers.test.ts @@ -1,3 +1,5 @@ +// PDF tool helper tests cover page ranges, PDF input normalization, provider +// capability checks, and assistant text coercion. import { describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../../config/config.js"; @@ -87,6 +89,8 @@ describe("parsePageRange", () => { describe("providerSupportsNativePdf", () => { it("returns true for anthropic", () => { + // Native PDF support is derived from plugin metadata, not a hard-coded + // provider allowlist in the helper. expect(providerSupportsNativePdf("anthropic")).toBe(true); }); @@ -114,6 +118,8 @@ describe("pdf-tool.helpers", () => { }); it("resolvePdfInputs deduplicates pdf and pdfs entries", () => { + // `pdf` and `pdfs` are both public inputs; normalize them to one ordered + // list before any filesystem or provider work begins. expect( resolvePdfInputs({ pdf: " /tmp/nonexistent.pdf ", diff --git a/src/agents/tools/pdf-tool.model-config.test.ts b/src/agents/tools/pdf-tool.model-config.test.ts index 6bea72566dd6..0184812aa610 100644 --- a/src/agents/tools/pdf-tool.model-config.test.ts +++ b/src/agents/tools/pdf-tool.model-config.test.ts @@ -1,3 +1,5 @@ +// PDF model config tests cover provider precedence and fallback model selection +// for PDF understanding tools. import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../../config/config.js"; import { resolvePdfModelConfigForTool } from "./pdf-tool.model-config.js"; @@ -119,6 +121,8 @@ describe("resolvePdfModelConfigForTool", () => { }); it("uses configured MiniMax chat models for PDF text extraction fallback", () => { + // MiniMax VLM models do not provide the text extraction fallback contract; + // choose configured chat-capable models instead. vi.stubEnv("MINIMAX_API_KEY", "minimax-test"); const cfg = { ...withDefaultModel("openai/gpt-5.4"), @@ -149,6 +153,8 @@ describe("resolvePdfModelConfigForTool", () => { }); it("preserves generic image provider precedence when the default model is not MiniMax", () => { + // MiniMax remains a fallback for PDF text extraction, but should not jump + // ahead of an authenticated generic image/PDF provider. vi.stubEnv("OPENAI_API_KEY", "openai-test"); vi.stubEnv("MINIMAX_API_KEY", "minimax-test"); const cfg = { @@ -174,7 +180,7 @@ describe("resolvePdfModelConfigForTool", () => { } as OpenClawConfig; expect(resolvePdfModelConfigForTool({ cfg, agentDir: TEST_AGENT_DIR })).toEqual({ - primary: "openai/gpt-5.5", + primary: "openai/gpt-5.4-mini", fallbacks: ["minimax/MiniMax-M2.7", "minimax-portal/MiniMax-M2.7"], }); }); diff --git a/src/agents/tools/web-tools.enabled-defaults.test.ts b/src/agents/tools/web-tools.enabled-defaults.test.ts index 76339aa05ece..595944573d6e 100644 --- a/src/agents/tools/web-tools.enabled-defaults.test.ts +++ b/src/agents/tools/web-tools.enabled-defaults.test.ts @@ -1,3 +1,5 @@ +// Web tool default tests cover enablement, runtime provider discovery, and +// late-bound runtime config for web_search/web_fetch tools. import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { createEmptyPluginRegistry } from "../../plugins/registry-empty.js"; import { setActivePluginRegistry } from "../../plugins/runtime.js"; @@ -51,6 +53,8 @@ vi.mock("../../web-search/runtime.js", async () => { config?: unknown; runtimeWebSearch?: { selectedProvider?: string; providerConfigured?: string }; }) => { + // The mock mirrors production provider resolution order closely enough to + // catch stale construction-time metadata in late-bound tool instances. const providerId = options?.runtimeWebSearch?.selectedProvider ?? options?.runtimeWebSearch?.providerConfigured ?? @@ -217,6 +221,8 @@ describe("web tools defaults", () => { }); it("late-binds managed web_search execution to the current runtime snapshot", async () => { + // Managed agents can outlive a credentials refresh; execution should read + // the active runtime snapshot just before dispatch. const registry = createEmptyPluginRegistry(); registry.webSearchProviders.push( {