mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:50:43 +00:00
perf: reuse run auth store for media tool availability
This commit is contained in:
@@ -159,6 +159,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Agents/tools: reuse the auth profile store already loaded for the active run when deciding media and generation tool availability, avoiding repeated provider-auth runtime discovery during reply startup. Thanks @shakkernerd.
|
||||
- Agents/tools: keep image, video, and music generation tool registration on manifest/auth control-plane checks instead of loading runtime provider registries during reply startup, reducing live-path tool-prep blocking while leaving provider runtime resolution for execution and list actions. Thanks @shakkernerd.
|
||||
- fix: block workspace CLOUDSDK_PYTHON override and always set trusted interpreter for gcloud. (#74492) Thanks @pgondhi987.
|
||||
- Providers/Z.AI: move the bundled GLM catalog and auth env metadata into the plugin manifest, so `models list --all --provider zai` shows the full known catalog without duplicated runtime seed data. Thanks @shakkernerd.
|
||||
|
||||
@@ -5,6 +5,7 @@ import { getActiveRuntimeWebToolsMetadata } from "../secrets/runtime.js";
|
||||
import { normalizeDeliveryContext } from "../utils/delivery-context.js";
|
||||
import type { GatewayMessageChannel } from "../utils/message-channel.js";
|
||||
import { resolveAgentWorkspaceDir, resolveSessionAgentIds } from "./agent-scope.js";
|
||||
import type { AuthProfileStore } from "./auth-profiles/types.js";
|
||||
import { resolveOpenClawPluginToolsForOptions } from "./openclaw-plugin-tools.js";
|
||||
import { applyNodesToolWorkspaceGuard } from "./openclaw-tools.nodes-workspace-guard.js";
|
||||
import {
|
||||
@@ -104,6 +105,8 @@ export function createOpenClawTools(
|
||||
recordToolPrepStage?: (name: string) => void;
|
||||
/** Trusted sender id from inbound context (not tool args). */
|
||||
requesterSenderId?: string | null;
|
||||
/** Auth profiles already loaded for this run; used for prompt-time tool availability. */
|
||||
authProfileStore?: AuthProfileStore;
|
||||
/** Whether the requesting sender is an owner. */
|
||||
senderIsOwner?: boolean;
|
||||
/** Ephemeral session UUID — regenerated on /new and /reset. */
|
||||
@@ -153,6 +156,7 @@ export function createOpenClawTools(
|
||||
? createImageTool({
|
||||
config: options?.config,
|
||||
agentDir: options.agentDir,
|
||||
authProfileStore: options?.authProfileStore,
|
||||
workspaceDir,
|
||||
sandbox,
|
||||
fsPolicy: options?.fsPolicy,
|
||||
@@ -163,6 +167,7 @@ export function createOpenClawTools(
|
||||
const imageGenerateTool = createImageGenerateTool({
|
||||
config: options?.config,
|
||||
agentDir: options?.agentDir,
|
||||
authProfileStore: options?.authProfileStore,
|
||||
workspaceDir,
|
||||
sandbox,
|
||||
fsPolicy: options?.fsPolicy,
|
||||
@@ -171,6 +176,7 @@ export function createOpenClawTools(
|
||||
const videoGenerateTool = createVideoGenerateTool({
|
||||
config: options?.config,
|
||||
agentDir: options?.agentDir,
|
||||
authProfileStore: options?.authProfileStore,
|
||||
agentSessionKey: options?.agentSessionKey,
|
||||
requesterOrigin: deliveryContext ?? undefined,
|
||||
workspaceDir,
|
||||
@@ -181,6 +187,7 @@ export function createOpenClawTools(
|
||||
const musicGenerateTool = createMusicGenerateTool({
|
||||
config: options?.config,
|
||||
agentDir: options?.agentDir,
|
||||
authProfileStore: options?.authProfileStore,
|
||||
agentSessionKey: options?.agentSessionKey,
|
||||
requesterOrigin: deliveryContext ?? undefined,
|
||||
workspaceDir,
|
||||
@@ -192,6 +199,7 @@ export function createOpenClawTools(
|
||||
? createPdfTool({
|
||||
config: options?.config,
|
||||
agentDir: options.agentDir,
|
||||
authProfileStore: options?.authProfileStore,
|
||||
workspaceDir,
|
||||
sandbox,
|
||||
fsPolicy: options?.fsPolicy,
|
||||
|
||||
@@ -1078,6 +1078,7 @@ export async function runEmbeddedPiAgent(
|
||||
authProfileIdSource: lockedProfileId ? "user" : "auto",
|
||||
initialReplayState: accumulatedReplayState,
|
||||
authStorage,
|
||||
authProfileStore: authStore,
|
||||
modelRegistry,
|
||||
agentId: workspaceResolution.agentId,
|
||||
legacyBeforeAgentStartResult,
|
||||
|
||||
@@ -918,6 +918,7 @@ export async function runEmbeddedAttempt(
|
||||
params.requireExplicitMessageTarget ?? isSubagentSessionKey(params.sessionKey),
|
||||
disableMessageTool: params.disableMessageTool,
|
||||
forceMessageTool: params.forceMessageTool,
|
||||
authProfileStore: params.authProfileStore,
|
||||
recordToolPrepStage: (name) => corePluginToolStages.mark(name),
|
||||
onYield: (message) => {
|
||||
yieldDetected = true;
|
||||
|
||||
@@ -7,6 +7,7 @@ import type { SessionSystemPromptReport } from "../../../config/sessions/types.j
|
||||
import type { ContextEngine, ContextEnginePromptCacheInfo } from "../../../context-engine/types.js";
|
||||
import type { DiagnosticTraceContext } from "../../../infra/diagnostic-trace-context.js";
|
||||
import type { PluginHookBeforeAgentStartResult } from "../../../plugins/hook-before-agent-start.types.js";
|
||||
import type { AuthProfileStore } from "../../auth-profiles/types.js";
|
||||
import type { MessagingToolSend } from "../../pi-embedded-messaging.types.js";
|
||||
import type { AgentRuntimePlan } from "../../runtime-plan/types.js";
|
||||
import type { ToolErrorSummary } from "../../tool-error-summary.js";
|
||||
@@ -41,6 +42,8 @@ export type EmbeddedRunAttemptParams = EmbeddedRunAttemptBase & {
|
||||
runtimePlan?: AgentRuntimePlan;
|
||||
model: Model<Api>;
|
||||
authStorage: AuthStorage;
|
||||
/** Auth profile store already resolved during startup for this attempt. */
|
||||
authProfileStore: AuthProfileStore;
|
||||
modelRegistry: ModelRegistry;
|
||||
thinkLevel: ThinkLevel;
|
||||
legacyBeforeAgentStartResult?: PluginHookBeforeAgentStartResult;
|
||||
|
||||
@@ -3,6 +3,7 @@ import { HEARTBEAT_RESPONSE_TOOL_NAME } from "../auto-reply/heartbeat-tool-respo
|
||||
import type { ModelCompatConfig } from "../config/types.models.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { ToolLoopDetectionConfig } from "../config/types.tools.js";
|
||||
import type { AuthProfileStore } from "./auth-profiles/types.js";
|
||||
import type { DiagnosticTraceContext } from "../infra/diagnostic-trace-context.js";
|
||||
import { resolveMergedSafeBinProfileFixtures } from "../infra/exec-safe-bin-runtime-policy.js";
|
||||
import { logWarn } from "../logger.js";
|
||||
@@ -362,6 +363,8 @@ export function createOpenClawCodingTools(options?: {
|
||||
* Keep this narrowly scoped; it is not a replacement for sender ownership.
|
||||
*/
|
||||
ownerOnlyToolAllowlist?: string[];
|
||||
/** Auth profiles already loaded for this run; used for prompt-time tool availability. */
|
||||
authProfileStore?: AuthProfileStore;
|
||||
/** Callback invoked when sessions_yield tool is called. */
|
||||
onYield?: (message: string) => Promise<void> | void;
|
||||
}): AnyAgentTool[] {
|
||||
@@ -711,6 +714,7 @@ export function createOpenClawCodingTools(options?: {
|
||||
...(cronSelfRemoveOnlyJobId ? { cronSelfRemoveOnlyJobId } : {}),
|
||||
requesterAgentIdOverride: agentId,
|
||||
requesterSenderId: options?.senderId,
|
||||
authProfileStore: options?.authProfileStore,
|
||||
senderIsOwner: options?.senderIsOwner,
|
||||
sessionId: options?.sessionId,
|
||||
onYield: options?.onYield,
|
||||
|
||||
@@ -33,6 +33,7 @@ import { saveMediaBuffer } from "../../media/store.js";
|
||||
import { loadWebMedia } from "../../media/web-media.js";
|
||||
import { getProviderEnvVars } from "../../secrets/provider-env-vars.js";
|
||||
import { resolveUserPath } from "../../utils.js";
|
||||
import type { AuthProfileStore } from "../auth-profiles/types.js";
|
||||
import { optionalStringEnum } from "../schema/string-enum.js";
|
||||
import { ToolInputError, readNumberParam, readStringParam } from "./common.js";
|
||||
import { decodeDataUrl } from "./image-tool.helpers.js";
|
||||
@@ -195,10 +196,12 @@ function formatImageGenerationAuthHint(provider: {
|
||||
export function resolveImageGenerationModelConfigForTool(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
authStore?: AuthProfileStore;
|
||||
}): ToolModelConfig | null {
|
||||
return resolveCapabilityModelConfigForTool({
|
||||
cfg: params.cfg,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
modelConfig: params.cfg?.agents?.defaults?.imageGenerationModel,
|
||||
providers: listRuntimeImageGenerationProviders({ config: params.cfg }),
|
||||
});
|
||||
@@ -563,6 +566,7 @@ async function inferResolutionFromInputImages(
|
||||
export function createImageGenerateTool(options?: {
|
||||
config?: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
authProfileStore?: AuthProfileStore;
|
||||
workspaceDir?: string;
|
||||
sandbox?: ImageGenerateSandboxConfig;
|
||||
fsPolicy?: ToolFsPolicy;
|
||||
@@ -572,6 +576,7 @@ export function createImageGenerateTool(options?: {
|
||||
!hasGenerationToolAvailability({
|
||||
cfg,
|
||||
agentDir: options?.agentDir,
|
||||
authStore: options?.authProfileStore,
|
||||
modelConfig: cfg.agents?.defaults?.imageGenerationModel,
|
||||
providerKey: "imageGenerationProviders",
|
||||
})
|
||||
@@ -610,6 +615,7 @@ export function createImageGenerateTool(options?: {
|
||||
provider,
|
||||
cfg,
|
||||
agentDir: options?.agentDir,
|
||||
authStore: options?.authProfileStore,
|
||||
}),
|
||||
authEnvVars: getImageGenerationProviderAuthEnvVars(provider.id),
|
||||
capabilities: provider.capabilities,
|
||||
@@ -661,6 +667,7 @@ export function createImageGenerateTool(options?: {
|
||||
const imageGenerationModelConfig = resolveImageGenerationModelConfigForTool({
|
||||
cfg,
|
||||
agentDir: options?.agentDir,
|
||||
authStore: options?.authProfileStore,
|
||||
});
|
||||
if (!imageGenerationModelConfig) {
|
||||
throw new ToolInputError("No image-generation model configured.");
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
type MediaUnderstandingProvider,
|
||||
} from "../../plugin-sdk/media-understanding.js";
|
||||
import { resolveUserPath } from "../../utils.js";
|
||||
import type { AuthProfileStore } from "../auth-profiles/types.js";
|
||||
import { isMinimaxVlmProvider } from "../minimax-vlm.js";
|
||||
import {
|
||||
coerceImageAssistantText,
|
||||
@@ -117,6 +118,7 @@ function resolveImageToolMaxTokens(modelMaxTokens: number | undefined, requested
|
||||
export function resolveImageModelConfigForTool(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
agentDir: string;
|
||||
authStore?: AuthProfileStore;
|
||||
}): ImageModelConfig | null {
|
||||
// Note: We intentionally do NOT gate based on primarySupportsImages here.
|
||||
// Even when the primary model supports images, we keep the tool available
|
||||
@@ -171,6 +173,7 @@ export function resolveImageModelConfigForTool(params: {
|
||||
return buildToolModelConfigFromCandidates({
|
||||
explicit,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
candidates: [...primaryCandidates, ...autoCandidates],
|
||||
});
|
||||
}
|
||||
@@ -366,6 +369,7 @@ async function runImagePrompt(params: {
|
||||
export function createImageTool(options?: {
|
||||
config?: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
authProfileStore?: AuthProfileStore;
|
||||
workspaceDir?: string;
|
||||
sandbox?: ImageSandboxConfig;
|
||||
fsPolicy?: ToolFsPolicy;
|
||||
@@ -383,6 +387,7 @@ export function createImageTool(options?: {
|
||||
const imageModelConfig = resolveImageModelConfigForTool({
|
||||
cfg: options?.config,
|
||||
agentDir,
|
||||
authStore: options?.authProfileStore,
|
||||
});
|
||||
if (!imageModelConfig) {
|
||||
return null;
|
||||
|
||||
@@ -146,4 +146,23 @@ describe("hasGenerationToolAvailability", () => {
|
||||
).toBe(true);
|
||||
expect(loadProviders).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("checks configured runtime providers against the supplied auth store", () => {
|
||||
expect(
|
||||
hasGenerationToolAvailability({
|
||||
providerKey: "imageGenerationProviders",
|
||||
authStore: {
|
||||
version: 1,
|
||||
profiles: {
|
||||
"local-image:default": {
|
||||
provider: "local-image",
|
||||
type: "api_key",
|
||||
key: "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
providers: [{ id: "local-image", defaultModel: "workflow" }],
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
} from "../../shared/string-coerce.js";
|
||||
import type { AuthProfileStore } from "../auth-profiles/types.js";
|
||||
import { normalizeModelRef } from "../model-selection.js";
|
||||
import { normalizeProviderId } from "../provider-id.js";
|
||||
import {
|
||||
@@ -155,6 +156,7 @@ export function isCapabilityProviderConfigured<T extends CapabilityProvider>(par
|
||||
providerId?: string;
|
||||
cfg?: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
authStore?: AuthProfileStore;
|
||||
}): boolean {
|
||||
const provider =
|
||||
params.provider ??
|
||||
@@ -164,7 +166,11 @@ export function isCapabilityProviderConfigured<T extends CapabilityProvider>(par
|
||||
});
|
||||
if (!provider) {
|
||||
return params.providerId
|
||||
? hasAuthForProvider({ provider: params.providerId, agentDir: params.agentDir })
|
||||
? hasAuthForProvider({
|
||||
provider: params.providerId,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
})
|
||||
: false;
|
||||
}
|
||||
if (provider.isConfigured) {
|
||||
@@ -173,7 +179,11 @@ export function isCapabilityProviderConfigured<T extends CapabilityProvider>(par
|
||||
agentDir: params.agentDir,
|
||||
});
|
||||
}
|
||||
return hasAuthForProvider({ provider: provider.id, agentDir: params.agentDir });
|
||||
return hasAuthForProvider({
|
||||
provider: provider.id,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
});
|
||||
}
|
||||
|
||||
export function resolveSelectedCapabilityProvider<T extends CapabilityProvider>(params: {
|
||||
@@ -196,6 +206,7 @@ export function resolveSelectedCapabilityProvider<T extends CapabilityProvider>(
|
||||
export function resolveCapabilityModelCandidatesForTool(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
authStore?: AuthProfileStore;
|
||||
providers: CapabilityProvider[];
|
||||
}): string[] {
|
||||
const providerDefaults = new Map<string, { ref: string; aliases: string[] }>();
|
||||
@@ -211,6 +222,7 @@ export function resolveCapabilityModelCandidatesForTool(params: {
|
||||
provider,
|
||||
cfg: params.cfg,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
})
|
||||
) {
|
||||
continue;
|
||||
@@ -252,6 +264,7 @@ export function resolveCapabilityModelCandidatesForTool(params: {
|
||||
export function resolveCapabilityModelConfigForTool(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
authStore?: AuthProfileStore;
|
||||
modelConfig?: AgentModelConfig;
|
||||
providers: CapabilityProvider[];
|
||||
}): ToolModelConfig | null {
|
||||
@@ -262,9 +275,11 @@ export function resolveCapabilityModelConfigForTool(params: {
|
||||
return buildToolModelConfigFromCandidates({
|
||||
explicit,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
candidates: resolveCapabilityModelCandidatesForTool({
|
||||
cfg: params.cfg,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
providers: params.providers,
|
||||
}),
|
||||
isProviderConfigured: (providerId) =>
|
||||
@@ -273,6 +288,7 @@ export function resolveCapabilityModelConfigForTool(params: {
|
||||
providerId,
|
||||
cfg: params.cfg,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
}),
|
||||
});
|
||||
}
|
||||
@@ -280,6 +296,7 @@ export function resolveCapabilityModelConfigForTool(params: {
|
||||
export function hasGenerationToolAvailability(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
authStore?: AuthProfileStore;
|
||||
modelConfig?: AgentModelConfig;
|
||||
providers?: CapabilityProvider[] | (() => CapabilityProvider[]);
|
||||
providerKey: GenerationCapabilityProviderKey;
|
||||
@@ -295,13 +312,20 @@ export function hasGenerationToolAvailability(params: {
|
||||
provider,
|
||||
cfg: params.cfg,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
}),
|
||||
);
|
||||
}
|
||||
return resolveBundledCapabilityProviderIds({
|
||||
key: params.providerKey,
|
||||
cfg: params.cfg,
|
||||
}).some((providerId) => hasAuthForProvider({ provider: providerId, agentDir: params.agentDir }));
|
||||
}).some((providerId) =>
|
||||
hasAuthForProvider({
|
||||
provider: providerId,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
function formatQuotedList(values: readonly string[]): string {
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
hasAnyAuthProfileStoreSource,
|
||||
listProfilesForProvider,
|
||||
} from "../auth-profiles.js";
|
||||
import type { AuthProfileStore } from "../auth-profiles/types.js";
|
||||
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../defaults.js";
|
||||
import { resolveEnvApiKey } from "../model-auth.js";
|
||||
import { resolveConfiguredModelRef } from "../model-selection.js";
|
||||
@@ -35,10 +36,17 @@ export function resolveDefaultModelRef(cfg?: OpenClawConfig): { provider: string
|
||||
return { provider: DEFAULT_PROVIDER, model: DEFAULT_MODEL };
|
||||
}
|
||||
|
||||
export function hasAuthForProvider(params: { provider: string; agentDir?: string }): boolean {
|
||||
export function hasAuthForProvider(params: {
|
||||
provider: string;
|
||||
agentDir?: string;
|
||||
authStore?: AuthProfileStore;
|
||||
}): boolean {
|
||||
if (resolveEnvApiKey(params.provider)?.apiKey) {
|
||||
return true;
|
||||
}
|
||||
if (params.authStore) {
|
||||
return listProfilesForProvider(params.authStore, params.provider).length > 0;
|
||||
}
|
||||
const agentDir = params.agentDir?.trim();
|
||||
if (!agentDir) {
|
||||
return false;
|
||||
@@ -66,6 +74,7 @@ export function coerceToolModelConfig(model?: AgentModelConfig): ToolModelConfig
|
||||
export function buildToolModelConfigFromCandidates(params: {
|
||||
explicit: ToolModelConfig;
|
||||
agentDir?: string;
|
||||
authStore?: AuthProfileStore;
|
||||
candidates: Array<string | null | undefined>;
|
||||
isProviderConfigured?: (provider: string) => boolean;
|
||||
}): ToolModelConfig | null {
|
||||
@@ -82,7 +91,11 @@ export function buildToolModelConfigFromCandidates(params: {
|
||||
const provider = trimmed.slice(0, trimmed.indexOf("/")).trim();
|
||||
const providerConfigured =
|
||||
params.isProviderConfigured?.(provider) ??
|
||||
hasAuthForProvider({ provider, agentDir: params.agentDir });
|
||||
hasAuthForProvider({
|
||||
provider,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
});
|
||||
if (!provider || !providerConfigured) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js"
|
||||
import { resolveUserPath } from "../../utils.js";
|
||||
import type { DeliveryContext } from "../../utils/delivery-context.js";
|
||||
import { buildTimeoutAbortSignal } from "../../utils/fetch-timeout.js";
|
||||
import type { AuthProfileStore } from "../auth-profiles/types.js";
|
||||
import { ToolInputError, readNumberParam, readStringParam } from "./common.js";
|
||||
import { decodeDataUrl } from "./image-tool.helpers.js";
|
||||
import { withMediaGenerationTaskKeepalive } from "./media-generate-background-shared.js";
|
||||
@@ -131,10 +132,12 @@ const MusicGenerateToolSchema = Type.Object({
|
||||
export function resolveMusicGenerationModelConfigForTool(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
authStore?: AuthProfileStore;
|
||||
}): ToolModelConfig | null {
|
||||
return resolveCapabilityModelConfigForTool({
|
||||
cfg: params.cfg,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
modelConfig: params.cfg?.agents?.defaults?.musicGenerationModel,
|
||||
providers: listRuntimeMusicGenerationProviders({ config: params.cfg }),
|
||||
});
|
||||
@@ -488,6 +491,7 @@ async function executeMusicGenerationJob(params: {
|
||||
export function createMusicGenerateTool(options?: {
|
||||
config?: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
authProfileStore?: AuthProfileStore;
|
||||
agentSessionKey?: string;
|
||||
requesterOrigin?: DeliveryContext;
|
||||
workspaceDir?: string;
|
||||
@@ -500,6 +504,7 @@ export function createMusicGenerateTool(options?: {
|
||||
!hasGenerationToolAvailability({
|
||||
cfg,
|
||||
agentDir: options?.agentDir,
|
||||
authStore: options?.authProfileStore,
|
||||
modelConfig: cfg.agents?.defaults?.musicGenerationModel,
|
||||
providerKey: "musicGenerationProviders",
|
||||
})
|
||||
@@ -539,6 +544,7 @@ export function createMusicGenerateTool(options?: {
|
||||
const musicGenerationModelConfig = resolveMusicGenerationModelConfigForTool({
|
||||
cfg,
|
||||
agentDir: options?.agentDir,
|
||||
authStore: options?.authProfileStore,
|
||||
});
|
||||
if (!musicGenerationModelConfig) {
|
||||
throw new ToolInputError("No music-generation model configured.");
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
resolveAutoMediaKeyProviders,
|
||||
resolveDefaultMediaModel,
|
||||
} from "../../media-understanding/defaults.js";
|
||||
import type { AuthProfileStore } from "../auth-profiles/types.js";
|
||||
import {
|
||||
coerceImageModelConfig,
|
||||
type ImageModelConfig,
|
||||
@@ -16,11 +17,18 @@ import { coercePdfModelConfig } from "./pdf-tool.helpers.js";
|
||||
function resolveImageCandidateRefs(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
agentDir: string;
|
||||
authStore?: AuthProfileStore;
|
||||
filter?: (providerId: string) => boolean;
|
||||
}): string[] {
|
||||
return resolveAutoMediaKeyProviders({ capability: "image", cfg: params.cfg })
|
||||
.filter((providerId) => !params.filter || params.filter(providerId))
|
||||
.filter((providerId) => hasAuthForProvider({ provider: providerId, agentDir: params.agentDir }))
|
||||
.filter((providerId) =>
|
||||
hasAuthForProvider({
|
||||
provider: providerId,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
}),
|
||||
)
|
||||
.map((providerId) => {
|
||||
const modelId =
|
||||
resolveProviderVisionModelFromConfig({
|
||||
@@ -40,6 +48,7 @@ function resolveImageCandidateRefs(params: {
|
||||
export function resolvePdfModelConfigForTool(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
agentDir: string;
|
||||
authStore?: AuthProfileStore;
|
||||
}): ImageModelConfig | null {
|
||||
const explicitPdf = coercePdfModelConfig(params.cfg);
|
||||
if (explicitPdf.primary?.trim() || (explicitPdf.fallbacks?.length ?? 0) > 0) {
|
||||
@@ -58,7 +67,11 @@ export function resolvePdfModelConfigForTool(params: {
|
||||
}
|
||||
|
||||
const primary = resolveDefaultModelRef(params.cfg);
|
||||
const googleOk = hasAuthForProvider({ provider: "google", agentDir: params.agentDir });
|
||||
const googleOk = hasAuthForProvider({
|
||||
provider: "google",
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
});
|
||||
|
||||
const fallbacks: string[] = [];
|
||||
const addFallback = (ref: string) => {
|
||||
@@ -70,7 +83,11 @@ export function resolvePdfModelConfigForTool(params: {
|
||||
|
||||
let preferred: string | null = null;
|
||||
|
||||
const providerOk = hasAuthForProvider({ provider: primary.provider, agentDir: params.agentDir });
|
||||
const providerOk = hasAuthForProvider({
|
||||
provider: primary.provider,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
});
|
||||
const providerVision = resolveProviderVisionModelFromConfig({
|
||||
cfg: params.cfg,
|
||||
provider: primary.provider,
|
||||
@@ -89,17 +106,26 @@ export function resolvePdfModelConfigForTool(params: {
|
||||
const nativePdfCandidates = resolveImageCandidateRefs({
|
||||
cfg: params.cfg,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
filter: (providerId) => providerSupportsNativePdfDocument({ cfg: params.cfg, providerId }),
|
||||
});
|
||||
const genericImageCandidates = resolveImageCandidateRefs({
|
||||
cfg: params.cfg,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
});
|
||||
|
||||
if (params.cfg?.models?.providers && typeof params.cfg.models.providers === "object") {
|
||||
for (const [providerKey, providerCfg] of Object.entries(params.cfg.models.providers)) {
|
||||
const providerId = providerKey.trim();
|
||||
if (!providerId || !hasAuthForProvider({ provider: providerId, agentDir: params.agentDir })) {
|
||||
if (
|
||||
!providerId ||
|
||||
!hasAuthForProvider({
|
||||
provider: providerId,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
})
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const models = providerCfg?.models ?? [];
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
normalizeOptionalString,
|
||||
} from "../../shared/string-coerce.js";
|
||||
import { resolveUserPath } from "../../utils.js";
|
||||
import type { AuthProfileStore } from "../auth-profiles/types.js";
|
||||
import { type ImageModelConfig } from "./image-tool.helpers.js";
|
||||
import {
|
||||
applyImageModelConfigDefaults,
|
||||
@@ -244,6 +245,7 @@ async function runPdfPrompt(params: {
|
||||
export function createPdfTool(options?: {
|
||||
config?: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
authProfileStore?: AuthProfileStore;
|
||||
workspaceDir?: string;
|
||||
sandbox?: PdfSandboxConfig;
|
||||
fsPolicy?: ToolFsPolicy;
|
||||
@@ -257,7 +259,11 @@ export function createPdfTool(options?: {
|
||||
return null;
|
||||
}
|
||||
|
||||
const pdfModelConfig = resolvePdfModelConfigForTool({ cfg: options?.config, agentDir });
|
||||
const pdfModelConfig = resolvePdfModelConfigForTool({
|
||||
cfg: options?.config,
|
||||
agentDir,
|
||||
authStore: options?.authProfileStore,
|
||||
});
|
||||
if (!pdfModelConfig) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import type {
|
||||
VideoGenerationResolution,
|
||||
VideoGenerationSourceAsset,
|
||||
} from "../../video-generation/types.js";
|
||||
import type { AuthProfileStore } from "../auth-profiles/types.js";
|
||||
import { ToolInputError, readNumberParam, readStringParam } from "./common.js";
|
||||
import { decodeDataUrl } from "./image-tool.helpers.js";
|
||||
import { withMediaGenerationTaskKeepalive } from "./media-generate-background-shared.js";
|
||||
@@ -225,10 +226,12 @@ const VideoGenerateToolSchema = Type.Object({
|
||||
export function resolveVideoGenerationModelConfigForTool(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
authStore?: AuthProfileStore;
|
||||
}): ToolModelConfig | null {
|
||||
return resolveCapabilityModelConfigForTool({
|
||||
cfg: params.cfg,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
modelConfig: params.cfg?.agents?.defaults?.videoGenerationModel,
|
||||
providers: listRuntimeVideoGenerationProviders({ config: params.cfg }),
|
||||
});
|
||||
@@ -795,6 +798,7 @@ async function executeVideoGenerationJob(params: {
|
||||
export function createVideoGenerateTool(options?: {
|
||||
config?: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
authProfileStore?: AuthProfileStore;
|
||||
agentSessionKey?: string;
|
||||
requesterOrigin?: DeliveryContext;
|
||||
workspaceDir?: string;
|
||||
@@ -807,6 +811,7 @@ export function createVideoGenerateTool(options?: {
|
||||
!hasGenerationToolAvailability({
|
||||
cfg,
|
||||
agentDir: options?.agentDir,
|
||||
authStore: options?.authProfileStore,
|
||||
modelConfig: cfg.agents?.defaults?.videoGenerationModel,
|
||||
providerKey: "videoGenerationProviders",
|
||||
})
|
||||
@@ -846,6 +851,7 @@ export function createVideoGenerateTool(options?: {
|
||||
const videoGenerationModelConfig = resolveVideoGenerationModelConfigForTool({
|
||||
cfg,
|
||||
agentDir: options?.agentDir,
|
||||
authStore: options?.authProfileStore,
|
||||
});
|
||||
if (!videoGenerationModelConfig) {
|
||||
throw new ToolInputError("No video-generation model configured.");
|
||||
|
||||
Reference in New Issue
Block a user