前言

在AI辅助编程实践中,Claude Code已成为开发者的得力助手。然而,Claude Code的对话历史无法持久化保存,每次新会话都无法访问之前的上下文信息,这影响了开发效率。

为解决这个问题,Claude-Mem作为一个专门为Claude Code设计的插件应运而生,提供持久化记忆能力。但Claude-Mem原生支持的GEMINI和OPENROUTER等AI提供商存在速率和额度限制,成为新的瓶颈。

本文介绍Claude-Mem如何通过自定义API支持功能突破这些限制,并修复因Claude平台升级导致的上下文显示问题,具有实际应用价值。

问题分析

速率和额度限制问题

Claude-Mem原生支持Anthropic、GEMINI、OPENROUTER等多种AI提供商,但存在以下限制:

  • 用户无法使用自己的模型部署(如本地模型、企业模型)
  • 无法使用其他AI提供商的API(如OpenAI、Azure OpenAI等)
  • 不同地区访问官方API可能面临网络或合规性问题
  • 原生提供商的速率和额度限制影响高频使用场景

上下文显示问题

由于Claude平台升级,原有的上下文处理机制出现兼容性问题,导致:

  • 对话历史无法正常显示
  • 上下文注入功能失效
  • 用户无法查看和管理会话记忆
  • 降低整体用户体验

解决方案

自定义API代理实现

Claude-Mem引入了CustomApiAgent类,这是自定义API支持的核心实现。通过配置参数动态选择API端点,包含速率限制、错误处理等重要功能。

 1// src/services/worker/CustomApiAgent.ts
 2export class CustomApiAgent {
 3  private dbManager: DatabaseManager;
 4  private sessionManager: SessionManager;
 5  private fallbackAgent: FallbackAgent | null = null;
 6
 7  // Rate limiting implementation
 8  private requestQueue: Array<{
 9    config: CustomApiConfig;
10    history: ConversationMessage[];
11    resolve: (value: { content: string; tokensUsed?: number }) => void;
12    reject: (reason: any) => void;
13  }> = [];
14  private isProcessing: boolean = false;
15  private readonly rateLimitDelay: number = 1000; // 1 second delay between requests
16
17  constructor(dbManager: DatabaseManager, sessionManager: SessionManager) {
18    this.dbManager = dbManager;
19    this.sessionManager = sessionManager;
20  }
21
22  // ... 其他实现细节
23}

这个实现包含多个关键特性:

1. 队列管理与速率限制

CustomApiAgent使用队列机制管理API请求频率,避免请求过于频繁:

 1private async processQueue(): Promise<void> {
 2  if (this.isProcessing || this.requestQueue.length === 0) {
 3    return;
 4  }
 5
 6  this.isProcessing = true;
 7
 8  while (this.requestQueue.length > 0) {
 9    const { config, history, resolve, reject } = this.requestQueue.shift()!;
10
11    try {
12      const result = await this.executeCustomApiRequest(config, history);
13      resolve(result);
14    } catch (error) {
15      reject(error);
16    }
17
18    // Wait before processing the next request to implement rate limiting
19    if (this.requestQueue.length > 0) {
20      await this.delay(this.rateLimitDelay);
21    }
22  }
23
24  this.isProcessing = false;
25}

注意事项: 通过1秒的延迟机制,有效防止API调用超限。

2. 多格式API适配

CustomApiAgent支持Anthropic和OpenAI兼容的API格式,可动态识别不同提供商的API端点:

 1private async executeCustomApiRequest(
 2  config: CustomApiConfig,
 3  history: ConversationMessage[]
 4): Promise<{ content: string; tokensUsed?: number }> {
 5  const messages = this.conversationToOpenAIMessages(history);
 6
 7  // Determine the correct API endpoint based on provider name
 8  let apiUrl: string;
 9  if (config.providerName.toLowerCase() === 'anthropic') {
10    // For Anthropic-compatible API
11    apiUrl = `${config.baseUrl}/v1/messages`;
12  } else if (config.providerName.toLowerCase() === 'openai') {
13    // For OpenAI-compatible API
14    apiUrl = `${config.baseUrl}/v1/chat/completions`;
15  } else {
16    // Default to Anthropic-compatible API
17    apiUrl = `${config.baseUrl}/v1/messages`;
18  }
19
20  let requestBody: any;
21  if (config.providerName.toLowerCase() === 'anthropic') {
22    // Anthropic-compatible request format
23    requestBody = {
24      model: config.model,
25      messages,
26      max_tokens: 4096,
27      temperature: 0.3,
28    };
29  } else {
30    // OpenAI-compatible request format (default)
31    requestBody = {
32      model: config.model,
33      messages,
34      temperature: 0.3,
35      max_tokens: 4096,
36    };
37  }
38
39  // ... 请求执行和响应处理
40}

配置同步功能

Claude-Mem新增配置同步功能,自动从Claude Code的设置文件中读取API配置并应用到Claude-Mem中:

 1// src/utils/config-sync.ts
 2export function syncClaudeCodeSettingsToCustomApi(): void {
 3  try {
 4    const claudeCodeSettingsPath = join(homedir(), '.claude', 'settings.json');
 5
 6    if (!existsSync(claudeCodeSettingsPath)) {
 7      logger.info('CONFIG', 'Claude Code settings file not found, skipping sync', {
 8        path: claudeCodeSettingsPath
 9      });
10      return;
11    }
12
13    const settingsContent = readFileSync(claudeCodeSettingsPath, 'utf-8');
14    const settings: ClaudeCodeSettings = JSON.parse(settingsContent);
15
16    // Extract environment variables from Claude Code settings
17    const env = settings.env || {};
18
19    // Map Claude Code env variables to claude-mem custom API settings
20    const customApiSettings = {
21      CLAUDE_MEM_CUSTOM_API_BASE_URL: env.ANTHROPIC_BASE_URL || '',
22      CLAUDE_MEM_CUSTOM_API_KEY: env.ANTHROPIC_API_KEY || env.ANTHROPIC_AUTH_TOKEN || '',
23      CLAUDE_MEM_CUSTOM_API_MODEL: env.CLAUDE_MEM_CUSTOM_API_MODEL || 'iflow,qwen3-coder-plus',
24      CLAUDE_MEM_CUSTOM_API_PROVIDER_NAME: env.ANTHROPIC_BASE_URL ? 'anthropic' : 'custom'
25    };
26
27    // Update claude-mem settings if custom provider is selected
28    const currentSettingsPath = join(homedir(), '.claude-mem', 'settings.json');
29    const currentSettings = SettingsDefaultsManager.loadFromFile(currentSettingsPath);
30
31    if (currentSettings.CLAUDE_MEM_PROVIDER === 'custom') {
32      // Only update if custom API settings are not already configured
33      // This prevents overwriting user's manual settings
34      if (!currentSettings.CLAUDE_MEM_CUSTOM_API_BASE_URL) {
35        logger.info('CONFIG', 'Syncing Claude Code settings to claude-mem custom API', {
36          ANTHROPIC_BASE_URL: customApiSettings.CLAUDE_MEM_CUSTOM_API_BASE_URL,
37          ANTHROPIC_API_KEY: customApiSettings.CLAUDE_MEM_CUSTOM_API_KEY ? '[HIDDEN]' : '[NOT SET]'
38        });
39
40        // Write updated settings to claude-mem settings file
41        updateClaudeMemSettings(customApiSettings, currentSettingsPath);
42      }
43    }
44  } catch (error) {
45    logger.error('CONFIG', 'Failed to sync Claude Code settings to custom API', {}, error as Error);
46  }
47}

注意事项: 配置同步会先检查是否已有手动配置,避免覆盖用户设置。

会话路由重构

Claude-Mem实现智能代理选择机制,根据设置自动选择合适的AI提供商:

 1private getActiveAgent(): SDKAgent | GeminiAgent | OpenRouterAgent | CustomApiAgent {
 2  if (isCustomApiSelected()) {
 3    if (isCustomApiAvailable()) {
 4      logger.debug('SESSION', 'Using Custom API agent');
 5      return this.customApiAgent;
 6    } else {
 7      throw new Error('Custom API provider selected but no base URL configured. Set CLAUDE_MEM_CUSTOM_API_BASE_URL in settings.');
 8    }
 9  }
10  if (isOpenRouterSelected()) {
11    if (isOpenRouterAvailable()) {
12      logger.debug('SESSION', 'Using OpenRouter agent');
13      return this.openRouterAgent;
14    } else {
15      throw new Error('OpenRouter provider selected but no API key configured. Set CLAUDE_MEM_OPENROUTER_API_KEY in settings or OPENROUTER_API_KEY environment variable.');
16    }
17  }
18  if (isGeminiSelected()) {
19    if (isGeminiAvailable()) {
20      logger.debug('SESSION', 'Using Gemini agent');
21      return this.geminiAgent;
22    } else {
23      throw new Error('Gemini provider selected but no API key configured. Set CLAUDE_MEM_GEMINI_API_KEY in settings or GEMINI_API_KEY environment variable.');
24    }
25  }
26  return this.sdkAgent;
27}

上下文处理修复

针对Claude升级导致的上下文显示问题,Claude-Mem修改了上下文传递方式:

 1// src/cli/adapters/claude-code.ts
 2formatOutput(result) {
 3  if (result.hookSpecificOutput) {
 4    if (result.hookSpecificOutput.additionalContext) {
 5        return { hookSpecificOutput: result.hookSpecificOutput, systemMessage: result.hookSpecificOutput.additionalContext };
 6    } else {
 7        return { hookSpecificOutput: result.hookSpecificOutput };
 8    }
 9  }
10  return { continue: result.continue ?? true, suppressOutput: result.suppressOutput ?? true };
11}

关键改进: 通过添加systemMessage字段,确保上下文信息正确注入Claude会话。

使用说明

配置自定义API

用户可以通过以下方式配置自定义API:

方式一:通过Claude Code设置文件(推荐)

~/.claude/settings.json 中添加配置:

1{
2  "env": {
3    "ANTHROPIC_BASE_URL": "https://your-custom-endpoint.com/v1",
4    "ANTHROPIC_API_KEY": "your-api-key",
5    "CLAUDE_MEM_CUSTOM_API_MODEL": "your-model-name"
6  }
7}

方式二:直接配置Claude-Mem设置

~/.claude-mem/settings.json 中配置:

1{
2  "CLAUDE_MEM_PROVIDER": "custom",
3  "CLAUDE_MEM_CUSTOM_API_BASE_URL": "https://your-custom-endpoint.com/v1",
4  "CLAUDE_MEM_CUSTOM_API_KEY": "your-api-key",
5  "CLAUDE_MEM_CUSTOM_API_MODEL": "your-model-name",
6  "CLAUDE_MEM_CUSTOM_API_PROVIDER_NAME": "anthropic"
7}

配置更改后,重启Claude-Mem服务:

1# 停止服务
2claude-mem stop
3
4# 启动服务
5claude-mem start

总结

Claude-Mem的自定义API支持功能解决了原生API提供商的速率和额度限制问题。通过CustomApiAgent实现多格式API适配,配置同步功能简化设置流程,上下文处理修复确保兼容性。

该功能为开发者提供了更灵活的AI编程助手,可根据需求选择合适的API提供商,专注于创造性工作。