Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugin/hooks/hooks.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"description": "Supermemory: persistent memory for Claude Code. Injection hooks (SessionStart, UserPromptSubmit, PreToolUse) must stay synchronous — async hooks' output is discarded, which would silently kill context injection and auto-approval. They fail open instead: every network call is capped at 3s and the hook timeout is a backstop, so a dead network never stalls the session. Capture has no output anyone reads, so it runs async.",
"description": "Supermemory hooks: SessionStart loads project memories; UserPromptSubmit recalls memories relevant to the prompt; PreToolUse approves read-only Supermemory tool calls; Stop saves new conversation content to memory.",
"hooks": {
"SessionStart": [
{
Expand Down
4 changes: 2 additions & 2 deletions plugin/hooks/lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ SKIP:
- Granular details that do not help future work`;

// Hooks sit between the user and Claude — a slow or dead network must never
// hold the session hostage, so every request is capped hard at 3s and callers
// treat failure as "no memory this time", not a blocker.
// hold the session hostage. Requests default to 3s; prompt recall allows 4s.
// Callers treat failure as "no memory this time", not a blocker.
const REQUEST_TIMEOUT_MS = 3000;

async function post(baseUrl, apiKey, path, body, timeoutMs = REQUEST_TIMEOUT_MS) {
Expand Down
7 changes: 6 additions & 1 deletion plugin/hooks/recall-directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const MAX_QUERY_LENGTH = 500;
const MAX_RESULTS = 5;
const MAX_RESULT_CHARS = 300;
const MIN_SIMILARITY = 0.55;
const SEARCH_TIMEOUT_MS = 3000;
const SEARCH_TIMEOUT_MS = 4000;
const MAX_SEEN_HASHES = 500;

function shouldSkip(prompt) {
Expand Down Expand Up @@ -188,6 +188,11 @@ async function main() {
});
} catch (err) {
debugLog(settings, 'Recall directive error', { error: err.message });
// A slow recall should not interrupt every prompt with an error banner.
if (err?.name === 'TimeoutError' || err?.name === 'AbortError') {
writeOutput({ continue: true, suppressOutput: true });
return;
}
writeOutput({
systemMessage: `${BRAND} ${gray('·')} ${red(`recall failed: ${getUserFriendlyError(err).slice(0, 80)}`)}`,
continue: true,
Expand Down
Loading