chatccc 0.2.186 → 0.2.188
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.
- package/config.sample.json +39 -32
- package/package.json +1 -1
- package/src/__tests__/builtin-config.test.ts +33 -0
- package/src/__tests__/chrome-devtools-guard.test.ts +40 -0
- package/src/__tests__/config-reload.test.ts +30 -16
- package/src/__tests__/config-sample.test.ts +41 -19
- package/src/__tests__/feishu-avatar.test.ts +180 -115
- package/src/__tests__/orchestrator.test.ts +165 -17
- package/src/__tests__/session.test.ts +17 -7
- package/src/__tests__/web-ui.test.ts +22 -0
- package/src/adapters/codex-adapter.ts +26 -21
- package/src/builtin/cli.ts +8 -16
- package/src/builtin/index.ts +12 -11
- package/src/cards.ts +48 -7
- package/src/chrome-devtools-guard.ts +78 -2
- package/src/config.ts +158 -108
- package/src/feishu-api.ts +219 -190
- package/src/index.ts +2 -2
- package/src/orchestrator.ts +211 -19
- package/src/platform-adapter.ts +9 -1
- package/src/session.ts +92 -64
- package/src/web-ui.ts +32 -7
package/src/config.ts
CHANGED
|
@@ -39,10 +39,10 @@ export const USER_DATA_DIR = join(homedir(), ".chatccc");
|
|
|
39
39
|
export const PID_FILE = join(USER_DATA_DIR, "state", "runtime.pid");
|
|
40
40
|
|
|
41
41
|
export const LOG_DIR = join(USER_DATA_DIR, "logs");
|
|
42
|
-
export const fileLog = setupFileLogging(LOG_DIR, "index");
|
|
43
|
-
|
|
44
|
-
export const CHAT_LOGS_DIR = join(USER_DATA_DIR, "state", "chat_logs");
|
|
45
|
-
export const RAW_STREAM_LOGS_DIR = join(LOG_DIR, "raw-streams");
|
|
42
|
+
export const fileLog = setupFileLogging(LOG_DIR, "index");
|
|
43
|
+
|
|
44
|
+
export const CHAT_LOGS_DIR = join(USER_DATA_DIR, "state", "chat_logs");
|
|
45
|
+
export const RAW_STREAM_LOGS_DIR = join(LOG_DIR, "raw-streams");
|
|
46
46
|
|
|
47
47
|
export async function appendChatLog(chatId: string, sender: string, text: string): Promise<void> {
|
|
48
48
|
try {
|
|
@@ -82,25 +82,38 @@ export interface CursorConfig {
|
|
|
82
82
|
/** Cursor Agent CLI 可执行文件绝对路径;留空时由运行时按 LocalAppData / PATH 兜底 */
|
|
83
83
|
path: string;
|
|
84
84
|
model: string;
|
|
85
|
+
/** /model 可切换的单个备选模型;留空则不加入候选列表 */
|
|
86
|
+
alternativeModel: string;
|
|
85
87
|
avatarBatteryMode: CursorAvatarBatteryMode;
|
|
86
88
|
onDemandMonthlyBudget: number;
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
export interface CodexConfig {
|
|
90
|
-
/** 是否启用 Codex Agent;缺省时按"有任意字段非空"自动判定(向后兼容) */
|
|
91
|
-
enabled: boolean;
|
|
91
|
+
export interface CodexConfig {
|
|
92
|
+
/** 是否启用 Codex Agent;缺省时按"有任意字段非空"自动判定(向后兼容) */
|
|
93
|
+
enabled: boolean;
|
|
92
94
|
/** 是否作为 /new 未指定工具时使用的默认 Agent */
|
|
93
95
|
defaultAgent: boolean;
|
|
94
96
|
/** Codex CLI 可执行文件绝对路径;留空时退回到 PATH 中的 `codex` */
|
|
95
97
|
path: string;
|
|
96
98
|
model: string;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
/** /model 可切换的单个备选模型;留空则不加入候选列表 */
|
|
100
|
+
alternativeModel: string;
|
|
101
|
+
effort: string;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface CccConfig {
|
|
105
|
+
/** DeepSeek API Key for the ChatCCC self-developed agent. */
|
|
106
|
+
DEEPSEEK_API_KEY: string;
|
|
107
|
+
/** DeepSeek-compatible API Base URL for the ChatCCC self-developed agent. */
|
|
108
|
+
DEEPSEEK_BASE_URL: string;
|
|
109
|
+
/** Model used by the ChatCCC self-developed agent. */
|
|
110
|
+
model: string;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface FeishuConfig {
|
|
114
|
+
appId: string;
|
|
115
|
+
appSecret: string;
|
|
116
|
+
}
|
|
104
117
|
|
|
105
118
|
export interface PlatformConfig {
|
|
106
119
|
enabled: boolean;
|
|
@@ -114,40 +127,41 @@ export interface PlatformsConfig {
|
|
|
114
127
|
ilink: PlatformConfig;
|
|
115
128
|
}
|
|
116
129
|
|
|
117
|
-
export interface ChromeDevtoolsConfig {
|
|
130
|
+
export interface ChromeDevtoolsConfig {
|
|
118
131
|
/** 是否由 ChatCCC 守护一个常驻 Chrome CDP 实例 */
|
|
119
132
|
enabled: boolean;
|
|
120
133
|
/** Chrome remote debugging 端口,默认 15166 */
|
|
121
134
|
port: number;
|
|
122
135
|
/** Chrome 可执行文件路径;留空时按常见安装位置自动探测 */
|
|
123
|
-
chromePath: string;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export interface RawStreamAgentLogConfig {
|
|
127
|
-
enabled: boolean;
|
|
128
|
-
maxBytesPerTurn: number;
|
|
129
|
-
retentionDays: number;
|
|
130
|
-
keepCompleted: boolean;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export interface RawStreamLogsConfig {
|
|
134
|
-
claude: RawStreamAgentLogConfig;
|
|
135
|
-
cursor: RawStreamAgentLogConfig;
|
|
136
|
-
codex: RawStreamAgentLogConfig;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export interface AppConfig {
|
|
136
|
+
chromePath: string;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface RawStreamAgentLogConfig {
|
|
140
|
+
enabled: boolean;
|
|
141
|
+
maxBytesPerTurn: number;
|
|
142
|
+
retentionDays: number;
|
|
143
|
+
keepCompleted: boolean;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface RawStreamLogsConfig {
|
|
147
|
+
claude: RawStreamAgentLogConfig;
|
|
148
|
+
cursor: RawStreamAgentLogConfig;
|
|
149
|
+
codex: RawStreamAgentLogConfig;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface AppConfig {
|
|
140
153
|
feishu: FeishuConfig;
|
|
141
154
|
platforms: PlatformsConfig;
|
|
142
155
|
chromeDevtools: ChromeDevtoolsConfig;
|
|
143
156
|
port: number;
|
|
144
|
-
gitTimeoutSeconds: number;
|
|
145
|
-
/** 若为 false,AI 生成过程中用户发送消息不会打断,须先点「停止」再发送新消息 */
|
|
146
|
-
allowInterrupt: boolean;
|
|
147
|
-
rawStreamLogs: RawStreamLogsConfig;
|
|
157
|
+
gitTimeoutSeconds: number;
|
|
158
|
+
/** 若为 false,AI 生成过程中用户发送消息不会打断,须先点「停止」再发送新消息 */
|
|
159
|
+
allowInterrupt: boolean;
|
|
160
|
+
rawStreamLogs: RawStreamLogsConfig;
|
|
148
161
|
claude: ClaudeConfig;
|
|
149
162
|
cursor: CursorConfig;
|
|
150
163
|
codex: CodexConfig;
|
|
164
|
+
ccc: CccConfig;
|
|
151
165
|
}
|
|
152
166
|
|
|
153
167
|
export type AgentTool = "claude" | "cursor" | "codex";
|
|
@@ -155,26 +169,45 @@ export const AGENT_TOOLS: AgentTool[] = ["claude", "cursor", "codex"];
|
|
|
155
169
|
export type CursorAvatarBatteryMode = "apiPercent" | "onDemandUse";
|
|
156
170
|
|
|
157
171
|
/** 获取指定 agent 配置中所有模型相关的值(最多 100 个,去重) */
|
|
158
|
-
export function getAllModelsForTool(tool: AgentTool, cfg: AppConfig = config): string[] {
|
|
159
|
-
const seen = new Set<string>();
|
|
160
|
-
const collect = (v: unknown) => {
|
|
161
|
-
if (typeof v === "string" && v.trim()) seen.add(v.trim());
|
|
162
|
-
};
|
|
172
|
+
export function getAllModelsForTool(tool: AgentTool, cfg: AppConfig = config): string[] {
|
|
173
|
+
const seen = new Set<string>();
|
|
174
|
+
const collect = (v: unknown) => {
|
|
175
|
+
if (typeof v === "string" && v.trim()) seen.add(v.trim());
|
|
176
|
+
};
|
|
163
177
|
|
|
164
178
|
if (tool === "claude") {
|
|
165
179
|
collect(cfg.claude.model);
|
|
166
180
|
collect(cfg.claude.subagentModel);
|
|
167
181
|
} else if (tool === "cursor") {
|
|
168
182
|
collect(cfg.cursor.model);
|
|
183
|
+
collect(cfg.cursor.alternativeModel);
|
|
169
184
|
} else if (tool === "codex") {
|
|
170
185
|
collect(cfg.codex.model);
|
|
186
|
+
collect(cfg.codex.alternativeModel);
|
|
171
187
|
}
|
|
172
|
-
|
|
173
|
-
return Array.from(seen).slice(0, 100);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const
|
|
177
|
-
const
|
|
188
|
+
|
|
189
|
+
return Array.from(seen).slice(0, 100);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export const CLAUDE_EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"] as const;
|
|
193
|
+
export const CODEX_EFFORT_LEVELS = ["minimal", "low", "medium", "high", "xhigh"] as const;
|
|
194
|
+
|
|
195
|
+
export function getAllEffortsForTool(tool: AgentTool): string[] {
|
|
196
|
+
if (tool === "claude") return [...CLAUDE_EFFORT_LEVELS];
|
|
197
|
+
if (tool === "codex") return [...CODEX_EFFORT_LEVELS];
|
|
198
|
+
return [];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function getDefaultEffortForTool(tool: AgentTool, cfg: AppConfig = config): string {
|
|
202
|
+
if (tool === "claude") return cfg.claude.effort;
|
|
203
|
+
if (tool === "codex") return cfg.codex.effort;
|
|
204
|
+
return "";
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const CONFIG_FILE = join(USER_DATA_DIR, "config.json");
|
|
208
|
+
const CONFIG_SAMPLE_FILE = join(PROJECT_ROOT, "config.sample.json");
|
|
209
|
+
export const DEFAULT_CCC_DEEPSEEK_BASE_URL = "https://api.deepseek.com/v1";
|
|
210
|
+
export const DEFAULT_CCC_MODEL = "deepseek-v4-pro[1m]";
|
|
178
211
|
|
|
179
212
|
/**
|
|
180
213
|
* 将旧位置(PROJECT_ROOT)的持久化数据一次性迁移到 USER_DATA_DIR。
|
|
@@ -358,40 +391,40 @@ function normalizeCursorAvatarBatteryMode(raw: unknown): CursorAvatarBatteryMode
|
|
|
358
391
|
return raw === "onDemandUse" ? "onDemandUse" : "apiPercent";
|
|
359
392
|
}
|
|
360
393
|
|
|
361
|
-
function normalizeCursorOnDemandMonthlyBudget(raw: unknown): number {
|
|
362
|
-
const value = typeof raw === "string" ? Number(raw.trim()) : Number(raw);
|
|
363
|
-
return Number.isFinite(value) && value > 0 ? value : 1000;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
function normalizePositiveInteger(raw: unknown, fallback: number): number {
|
|
367
|
-
const value = typeof raw === "string" ? Number(raw.trim()) : Number(raw);
|
|
368
|
-
return Number.isInteger(value) && value > 0 ? value : fallback;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
function normalizeRawStreamAgentLogConfig(raw: unknown): RawStreamAgentLogConfig {
|
|
372
|
-
const obj = typeof raw === "object" && raw !== null
|
|
373
|
-
? raw as Record<string, unknown>
|
|
374
|
-
: {};
|
|
375
|
-
return {
|
|
376
|
-
enabled: typeof obj.enabled === "boolean" ? obj.enabled : false,
|
|
377
|
-
maxBytesPerTurn: normalizePositiveInteger(obj.maxBytesPerTurn, 50 * 1024 * 1024),
|
|
378
|
-
retentionDays: normalizePositiveInteger(obj.retentionDays, 7),
|
|
379
|
-
keepCompleted: typeof obj.keepCompleted === "boolean" ? obj.keepCompleted : false,
|
|
380
|
-
};
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
function loadConfig(): AppConfig {
|
|
384
|
-
const defaults: AppConfig = {
|
|
385
|
-
feishu: { appId: "", appSecret: "" },
|
|
386
|
-
platforms: { feishu: { enabled: true }, ilink: { enabled: true } },
|
|
387
|
-
chromeDevtools: { enabled: false, port: 15166, chromePath: "" },
|
|
388
|
-
port: 18080,
|
|
389
|
-
gitTimeoutSeconds: 180,
|
|
390
|
-
allowInterrupt: false,
|
|
391
|
-
rawStreamLogs: {
|
|
392
|
-
claude: { enabled: false, maxBytesPerTurn: 50 * 1024 * 1024, retentionDays: 7, keepCompleted: false },
|
|
393
|
-
cursor: { enabled: false, maxBytesPerTurn: 50 * 1024 * 1024, retentionDays: 7, keepCompleted: false },
|
|
394
|
-
codex: { enabled: false, maxBytesPerTurn: 50 * 1024 * 1024, retentionDays: 7, keepCompleted: false },
|
|
394
|
+
function normalizeCursorOnDemandMonthlyBudget(raw: unknown): number {
|
|
395
|
+
const value = typeof raw === "string" ? Number(raw.trim()) : Number(raw);
|
|
396
|
+
return Number.isFinite(value) && value > 0 ? value : 1000;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function normalizePositiveInteger(raw: unknown, fallback: number): number {
|
|
400
|
+
const value = typeof raw === "string" ? Number(raw.trim()) : Number(raw);
|
|
401
|
+
return Number.isInteger(value) && value > 0 ? value : fallback;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function normalizeRawStreamAgentLogConfig(raw: unknown): RawStreamAgentLogConfig {
|
|
405
|
+
const obj = typeof raw === "object" && raw !== null
|
|
406
|
+
? raw as Record<string, unknown>
|
|
407
|
+
: {};
|
|
408
|
+
return {
|
|
409
|
+
enabled: typeof obj.enabled === "boolean" ? obj.enabled : false,
|
|
410
|
+
maxBytesPerTurn: normalizePositiveInteger(obj.maxBytesPerTurn, 50 * 1024 * 1024),
|
|
411
|
+
retentionDays: normalizePositiveInteger(obj.retentionDays, 7),
|
|
412
|
+
keepCompleted: typeof obj.keepCompleted === "boolean" ? obj.keepCompleted : false,
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function loadConfig(): AppConfig {
|
|
417
|
+
const defaults: AppConfig = {
|
|
418
|
+
feishu: { appId: "", appSecret: "" },
|
|
419
|
+
platforms: { feishu: { enabled: true }, ilink: { enabled: true } },
|
|
420
|
+
chromeDevtools: { enabled: false, port: 15166, chromePath: "" },
|
|
421
|
+
port: 18080,
|
|
422
|
+
gitTimeoutSeconds: 180,
|
|
423
|
+
allowInterrupt: false,
|
|
424
|
+
rawStreamLogs: {
|
|
425
|
+
claude: { enabled: false, maxBytesPerTurn: 50 * 1024 * 1024, retentionDays: 7, keepCompleted: false },
|
|
426
|
+
cursor: { enabled: false, maxBytesPerTurn: 50 * 1024 * 1024, retentionDays: 7, keepCompleted: false },
|
|
427
|
+
codex: { enabled: false, maxBytesPerTurn: 50 * 1024 * 1024, retentionDays: 7, keepCompleted: false },
|
|
395
428
|
},
|
|
396
429
|
claude: { enabled: false, defaultAgent: true, model: "", subagentModel: "", effort: "", apiKey: "", baseUrl: "", maxTurn: 0 },
|
|
397
430
|
cursor: {
|
|
@@ -399,11 +432,13 @@ function loadConfig(): AppConfig {
|
|
|
399
432
|
defaultAgent: false,
|
|
400
433
|
path: "",
|
|
401
434
|
model: "claude-opus-4-7-max",
|
|
435
|
+
alternativeModel: "",
|
|
402
436
|
avatarBatteryMode: "apiPercent",
|
|
403
437
|
onDemandMonthlyBudget: 1000,
|
|
404
|
-
},
|
|
405
|
-
codex: { enabled: false, defaultAgent: false, path: "", model: "", effort: "" },
|
|
406
|
-
|
|
438
|
+
},
|
|
439
|
+
codex: { enabled: false, defaultAgent: false, path: "", model: "", alternativeModel: "", effort: "" },
|
|
440
|
+
ccc: { DEEPSEEK_API_KEY: "", DEEPSEEK_BASE_URL: DEFAULT_CCC_DEEPSEEK_BASE_URL, model: DEFAULT_CCC_MODEL },
|
|
441
|
+
};
|
|
407
442
|
|
|
408
443
|
if (!IS_TEST_ENV) {
|
|
409
444
|
migrateLegacyData();
|
|
@@ -450,10 +485,12 @@ function loadConfig(): AppConfig {
|
|
|
450
485
|
path?: unknown;
|
|
451
486
|
command?: unknown;
|
|
452
487
|
model?: unknown;
|
|
488
|
+
alternativeModel?: unknown;
|
|
453
489
|
avatarBatteryMode?: unknown;
|
|
454
490
|
onDemandMonthlyBudget?: unknown;
|
|
455
|
-
};
|
|
456
|
-
codex?: { enabled?: unknown; defaultAgent?: unknown; path?: unknown; command?: unknown; model?: unknown; effort?: unknown };
|
|
491
|
+
};
|
|
492
|
+
codex?: { enabled?: unknown; defaultAgent?: unknown; path?: unknown; command?: unknown; model?: unknown; alternativeModel?: unknown; effort?: unknown };
|
|
493
|
+
ccc?: { DEEPSEEK_API_KEY?: unknown; DEEPSEEK_BASE_URL?: unknown; model?: unknown };
|
|
457
494
|
chromeDevtools?: { enabled?: unknown; port?: unknown; chromePath?: unknown };
|
|
458
495
|
rawStreamLogs?: unknown;
|
|
459
496
|
};
|
|
@@ -468,10 +505,11 @@ function loadConfig(): AppConfig {
|
|
|
468
505
|
const claude = parsed.claude ?? {} as Partial<ClaudeConfig>;
|
|
469
506
|
const cursorRaw = (parsed.cursor ?? {}) as NonNullable<typeof parsed.cursor>;
|
|
470
507
|
const codexRaw = (parsed.codex ?? {}) as NonNullable<typeof parsed.codex>;
|
|
508
|
+
const cccRaw = (parsed.ccc ?? {}) as NonNullable<typeof parsed.ccc>;
|
|
471
509
|
const chromeDevtoolsRaw = (parsed.chromeDevtools ?? {}) as NonNullable<typeof parsed.chromeDevtools>;
|
|
472
|
-
const rawStreamLogsRaw = typeof parsed.rawStreamLogs === "object" && parsed.rawStreamLogs !== null
|
|
473
|
-
? parsed.rawStreamLogs as unknown as Record<string, unknown>
|
|
474
|
-
: {};
|
|
510
|
+
const rawStreamLogsRaw = typeof parsed.rawStreamLogs === "object" && parsed.rawStreamLogs !== null
|
|
511
|
+
? parsed.rawStreamLogs as unknown as Record<string, unknown>
|
|
512
|
+
: {};
|
|
475
513
|
|
|
476
514
|
// 兼容旧字段 `command`:命中时打印一次性 warning 提示用户改名
|
|
477
515
|
const onLegacyField = (label: string, value: string): void => {
|
|
@@ -502,13 +540,15 @@ function loadConfig(): AppConfig {
|
|
|
502
540
|
Boolean(
|
|
503
541
|
(typeof cursorRaw.path === "string" && cursorRaw.path.trim()) ||
|
|
504
542
|
(typeof cursorRaw.command === "string" && (cursorRaw.command as string).trim()) ||
|
|
505
|
-
(typeof cursorRaw.model === "string" && (cursorRaw.model as string).trim())
|
|
543
|
+
(typeof cursorRaw.model === "string" && (cursorRaw.model as string).trim()) ||
|
|
544
|
+
(typeof cursorRaw.alternativeModel === "string" && (cursorRaw.alternativeModel as string).trim()),
|
|
506
545
|
);
|
|
507
546
|
const codexNonEmpty = (): boolean =>
|
|
508
547
|
Boolean(
|
|
509
548
|
(typeof codexRaw.path === "string" && codexRaw.path.trim()) ||
|
|
510
549
|
(typeof codexRaw.command === "string" && (codexRaw.command as string).trim()) ||
|
|
511
550
|
(typeof codexRaw.model === "string" && (codexRaw.model as string).trim()) ||
|
|
551
|
+
(typeof codexRaw.alternativeModel === "string" && (codexRaw.alternativeModel as string).trim()) ||
|
|
512
552
|
(typeof codexRaw.effort === "string" && (codexRaw.effort as string).trim()),
|
|
513
553
|
);
|
|
514
554
|
|
|
@@ -560,15 +600,15 @@ function loadConfig(): AppConfig {
|
|
|
560
600
|
: 15166,
|
|
561
601
|
chromePath: normalizeOptionalConfigField(chromeDevtoolsRaw.chromePath, { label: "chromeDevtools.chromePath" }),
|
|
562
602
|
},
|
|
563
|
-
port: typeof parsed.port === "number" ? parsed.port : 18080,
|
|
564
|
-
gitTimeoutSeconds: typeof parsed.gitTimeoutSeconds === "number" ? parsed.gitTimeoutSeconds : 180,
|
|
565
|
-
allowInterrupt: typeof parsed.allowInterrupt === "boolean" ? parsed.allowInterrupt : false,
|
|
566
|
-
rawStreamLogs: {
|
|
567
|
-
claude: normalizeRawStreamAgentLogConfig(rawStreamLogsRaw.claude),
|
|
568
|
-
cursor: normalizeRawStreamAgentLogConfig(rawStreamLogsRaw.cursor),
|
|
569
|
-
codex: normalizeRawStreamAgentLogConfig(rawStreamLogsRaw.codex),
|
|
570
|
-
},
|
|
571
|
-
claude: {
|
|
603
|
+
port: typeof parsed.port === "number" ? parsed.port : 18080,
|
|
604
|
+
gitTimeoutSeconds: typeof parsed.gitTimeoutSeconds === "number" ? parsed.gitTimeoutSeconds : 180,
|
|
605
|
+
allowInterrupt: typeof parsed.allowInterrupt === "boolean" ? parsed.allowInterrupt : false,
|
|
606
|
+
rawStreamLogs: {
|
|
607
|
+
claude: normalizeRawStreamAgentLogConfig(rawStreamLogsRaw.claude),
|
|
608
|
+
cursor: normalizeRawStreamAgentLogConfig(rawStreamLogsRaw.cursor),
|
|
609
|
+
codex: normalizeRawStreamAgentLogConfig(rawStreamLogsRaw.codex),
|
|
610
|
+
},
|
|
611
|
+
claude: {
|
|
572
612
|
enabled: claudeEnabled,
|
|
573
613
|
defaultAgent: defaultTool === "claude",
|
|
574
614
|
model: normalizeOptionalConfigField(claude.model, { label: "claude.model" }),
|
|
@@ -585,18 +625,28 @@ function loadConfig(): AppConfig {
|
|
|
585
625
|
defaultAgent: defaultTool === "cursor",
|
|
586
626
|
path: readToolCliPath(cursorRaw, { label: "cursor", onLegacyField }),
|
|
587
627
|
model: normalizeOptionalConfigField(cursorRaw.model, { label: "cursor.model", fallback: "claude-opus-4-7-max" }),
|
|
628
|
+
alternativeModel: normalizeOptionalConfigField(cursorRaw.alternativeModel, { label: "cursor.alternativeModel" }),
|
|
588
629
|
avatarBatteryMode: normalizeCursorAvatarBatteryMode(cursorRaw.avatarBatteryMode),
|
|
589
630
|
onDemandMonthlyBudget: normalizeCursorOnDemandMonthlyBudget(cursorRaw.onDemandMonthlyBudget),
|
|
590
631
|
},
|
|
591
|
-
codex: {
|
|
592
|
-
enabled: codexEnabled,
|
|
593
|
-
defaultAgent: defaultTool === "codex",
|
|
594
|
-
path: readToolCliPath(codexRaw, { label: "codex", onLegacyField }),
|
|
595
|
-
model: normalizeOptionalConfigField(codexRaw.model, { label: "codex.model" }),
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
632
|
+
codex: {
|
|
633
|
+
enabled: codexEnabled,
|
|
634
|
+
defaultAgent: defaultTool === "codex",
|
|
635
|
+
path: readToolCliPath(codexRaw, { label: "codex", onLegacyField }),
|
|
636
|
+
model: normalizeOptionalConfigField(codexRaw.model, { label: "codex.model" }),
|
|
637
|
+
alternativeModel: normalizeOptionalConfigField(codexRaw.alternativeModel, { label: "codex.alternativeModel" }),
|
|
638
|
+
effort: normalizeOptionalConfigField(codexRaw.effort, { label: "codex.effort" }),
|
|
639
|
+
},
|
|
640
|
+
ccc: {
|
|
641
|
+
DEEPSEEK_API_KEY: normalizeOptionalConfigField(cccRaw.DEEPSEEK_API_KEY, { label: "ccc.DEEPSEEK_API_KEY" }),
|
|
642
|
+
DEEPSEEK_BASE_URL: normalizeOptionalConfigField(cccRaw.DEEPSEEK_BASE_URL, {
|
|
643
|
+
label: "ccc.DEEPSEEK_BASE_URL",
|
|
644
|
+
fallback: DEFAULT_CCC_DEEPSEEK_BASE_URL,
|
|
645
|
+
}),
|
|
646
|
+
model: normalizeOptionalConfigField(cccRaw.model, { label: "ccc.model", fallback: DEFAULT_CCC_MODEL }),
|
|
647
|
+
},
|
|
648
|
+
};
|
|
649
|
+
}
|
|
600
650
|
|
|
601
651
|
/**
|
|
602
652
|
* 全局可变 config 对象。
|