fix(openclaw): add recallTimeoutMs config option for auto-recall (#736)
The auto-recall timeout was hardcoded to 10s but recall with budget=high can take 13s+. This adds a configurable recallTimeoutMs option (default: 10000ms) so users can increase the timeout when using higher recall budgets. Also adds recallInjectionPosition to the plugin schema (it was already implemented in code but missing from the JSON schema validation, causing config rejection). Co-authored-by: Marco Rutsch <marco@rutimka.de> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
7a3dbc1958
commit
cd4d449f8e
3 changed files with 27 additions and 4 deletions
|
|
@ -188,6 +188,18 @@
|
|||
"description": "Text shown above recalled memories in the injected context block.",
|
||||
"default": "Relevant memories from past conversations (prioritize recent when conflicting). Only use memories that are directly useful to continue this conversation; ignore the rest:"
|
||||
},
|
||||
"recallTimeoutMs": {
|
||||
"type": "integer",
|
||||
"minimum": 1000,
|
||||
"description": "Timeout for auto-recall in milliseconds. Increase if recall times out with high budget.",
|
||||
"default": 10000
|
||||
},
|
||||
"recallInjectionPosition": {
|
||||
"type": "string",
|
||||
"enum": ["prepend", "append", "user"],
|
||||
"description": "Where to inject recalled memories. 'prepend' = start of system prompt (default), 'append' = end of system prompt (preserves prompt cache), 'user' = before user message.",
|
||||
"default": "prepend"
|
||||
},
|
||||
"debug": {
|
||||
"type": "boolean",
|
||||
"description": "Enable debug logging for Hindsight plugin operations.",
|
||||
|
|
@ -309,6 +321,14 @@
|
|||
"label": "Recall Prompt Preamble",
|
||||
"placeholder": "Instruction shown above recalled memories in injected context"
|
||||
},
|
||||
"recallTimeoutMs": {
|
||||
"label": "Recall Timeout (ms)",
|
||||
"placeholder": "10000 (default)"
|
||||
},
|
||||
"recallInjectionPosition": {
|
||||
"label": "Recall Injection Position",
|
||||
"placeholder": "prepend, append, or user"
|
||||
},
|
||||
"debug": {
|
||||
"label": "Debug"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import type { RecallResponse } from './types.js';
|
|||
const inflightRecalls = new Map<string, Promise<RecallResponse>>();
|
||||
const turnCountBySession = new Map<string, number>();
|
||||
const MAX_TRACKED_SESSIONS = 10_000;
|
||||
const RECALL_TIMEOUT_MS = 10_000;
|
||||
const DEFAULT_RECALL_TIMEOUT_MS = 10_000;
|
||||
|
||||
// Cache sender IDs discovered in before_prompt_build (where event.prompt has the metadata
|
||||
// blocks) so agent_end can look them up — event.messages in agent_end is clean history.
|
||||
|
|
@ -727,6 +727,7 @@ function getPluginConfig(api: MoltbotPluginAPI): PluginConfig {
|
|||
? config.recallPromptPreamble
|
||||
: DEFAULT_RECALL_PROMPT_PREAMBLE,
|
||||
recallInjectionPosition: typeof config.recallInjectionPosition === 'string' && ['prepend', 'append', 'user'].includes(config.recallInjectionPosition) ? config.recallInjectionPosition as PluginConfig['recallInjectionPosition'] : undefined,
|
||||
recallTimeoutMs: typeof config.recallTimeoutMs === 'number' && config.recallTimeoutMs >= 1000 ? config.recallTimeoutMs : undefined,
|
||||
debug: config.debug ?? false,
|
||||
};
|
||||
}
|
||||
|
|
@ -1112,7 +1113,8 @@ export default function (api: MoltbotPluginAPI) {
|
|||
debug(`[Hindsight] Reusing in-flight recall for bank ${bankId}`);
|
||||
recallPromise = existing;
|
||||
} else {
|
||||
recallPromise = client.recall({ query: prompt, max_tokens: pluginConfig.recallMaxTokens || 1024, budget: pluginConfig.recallBudget, types: pluginConfig.recallTypes }, RECALL_TIMEOUT_MS);
|
||||
const recallTimeoutMs = pluginConfig.recallTimeoutMs ?? DEFAULT_RECALL_TIMEOUT_MS;
|
||||
recallPromise = client.recall({ query: prompt, max_tokens: pluginConfig.recallMaxTokens || 1024, budget: pluginConfig.recallBudget, types: pluginConfig.recallTypes }, recallTimeoutMs);
|
||||
inflightRecalls.set(recallKey, recallPromise);
|
||||
void recallPromise.catch(() => {}).finally(() => inflightRecalls.delete(recallKey));
|
||||
}
|
||||
|
|
@ -1156,9 +1158,9 @@ ${memoriesFormatted}
|
|||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DOMException && error.name === 'TimeoutError') {
|
||||
console.warn(`[Hindsight] Auto-recall timed out after ${RECALL_TIMEOUT_MS}ms, skipping memory injection`);
|
||||
console.warn(`[Hindsight] Auto-recall timed out after ${pluginConfig.recallTimeoutMs ?? DEFAULT_RECALL_TIMEOUT_MS}ms, skipping memory injection`);
|
||||
} else if (error instanceof Error && error.name === 'AbortError') {
|
||||
console.warn(`[Hindsight] Auto-recall aborted after ${RECALL_TIMEOUT_MS}ms, skipping memory injection`);
|
||||
console.warn(`[Hindsight] Auto-recall aborted after ${pluginConfig.recallTimeoutMs ?? DEFAULT_RECALL_TIMEOUT_MS}ms, skipping memory injection`);
|
||||
} else {
|
||||
console.error('[Hindsight] Auto-recall error:', error);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ export interface PluginConfig {
|
|||
retainOverlapTurns?: number; // Extra prior turns included when chunked retention fires (default: 0). Window = retainEveryNTurns + retainOverlapTurns.
|
||||
recallTopK?: number; // Max number of memories to inject. Default: unlimited
|
||||
recallContextTurns?: number; // Number of user turns to include in recall query context. Default: 1 (latest only)
|
||||
recallTimeoutMs?: number; // Timeout for auto-recall in milliseconds. Default: 10000
|
||||
recallMaxQueryChars?: number; // Max chars for composed recall query. Default: 800
|
||||
recallPromptPreamble?: string; // Prompt preamble placed above recalled memories. Default: built-in guidance text.
|
||||
recallInjectionPosition?: 'prepend' | 'append' | 'user'; // Where to inject recalled memories. 'prepend' = start of system prompt (default), 'append' = end of system prompt (preserves prompt cache), 'user' = before user message.
|
||||
|
|
|
|||
Loading…
Reference in a new issue