@@ -35,6 +35,7 @@ const DEFAULT_CACHE_TTL_MS = 15_000;
3535const DEFAULT_MAX_CACHE_ENTRIES = 1000 ;
3636const CACHE_SWEEP_INTERVAL_MS = 1000 ;
3737const DEFAULT_MIN_TIMEOUT_MS = 250 ;
38+ const DEFAULT_SETUP_GRACE_TIMEOUT_MS = 30_000 ;
3839const DEFAULT_QUERY_MODE = "recent" as const ;
3940const DEFAULT_QMD_SEARCH_MODE = "search" as const ;
4041const DEFAULT_TRANSCRIPT_DIR = "active-memory" ;
@@ -216,6 +217,7 @@ type AsyncLock = <T>(task: () => Promise<T>) => Promise<T>;
216217const toggleStoreLocks = new Map < string , AsyncLock > ( ) ;
217218let lastActiveRecallCacheSweepAt = 0 ;
218219let minimumTimeoutMs = DEFAULT_MIN_TIMEOUT_MS ;
220+ let setupGraceTimeoutMs = DEFAULT_SETUP_GRACE_TIMEOUT_MS ;
219221
220222function createAsyncLock ( ) : AsyncLock {
221223 let lock : Promise < void > = Promise . resolve ( ) ;
@@ -2182,9 +2184,10 @@ async function maybeResolveActiveRecall(params: {
21822184 const controller = new AbortController ( ) ;
21832185 const TIMEOUT_SENTINEL = Symbol ( "timeout" ) ;
21842186 let sessionFile : string | undefined ;
2187+ const watchdogTimeoutMs = params . config . timeoutMs + setupGraceTimeoutMs ;
21852188 const timeoutId = setTimeout ( ( ) => {
2186- controller . abort ( new Error ( `active-memory timeout after ${ params . config . timeoutMs } ms` ) ) ;
2187- } , params . config . timeoutMs ) ;
2189+ controller . abort ( new Error ( `active-memory timeout after ${ watchdogTimeoutMs } ms` ) ) ;
2190+ } , watchdogTimeoutMs ) ;
21882191 timeoutId . unref ?.( ) ;
21892192
21902193 const timeoutPromise = new Promise < typeof TIMEOUT_SENTINEL > ( ( resolve ) => {
@@ -2422,109 +2425,114 @@ export default definePluginEntry({
24222425 } ,
24232426 } ) ;
24242427
2425- api . on ( "before_prompt_build" , async ( event , ctx ) => {
2426- try {
2427- refreshLiveConfigFromRuntime ( ) ;
2428- const resolvedAgentId = resolveStatusUpdateAgentId ( ctx ) ;
2429- const resolvedSessionKey =
2430- ctx . sessionKey ?. trim ( ) ||
2431- ( resolvedAgentId
2432- ? resolveCanonicalSessionKeyFromSessionId ( {
2433- api,
2434- agentId : resolvedAgentId ,
2435- sessionId : ctx . sessionId ,
2436- } )
2437- : undefined ) ;
2438- const effectiveAgentId =
2439- resolvedAgentId || resolveStatusUpdateAgentId ( { sessionKey : resolvedSessionKey } ) ;
2440- if ( await isSessionActiveMemoryDisabled ( { api, sessionKey : resolvedSessionKey } ) ) {
2441- await persistPluginStatusLines ( {
2442- api,
2443- agentId : effectiveAgentId ,
2444- sessionKey : resolvedSessionKey ,
2445- } ) ;
2446- return undefined ;
2447- }
2448- if ( ! isEnabledForAgent ( config , effectiveAgentId ) ) {
2449- await persistPluginStatusLines ( {
2450- api,
2451- agentId : effectiveAgentId ,
2452- sessionKey : resolvedSessionKey ,
2453- } ) ;
2454- return undefined ;
2455- }
2456- if ( ! isEligibleInteractiveSession ( ctx ) ) {
2457- await persistPluginStatusLines ( {
2458- api,
2459- agentId : effectiveAgentId ,
2460- sessionKey : resolvedSessionKey ,
2428+ const beforePromptBuildTimeoutMs = 120_000 + setupGraceTimeoutMs ;
2429+ api . on (
2430+ "before_prompt_build" ,
2431+ async ( event , ctx ) => {
2432+ try {
2433+ refreshLiveConfigFromRuntime ( ) ;
2434+ const resolvedAgentId = resolveStatusUpdateAgentId ( ctx ) ;
2435+ const resolvedSessionKey =
2436+ ctx . sessionKey ?. trim ( ) ||
2437+ ( resolvedAgentId
2438+ ? resolveCanonicalSessionKeyFromSessionId ( {
2439+ api,
2440+ agentId : resolvedAgentId ,
2441+ sessionId : ctx . sessionId ,
2442+ } )
2443+ : undefined ) ;
2444+ const effectiveAgentId =
2445+ resolvedAgentId || resolveStatusUpdateAgentId ( { sessionKey : resolvedSessionKey } ) ;
2446+ if ( await isSessionActiveMemoryDisabled ( { api, sessionKey : resolvedSessionKey } ) ) {
2447+ await persistPluginStatusLines ( {
2448+ api,
2449+ agentId : effectiveAgentId ,
2450+ sessionKey : resolvedSessionKey ,
2451+ } ) ;
2452+ return undefined ;
2453+ }
2454+ if ( ! isEnabledForAgent ( config , effectiveAgentId ) ) {
2455+ await persistPluginStatusLines ( {
2456+ api,
2457+ agentId : effectiveAgentId ,
2458+ sessionKey : resolvedSessionKey ,
2459+ } ) ;
2460+ return undefined ;
2461+ }
2462+ if ( ! isEligibleInteractiveSession ( ctx ) ) {
2463+ await persistPluginStatusLines ( {
2464+ api,
2465+ agentId : effectiveAgentId ,
2466+ sessionKey : resolvedSessionKey ,
2467+ } ) ;
2468+ return undefined ;
2469+ }
2470+ if (
2471+ ! isAllowedChatType ( config , {
2472+ ...ctx ,
2473+ sessionKey : resolvedSessionKey ?? ctx . sessionKey ,
2474+ mainKey : api . config . session ?. mainKey ,
2475+ } )
2476+ ) {
2477+ await persistPluginStatusLines ( {
2478+ api,
2479+ agentId : effectiveAgentId ,
2480+ sessionKey : resolvedSessionKey ,
2481+ } ) ;
2482+ return undefined ;
2483+ }
2484+ if (
2485+ ! isAllowedChatId ( config , {
2486+ sessionKey : resolvedSessionKey ?? ctx . sessionKey ,
2487+ messageProvider : ctx . messageProvider ,
2488+ } )
2489+ ) {
2490+ await persistPluginStatusLines ( {
2491+ api,
2492+ agentId : effectiveAgentId ,
2493+ sessionKey : resolvedSessionKey ,
2494+ } ) ;
2495+ return undefined ;
2496+ }
2497+ const query = buildQuery ( {
2498+ latestUserMessage : event . prompt ,
2499+ recentTurns : extractRecentTurns ( event . messages ) ,
2500+ config,
24612501 } ) ;
2462- return undefined ;
2463- }
2464- if (
2465- ! isAllowedChatType ( config , {
2466- ...ctx ,
2467- sessionKey : resolvedSessionKey ?? ctx . sessionKey ,
2468- mainKey : api . config . session ?. mainKey ,
2469- } )
2470- ) {
2471- await persistPluginStatusLines ( {
2502+ const result = await maybeResolveActiveRecall ( {
24722503 api,
2504+ config,
24732505 agentId : effectiveAgentId ,
24742506 sessionKey : resolvedSessionKey ,
2475- } ) ;
2476- return undefined ;
2477- }
2478- if (
2479- ! isAllowedChatId ( config , {
2480- sessionKey : resolvedSessionKey ?? ctx . sessionKey ,
2507+ sessionId : ctx . sessionId ,
24812508 messageProvider : ctx . messageProvider ,
2482- } )
2483- ) {
2484- await persistPluginStatusLines ( {
2485- api,
2486- agentId : effectiveAgentId ,
2487- sessionKey : resolvedSessionKey ,
2509+ channelId : ctx . channelId ,
2510+ query,
2511+ currentModelProviderId : ctx . modelProviderId ,
2512+ currentModelId : ctx . modelId ,
24882513 } ) ;
2514+ if ( ! result . summary ) {
2515+ return undefined ;
2516+ }
2517+ const promptPrefix = buildPromptPrefix ( result . summary ) ;
2518+ if ( ! promptPrefix ) {
2519+ return undefined ;
2520+ }
2521+ return {
2522+ prependContext : promptPrefix ,
2523+ } ;
2524+ } catch ( error ) {
2525+ const message = toSingleLineLogValue (
2526+ error instanceof Error ? error . message : String ( error ) ,
2527+ ) ;
2528+ api . logger . warn ?.(
2529+ `active-memory: before_prompt_build failed, skipping memory lookup: ${ message } ` ,
2530+ ) ;
24892531 return undefined ;
24902532 }
2491- const query = buildQuery ( {
2492- latestUserMessage : event . prompt ,
2493- recentTurns : extractRecentTurns ( event . messages ) ,
2494- config,
2495- } ) ;
2496- const result = await maybeResolveActiveRecall ( {
2497- api,
2498- config,
2499- agentId : effectiveAgentId ,
2500- sessionKey : resolvedSessionKey ,
2501- sessionId : ctx . sessionId ,
2502- messageProvider : ctx . messageProvider ,
2503- channelId : ctx . channelId ,
2504- query,
2505- currentModelProviderId : ctx . modelProviderId ,
2506- currentModelId : ctx . modelId ,
2507- } ) ;
2508- if ( ! result . summary ) {
2509- return undefined ;
2510- }
2511- const promptPrefix = buildPromptPrefix ( result . summary ) ;
2512- if ( ! promptPrefix ) {
2513- return undefined ;
2514- }
2515- return {
2516- prependContext : promptPrefix ,
2517- } ;
2518- } catch ( error ) {
2519- const message = toSingleLineLogValue (
2520- error instanceof Error ? error . message : String ( error ) ,
2521- ) ;
2522- api . logger . warn ?.(
2523- `active-memory: before_prompt_build failed, skipping memory lookup: ${ message } ` ,
2524- ) ;
2525- return undefined ;
2526- }
2527- } ) ;
2533+ } ,
2534+ { timeoutMs : beforePromptBuildTimeoutMs } ,
2535+ ) ;
25282536 } ,
25292537} ) ;
25302538
@@ -2542,9 +2550,13 @@ export const __testing = {
25422550 activeRecallCache . clear ( ) ;
25432551 lastActiveRecallCacheSweepAt = 0 ;
25442552 minimumTimeoutMs = DEFAULT_MIN_TIMEOUT_MS ;
2553+ setupGraceTimeoutMs = DEFAULT_SETUP_GRACE_TIMEOUT_MS ;
25452554 } ,
25462555 setMinimumTimeoutMsForTests ( value : number ) {
25472556 minimumTimeoutMs = value ;
25482557 } ,
2558+ setSetupGraceTimeoutMsForTests ( value : number ) {
2559+ setupGraceTimeoutMs = Math . max ( 0 , Math . floor ( value ) ) ;
2560+ } ,
25492561 setCachedResult,
25502562} ;
0 commit comments