chatccc 0.2.219 → 0.2.220

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/src/config.ts CHANGED
@@ -104,12 +104,18 @@ export interface CodexConfig {
104
104
  }
105
105
 
106
106
  export interface CccConfig {
107
+ /** Whether the built-in CCC Agent is available for new sessions. */
108
+ enabled: boolean;
109
+ /** Whether /new without an explicit tool should use CCC Agent. */
110
+ defaultAgent: boolean;
107
111
  /** DeepSeek API Key for the ChatCCC self-developed agent. */
108
112
  DEEPSEEK_API_KEY: string;
109
113
  /** DeepSeek-compatible API Base URL for the ChatCCC self-developed agent. */
110
114
  DEEPSEEK_BASE_URL: string;
111
115
  /** Model used by the ChatCCC self-developed agent. */
112
116
  model: string;
117
+ /** Optional model exposed through /model for manual per-session switching. */
118
+ alternativeModel: string;
113
119
  }
114
120
 
115
121
  export interface FeishuConfig {
@@ -168,8 +174,8 @@ export interface AppConfig {
168
174
  ccc: CccConfig;
169
175
  }
170
176
 
171
- export type AgentTool = "claude" | "cursor" | "codex";
172
- export const AGENT_TOOLS: AgentTool[] = ["claude", "cursor", "codex"];
177
+ export type AgentTool = "claude" | "cursor" | "codex" | "ccc";
178
+ export const AGENT_TOOLS: AgentTool[] = ["claude", "cursor", "codex", "ccc"];
173
179
  export type CursorAvatarBatteryMode = "apiPercent" | "onDemandUse";
174
180
 
175
181
  /** 获取指定 agent 配置中所有模型相关的值(最多 100 个,去重) */
@@ -190,6 +196,7 @@ export function getAllModelsForTool(tool: string, cfg: AppConfig = config): stri
190
196
  collect(cfg.codex.alternativeModel);
191
197
  } else if (tool === "ccc") {
192
198
  collect(cfg.ccc.model);
199
+ collect(cfg.ccc.alternativeModel);
193
200
  }
194
201
 
195
202
  return Array.from(seen).slice(0, 100);
@@ -445,7 +452,14 @@ function loadConfig(): AppConfig {
445
452
  onDemandMonthlyBudget: 1000,
446
453
  },
447
454
  codex: { enabled: false, defaultAgent: false, path: "", model: "", alternativeModel: "", effort: "", fastMode: false },
448
- ccc: { DEEPSEEK_API_KEY: "", DEEPSEEK_BASE_URL: DEFAULT_CCC_DEEPSEEK_BASE_URL, model: DEFAULT_CCC_MODEL },
455
+ ccc: {
456
+ enabled: false,
457
+ defaultAgent: false,
458
+ DEEPSEEK_API_KEY: "",
459
+ DEEPSEEK_BASE_URL: DEFAULT_CCC_DEEPSEEK_BASE_URL,
460
+ model: DEFAULT_CCC_MODEL,
461
+ alternativeModel: "",
462
+ },
449
463
  };
450
464
 
451
465
  if (!IS_TEST_ENV) {
@@ -498,7 +512,14 @@ function loadConfig(): AppConfig {
498
512
  onDemandMonthlyBudget?: unknown;
499
513
  };
500
514
  codex?: { enabled?: unknown; defaultAgent?: unknown; path?: unknown; command?: unknown; model?: unknown; alternativeModel?: unknown; effort?: unknown; fastMode?: unknown };
501
- ccc?: { DEEPSEEK_API_KEY?: unknown; DEEPSEEK_BASE_URL?: unknown; model?: unknown };
515
+ ccc?: {
516
+ enabled?: unknown;
517
+ defaultAgent?: unknown;
518
+ DEEPSEEK_API_KEY?: unknown;
519
+ DEEPSEEK_BASE_URL?: unknown;
520
+ model?: unknown;
521
+ alternativeModel?: unknown;
522
+ };
502
523
  webUi?: { openOnStart?: unknown };
503
524
  chromeDevtools?: { enabled?: unknown; port?: unknown; chromePath?: unknown };
504
525
  rawStreamLogs?: unknown;
@@ -553,7 +574,7 @@ function loadConfig(): AppConfig {
553
574
  (typeof cursorRaw.model === "string" && (cursorRaw.model as string).trim()) ||
554
575
  (typeof cursorRaw.alternativeModel === "string" && (cursorRaw.alternativeModel as string).trim()),
555
576
  );
556
- const codexNonEmpty = (): boolean =>
577
+ const codexNonEmpty = (): boolean =>
557
578
  Boolean(
558
579
  (typeof codexRaw.path === "string" && codexRaw.path.trim()) ||
559
580
  (typeof codexRaw.command === "string" && (codexRaw.command as string).trim()) ||
@@ -561,21 +582,28 @@ function loadConfig(): AppConfig {
561
582
  (typeof codexRaw.alternativeModel === "string" && (codexRaw.alternativeModel as string).trim()) ||
562
583
  (typeof codexRaw.effort === "string" && (codexRaw.effort as string).trim()) ||
563
584
  codexRaw.fastMode === true,
564
- );
585
+ );
586
+ // 旧版 ccc 配置没有 enabled。只用 API Key 推断启用,避免 sample 中自带的
587
+ // 默认 Base URL / model 让升级用户在未配置凭证时意外启用 CCC Agent。
588
+ const cccNonEmpty = (): boolean =>
589
+ Boolean(typeof cccRaw.DEEPSEEK_API_KEY === "string" && cccRaw.DEEPSEEK_API_KEY.trim());
565
590
 
566
591
  const claudeEnabled = resolveEnabled(claude.enabled, claudeNonEmpty);
567
592
  const cursorEnabled = resolveEnabled(cursorRaw.enabled, cursorNonEmpty);
568
- const codexEnabled = resolveEnabled(codexRaw.enabled, codexNonEmpty);
593
+ const codexEnabled = resolveEnabled(codexRaw.enabled, codexNonEmpty);
594
+ const cccEnabled = resolveEnabled(cccRaw.enabled, cccNonEmpty);
569
595
  const chromeDevtoolsPort = Number(chromeDevtoolsRaw.port);
570
596
  const explicitDefaultTool: AgentTool | null =
571
597
  typeof claude.defaultAgent === "boolean" && claude.defaultAgent && claudeEnabled ? "claude" :
572
598
  typeof cursorRaw.defaultAgent === "boolean" && cursorRaw.defaultAgent && cursorEnabled ? "cursor" :
573
- typeof codexRaw.defaultAgent === "boolean" && codexRaw.defaultAgent && codexEnabled ? "codex" :
599
+ typeof codexRaw.defaultAgent === "boolean" && codexRaw.defaultAgent && codexEnabled ? "codex" :
600
+ typeof cccRaw.defaultAgent === "boolean" && cccRaw.defaultAgent && cccEnabled ? "ccc" :
574
601
  null;
575
602
  const fallbackDefaultTool: AgentTool =
576
603
  claudeEnabled ? "claude" :
577
604
  cursorEnabled ? "cursor" :
578
- codexEnabled ? "codex" :
605
+ codexEnabled ? "codex" :
606
+ cccEnabled ? "ccc" :
579
607
  "claude";
580
608
  const defaultTool = explicitDefaultTool ?? fallbackDefaultTool;
581
609
 
@@ -655,12 +683,15 @@ function loadConfig(): AppConfig {
655
683
  fastMode: codexRaw.fastMode === true,
656
684
  },
657
685
  ccc: {
686
+ enabled: cccEnabled,
687
+ defaultAgent: defaultTool === "ccc",
658
688
  DEEPSEEK_API_KEY: normalizeOptionalConfigField(cccRaw.DEEPSEEK_API_KEY, { label: "ccc.DEEPSEEK_API_KEY" }),
659
689
  DEEPSEEK_BASE_URL: normalizeOptionalConfigField(cccRaw.DEEPSEEK_BASE_URL, {
660
690
  label: "ccc.DEEPSEEK_BASE_URL",
661
691
  fallback: DEFAULT_CCC_DEEPSEEK_BASE_URL,
662
692
  }),
663
693
  model: normalizeOptionalConfigField(cccRaw.model, { label: "ccc.model", fallback: DEFAULT_CCC_MODEL }),
694
+ alternativeModel: normalizeOptionalConfigField(cccRaw.alternativeModel, { label: "ccc.alternativeModel" }),
664
695
  },
665
696
  };
666
697
  }
@@ -981,7 +1012,7 @@ export const CLAUDE_SESSION_PREFIX = "Claude Code Session:";
981
1012
  export const CURSOR_SESSION_PREFIX = "Cursor Session:";
982
1013
  /** 群描述中用于识别 Codex 会话的前缀 */
983
1014
  export const CODEX_SESSION_PREFIX = "Codex Session:";
984
- /** 群描述中用于识别 hidden ccc agent 会话的前缀 */
1015
+ /** 群描述中用于识别 CCC Agent 会话的前缀 */
985
1016
  export const CCC_SESSION_PREFIX = "CCC Session:";
986
1017
 
987
1018
  /** 根据 tool 名称返回对应的群描述前缀 */
package/src/index.ts CHANGED
@@ -333,6 +333,19 @@ async function processFeishuMessageEvent(data: Evt): Promise<void> {
333
333
  if (delayNotice) {
334
334
  const delayToken = await getTenantAccessToken();
335
335
  await sendCardReply(delayToken, chatId, "延迟送达", delayNotice, "yellow").catch(() => {});
336
+ // 延迟送达的旧消息只发提醒、不转发给 agent 执行:
337
+ // 断线重连或补推时,早已过期的消息不应未经确认就触发新任务。
338
+ // 用户如需执行可自行重发。
339
+ logTrace(traceId, "DONE", {
340
+ outcome: "skip_delayed_feishu_message",
341
+ chatId,
342
+ msgTimestamp,
343
+ delayMinutes: Math.floor((Date.now() - msgTimestamp) / 60000),
344
+ });
345
+ console.log(
346
+ `[${ts()}] [SKIP] Delayed Feishu message not forwarded to agent: messageId=${messageId ?? "(missing id)"} chatId=${chatId} createTime=${msgTimestamp}`,
347
+ );
348
+ return;
336
349
  }
337
350
 
338
351
  await handleCommand(