Skip to content

Commit 2e5acfb

Browse files
fix(hooks): Write pending prompts to correct config location
- Save pending prompts to sms-notify.json instead of separate file - Use correct format (key/label options, type field) for webhook matching - Add debug logging to claude-session-debug.log - Extend prompt TTL from 10 min to 1 hour
1 parent 4684ece commit 2e5acfb

1 file changed

Lines changed: 69 additions & 35 deletions

File tree

templates/claude-hooks/notify-review-hook.js

Lines changed: 69 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ for (const envPath of envPaths) {
4040
}
4141

4242
const CONFIG_PATH = path.join(os.homedir(), '.stackmemory', 'sms-notify.json');
43-
const PENDING_PATH = path.join(
43+
const DEBUG_LOG = path.join(
4444
os.homedir(),
4545
'.stackmemory',
46-
'sms-pending-prompts.json'
46+
'claude-session-debug.log'
4747
);
4848

4949
function loadConfig() {
@@ -52,25 +52,44 @@ function loadConfig() {
5252
return JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
5353
}
5454
} catch {}
55-
return { enabled: false };
55+
return { enabled: false, pendingPrompts: [] };
5656
}
5757

58-
function savePendingPrompt(prompt) {
58+
function saveConfig(config) {
5959
try {
6060
const dir = path.join(os.homedir(), '.stackmemory');
6161
if (!fs.existsSync(dir)) {
6262
fs.mkdirSync(dir, { recursive: true });
6363
}
64-
let pending = { prompts: [] };
65-
if (fs.existsSync(PENDING_PATH)) {
66-
pending = JSON.parse(fs.readFileSync(PENDING_PATH, 'utf8'));
64+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
65+
} catch (err) {
66+
console.error('[notify-hook] Failed to save config:', err.message);
67+
}
68+
}
69+
70+
function logDebug(event, data) {
71+
try {
72+
const entry = `[${new Date().toISOString()}] ${event}: ${typeof data === 'string' ? data : JSON.stringify(data)}\n`;
73+
fs.appendFileSync(DEBUG_LOG, entry);
74+
} catch {}
75+
}
76+
77+
function savePendingPrompt(prompt) {
78+
try {
79+
const config = loadConfig();
80+
if (!config.pendingPrompts) {
81+
config.pendingPrompts = [];
6782
}
68-
pending.prompts.push(prompt);
83+
config.pendingPrompts.push(prompt);
6984
// Keep only last 10 prompts
70-
if (pending.prompts.length > 10) {
71-
pending.prompts = pending.prompts.slice(-10);
85+
if (config.pendingPrompts.length > 10) {
86+
config.pendingPrompts = config.pendingPrompts.slice(-10);
7287
}
73-
fs.writeFileSync(PENDING_PATH, JSON.stringify(pending, null, 2));
88+
saveConfig(config);
89+
logDebug('PENDING_PROMPT', {
90+
id: prompt.id,
91+
options: prompt.options.length,
92+
});
7493
} catch (err) {
7594
console.error('[notify-hook] Failed to save pending prompt:', err.message);
7695
}
@@ -85,40 +104,46 @@ function shouldNotify(toolName, toolInput, output) {
85104
const questions = toolInput?.questions || [];
86105
if (questions.length === 0) return null;
87106

88-
// Format questions for WhatsApp
89-
const formattedQuestions = questions.map((q, qIdx) => {
90-
let text = q.question;
91-
if (q.options && q.options.length > 0) {
92-
text += '\n';
93-
q.options.forEach((opt, i) => {
94-
text += `${i + 1}. ${opt.label}`;
95-
if (opt.description) {
96-
text += ` - ${opt.description}`;
97-
}
98-
text += '\n';
99-
});
100-
text += `${q.options.length + 1}. Other (type your answer)`;
101-
}
102-
return { index: qIdx, text, options: q.options, header: q.header };
103-
});
104-
105-
// Store pending prompt for response matching
107+
// Take first question (most common case)
108+
const q = questions[0];
106109
const promptId = Math.random().toString(36).substring(2, 10);
110+
111+
// Build message text
112+
let messageText = q.question;
113+
const options = [];
114+
115+
if (q.options && q.options.length > 0) {
116+
messageText += '\n';
117+
q.options.forEach((opt, i) => {
118+
const key = String(i + 1);
119+
messageText += `${key}. ${opt.label}`;
120+
if (opt.description) {
121+
messageText += ` - ${opt.description}`;
122+
}
123+
messageText += '\n';
124+
options.push({ key, label: opt.label });
125+
});
126+
// Add "Other" option
127+
const otherKey = String(q.options.length + 1);
128+
messageText += `${otherKey}. Other (type your answer)`;
129+
options.push({ key: otherKey, label: 'Other' });
130+
}
131+
132+
// Store pending prompt in format webhook expects
107133
const pendingPrompt = {
108134
id: promptId,
109135
timestamp: new Date().toISOString(),
110-
questions: formattedQuestions,
111-
expiresAt: new Date(Date.now() + 10 * 60 * 1000).toISOString(), // 10 min
136+
message: q.question,
137+
options: options,
138+
type: options.length > 0 ? 'options' : 'freeform',
139+
expiresAt: new Date(Date.now() + 60 * 60 * 1000).toISOString(), // 1 hour
112140
};
113141
savePendingPrompt(pendingPrompt);
114142

115-
// Build message
116-
const message = formattedQuestions.map((q) => q.text).join('\n\n');
117-
118143
return {
119144
type: 'custom',
120145
title: 'Claude needs your input',
121-
message: message,
146+
message: messageText,
122147
promptId: promptId,
123148
isQuestion: true,
124149
};
@@ -282,8 +307,14 @@ function sendNotification(notification) {
282307
console.error(
283308
`[notify-hook] Sent via ${numbers.channel}: ${notification.title}`
284309
);
310+
logDebug('MESSAGE_SENT', {
311+
channel: numbers.channel,
312+
title: notification.title,
313+
promptId: notification.promptId,
314+
});
285315
} else {
286316
console.error(`[notify-hook] Failed (${res.statusCode}): ${body}`);
317+
logDebug('MESSAGE_FAILED', { status: res.statusCode, error: body });
287318
}
288319
});
289320
});
@@ -305,6 +336,8 @@ process.stdin.on('end', () => {
305336
const hookData = JSON.parse(input);
306337
const { tool_name, tool_input, tool_output } = hookData;
307338

339+
logDebug('PostToolUse', { tool: tool_name, session: hookData.session_id });
340+
308341
const notification = shouldNotify(tool_name, tool_input, tool_output);
309342

310343
if (notification) {
@@ -314,6 +347,7 @@ process.stdin.on('end', () => {
314347
// Always allow (post-tool hooks don't block)
315348
console.log(JSON.stringify({ status: 'ok' }));
316349
} catch (err) {
350+
logDebug('ERROR', err.message);
317351
console.error('[notify-hook] Error:', err.message);
318352
console.log(JSON.stringify({ status: 'ok' }));
319353
}

0 commit comments

Comments
 (0)