68290a9121
* refactor: Reduce continuation prompt token usage by 95 lines Removed redundant instructions from continuation prompt that were originally added to mitigate a session continuity issue. That issue has since been resolved, making these detailed instructions unnecessary on every continuation. Changes: - Reduced continuation prompt from ~106 lines to ~11 lines (~95 line reduction) - Changed "User's Goal:" to "Next Prompt in Session:" (more accurate framing) - Removed redundant WHAT TO RECORD, WHEN TO SKIP, and OUTPUT FORMAT sections - Kept concise reminder: "Continue generating observations and progress summaries..." - Initial prompt still contains all detailed instructions Impact: - Significant token savings on every continuation prompt - Faster context injection with no loss of functionality - Instructions remain comprehensive in initial prompt Files modified: - src/sdk/prompts.ts (buildContinuationPrompt function) - plugin/scripts/worker-service.cjs (compiled output) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: Enhance observation and summary prompts for clarity and token efficiency * Enhance prompt clarity and instructions in prompts.ts - Added a reminder to think about instructions before starting work. - Simplified the continuation prompt instruction by removing "for this ongoing session." * feat: Enhance settings.json with permissions and deny access to sensitive files refactor: Remove PLAN-full-observation-display.md and PR_SUMMARY.md as they are no longer needed chore: Delete SECURITY_SUMMARY.md since it is redundant after recent changes fix: Update worker-service.cjs to streamline observation generation instructions cleanup: Remove src-analysis.md and src-tree.md for a cleaner codebase refactor: Modify prompts.ts to clarify instructions for memory processing * refactor: Remove legacy worker service implementation * feat: Enhance summary hook to extract last assistant message and improve logging - Added function to extract the last assistant message from the transcript. - Updated summary hook to include last assistant message in the summary request. - Modified SDKSession interface to store last assistant message. - Adjusted buildSummaryPrompt to utilize last assistant message for generating summaries. - Updated worker service and session manager to handle last assistant message in summarize requests. - Introduced silentDebug utility for improved logging and diagnostics throughout the summary process. * docs: Add comprehensive implementation plan for ROI metrics feature Added detailed implementation plan covering: - Token usage capture from Agent SDK - Database schema changes (migration #8) - Discovery cost tracking per observation - Context hook display with ROI metrics - Testing and rollout strategy Timeline: ~20 hours over 4 days Goal: Empirical data for YC application amendment 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: Add transcript processing scripts for analysis and formatting - Implemented `dump-transcript-readable.ts` to generate a readable markdown dump of transcripts, excluding certain entry types. - Created `extract-rich-context-examples.ts` to extract and showcase rich context examples from transcripts, highlighting user requests and assistant reasoning. - Developed `format-transcript-context.ts` to format transcript context into a structured markdown format for improved observation generation. - Added `test-transcript-parser.ts` for validating data extraction from transcript JSONL files, including statistics and error reporting. - Introduced `transcript-to-markdown.ts` for a complete representation of transcript data in markdown format, showing all context data. - Enhanced type definitions in `transcript.ts` to support new features and ensure type safety. - Built `transcript-parser.ts` to handle parsing of transcript JSONL files, including error handling and data extraction methods. * Refactor hooks and SDKAgent for improved observation handling - Updated `new-hook.ts` to clean user prompts by stripping leading slashes for better semantic clarity. - Enhanced `save-hook.ts` to include additional tools in the SKIP_TOOLS set, preventing unnecessary observations from certain command invocations. - Modified `prompts.ts` to change the structure of observation prompts, emphasizing the observational role and providing a detailed XML output format for observations. - Adjusted `SDKAgent.ts` to enforce stricter tool usage restrictions, ensuring the memory agent operates solely as an observer without any tool access. * feat: Enhance session initialization to accept user prompts and prompt numbers - Updated `handleSessionInit` in `worker-service.ts` to extract `userPrompt` and `promptNumber` from the request body and pass them to `initializeSession`. - Modified `initializeSession` in `SessionManager.ts` to handle optional `currentUserPrompt` and `promptNumber` parameters. - Added logic to update the existing session's `userPrompt` and `lastPromptNumber` if a `currentUserPrompt` is provided. - Implemented debug logging for session initialization and updates to track user prompts and prompt numbers. --------- Co-authored-by: Claude <noreply@anthropic.com>
116 lines
4.2 KiB
TypeScript
116 lines
4.2 KiB
TypeScript
/**
|
|
* New Hook - UserPromptSubmit
|
|
*
|
|
* DUAL PURPOSE HOOK: Handles BOTH session initialization AND continuation
|
|
* ==========================================================================
|
|
*
|
|
* CRITICAL ARCHITECTURE FACTS (NEVER FORGET):
|
|
*
|
|
* 1. SESSION ID THREADING - The Single Source of Truth
|
|
* - Claude Code assigns ONE session_id per conversation
|
|
* - ALL hooks in that conversation receive the SAME session_id
|
|
* - We ALWAYS use this session_id - NEVER generate our own
|
|
* - This is how NEW hook, SAVE hook, and SUMMARY hook stay connected
|
|
*
|
|
* 2. NO EXISTENCE CHECKS NEEDED
|
|
* - createSDKSession is idempotent (INSERT OR IGNORE)
|
|
* - Prompt #1: Creates new database row, returns new ID
|
|
* - Prompt #2+: Row exists, returns existing ID
|
|
* - We NEVER need to check "does session exist?" - just use the session_id
|
|
*
|
|
* 3. CONTINUATION LOGIC LOCATION
|
|
* - This hook does NOT contain continuation prompt logic
|
|
* - That lives in SDKAgent.ts (lines 125-127)
|
|
* - SDKAgent checks promptNumber to choose init vs continuation prompt
|
|
* - BOTH prompts receive the SAME session_id from this hook
|
|
*
|
|
* 4. UNIFIED WITH SAVE HOOK
|
|
* - SAVE hook uses: db.createSDKSession(session_id, '', '')
|
|
* - NEW hook uses: db.createSDKSession(session_id, project, prompt)
|
|
* - Both use session_id from hook context - this keeps everything connected
|
|
*
|
|
* This is KISS in action: Use the session_id we're given, trust idempotent
|
|
* database operations, and let SDKAgent handle init vs continuation logic.
|
|
*/
|
|
|
|
import path from 'path';
|
|
import { stdin } from 'process';
|
|
import { SessionStore } from '../services/sqlite/SessionStore.js';
|
|
import { createHookResponse } from './hook-response.js';
|
|
import { ensureWorkerRunning, getWorkerPort } from '../shared/worker-utils.js';
|
|
|
|
export interface UserPromptSubmitInput {
|
|
session_id: string;
|
|
cwd: string;
|
|
prompt: string;
|
|
[key: string]: any;
|
|
}
|
|
|
|
/**
|
|
* New Hook Main Logic
|
|
*/
|
|
async function newHook(input?: UserPromptSubmitInput): Promise<void> {
|
|
if (!input) {
|
|
throw new Error('newHook requires input');
|
|
}
|
|
|
|
const { session_id, cwd, prompt } = input;
|
|
const project = path.basename(cwd);
|
|
|
|
// Ensure worker is running
|
|
await ensureWorkerRunning();
|
|
|
|
const db = new SessionStore();
|
|
|
|
// CRITICAL: Use session_id from hook as THE source of truth
|
|
// createSDKSession is idempotent - creates new or returns existing
|
|
// This is how ALL hooks stay connected to the same session
|
|
const sessionDbId = db.createSDKSession(session_id, project, prompt);
|
|
const promptNumber = db.incrementPromptCounter(sessionDbId);
|
|
|
|
// Save raw user prompt for full-text search
|
|
db.saveUserPrompt(session_id, promptNumber, prompt);
|
|
|
|
console.error(`[new-hook] Session ${sessionDbId}, prompt #${promptNumber}`);
|
|
|
|
db.close();
|
|
|
|
const port = getWorkerPort();
|
|
|
|
// 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 session via HTTP
|
|
const response = await fetch(`http://127.0.0.1:${port}/sessions/${sessionDbId}/init`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ project, userPrompt: cleanedPrompt, promptNumber }),
|
|
signal: AbortSignal.timeout(5000)
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errorText = await response.text();
|
|
throw new Error(`Failed to initialize session: ${response.status} ${errorText}`);
|
|
}
|
|
} catch (error: any) {
|
|
// Only show restart message for connection errors, not HTTP errors
|
|
if (error.cause?.code === 'ECONNREFUSED' || error.name === 'TimeoutError' || error.message.includes('fetch failed')) {
|
|
throw new Error("There's a problem with the worker. If you just updated, type `pm2 restart claude-mem-worker` in your terminal to continue");
|
|
}
|
|
// Re-throw HTTP errors and other errors as-is
|
|
throw 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);
|
|
});
|