@wu529778790/open-im 1.10.4 → 1.10.5-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,6 +13,7 @@ import { existsSync, readFileSync } from 'fs';
13
13
  import { homedir } from 'os';
14
14
  import { join } from 'path';
15
15
  import { createLogger } from '../logger.js';
16
+ import { refreshClaudeEnvToProcess } from '../config/file-io.js';
16
17
  import { toReplyPlainText } from '../shared/utils.js';
17
18
  const log = createLogger('ClaudeSDK');
18
19
  function loadUserPluginSettings() {
@@ -145,7 +146,9 @@ function isSessionCorruptionError(msg) {
145
146
  * @returns SDKSession 对象和实际的 sessionId
146
147
  */
147
148
  async function getOrCreateSession(sessionId, workDir, model, permissionMode) {
148
- const resolvedModel = model?.trim() || 'claude-opus-4-5';
149
+ // 刷新 Claude 环境变量(支持 cc switch 后无需重启即可生效)
150
+ refreshClaudeEnvToProcess();
151
+ const resolvedModel = model?.trim() || process.env.ANTHROPIC_MODEL?.trim() || 'claude-opus-4-5';
149
152
  if (activeSessions.size >= MAX_ACTIVE_SESSIONS) {
150
153
  throw new Error(`Session pool is full (${MAX_ACTIVE_SESSIONS}). Cannot create new session.`);
151
154
  }
@@ -1,6 +1,8 @@
1
1
  import type { AiCommand, FileConfig } from './types.js';
2
2
  export declare const CONFIG_PATH: string;
3
3
  export declare const CODEX_AUTH_PATHS: string[];
4
+ /** Claude 认证相关的环境变量 key 列表 */
5
+ export declare const CLAUDE_AUTH_ENV_KEYS: readonly ["ANTHROPIC_API_KEY", "ANTHROPIC_AUTH_TOKEN", "CLAUDE_CODE_OAUTH_TOKEN", "ANTHROPIC_BASE_URL", "ANTHROPIC_MODEL"];
4
6
  export declare function loadFileConfig(): FileConfig;
5
7
  export declare function saveFileConfig(raw: FileConfig): void;
6
8
  export declare function getClaudeConfigHome(): string;
@@ -9,3 +11,9 @@ export declare function saveClaudeSettingsEnv(env: Record<string, string>): void
9
11
  export declare function normalizeAiCommand(value: unknown, fallback: AiCommand): AiCommand;
10
12
  export declare function hasCodexAuth(): boolean;
11
13
  export declare function parseCommaSeparated(value: string): string[];
14
+ /**
15
+ * 将最新的 Claude 认证环境变量按优先级合并到 process.env。
16
+ * 优先级:shell 环境变量 > tools.claude.env(config.json) > ~/.claude/settings.json
17
+ * 启动时调用一次;cc switch 后再次调用即可生效。
18
+ */
19
+ export declare function refreshClaudeEnvToProcess(): void;
@@ -16,9 +16,24 @@ const OLD_ROOT_KEYS = [
16
16
  'claudeModel',
17
17
  ];
18
18
  const AI_COMMANDS = ['claude', 'codex', 'codebuddy'];
19
+ /** Claude 认证相关的环境变量 key 列表 */
20
+ export const CLAUDE_AUTH_ENV_KEYS = [
21
+ 'ANTHROPIC_API_KEY',
22
+ 'ANTHROPIC_AUTH_TOKEN',
23
+ 'CLAUDE_CODE_OAUTH_TOKEN',
24
+ 'ANTHROPIC_BASE_URL',
25
+ 'ANTHROPIC_MODEL',
26
+ ];
19
27
  // Config cache with mtime tracking
20
28
  let cachedConfig = null;
21
29
  let cachedClaudeEnv = null;
30
+ // 保存进程启动时 shell 环境中的 Claude 相关 key 原始值(优先级最高,不可被文件配置覆盖)
31
+ const originalShellEnv = {};
32
+ for (const key of CLAUDE_AUTH_ENV_KEYS) {
33
+ if (process.env[key] !== undefined) {
34
+ originalShellEnv[key] = process.env[key];
35
+ }
36
+ }
22
37
  function hasOldConfigFormat(raw) {
23
38
  const hasOld = OLD_ROOT_KEYS.some((k) => raw[k] !== undefined && raw[k] !== null);
24
39
  const hasNew = raw.tools && typeof raw.tools === 'object' && raw.tools.claude;
@@ -174,3 +189,28 @@ export function hasCodexAuth() {
174
189
  export function parseCommaSeparated(value) {
175
190
  return value.split(',').map((s) => s.trim()).filter(Boolean);
176
191
  }
192
+ /**
193
+ * 将最新的 Claude 认证环境变量按优先级合并到 process.env。
194
+ * 优先级:shell 环境变量 > tools.claude.env(config.json) > ~/.claude/settings.json
195
+ * 启动时调用一次;cc switch 后再次调用即可生效。
196
+ */
197
+ export function refreshClaudeEnvToProcess() {
198
+ const file = loadFileConfig();
199
+ const claudeToolEnv = (file.tools?.claude?.env ?? {});
200
+ const claudeSettingsEnv = loadClaudeSettingsEnv();
201
+ for (const key of CLAUDE_AUTH_ENV_KEYS) {
202
+ if (key in originalShellEnv) {
203
+ process.env[key] = originalShellEnv[key];
204
+ continue;
205
+ }
206
+ if (key in claudeToolEnv) {
207
+ process.env[key] = claudeToolEnv[key];
208
+ continue;
209
+ }
210
+ if (key in claudeSettingsEnv) {
211
+ process.env[key] = claudeSettingsEnv[key];
212
+ continue;
213
+ }
214
+ delete process.env[key];
215
+ }
216
+ }
package/dist/config.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export type { Platform, AiCommand, Config, FilePlatformTelegram, FilePlatformFeishu, FilePlatformQQ, FilePlatformWechat, FilePlatformWework, FilePlatformDingtalk, FilePlatformWorkBuddy, FileToolClaude, FileToolCodex, FileToolCodeBuddy, FileConfig, } from './config/types.js';
2
2
  import type { Platform, AiCommand, Config } from './config/types.js';
3
- export { CONFIG_PATH, loadFileConfig, saveFileConfig, getClaudeConfigHome, loadClaudeSettingsEnv, saveClaudeSettingsEnv, normalizeAiCommand, hasCodexAuth, parseCommaSeparated, } from './config/file-io.js';
3
+ export { CONFIG_PATH, loadFileConfig, saveFileConfig, getClaudeConfigHome, loadClaudeSettingsEnv, saveClaudeSettingsEnv, normalizeAiCommand, hasCodexAuth, parseCommaSeparated, CLAUDE_AUTH_ENV_KEYS, refreshClaudeEnvToProcess, } from './config/file-io.js';
4
4
  /** 检测是否需要交互式配置(无 token 且无环境变量) */
5
5
  export declare function needsSetup(): boolean;
6
6
  export declare function loadConfig(): Config;
package/dist/config.js CHANGED
@@ -11,7 +11,7 @@ import { createLogger } from './logger.js';
11
11
  import { APP_HOME, DEFAULT_TELEMETRY_INGEST_URL, DEFAULT_TELEMETRY_INGEST_TOKEN, } from './constants.js';
12
12
  const log = createLogger('config');
13
13
  // Re-export file I/O and credential helpers from sub-modules
14
- export { CONFIG_PATH, loadFileConfig, saveFileConfig, getClaudeConfigHome, loadClaudeSettingsEnv, saveClaudeSettingsEnv, normalizeAiCommand, hasCodexAuth, parseCommaSeparated, } from './config/file-io.js';
14
+ export { CONFIG_PATH, loadFileConfig, saveFileConfig, getClaudeConfigHome, loadClaudeSettingsEnv, saveClaudeSettingsEnv, normalizeAiCommand, hasCodexAuth, parseCommaSeparated, CLAUDE_AUTH_ENV_KEYS, refreshClaudeEnvToProcess, } from './config/file-io.js';
15
15
  import { loadFileConfig, normalizeAiCommand, hasCodexAuth, parseCommaSeparated, loadClaudeSettingsEnv, } from './config/file-io.js';
16
16
  /** 检测是否需要交互式配置(无 token 且无环境变量) */
17
17
  export function needsSetup() {
@@ -61,13 +61,9 @@ export function loadConfig() {
61
61
  // 1. 全局 env(最低优先级之一)
62
62
  if (file.env)
63
63
  mergeEnv(file.env);
64
- // 2. tools.claude.env(优先级高于 Claude settings
65
- const claudeToolEnv = file.tools?.claude?.env;
66
- if (claudeToolEnv)
67
- mergeEnv(claudeToolEnv);
68
- // 3. 从 Claude Code 配置合并(最低优先级)
69
- const claudeSettingsEnv = loadClaudeSettingsEnv();
70
- mergeEnv(claudeSettingsEnv);
64
+ // 2. tools.claude.env Claude Code 的 ~/.claude/settings.json 不在此处合并到 process.env,
65
+ // 改由 Claude adapter 在创建 session 前按需加载(refreshClaudeEnvToProcess),
66
+ // 避免 Claude 凭证泄漏到 Codex / CodeBuddy 等子进程。
71
67
  const fileTelegram = file.platforms?.telegram;
72
68
  const fileFeishu = file.platforms?.feishu;
73
69
  const fileQQ = file.platforms?.qq;
@@ -235,10 +231,20 @@ export function loadConfig() {
235
231
  // 6. 校验 Claude API 凭证(SDK 模式需要)
236
232
  // 支持:官方 API Key、Auth Token、或自定义 API(第三方模型等,BASE_URL + token)
237
233
  if (aiCommand === 'claude') {
234
+ // 校验凭证时直接从各来源读取,不修改 process.env
235
+ const claudeToolEnvForCheck = file.tools?.claude?.env;
236
+ const claudeSettingsForCheck = loadClaudeSettingsEnv();
238
237
  const hasCreds = !!(process.env.ANTHROPIC_API_KEY ||
239
238
  process.env.ANTHROPIC_AUTH_TOKEN ||
240
239
  process.env.CLAUDE_CODE_OAUTH_TOKEN ||
241
- process.env.ANTHROPIC_BASE_URL);
240
+ process.env.ANTHROPIC_BASE_URL ||
241
+ claudeToolEnvForCheck?.ANTHROPIC_API_KEY ||
242
+ claudeToolEnvForCheck?.ANTHROPIC_AUTH_TOKEN ||
243
+ claudeToolEnvForCheck?.ANTHROPIC_BASE_URL ||
244
+ claudeSettingsForCheck.ANTHROPIC_API_KEY ||
245
+ claudeSettingsForCheck.ANTHROPIC_AUTH_TOKEN ||
246
+ claudeSettingsForCheck.CLAUDE_CODE_OAUTH_TOKEN ||
247
+ claudeSettingsForCheck.ANTHROPIC_BASE_URL);
242
248
  if (!hasCreds) {
243
249
  const errorMsg = [
244
250
  '',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wu529778790/open-im",
3
- "version": "1.10.4",
3
+ "version": "1.10.5-beta.1",
4
4
  "description": "Multi-platform IM bridge for AI CLI tools (Claude, Codex, CodeBuddy)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",