Enhance conversation history and runtime variable management

- Update ConversationRecorder to include source and nodeId metadata in transcripts for better context tracking.
- Introduce optional variable handling in DynamicVariableStore, allowing for unset variables to be rendered as empty without raising errors.
- Refactor WorkflowBrain to apply turn configurations and manage interaction policies dynamically, improving agent responsiveness.
- Implement tests to ensure proper handling of updated session variables and workflow metadata in various scenarios.
This commit is contained in:
Xin Wang
2026-07-14 11:08:11 +08:00
parent 665f727796
commit f74040adf3
18 changed files with 848 additions and 194 deletions

View File

@@ -46,6 +46,22 @@ export type ChatMessage = {
};
type AppMessage = Record<string, unknown> & { type?: string };
type DynamicVariableValue = string | number | boolean;
function publicVariableSnapshot(
value: unknown,
): Record<string, DynamicVariableValue> {
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
return Object.fromEntries(
Object.entries(value).filter(([name, item]) =>
!name.startsWith("system__") &&
!name.startsWith("secret__") &&
(typeof item === "string" ||
typeof item === "number" ||
typeof item === "boolean"),
) as [string, DynamicVariableValue][],
);
}
class AppSmallWebRTCTransport extends SmallWebRTCTransport {
onAppMessage?: (message: AppMessage) => void;
@@ -185,6 +201,9 @@ export function useVoicePreview(
const [videoStream, setVideoStream] = useState<MediaStream | null>(null);
const [remoteStream, setRemoteStream] = useState<MediaStream | null>(null);
const [messages, setMessages] = useState<ChatMessage[]>([]);
const [sessionVariables, setSessionVariables] = useState<
Record<string, DynamicVariableValue>
>({});
const [callEnded, setCallEnded] = useState(false);
const [networkQuality, setNetworkQuality] =
useState<NetworkQuality>("unknown");
@@ -387,6 +406,8 @@ export function useVoicePreview(
);
} else if (msg.type === "node-active" && typeof msg.nodeId === "string") {
onNodeActiveRef.current?.(msg.nodeId);
} else if (msg.type === "workflow-variables") {
setSessionVariables(publicVariableSnapshot(msg.variables));
} else if (msg.type === "call-ended") {
endedByServerRef.current = true;
setCallEnded(true);
@@ -407,6 +428,7 @@ export function useVoicePreview(
setError(null);
setMicWarning(null);
setMessages([]);
setSessionVariables(publicVariableSnapshot(options.dynamicVariables ?? {}));
pendingAssistantTurnsRef.current.clear();
setCallEnded(false);
endedByServerRef.current = false;
@@ -593,6 +615,7 @@ export function useVoicePreview(
videoStream,
remoteStream,
messages,
sessionVariables,
callEnded,
networkQuality,
audioInputs,