fix(tts): use prepared completion auth

This commit is contained in:
Vincent Koc
2026-06-11 10:20:08 +09:00
parent f76bdffd06
commit 33f44d0f27
2 changed files with 15 additions and 29 deletions

View File

@@ -1,7 +1,5 @@
// TTS core tests cover provider selection, synthesis, and error handling.
import { describe, expect, it, vi } from "vitest";
import type { ResolvedProviderAuth } from "../agents/model-auth-runtime-shared.js";
import { AuthStorage, ModelRegistry } from "../agents/sessions/index.js";
import type { AssistantMessage, Model, Usage } from "../llm/types.js";
import { MAX_TIMER_TIMEOUT_MS } from "../shared/number-coercion.js";
import type { SpeechModelOverridePolicy } from "./provider-types.js";
@@ -66,9 +64,7 @@ describe("TTS core", () => {
apiKey: "key",
source: "test",
mode: "api-key",
} satisfies ResolvedProviderAuth;
const authStorage = AuthStorage.inMemory();
const modelRegistry = ModelRegistry.inMemory(authStorage);
} as const;
const assistant = {
role: "assistant",
content: [{ type: "text", text: "Short summary." }],
@@ -90,14 +86,8 @@ describe("TTS core", () => {
},
{
completeSimple: vi.fn(async () => assistant),
getApiKeyForModel: vi.fn(async () => auth),
prepareModelForSimpleCompletion: vi.fn(() => model),
prepareSimpleCompletionModel: vi.fn(async () => ({ model, auth })),
requireApiKey: vi.fn(() => "key"),
resolveModelAsync: vi.fn(async () => ({
model,
authStorage,
modelRegistry,
})),
},
);

View File

@@ -1,14 +1,13 @@
// TTS core coordinates text preparation, provider selection, and speech output.
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { resolveModelAsync } from "../agents/embedded-agent-runner/model.js";
import { getApiKeyForModel, requireApiKey } from "../agents/model-auth.js";
import { requireApiKey } from "../agents/model-auth.js";
import {
buildModelAliasIndex,
resolveDefaultModelForAgent,
resolveModelRefFromString,
type ModelRef,
} from "../agents/model-selection.js";
import { prepareModelForSimpleCompletion } from "../agents/simple-completion-transport.js";
import { prepareSimpleCompletionModel } from "../agents/simple-completion-runtime.js";
import type { OpenClawConfig } from "../config/types.js";
import { completeSimple } from "../llm/stream.js";
import type { TextContent } from "../llm/types.js";
@@ -24,19 +23,15 @@ export {
type SummarizeTextDeps = {
completeSimple: typeof completeSimple;
getApiKeyForModel: typeof getApiKeyForModel;
prepareModelForSimpleCompletion: typeof prepareModelForSimpleCompletion;
prepareSimpleCompletionModel: typeof prepareSimpleCompletionModel;
requireApiKey: typeof requireApiKey;
resolveModelAsync: typeof resolveModelAsync;
};
function resolveDefaultSummarizeTextDeps(): SummarizeTextDeps {
return {
completeSimple,
getApiKeyForModel,
prepareModelForSimpleCompletion,
prepareSimpleCompletionModel,
requireApiKey,
resolveModelAsync,
};
}
@@ -96,15 +91,16 @@ export async function summarizeText(
const startTime = Date.now();
const { ref } = resolveSummaryModelRef(cfg, config);
const resolved = await deps.resolveModelAsync(ref.provider, ref.model, undefined, cfg);
if (!resolved.model) {
throw new Error(resolved.error ?? `Unknown summary model: ${ref.provider}/${ref.model}`);
const prepared = await deps.prepareSimpleCompletionModel({
cfg,
provider: ref.provider,
modelId: ref.model,
});
if ("error" in prepared) {
throw new Error(prepared.error);
}
const completionModel = deps.prepareModelForSimpleCompletion({ model: resolved.model, cfg });
const apiKey = deps.requireApiKey(
await deps.getApiKeyForModel({ model: completionModel, cfg }),
ref.provider,
);
const completionModel = prepared.model;
const apiKey = deps.requireApiKey(prepared.auth, ref.provider);
try {
const controller = new AbortController();