mirror of
https://github.com/thedotmack/claude-mem
synced 2026-04-25 17:15:04 +02:00
* 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>
178 lines
7.2 KiB
TypeScript
178 lines
7.2 KiB
TypeScript
#!/usr/bin/env tsx
|
|
/**
|
|
* Extract Rich Context Examples
|
|
* Shows what data we have available for memory worker using TranscriptParser API
|
|
*/
|
|
|
|
import { TranscriptParser } from '../src/utils/transcript-parser.js';
|
|
import { writeFileSync } from 'fs';
|
|
import type { AssistantTranscriptEntry, UserTranscriptEntry } from '../src/types/transcript.js';
|
|
|
|
const transcriptPath = process.argv[2];
|
|
|
|
if (!transcriptPath) {
|
|
console.error('Usage: tsx scripts/extract-rich-context-examples.ts <path-to-transcript.jsonl>');
|
|
process.exit(1);
|
|
}
|
|
|
|
const parser = new TranscriptParser(transcriptPath);
|
|
|
|
let output = '# Rich Context Examples\n\n';
|
|
output += 'This document shows what contextual data is available in transcripts\n';
|
|
output += 'that could improve observation generation quality.\n\n';
|
|
|
|
// Get stats using parser API
|
|
const stats = parser.getParseStats();
|
|
const tokens = parser.getTotalTokenUsage();
|
|
|
|
output += `## Statistics\n\n`;
|
|
output += `- Total entries: ${stats.parsedEntries}\n`;
|
|
output += `- User messages: ${stats.entriesByType['user'] || 0}\n`;
|
|
output += `- Assistant messages: ${stats.entriesByType['assistant'] || 0}\n`;
|
|
output += `- Token usage: ${(tokens.inputTokens + tokens.outputTokens).toLocaleString()} total\n`;
|
|
output += `- Cache efficiency: ${tokens.cacheReadTokens.toLocaleString()} tokens read from cache\n\n`;
|
|
|
|
// Extract conversation pairs with tool uses
|
|
const assistantEntries = parser.getAssistantEntries();
|
|
const userEntries = parser.getUserEntries();
|
|
|
|
output += `## Conversation Flow\n\n`;
|
|
output += `This shows how user requests, assistant reasoning, and tool executions flow together.\n`;
|
|
output += `This is the rich context currently missing from individual tool observations.\n\n`;
|
|
|
|
let examplesFound = 0;
|
|
const maxExamples = 5;
|
|
|
|
// Match assistant entries with their preceding user message
|
|
for (let i = 0; i < assistantEntries.length && examplesFound < maxExamples; i++) {
|
|
const assistantEntry = assistantEntries[i];
|
|
const content = assistantEntry.message.content;
|
|
|
|
if (!Array.isArray(content)) continue;
|
|
|
|
// Extract components from assistant message
|
|
const textBlocks = content.filter((c: any) => c.type === 'text');
|
|
const thinkingBlocks = content.filter((c: any) => c.type === 'thinking');
|
|
const toolUseBlocks = content.filter((c: any) => c.type === 'tool_use');
|
|
|
|
// Skip if no tools or only MCP tools
|
|
const regularTools = toolUseBlocks.filter((t: any) =>
|
|
!t.name.startsWith('mcp__')
|
|
);
|
|
|
|
if (regularTools.length === 0) continue;
|
|
|
|
// Find the user message that preceded this assistant response
|
|
let userMessage = '';
|
|
const assistantTimestamp = new Date(assistantEntry.timestamp).getTime();
|
|
|
|
for (const userEntry of userEntries) {
|
|
const userTimestamp = new Date(userEntry.timestamp).getTime();
|
|
if (userTimestamp < assistantTimestamp) {
|
|
// Extract user text using parser's helper
|
|
const extractText = (content: any): string => {
|
|
if (typeof content === 'string') return content;
|
|
if (Array.isArray(content)) {
|
|
return content
|
|
.filter((c: any) => c.type === 'text')
|
|
.map((c: any) => c.text)
|
|
.join('\n');
|
|
}
|
|
return '';
|
|
};
|
|
|
|
const text = extractText(userEntry.message.content);
|
|
if (text.trim()) {
|
|
userMessage = text;
|
|
}
|
|
}
|
|
}
|
|
|
|
examplesFound++;
|
|
output += `---\n\n`;
|
|
output += `### Example ${examplesFound}\n\n`;
|
|
|
|
// 1. User Request
|
|
if (userMessage) {
|
|
output += `#### 👤 User Request\n`;
|
|
const preview = userMessage.substring(0, 400);
|
|
output += `\`\`\`\n${preview}${userMessage.length > 400 ? '\n...(truncated)' : ''}\n\`\`\`\n\n`;
|
|
}
|
|
|
|
// 2. Assistant's Explanation (what it plans to do)
|
|
if (textBlocks.length > 0) {
|
|
const text = textBlocks.map((b: any) => b.text).join('\n');
|
|
output += `#### 🤖 Assistant's Plan\n`;
|
|
const preview = text.substring(0, 400);
|
|
output += `\`\`\`\n${preview}${text.length > 400 ? '\n...(truncated)' : ''}\n\`\`\`\n\n`;
|
|
}
|
|
|
|
// 3. Internal Reasoning (thinking)
|
|
if (thinkingBlocks.length > 0) {
|
|
const thinking = thinkingBlocks.map((b: any) => b.thinking).join('\n');
|
|
output += `#### 💭 Internal Reasoning\n`;
|
|
const preview = thinking.substring(0, 300);
|
|
output += `\`\`\`\n${preview}${thinking.length > 300 ? '\n...(truncated)' : ''}\n\`\`\`\n\n`;
|
|
}
|
|
|
|
// 4. Tool Executions
|
|
output += `#### 🔧 Tools Executed (${regularTools.length})\n\n`;
|
|
for (const tool of regularTools) {
|
|
const toolData = tool as any;
|
|
output += `**${toolData.name}**\n`;
|
|
|
|
// Show relevant input fields
|
|
const input = toolData.input;
|
|
if (toolData.name === 'Read') {
|
|
output += `- Reading: \`${input.file_path}\`\n`;
|
|
} else if (toolData.name === 'Write') {
|
|
output += `- Writing: \`${input.file_path}\` (${input.content?.length || 0} chars)\n`;
|
|
} else if (toolData.name === 'Edit') {
|
|
output += `- Editing: \`${input.file_path}\`\n`;
|
|
} else if (toolData.name === 'Bash') {
|
|
output += `- Command: \`${input.command}\`\n`;
|
|
} else if (toolData.name === 'Glob') {
|
|
output += `- Pattern: \`${input.pattern}\`\n`;
|
|
} else if (toolData.name === 'Grep') {
|
|
output += `- Searching for: \`${input.pattern}\`\n`;
|
|
} else {
|
|
output += `\`\`\`json\n${JSON.stringify(input, null, 2).substring(0, 200)}\n\`\`\`\n`;
|
|
}
|
|
}
|
|
output += `\n`;
|
|
|
|
// Summary of what data is available
|
|
output += `**📊 Data Available for This Exchange:**\n`;
|
|
output += `- User intent: ✅ (${userMessage.length} chars)\n`;
|
|
output += `- Assistant reasoning: ✅ (${textBlocks.reduce((sum, b: any) => sum + b.text.length, 0)} chars)\n`;
|
|
output += `- Thinking process: ${thinkingBlocks.length > 0 ? '✅' : '❌'} ${thinkingBlocks.length > 0 ? `(${thinkingBlocks.reduce((sum, b: any) => sum + b.thinking.length, 0)} chars)` : ''}\n`;
|
|
output += `- Tool executions: ✅ (${regularTools.length} tools)\n`;
|
|
output += `- **Currently sent to memory worker:** Tool inputs/outputs only (no context!) ❌\n\n`;
|
|
}
|
|
|
|
output += `\n---\n\n`;
|
|
output += `## Key Insight\n\n`;
|
|
output += `Currently, the memory worker receives **isolated tool executions** via save-hook:\n`;
|
|
output += `- tool_name: "Read"\n`;
|
|
output += `- tool_input: {"file_path": "src/foo.ts"}\n`;
|
|
output += `- tool_output: {file contents}\n\n`;
|
|
output += `But the transcript contains **rich contextual data**:\n`;
|
|
output += `- WHY the tool was used (user's request)\n`;
|
|
output += `- WHAT the assistant planned to accomplish\n`;
|
|
output += `- HOW it fits into the broader task\n`;
|
|
output += `- The assistant's reasoning/thinking\n`;
|
|
output += `- Multiple related tools used together\n\n`;
|
|
output += `This context would help the memory worker:\n`;
|
|
output += `1. Understand if a tool use is meaningful or routine\n`;
|
|
output += `2. Generate observations that capture WHY, not just WHAT\n`;
|
|
output += `3. Group related tools into coherent actions\n`;
|
|
output += `4. Avoid "investigating" - the context is already present\n\n`;
|
|
|
|
// Write to file
|
|
const outputPath = '/Users/alexnewman/Scripts/claude-mem/docs/context/rich-context-examples.md';
|
|
writeFileSync(outputPath, output, 'utf-8');
|
|
|
|
console.log(`\nExtracted ${examplesFound} examples with rich context`);
|
|
console.log(`Written to: ${outputPath}\n`);
|
|
console.log(`This shows the gap between what's available (rich context) and what's sent (isolated tools)\n`);
|