diff --git a/README.md b/README.md index 40e7d05..9b6eb3e 100644 --- a/README.md +++ b/README.md @@ -144,8 +144,21 @@ export EPISODIC_MEMORY_API_TOKEN=your-token # Increase timeout for slow endpoints (milliseconds) export EPISODIC_MEMORY_API_TIMEOUT_MS=3000000 + +# Load Claude Code settings (comma-separated: user, project, local) +export EPISODIC_MEMORY_CLAUDE_CODE_SETTING_SOURCES=user ``` +The `EPISODIC_MEMORY_CLAUDE_CODE_SETTING_SOURCES` variable controls which [Claude Code settings](https://docs.anthropic.com/en/docs/claude-code/settings) are loaded during summarization. By default, no settings are loaded (SDK isolation mode). Accepts a comma-separated list of: + +| Value | Settings file | Description | +|-------|---------------|-------------| +| `user` | `~/.claude/settings.json` | Global user settings (e.g. `awsCredentialExport` for Bedrock) | +| `project` | `.claude/settings.json` | Shared project settings (version-controlled) | +| `local` | `.claude/settings.local.json` | Local project overrides (typically gitignored) | + +**Recommended:** Leave empty or use `user` only. The `project` and `local` sources also load CLAUDE.md files and MCP servers into the summarization context, which can interfere with summary quality. + These settings only affect episodic-memory's summarization calls, not your interactive Claude sessions. ### What's Affected diff --git a/dist/summarizer.js b/dist/summarizer.js index f24cb83..ae94ba5 100644 --- a/dist/summarizer.js +++ b/dist/summarizer.js @@ -10,6 +10,7 @@ import { SUMMARIZER_CONTEXT_MARKER } from './constants.js'; * - EPISODIC_MEMORY_API_BASE_URL: Custom API endpoint * - EPISODIC_MEMORY_API_TOKEN: Auth token for custom endpoint * - EPISODIC_MEMORY_API_TIMEOUT_MS: Timeout for API calls (default: SDK default) + * - EPISODIC_MEMORY_CLAUDE_CODE_SETTING_SOURCES: Comma-separated list of Claude Code setting sources to load (default: none) */ function getApiEnv() { const baseUrl = process.env.EPISODIC_MEMORY_API_BASE_URL; @@ -26,6 +27,18 @@ function getApiEnv() { ...(timeoutMs && { API_TIMEOUT_MS: timeoutMs }), }; } +/** + * Get setting sources for SDK configuration. + * Parses EPISODIC_MEMORY_CLAUDE_CODE_SETTING_SOURCES as comma-separated list. + * Default: empty (no settings loaded). Set to 'user' to load user settings (e.g., awsCredentialExport for Bedrock) + */ +function getSettingSources() { + const sources = process.env.EPISODIC_MEMORY_CLAUDE_CODE_SETTING_SOURCES; + if (!sources) { + return undefined; + } + return sources.split(',').map(s => s.trim()).filter(Boolean); +} export function formatConversationText(exchanges) { return exchanges.map(ex => { return `User: ${ex.userMessage}\n\nAgent: ${ex.assistantMessage}`; @@ -39,6 +52,10 @@ function extractSummary(text) { // Fallback if no tags found return text.trim(); } +/** + * Call Claude API to generate a summary. + * Uses the configured model and settings, with automatic fallback on errors. + */ async function callClaude(prompt, sessionId, useFallback = false) { const primaryModel = process.env.EPISODIC_MEMORY_API_MODEL || 'haiku'; const fallbackModel = process.env.EPISODIC_MEMORY_API_MODEL_FALLBACK || 'sonnet'; @@ -50,6 +67,8 @@ async function callClaude(prompt, sessionId, useFallback = false) { max_tokens: 4096, env: getApiEnv(), resume: sessionId, + // Load settings to pick up API config (e.g., awsCredentialExport for Bedrock) + settingSources: getSettingSources(), // Don't override systemPrompt when resuming - it uses the original session's prompt // Instead, the prompt itself should provide clear instructions ...(sessionId ? {} : { diff --git a/src/summarizer.ts b/src/summarizer.ts index 85ba8d0..2a7e1b3 100644 --- a/src/summarizer.ts +++ b/src/summarizer.ts @@ -12,6 +12,7 @@ import { SUMMARIZER_CONTEXT_MARKER } from './constants.js'; * - EPISODIC_MEMORY_API_BASE_URL: Custom API endpoint * - EPISODIC_MEMORY_API_TOKEN: Auth token for custom endpoint * - EPISODIC_MEMORY_API_TIMEOUT_MS: Timeout for API calls (default: SDK default) + * - EPISODIC_MEMORY_CLAUDE_CODE_SETTING_SOURCES: Comma-separated list of Claude Code setting sources to load (default: none) */ function getApiEnv(): Record | undefined { const baseUrl = process.env.EPISODIC_MEMORY_API_BASE_URL; @@ -31,6 +32,19 @@ function getApiEnv(): Record | undefined { }; } +/** + * Get setting sources for SDK configuration. + * Parses EPISODIC_MEMORY_CLAUDE_CODE_SETTING_SOURCES as comma-separated list. + * Default: empty (no settings loaded). Set to 'user' to load user settings (e.g., awsCredentialExport for Bedrock) + */ +function getSettingSources(): string[] | undefined { + const sources = process.env.EPISODIC_MEMORY_CLAUDE_CODE_SETTING_SOURCES; + if (!sources) { + return undefined; + } + return sources.split(',').map(s => s.trim()).filter(Boolean); +} + export function formatConversationText(exchanges: ConversationExchange[]): string { return exchanges.map(ex => { return `User: ${ex.userMessage}\n\nAgent: ${ex.assistantMessage}`; @@ -46,6 +60,10 @@ function extractSummary(text: string): string { return text.trim(); } +/** + * Call Claude API to generate a summary. + * Uses the configured model and settings, with automatic fallback on errors. + */ async function callClaude(prompt: string, sessionId?: string, useFallback = false): Promise { const primaryModel = process.env.EPISODIC_MEMORY_API_MODEL || 'haiku'; const fallbackModel = process.env.EPISODIC_MEMORY_API_MODEL_FALLBACK || 'sonnet'; @@ -58,6 +76,8 @@ async function callClaude(prompt: string, sessionId?: string, useFallback = fals max_tokens: 4096, env: getApiEnv(), resume: sessionId, + // Load settings to pick up API config (e.g., awsCredentialExport for Bedrock) + settingSources: getSettingSources(), // Don't override systemPrompt when resuming - it uses the original session's prompt // Instead, the prompt itself should provide clear instructions ...(sessionId ? {} : {