@@ -19,11 +19,20 @@ export const REALTIME_BOOTSTRAP_CONTEXT_FILE_NAMES = [
1919export type RealtimeBootstrapContextFileName =
2020 ( typeof REALTIME_BOOTSTRAP_CONTEXT_FILE_NAMES ) [ number ] ;
2121
22+ const REALTIME_BOOTSTRAP_CONTEXT_FILE_NAME_SET : ReadonlySet < string > = new Set (
23+ REALTIME_BOOTSTRAP_CONTEXT_FILE_NAMES ,
24+ ) ;
2225const DEFAULT_REALTIME_BOOTSTRAP_CONTEXT_MAX_CHARS = 4_000 ;
2326const REALTIME_BOOTSTRAP_CONTEXT_TITLE = "OpenClaw realtime voice profile context:" ;
2427const REALTIME_BOOTSTRAP_CONTEXT_GUIDANCE =
2528 "Use these profile files for identity, persona, and user grounding; do not mention them unless asked." ;
2629
30+ function isRealtimeBootstrapContextFileName (
31+ value : string ,
32+ ) : value is RealtimeBootstrapContextFileName {
33+ return REALTIME_BOOTSTRAP_CONTEXT_FILE_NAME_SET . has ( value ) ;
34+ }
35+
2736function formatRealtimeBootstrapContextFileName ( pathValue : string ) : string {
2837 return path . basename ( pathValue . trim ( ) . replace ( / \\ / g, "/" ) ) ;
2938}
@@ -41,14 +50,32 @@ function resolveRealtimeBootstrapContextContentBudget(params: {
4150 return params . totalMaxChars - params . preamble . length - separatorChars - headingChars ;
4251}
4352
53+ function normalizeRealtimeBootstrapContextFileNames (
54+ files : readonly string [ ] ,
55+ warn ?: ( message : string ) => void ,
56+ ) : RealtimeBootstrapContextFileName [ ] {
57+ const normalized : RealtimeBootstrapContextFileName [ ] = [ ] ;
58+ for ( const fileName of files ) {
59+ if ( isRealtimeBootstrapContextFileName ( fileName ) ) {
60+ normalized . push ( fileName ) ;
61+ continue ;
62+ }
63+ warn ?.( `skipping unsupported realtime bootstrap context file "${ fileName } "` ) ;
64+ }
65+ return normalized ;
66+ }
67+
4468export async function resolveRealtimeBootstrapContextInstructions ( params : {
4569 agentId : string ;
4670 config : OpenClawConfig ;
4771 files ?: readonly RealtimeBootstrapContextFileName [ ] ;
4872 sessionKey ?: string ;
4973 warn ?: ( message : string ) => void ;
5074} ) : Promise < string | undefined > {
51- const requestedFiles = params . files ?? REALTIME_BOOTSTRAP_CONTEXT_FILE_NAMES ;
75+ const requestedFiles = normalizeRealtimeBootstrapContextFileNames (
76+ params . files ?? REALTIME_BOOTSTRAP_CONTEXT_FILE_NAMES ,
77+ params . warn ,
78+ ) ;
5279 if ( requestedFiles . length === 0 ) {
5380 return undefined ;
5481 }
@@ -63,11 +90,18 @@ export async function resolveRealtimeBootstrapContextInstructions(params: {
6390 } ) ;
6491 const selectedFiles = bootstrapFiles
6592 . filter (
66- ( file ) => ! file . missing && requestedOrder . has ( file . name as RealtimeBootstrapContextFileName ) ,
93+ ( file ) =>
94+ ! file . missing &&
95+ isRealtimeBootstrapContextFileName ( file . name ) &&
96+ requestedOrder . has ( file . name ) ,
6797 )
6898 . toSorted ( ( left , right ) => {
69- const leftOrder = requestedOrder . get ( left . name as RealtimeBootstrapContextFileName ) ?? 0 ;
70- const rightOrder = requestedOrder . get ( right . name as RealtimeBootstrapContextFileName ) ?? 0 ;
99+ const leftOrder = isRealtimeBootstrapContextFileName ( left . name )
100+ ? ( requestedOrder . get ( left . name ) ?? 0 )
101+ : 0 ;
102+ const rightOrder = isRealtimeBootstrapContextFileName ( right . name )
103+ ? ( requestedOrder . get ( right . name ) ?? 0 )
104+ : 0 ;
71105 if ( leftOrder !== rightOrder ) {
72106 return leftOrder - rightOrder ;
73107 }
0 commit comments