refactor(agents): dedupe model and tool test helpers

This commit is contained in:
Peter Steinberger
2026-03-02 21:30:12 +00:00
parent 067855e623
commit ab8b8dae70
13 changed files with 302 additions and 374 deletions

View File

@@ -327,36 +327,22 @@ export async function handleDiscordGuildAction(
integer: true,
});
const availableTags = parseAvailableTags(params.availableTags);
const editPayload = {
channelId,
name: name ?? undefined,
topic: topic ?? undefined,
position: position ?? undefined,
parentId,
nsfw,
rateLimitPerUser: rateLimitPerUser ?? undefined,
archived,
locked,
autoArchiveDuration: autoArchiveDuration ?? undefined,
availableTags,
};
const channel = accountId
? await editChannelDiscord(
{
channelId,
name: name ?? undefined,
topic: topic ?? undefined,
position: position ?? undefined,
parentId,
nsfw,
rateLimitPerUser: rateLimitPerUser ?? undefined,
archived,
locked,
autoArchiveDuration: autoArchiveDuration ?? undefined,
availableTags,
},
{ accountId },
)
: await editChannelDiscord({
channelId,
name: name ?? undefined,
topic: topic ?? undefined,
position: position ?? undefined,
parentId,
nsfw,
rateLimitPerUser: rateLimitPerUser ?? undefined,
archived,
locked,
autoArchiveDuration: autoArchiveDuration ?? undefined,
availableTags,
});
? await editChannelDiscord(editPayload, { accountId })
: await editChannelDiscord(editPayload);
return jsonResult({ ok: true, channel });
}
case "channelDelete": {

View File

@@ -2,7 +2,7 @@ import { type Context, complete } from "@mariozechner/pi-ai";
import { Type } from "@sinclair/typebox";
import type { OpenClawConfig } from "../../config/config.js";
import { resolveUserPath } from "../../utils.js";
import { getDefaultLocalRoots, loadWebMedia } from "../../web/media.js";
import { loadWebMedia } from "../../web/media.js";
import { minimaxUnderstandImage } from "../minimax-vlm.js";
import {
coerceImageAssistantText,
@@ -15,6 +15,7 @@ import {
applyImageModelConfigDefaults,
buildTextToolResult,
resolveModelFromRegistry,
resolveMediaToolLocalRoots,
resolveModelRuntimeApiKey,
resolvePromptAndModelOverride,
} from "./media-tool-shared.js";
@@ -24,7 +25,6 @@ import {
discoverAuthStorage,
discoverModels,
ensureOpenClawModelsJson,
normalizeWorkspaceDir,
resolveSandboxedBridgeMediaPath,
runWithImageModelFallback,
type AnyAgentTool,
@@ -298,17 +298,9 @@ export function createImageTool(options?: {
? "Analyze one or more images with a vision model. Use image for a single path/URL, or images for multiple (up to 20). Only use this tool when images were NOT already provided in the user's message. Images mentioned in the prompt are automatically visible to you."
: "Analyze one or more images with the configured image model (agents.defaults.imageModel). Use image for a single path/URL, or images for multiple (up to 20). Provide a prompt describing what to analyze.";
const localRoots = (() => {
const workspaceDir = normalizeWorkspaceDir(options?.workspaceDir);
if (options?.fsPolicy?.workspaceOnly) {
return workspaceDir ? [workspaceDir] : [];
}
const roots = getDefaultLocalRoots();
if (!workspaceDir) {
return roots;
}
return Array.from(new Set([...roots, workspaceDir]));
})();
const localRoots = resolveMediaToolLocalRoots(options?.workspaceDir, {
workspaceOnly: options?.fsPolicy?.workspaceOnly === true,
});
return {
label: "Image",

View File

@@ -36,9 +36,15 @@ export function applyImageModelConfigDefaults(
};
}
export function resolveMediaToolLocalRoots(workspaceDirRaw: string | undefined): string[] {
const roots = getDefaultLocalRoots();
export function resolveMediaToolLocalRoots(
workspaceDirRaw: string | undefined,
options?: { workspaceOnly?: boolean },
): string[] {
const workspaceDir = normalizeWorkspaceDir(workspaceDirRaw);
if (options?.workspaceOnly) {
return workspaceDir ? [workspaceDir] : [];
}
const roots = getDefaultLocalRoots();
if (!workspaceDir) {
return [...roots];
}

View File

@@ -3,7 +3,7 @@ import { Type } from "@sinclair/typebox";
import type { OpenClawConfig } from "../../config/config.js";
import { extractPdfContent, type PdfExtractedContent } from "../../media/pdf-extract.js";
import { resolveUserPath } from "../../utils.js";
import { getDefaultLocalRoots, loadWebMediaRaw } from "../../web/media.js";
import { loadWebMediaRaw } from "../../web/media.js";
import {
coerceImageModelConfig,
type ImageModelConfig,
@@ -13,6 +13,7 @@ import {
applyImageModelConfigDefaults,
buildTextToolResult,
resolveModelFromRegistry,
resolveMediaToolLocalRoots,
resolveModelRuntimeApiKey,
resolvePromptAndModelOverride,
} from "./media-tool-shared.js";
@@ -30,7 +31,6 @@ import {
discoverAuthStorage,
discoverModels,
ensureOpenClawModelsJson,
normalizeWorkspaceDir,
resolveSandboxedBridgeMediaPath,
runWithImageModelFallback,
type AnyAgentTool,
@@ -327,17 +327,9 @@ export function createPdfTool(options?: {
? Math.floor(maxPagesDefault)
: DEFAULT_MAX_PAGES;
const localRoots = (() => {
const workspaceDir = normalizeWorkspaceDir(options?.workspaceDir);
if (options?.fsPolicy?.workspaceOnly) {
return workspaceDir ? [workspaceDir] : [];
}
const roots = getDefaultLocalRoots();
if (!workspaceDir) {
return roots;
}
return Array.from(new Set([...roots, workspaceDir]));
})();
const localRoots = resolveMediaToolLocalRoots(options?.workspaceDir, {
workspaceOnly: options?.fsPolicy?.workspaceOnly === true,
});
const description =
"Analyze one or more PDF documents with a model. Supports native PDF analysis for Anthropic and Google models, with text/image extraction fallback for other providers. Use pdf for a single path/URL, or pdfs for multiple (up to 10). Provide a prompt describing what to analyze.";