mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-29 19:01:44 +00:00
fix: avoid speech runtime import in status output
This commit is contained in:
@@ -28,14 +28,7 @@ import { resolveCommitHash } from "../infra/git-commit.js";
|
||||
import type { MediaUnderstandingDecision } from "../media-understanding/types.js";
|
||||
import { listPluginCommands } from "../plugins/commands.js";
|
||||
import { resolveAgentIdFromSessionKey } from "../routing/session-key.js";
|
||||
import {
|
||||
getTtsMaxLength,
|
||||
getTtsProvider,
|
||||
isSummarizationEnabled,
|
||||
resolveTtsAutoMode,
|
||||
resolveTtsConfig,
|
||||
resolveTtsPrefsPath,
|
||||
} from "../tts/tts.js";
|
||||
import { resolveStatusTtsSnapshot } from "../tts/status-config.js";
|
||||
import {
|
||||
estimateUsageCost,
|
||||
formatTokenCount as formatTokenCountShared,
|
||||
@@ -398,20 +391,14 @@ const formatVoiceModeLine = (
|
||||
if (!config) {
|
||||
return null;
|
||||
}
|
||||
const ttsConfig = resolveTtsConfig(config);
|
||||
const prefsPath = resolveTtsPrefsPath(ttsConfig);
|
||||
const autoMode = resolveTtsAutoMode({
|
||||
config: ttsConfig,
|
||||
prefsPath,
|
||||
const snapshot = resolveStatusTtsSnapshot({
|
||||
cfg: config,
|
||||
sessionAuto: sessionEntry?.ttsAuto,
|
||||
});
|
||||
if (autoMode === "off") {
|
||||
if (!snapshot) {
|
||||
return null;
|
||||
}
|
||||
const provider = getTtsProvider(ttsConfig, prefsPath);
|
||||
const maxLength = getTtsMaxLength(prefsPath);
|
||||
const summarize = isSummarizationEnabled(prefsPath) ? "on" : "off";
|
||||
return `🔊 Voice: ${autoMode} · provider=${provider} · limit=${maxLength} · summary=${summarize}`;
|
||||
return `🔊 Voice: ${snapshot.autoMode} · provider=${snapshot.provider} · limit=${snapshot.maxLength} · summary=${snapshot.summarize ? "on" : "off"}`;
|
||||
};
|
||||
|
||||
export function buildStatusMessage(args: StatusArgs): string {
|
||||
|
||||
54
src/tts/status-config.test.ts
Normal file
54
src/tts/status-config.test.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { withTempHome } from "../../test/helpers/temp-home.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resolveStatusTtsSnapshot } from "./status-config.js";
|
||||
|
||||
describe("resolveStatusTtsSnapshot", () => {
|
||||
it("uses prefs overrides without loading speech providers", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const prefsPath = path.join(home, ".openclaw", "settings", "tts.json");
|
||||
fs.mkdirSync(path.dirname(prefsPath), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
prefsPath,
|
||||
JSON.stringify({
|
||||
tts: {
|
||||
auto: "always",
|
||||
provider: "edge",
|
||||
maxLength: 2048,
|
||||
summarize: false,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
expect(resolveStatusTtsSnapshot({ cfg: {} as OpenClawConfig })).toEqual({
|
||||
autoMode: "always",
|
||||
provider: "microsoft",
|
||||
maxLength: 2048,
|
||||
summarize: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("reports auto provider when tts is on without an explicit provider", async () => {
|
||||
await withTempHome(async () => {
|
||||
expect(
|
||||
resolveStatusTtsSnapshot({
|
||||
cfg: {
|
||||
messages: {
|
||||
tts: {
|
||||
auto: "always",
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
}),
|
||||
).toEqual({
|
||||
autoMode: "always",
|
||||
provider: "auto",
|
||||
maxLength: 1500,
|
||||
summarize: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
100
src/tts/status-config.ts
Normal file
100
src/tts/status-config.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { TtsAutoMode, TtsConfig, TtsProvider } from "../config/types.tts.js";
|
||||
import { CONFIG_DIR, resolveUserPath } from "../utils.js";
|
||||
import { normalizeTtsAutoMode } from "./tts-auto-mode.js";
|
||||
|
||||
const DEFAULT_TTS_MAX_LENGTH = 1500;
|
||||
const DEFAULT_TTS_SUMMARIZE = true;
|
||||
|
||||
type TtsUserPrefs = {
|
||||
tts?: {
|
||||
auto?: TtsAutoMode;
|
||||
enabled?: boolean;
|
||||
provider?: TtsProvider;
|
||||
maxLength?: number;
|
||||
summarize?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
type TtsStatusSnapshot = {
|
||||
autoMode: TtsAutoMode;
|
||||
provider: TtsProvider;
|
||||
maxLength: number;
|
||||
summarize: boolean;
|
||||
};
|
||||
|
||||
function resolveConfiguredTtsAutoMode(raw: TtsConfig): TtsAutoMode {
|
||||
return normalizeTtsAutoMode(raw.auto) ?? (raw.enabled ? "always" : "off");
|
||||
}
|
||||
|
||||
function normalizeConfiguredSpeechProviderId(
|
||||
providerId: string | undefined,
|
||||
): TtsProvider | undefined {
|
||||
const normalized = providerId?.trim().toLowerCase();
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
return normalized === "edge" ? "microsoft" : normalized;
|
||||
}
|
||||
|
||||
function resolveTtsPrefsPathValue(prefsPath: string | undefined): string {
|
||||
if (prefsPath?.trim()) {
|
||||
return resolveUserPath(prefsPath.trim());
|
||||
}
|
||||
const envPath = process.env.OPENCLAW_TTS_PREFS?.trim();
|
||||
if (envPath) {
|
||||
return resolveUserPath(envPath);
|
||||
}
|
||||
return path.join(CONFIG_DIR, "settings", "tts.json");
|
||||
}
|
||||
|
||||
function readPrefs(prefsPath: string): TtsUserPrefs {
|
||||
try {
|
||||
if (!fs.existsSync(prefsPath)) {
|
||||
return {};
|
||||
}
|
||||
return JSON.parse(fs.readFileSync(prefsPath, "utf8")) as TtsUserPrefs;
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function resolveTtsAutoModeFromPrefs(prefs: TtsUserPrefs): TtsAutoMode | undefined {
|
||||
const auto = normalizeTtsAutoMode(prefs.tts?.auto);
|
||||
if (auto) {
|
||||
return auto;
|
||||
}
|
||||
if (typeof prefs.tts?.enabled === "boolean") {
|
||||
return prefs.tts.enabled ? "always" : "off";
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function resolveStatusTtsSnapshot(params: {
|
||||
cfg: OpenClawConfig;
|
||||
sessionAuto?: string;
|
||||
}): TtsStatusSnapshot | null {
|
||||
const raw: TtsConfig = params.cfg.messages?.tts ?? {};
|
||||
const prefsPath = resolveTtsPrefsPathValue(raw.prefsPath);
|
||||
const prefs = readPrefs(prefsPath);
|
||||
const autoMode =
|
||||
normalizeTtsAutoMode(params.sessionAuto) ??
|
||||
resolveTtsAutoModeFromPrefs(prefs) ??
|
||||
resolveConfiguredTtsAutoMode(raw);
|
||||
|
||||
if (autoMode === "off") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
autoMode,
|
||||
provider:
|
||||
normalizeConfiguredSpeechProviderId(prefs.tts?.provider) ??
|
||||
normalizeConfiguredSpeechProviderId(raw.provider) ??
|
||||
"auto",
|
||||
maxLength: prefs.tts?.maxLength ?? DEFAULT_TTS_MAX_LENGTH,
|
||||
summarize: prefs.tts?.summarize ?? DEFAULT_TTS_SUMMARIZE,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user