@@ -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 ( ) ;
@@ -2188,9 +2190,10 @@ async function maybeResolveActiveRecall(params: {
21882190 const controller = new AbortController ( ) ;
21892191 const TIMEOUT_SENTINEL = Symbol ( "timeout" ) ;
21902192 let sessionFile : string | undefined ;
2193+ const watchdogTimeoutMs = params . config . timeoutMs + setupGraceTimeoutMs ;
21912194 const timeoutId = setTimeout ( ( ) => {
2192- controller . abort ( new Error ( `active-memory timeout after ${ params . config . timeoutMs } ms` ) ) ;
2193- } , params . config . timeoutMs ) ;
2195+ controller . abort ( new Error ( `active-memory timeout after ${ watchdogTimeoutMs } ms` ) ) ;
2196+ } , watchdogTimeoutMs ) ;
21942197 timeoutId . unref ?.( ) ;
21952198
21962199 const timeoutPromise = new Promise < typeof TIMEOUT_SENTINEL > ( ( resolve ) => {
@@ -2428,109 +2431,114 @@ export default definePluginEntry({
24282431 } ,
24292432 } ) ;
24302433
2431- api . on ( "before_prompt_build" , 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 ,
2434+ const beforePromptBuildTimeoutMs = 120_000 + setupGraceTimeoutMs ;
2435+ api . on (
2436+ "before_prompt_build" ,
2437+ async ( event , ctx ) => {
2438+ try {
2439+ refreshLiveConfigFromRuntime ( ) ;
2440+ const resolvedAgentId = resolveStatusUpdateAgentId ( ctx ) ;
2441+ const resolvedSessionKey =
2442+ ctx . sessionKey ?. trim ( ) ||
2443+ ( resolvedAgentId
2444+ ? resolveCanonicalSessionKeyFromSessionId ( {
2445+ api,
2446+ agentId : resolvedAgentId ,
2447+ sessionId : ctx . sessionId ,
2448+ } )
2449+ : undefined ) ;
2450+ const effectiveAgentId =
2451+ resolvedAgentId || resolveStatusUpdateAgentId ( { sessionKey : resolvedSessionKey } ) ;
2452+ if ( await isSessionActiveMemoryDisabled ( { api, sessionKey : resolvedSessionKey } ) ) {
2453+ await persistPluginStatusLines ( {
2454+ api,
2455+ agentId : effectiveAgentId ,
2456+ sessionKey : resolvedSessionKey ,
2457+ } ) ;
2458+ return undefined ;
2459+ }
2460+ if ( ! isEnabledForAgent ( config , effectiveAgentId ) ) {
2461+ await persistPluginStatusLines ( {
2462+ api,
2463+ agentId : effectiveAgentId ,
2464+ sessionKey : resolvedSessionKey ,
2465+ } ) ;
2466+ return undefined ;
2467+ }
2468+ if ( ! isEligibleInteractiveSession ( ctx ) ) {
2469+ await persistPluginStatusLines ( {
2470+ api,
2471+ agentId : effectiveAgentId ,
2472+ sessionKey : resolvedSessionKey ,
2473+ } ) ;
2474+ return undefined ;
2475+ }
2476+ if (
2477+ ! isAllowedChatType ( config , {
2478+ ...ctx ,
2479+ sessionKey : resolvedSessionKey ?? ctx . sessionKey ,
2480+ mainKey : api . config . session ?. mainKey ,
2481+ } )
2482+ ) {
2483+ await persistPluginStatusLines ( {
2484+ api,
2485+ agentId : effectiveAgentId ,
2486+ sessionKey : resolvedSessionKey ,
2487+ } ) ;
2488+ return undefined ;
2489+ }
2490+ if (
2491+ ! isAllowedChatId ( config , {
2492+ sessionKey : resolvedSessionKey ?? ctx . sessionKey ,
2493+ messageProvider : ctx . messageProvider ,
2494+ } )
2495+ ) {
2496+ await persistPluginStatusLines ( {
2497+ api,
2498+ agentId : effectiveAgentId ,
2499+ sessionKey : resolvedSessionKey ,
2500+ } ) ;
2501+ return undefined ;
2502+ }
2503+ const query = buildQuery ( {
2504+ latestUserMessage : event . prompt ,
2505+ recentTurns : extractRecentTurns ( event . messages ) ,
2506+ config,
24672507 } ) ;
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 ( {
2508+ const result = await maybeResolveActiveRecall ( {
24782509 api,
2510+ config,
24792511 agentId : effectiveAgentId ,
24802512 sessionKey : resolvedSessionKey ,
2481- } ) ;
2482- return undefined ;
2483- }
2484- if (
2485- ! isAllowedChatId ( config , {
2486- sessionKey : resolvedSessionKey ?? ctx . sessionKey ,
2513+ sessionId : ctx . sessionId ,
24872514 messageProvider : ctx . messageProvider ,
2488- } )
2489- ) {
2490- await persistPluginStatusLines ( {
2491- api,
2492- agentId : effectiveAgentId ,
2493- sessionKey : resolvedSessionKey ,
2515+ channelId : ctx . channelId ,
2516+ query,
2517+ currentModelProviderId : ctx . modelProviderId ,
2518+ currentModelId : ctx . modelId ,
24942519 } ) ;
2520+ if ( ! result . summary ) {
2521+ return undefined ;
2522+ }
2523+ const promptPrefix = buildPromptPrefix ( result . summary ) ;
2524+ if ( ! promptPrefix ) {
2525+ return undefined ;
2526+ }
2527+ return {
2528+ prependContext : promptPrefix ,
2529+ } ;
2530+ } catch ( error ) {
2531+ const message = toSingleLineLogValue (
2532+ error instanceof Error ? error . message : String ( error ) ,
2533+ ) ;
2534+ api . logger . warn ?.(
2535+ `active-memory: before_prompt_build failed, skipping memory lookup: ${ message } ` ,
2536+ ) ;
24952537 return undefined ;
24962538 }
2497- const query = buildQuery ( {
2498- latestUserMessage : event . prompt ,
2499- recentTurns : extractRecentTurns ( event . messages ) ,
2500- config,
2501- } ) ;
2502- const result = await maybeResolveActiveRecall ( {
2503- api,
2504- config,
2505- agentId : effectiveAgentId ,
2506- sessionKey : resolvedSessionKey ,
2507- sessionId : ctx . sessionId ,
2508- messageProvider : ctx . messageProvider ,
2509- channelId : ctx . channelId ,
2510- query,
2511- currentModelProviderId : ctx . modelProviderId ,
2512- currentModelId : ctx . modelId ,
2513- } ) ;
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- ) ;
2531- return undefined ;
2532- }
2533- } ) ;
2539+ } ,
2540+ { timeoutMs : beforePromptBuildTimeoutMs } ,
2541+ ) ;
25342542 } ,
25352543} ) ;
25362544
@@ -2548,9 +2556,13 @@ export const __testing = {
25482556 activeRecallCache . clear ( ) ;
25492557 lastActiveRecallCacheSweepAt = 0 ;
25502558 minimumTimeoutMs = DEFAULT_MIN_TIMEOUT_MS ;
2559+ setupGraceTimeoutMs = DEFAULT_SETUP_GRACE_TIMEOUT_MS ;
25512560 } ,
25522561 setMinimumTimeoutMsForTests ( value : number ) {
25532562 minimumTimeoutMs = value ;
25542563 } ,
2564+ setSetupGraceTimeoutMsForTests ( value : number ) {
2565+ setupGraceTimeoutMs = Math . max ( 0 , Math . floor ( value ) ) ;
2566+ } ,
25552567 setCachedResult,
25562568} ;
0 commit comments