30b142d318
This commit fixes the session ID confusion identified in PR #475: PROBLEM: - Using contentSessionId (user's Claude Code session) for SDK resume was wrong - Memory agent conversation should persist across the entire user session - Each SDK call was starting fresh, losing memory agent continuity SOLUTION: 1. Semantic Renaming (clarity): - claudeSessionId → contentSessionId (user's observed session) - sdkSessionId → memorySessionId (memory agent's session for resume) - Database migration 17 renames columns accordingly 2. Memory Session ID Capture: - SDKAgent captures session_id from first SDK message - Persists to database via updateMemorySessionId() - SessionManager loads memorySessionId on session init 3. Resume Logic Fixed: - Only resume if memorySessionId captured from previous interaction - Enables memory agent continuity across user prompts Files changed: 33 (types, database, agents, hooks, routes) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
84 lines
2.4 KiB
TypeScript
84 lines
2.4 KiB
TypeScript
/**
|
|
* Save Hook - PostToolUse
|
|
*
|
|
* Pure HTTP client - sends data to worker, worker handles all database operations
|
|
* including privacy checks. This allows the hook to run under any runtime
|
|
* (Node.js or Bun) since it has no native module dependencies.
|
|
*/
|
|
|
|
import { stdin } from 'process';
|
|
import { STANDARD_HOOK_RESPONSE } from './hook-response.js';
|
|
import { logger } from '../utils/logger.js';
|
|
import { ensureWorkerRunning, getWorkerPort } from '../shared/worker-utils.js';
|
|
import { HOOK_TIMEOUTS } from '../shared/hook-constants.js';
|
|
|
|
export interface PostToolUseInput {
|
|
session_id: string;
|
|
cwd: string;
|
|
tool_name: string;
|
|
tool_input: any;
|
|
tool_response: any;
|
|
}
|
|
|
|
/**
|
|
* Save Hook Main Logic - Fire-and-forget HTTP client
|
|
*/
|
|
async function saveHook(input?: PostToolUseInput): Promise<void> {
|
|
// Ensure worker is running before any other logic
|
|
await ensureWorkerRunning();
|
|
|
|
if (!input) {
|
|
throw new Error('saveHook requires input');
|
|
}
|
|
|
|
const { session_id, cwd, tool_name, tool_input, tool_response } = input;
|
|
|
|
const port = getWorkerPort();
|
|
|
|
const toolStr = logger.formatTool(tool_name, tool_input);
|
|
|
|
logger.dataIn('HOOK', `PostToolUse: ${toolStr}`, {
|
|
workerPort: port
|
|
});
|
|
|
|
// Validate required fields before sending to worker
|
|
if (!cwd) {
|
|
throw new Error(`Missing cwd in PostToolUse hook input for session ${session_id}, tool ${tool_name}`);
|
|
}
|
|
|
|
// Send to worker - worker handles privacy check and database operations
|
|
const response = await fetch(`http://127.0.0.1:${port}/api/sessions/observations`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
contentSessionId: session_id,
|
|
tool_name,
|
|
tool_input,
|
|
tool_response,
|
|
cwd
|
|
}),
|
|
signal: AbortSignal.timeout(HOOK_TIMEOUTS.DEFAULT)
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`Observation storage failed: ${response.status}`);
|
|
}
|
|
|
|
logger.debug('HOOK', 'Observation sent successfully', { toolName: tool_name });
|
|
|
|
console.log(STANDARD_HOOK_RESPONSE);
|
|
}
|
|
|
|
// Entry Point
|
|
let input = '';
|
|
stdin.on('data', (chunk) => input += chunk);
|
|
stdin.on('end', async () => {
|
|
let parsed: PostToolUseInput | undefined;
|
|
try {
|
|
parsed = input ? JSON.parse(input) : undefined;
|
|
} catch (error) {
|
|
throw new Error(`Failed to parse hook input: ${error instanceof Error ? error.message : String(error)}`);
|
|
}
|
|
await saveHook(parsed);
|
|
});
|