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