7fdf5e75ab
- Removed all instances of happy_path_error__with_fallback from various hooks, services, and utilities. - Introduced logger.happyPathError for consistent logging of unexpected nulls and fallback values. - Updated the logger utility to include a new happyPathError method with enhanced context and stack trace. - Deprecated silent-debug utility as all logging functionality has been migrated to the logger.
110 lines
3.2 KiB
TypeScript
110 lines
3.2 KiB
TypeScript
import path from 'path';
|
|
import { stdin } from 'process';
|
|
import { createHookResponse } from './hook-response.js';
|
|
import { ensureWorkerRunning, getWorkerPort } from '../shared/worker-utils.js';
|
|
import { handleWorkerError } from '../shared/hook-error-handler.js';
|
|
import { handleFetchError } from './shared/error-handler.js';
|
|
|
|
export interface UserPromptSubmitInput {
|
|
session_id: string;
|
|
cwd: string;
|
|
prompt: string;
|
|
}
|
|
|
|
|
|
/**
|
|
* New Hook Main Logic
|
|
*/
|
|
async function newHook(input?: UserPromptSubmitInput): Promise<void> {
|
|
// Ensure worker is running before any other logic
|
|
await ensureWorkerRunning();
|
|
|
|
if (!input) {
|
|
throw new Error('newHook requires input');
|
|
}
|
|
|
|
const { session_id, cwd, prompt } = input;
|
|
const project = path.basename(cwd);
|
|
|
|
const port = getWorkerPort();
|
|
|
|
// Initialize session via HTTP - handles DB operations and privacy checks
|
|
let sessionDbId: number;
|
|
let promptNumber: number;
|
|
|
|
try {
|
|
const initResponse = await fetch(`http://127.0.0.1:${port}/api/sessions/init`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
claudeSessionId: session_id,
|
|
project,
|
|
prompt
|
|
}),
|
|
signal: AbortSignal.timeout(5000)
|
|
});
|
|
|
|
if (!initResponse.ok) {
|
|
const errorText = await initResponse.text();
|
|
handleFetchError(initResponse, errorText, {
|
|
hookName: 'new',
|
|
operation: 'Session initialization',
|
|
project,
|
|
port
|
|
});
|
|
}
|
|
|
|
const initResult = await initResponse.json();
|
|
sessionDbId = initResult.sessionDbId;
|
|
promptNumber = initResult.promptNumber;
|
|
|
|
// Check if prompt was entirely private (worker performs privacy check)
|
|
if (initResult.skipped && initResult.reason === 'private') {
|
|
console.error(`[new-hook] Session ${sessionDbId}, prompt #${promptNumber} (fully private - skipped)`);
|
|
console.log(createHookResponse('UserPromptSubmit', true));
|
|
return;
|
|
}
|
|
|
|
console.error(`[new-hook] Session ${sessionDbId}, prompt #${promptNumber}`);
|
|
} catch (error: any) {
|
|
handleWorkerError(error);
|
|
}
|
|
|
|
// Strip leading slash from commands for memory agent
|
|
// /review 101 → review 101 (more semantic for observations)
|
|
const cleanedPrompt = prompt.startsWith('/') ? prompt.substring(1) : prompt;
|
|
|
|
try {
|
|
// Initialize SDK agent session via HTTP (starts the agent!)
|
|
const response = await fetch(`http://127.0.0.1:${port}/sessions/${sessionDbId}/init`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ userPrompt: cleanedPrompt, promptNumber }),
|
|
signal: AbortSignal.timeout(5000)
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errorText = await response.text();
|
|
handleFetchError(response, errorText, {
|
|
hookName: 'new',
|
|
operation: 'SDK agent start',
|
|
project,
|
|
port,
|
|
sessionId: String(sessionDbId)
|
|
});
|
|
}
|
|
} catch (error: any) {
|
|
handleWorkerError(error);
|
|
}
|
|
|
|
console.log(createHookResponse('UserPromptSubmit', true));
|
|
}
|
|
|
|
// Entry Point
|
|
let input = '';
|
|
stdin.on('data', (chunk) => input += chunk);
|
|
stdin.on('end', async () => {
|
|
const parsed = input ? JSON.parse(input) : undefined;
|
|
await newHook(parsed);
|
|
});
|