feat: add TTS hint to system prompt
This commit is contained in:
@@ -13,6 +13,7 @@ import type { EmbeddedContextFile } from "../pi-embedded-helpers.js";
|
||||
import { buildSystemPromptParams } from "../system-prompt-params.js";
|
||||
import { resolveDefaultModelForAgent } from "../model-selection.js";
|
||||
import { buildAgentSystemPrompt } from "../system-prompt.js";
|
||||
import { buildTtsSystemPromptHint } from "../../tts/tts.js";
|
||||
|
||||
const CLI_RUN_QUEUE = new Map<string, Promise<unknown>>();
|
||||
|
||||
@@ -194,6 +195,7 @@ export function buildSystemPrompt(params: {
|
||||
defaultModel: defaultModelLabel,
|
||||
},
|
||||
});
|
||||
const ttsHint = params.config ? buildTtsSystemPromptHint(params.config) : undefined;
|
||||
return buildAgentSystemPrompt({
|
||||
workspaceDir: params.workspaceDir,
|
||||
defaultThinkLevel: params.defaultThinkLevel,
|
||||
@@ -209,6 +211,7 @@ export function buildSystemPrompt(params: {
|
||||
userTime,
|
||||
userTimeFormat,
|
||||
contextFiles: params.contextFiles,
|
||||
ttsHint,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ import { splitSdkTools } from "./tool-split.js";
|
||||
import type { EmbeddedPiCompactResult } from "./types.js";
|
||||
import { formatUserTime, resolveUserTimeFormat, resolveUserTimezone } from "../date-time.js";
|
||||
import { describeUnknownError, mapThinkingLevel, resolveExecToolDefaults } from "./utils.js";
|
||||
import { buildTtsSystemPromptHint } from "../../tts/tts.js";
|
||||
|
||||
export async function compactEmbeddedPiSession(params: {
|
||||
sessionId: string;
|
||||
@@ -298,6 +299,7 @@ export async function compactEmbeddedPiSession(params: {
|
||||
cwd: process.cwd(),
|
||||
moduleUrl: import.meta.url,
|
||||
});
|
||||
const ttsHint = params.config ? buildTtsSystemPromptHint(params.config) : undefined;
|
||||
const appendPrompt = buildEmbeddedSystemPrompt({
|
||||
workspaceDir: effectiveWorkspace,
|
||||
defaultThinkLevel: params.thinkLevel,
|
||||
@@ -310,6 +312,7 @@ export async function compactEmbeddedPiSession(params: {
|
||||
: undefined,
|
||||
skillsPrompt,
|
||||
docsPath: docsPath ?? undefined,
|
||||
ttsHint,
|
||||
promptMode,
|
||||
runtimeInfo,
|
||||
messageToolHints,
|
||||
|
||||
@@ -78,6 +78,7 @@ import { toClientToolDefinitions } from "../../pi-tool-definition-adapter.js";
|
||||
import { buildSystemPromptParams } from "../../system-prompt-params.js";
|
||||
import { describeUnknownError, mapThinkingLevel } from "../utils.js";
|
||||
import { resolveSandboxRuntimeStatus } from "../../sandbox/runtime-status.js";
|
||||
import { buildTtsSystemPromptHint } from "../../../tts/tts.js";
|
||||
import { isTimeoutError } from "../../failover-error.js";
|
||||
import { getGlobalHookRunner } from "../../../plugins/hook-runner-global.js";
|
||||
import { MAX_IMAGE_BYTES } from "../../../media/constants.js";
|
||||
@@ -315,6 +316,7 @@ export async function runEmbeddedAttempt(
|
||||
cwd: process.cwd(),
|
||||
moduleUrl: import.meta.url,
|
||||
});
|
||||
const ttsHint = params.config ? buildTtsSystemPromptHint(params.config) : undefined;
|
||||
|
||||
const appendPrompt = buildEmbeddedSystemPrompt({
|
||||
workspaceDir: effectiveWorkspace,
|
||||
@@ -328,6 +330,7 @@ export async function runEmbeddedAttempt(
|
||||
: undefined,
|
||||
skillsPrompt,
|
||||
docsPath: docsPath ?? undefined,
|
||||
ttsHint,
|
||||
workspaceNotes,
|
||||
reactionGuidance,
|
||||
promptMode,
|
||||
|
||||
@@ -16,6 +16,7 @@ export function buildEmbeddedSystemPrompt(params: {
|
||||
heartbeatPrompt?: string;
|
||||
skillsPrompt?: string;
|
||||
docsPath?: string;
|
||||
ttsHint?: string;
|
||||
reactionGuidance?: {
|
||||
level: "minimal" | "extensive";
|
||||
channel: string;
|
||||
@@ -55,6 +56,7 @@ export function buildEmbeddedSystemPrompt(params: {
|
||||
heartbeatPrompt: params.heartbeatPrompt,
|
||||
skillsPrompt: params.skillsPrompt,
|
||||
docsPath: params.docsPath,
|
||||
ttsHint: params.ttsHint,
|
||||
workspaceNotes: params.workspaceNotes,
|
||||
reactionGuidance: params.reactionGuidance,
|
||||
promptMode: params.promptMode,
|
||||
|
||||
@@ -34,6 +34,7 @@ describe("buildAgentSystemPrompt", () => {
|
||||
toolNames: ["message", "memory_search"],
|
||||
docsPath: "/tmp/clawd/docs",
|
||||
extraSystemPrompt: "Subagent details",
|
||||
ttsHint: "Voice (TTS) is enabled.",
|
||||
});
|
||||
|
||||
expect(prompt).not.toContain("## User Identity");
|
||||
@@ -42,6 +43,7 @@ describe("buildAgentSystemPrompt", () => {
|
||||
expect(prompt).not.toContain("## Documentation");
|
||||
expect(prompt).not.toContain("## Reply Tags");
|
||||
expect(prompt).not.toContain("## Messaging");
|
||||
expect(prompt).not.toContain("## Voice (TTS)");
|
||||
expect(prompt).not.toContain("## Silent Replies");
|
||||
expect(prompt).not.toContain("## Heartbeats");
|
||||
expect(prompt).toContain("## Subagent Context");
|
||||
@@ -49,6 +51,16 @@ describe("buildAgentSystemPrompt", () => {
|
||||
expect(prompt).toContain("Subagent details");
|
||||
});
|
||||
|
||||
it("includes voice hint when provided", () => {
|
||||
const prompt = buildAgentSystemPrompt({
|
||||
workspaceDir: "/tmp/clawd",
|
||||
ttsHint: "Voice (TTS) is enabled.",
|
||||
});
|
||||
|
||||
expect(prompt).toContain("## Voice (TTS)");
|
||||
expect(prompt).toContain("Voice (TTS) is enabled.");
|
||||
});
|
||||
|
||||
it("adds reasoning tag hint when enabled", () => {
|
||||
const prompt = buildAgentSystemPrompt({
|
||||
workspaceDir: "/tmp/clawd",
|
||||
|
||||
@@ -103,6 +103,13 @@ function buildMessagingSection(params: {
|
||||
];
|
||||
}
|
||||
|
||||
function buildVoiceSection(params: { isMinimal: boolean; ttsHint?: string }) {
|
||||
if (params.isMinimal) return [];
|
||||
const hint = params.ttsHint?.trim();
|
||||
if (!hint) return [];
|
||||
return ["## Voice (TTS)", hint, ""];
|
||||
}
|
||||
|
||||
function buildDocsSection(params: { docsPath?: string; isMinimal: boolean; readToolName: string }) {
|
||||
const docsPath = params.docsPath?.trim();
|
||||
if (!docsPath || params.isMinimal) return [];
|
||||
@@ -137,6 +144,7 @@ export function buildAgentSystemPrompt(params: {
|
||||
heartbeatPrompt?: string;
|
||||
docsPath?: string;
|
||||
workspaceNotes?: string[];
|
||||
ttsHint?: string;
|
||||
/** Controls which hardcoded sections to include. Defaults to "full". */
|
||||
promptMode?: PromptMode;
|
||||
runtimeInfo?: {
|
||||
@@ -464,6 +472,7 @@ export function buildAgentSystemPrompt(params: {
|
||||
runtimeChannel,
|
||||
messageToolHints: params.messageToolHints,
|
||||
}),
|
||||
...buildVoiceSection({ isMinimal, ttsHint: params.ttsHint }),
|
||||
];
|
||||
|
||||
if (extraSystemPrompt) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { buildToolSummaryMap } from "../../agents/tool-summaries.js";
|
||||
import { resolveBootstrapContextForRun } from "../../agents/bootstrap-files.js";
|
||||
import type { SessionSystemPromptReport } from "../../config/sessions/types.js";
|
||||
import { getRemoteSkillEligibility } from "../../infra/skills-remote.js";
|
||||
import { buildTtsSystemPromptHint } from "../../tts/tts.js";
|
||||
import type { ReplyPayload } from "../types.js";
|
||||
import type { HandleCommandsParams } from "./commands-types.js";
|
||||
|
||||
@@ -128,6 +129,7 @@ async function resolveContextReport(
|
||||
},
|
||||
}
|
||||
: { enabled: false };
|
||||
const ttsHint = params.cfg ? buildTtsSystemPromptHint(params.cfg) : undefined;
|
||||
|
||||
const systemPrompt = buildAgentSystemPrompt({
|
||||
workspaceDir,
|
||||
@@ -145,6 +147,7 @@ async function resolveContextReport(
|
||||
contextFiles: injectedFiles,
|
||||
skillsPrompt,
|
||||
heartbeatPrompt: undefined,
|
||||
ttsHint,
|
||||
runtimeInfo,
|
||||
sandboxInfo,
|
||||
});
|
||||
|
||||
@@ -244,6 +244,19 @@ export function resolveTtsPrefsPath(config: ResolvedTtsConfig): string {
|
||||
return path.join(CONFIG_DIR, "settings", "tts.json");
|
||||
}
|
||||
|
||||
export function buildTtsSystemPromptHint(cfg: ClawdbotConfig): string | undefined {
|
||||
const config = resolveTtsConfig(cfg);
|
||||
const prefsPath = resolveTtsPrefsPath(config);
|
||||
if (!isTtsEnabled(config, prefsPath)) return undefined;
|
||||
const maxLength = getTtsMaxLength(prefsPath);
|
||||
const summarize = isSummarizationEnabled(prefsPath) ? "on" : "off";
|
||||
return [
|
||||
"Voice (TTS) is enabled.",
|
||||
`Keep spoken text ≤${maxLength} chars to avoid auto-summary (summary ${summarize}).`,
|
||||
"Use [[tts:...]] and optional [[tts:text]]...[[/tts:text]] to control voice/expressiveness.",
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
function readPrefs(prefsPath: string): TtsUserPrefs {
|
||||
try {
|
||||
if (!existsSync(prefsPath)) return {};
|
||||
|
||||
Reference in New Issue
Block a user