chatccc 0.2.258 → 0.2.260

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.
@@ -57,6 +57,10 @@ export function reduceProgress(prev, event) {
57
57
  case "text":
58
58
  // accumulated 是全文累积,直接全量替换,天然幂等
59
59
  return withProgressView(prev, { text: event.accumulated });
60
+ case "progress":
61
+ return withProgressView(prev, { headerTitle: "思考中..." });
62
+ case "text_reset":
63
+ return withProgressView(prev, { text: "", tools: [] });
60
64
  case "tool_use": {
61
65
  const tool = {
62
66
  id: event.id ?? `tool-${prev.tools.length + 1}`,
@@ -2,10 +2,10 @@
2
2
  * Tracks how long the displayed output character count has remained unchanged.
3
3
  * Leaving a monitored phase clears the window; returning starts a fresh one.
4
4
  */
5
- export function observeResponseProgress(previous, isMonitoredPhase, totalChars, now = Date.now()) {
5
+ export function observeResponseProgress(previous, isMonitoredPhase, totalChars, now = Date.now(), heartbeat = false) {
6
6
  if (!isMonitoredPhase)
7
7
  return undefined;
8
- if (previous?.totalChars === totalChars)
8
+ if (!heartbeat && previous?.totalChars === totalChars)
9
9
  return previous;
10
10
  return { totalChars, unchangedSince: now };
11
11
  }
@@ -10,6 +10,7 @@ import { createClaudeAdapter } from "./adapters/claude-adapter.js";
10
10
  import { createCursorAdapter } from "./adapters/cursor-adapter.js";
11
11
  import { createCodexAdapter } from "./adapters/codex-adapter.js";
12
12
  import { createCccAdapter } from "./adapters/ccc-adapter.js";
13
+ import { createDshAdapter } from "./adapters/dsh-adapter.js";
13
14
  import { killProcessTree } from "./adapters/proc-tree-kill.js";
14
15
  import { resourceMonitor, registerProcess, unregisterProcess } from "./adapters/resource-monitor.js";
15
16
  import { buildImSkillsPromptCached, exportSkillSubDocs } from "./im-skills.js";
@@ -233,7 +234,7 @@ function formatAutoEndedReply(finalReply) {
233
234
  * 状态或资源保护,不能把它们消耗的时间算入回复停滞窗口。
234
235
  */
235
236
  function monitorsOutputProgress(kind) {
236
- return kind === "responding";
237
+ return kind === "responding" || kind === "thinking";
237
238
  }
238
239
  function formatTerminalReply(status, finalReply, terminalError) {
239
240
  if (status === "auto_ended")
@@ -418,6 +419,8 @@ export function getEffectiveModelForTool(tool, sessionId) {
418
419
  return config.codex.model;
419
420
  if (tool === "ccc")
420
421
  return config.ccc.model;
422
+ if (tool === "dsh")
423
+ return config.dsh.model;
421
424
  return CLAUDE_MODEL;
422
425
  }
423
426
  export function getEffectiveEffortForTool(tool, sessionId) {
@@ -528,14 +531,23 @@ export function getAdapterForTool(tool, sessionId) {
528
531
  apiKey: config.ccc.DEEPSEEK_API_KEY,
529
532
  baseURL: config.ccc.DEEPSEEK_BASE_URL,
530
533
  model: effectiveModel || undefined,
531
- effort: effectiveEffort || undefined,
532
534
  compactionTimeoutMs: config.ccc.compactionTimeoutMs,
533
535
  contextWindow: config.ccc.contextWindow,
536
+ ...(effectiveEffort ? { effort: effectiveEffort } : {}),
534
537
  // 留空("")不传 → ChatSession 跟随 DeepCCC 内核配置(~/.deepccc/config.json 或 DEEPCCC_PROVIDER)
535
538
  ...(config.ccc.provider ? { provider: config.ccc.provider } : {}),
536
539
  ...(config.ccc.subModel ? { subModel: config.ccc.subModel } : {}),
537
540
  });
538
541
  }
542
+ else if (tool === "dsh") {
543
+ adapter = createDshAdapter({
544
+ apiKey: config.dsh.apiKey,
545
+ baseUrl: config.dsh.baseUrl,
546
+ model: effectiveModel || config.dsh.model,
547
+ provider: config.dsh.provider,
548
+ maxTokens: config.dsh.maxTokens,
549
+ });
550
+ }
539
551
  else {
540
552
  adapter = createClaudeAdapter({
541
553
  model: effectiveModel,
@@ -761,6 +773,14 @@ export function accumulateBlockContent(block, state, toolCallMap) {
761
773
  // 覆盖而非追加:适配器已保证这是一段完整最终文本(如 Cursor 流末快照)
762
774
  state.finalCompleteText = block.text;
763
775
  break;
776
+ case "text_reset":
777
+ state.accumulatedContent = "";
778
+ state.finalText = "";
779
+ state.finalCompleteText = "";
780
+ state.chunkCount = 0;
781
+ break;
782
+ case "agent_progress":
783
+ break;
764
784
  case "compact_boundary": {
765
785
  const triggerLabel = block.trigger === "manual" ? "手动" : "自动"; // 手动 / 自动
766
786
  state.accumulatedContent +=
@@ -844,6 +864,10 @@ function formatToolConfigForLog(tool, sessionModel, sessionId) {
844
864
  const modelStr = m.trim() !== "" ? m : "(not configured)";
845
865
  return `model=${modelStr}, baseURL=${config.ccc.DEEPSEEK_BASE_URL}`;
846
866
  }
867
+ if (tool === "dsh") {
868
+ const model = getEffectiveModelForTool(tool, sessionId);
869
+ return `model=${model || "(not configured)"}, baseURL=${config.dsh.baseUrl}`;
870
+ }
847
871
  return `model=${anthropicConfigDisplay(getModelForSession(sessionId))}, subagentModel=${anthropicConfigDisplay(CLAUDE_SUBAGENT_MODEL)}, effort=${anthropicConfigDisplay(getEffectiveEffortForTool(tool, sessionId))}`;
848
872
  }
849
873
  export async function initClaudeSession(tool, overrideCwd, chatId) {
@@ -1238,7 +1262,15 @@ export async function runAgentSession(sessionId, userText, platform, _chatId, ms
1238
1262
  }
1239
1263
  }
1240
1264
  let activityChanged = false;
1265
+ let progressHeartbeat = false;
1266
+ let outputReset = false;
1241
1267
  for (const block of unifiedMsg.blocks) {
1268
+ if (block.type === "agent_progress")
1269
+ progressHeartbeat = true;
1270
+ if (block.type === "text_reset") {
1271
+ outputReset = true;
1272
+ toolCallMap.clear();
1273
+ }
1242
1274
  if (updateAgentActivity(activityTracker, block))
1243
1275
  activityChanged = true;
1244
1276
  accumulateBlockContent(block, state, toolCallMap);
@@ -1263,11 +1295,11 @@ export async function runAgentSession(sessionId, userText, platform, _chatId, ms
1263
1295
  prompt.responseProgress = observeResponseProgress(
1264
1296
  // starting → responding 本身是一次有效进展,即便首个文本块仍为空也应
1265
1297
  // 重新计时;其它活动阶段会清空观察窗口。
1266
- activityChanged ? undefined : prompt.responseProgress, monitorsOutputProgress(activityTracker.activity.kind), totalChars, Date.now());
1298
+ activityChanged ? undefined : prompt.responseProgress, monitorsOutputProgress(activityTracker.activity.kind), totalChars, Date.now(), progressHeartbeat);
1267
1299
  }
1268
1300
  // 定时写入文件
1269
1301
  const now2 = Date.now();
1270
- if (activityChanged || now2 - lastFileWrite >= FILE_WRITE_INTERVAL_MS) {
1302
+ if (activityChanged || outputReset || now2 - lastFileWrite >= FILE_WRITE_INTERVAL_MS) {
1271
1303
  lastFileWrite = now2;
1272
1304
  await writeStreamState({
1273
1305
  sessionId,
@@ -2045,6 +2077,13 @@ async function resolveModelEffort(tool, sessionId) {
2045
2077
  effort: null,
2046
2078
  };
2047
2079
  }
2080
+ if (tool === "dsh") {
2081
+ const model = getEffectiveModelForTool(tool, sessionId);
2082
+ return {
2083
+ model: model.trim() !== "" ? model : UNKNOWN_MODEL_PLACEHOLDER,
2084
+ effort: null,
2085
+ };
2086
+ }
2048
2087
  return {
2049
2088
  model: anthropicConfigDisplay(getModelForSession(sessionId)),
2050
2089
  effort: anthropicConfigDisplay(getEffectiveEffortForTool(tool, sessionId)),