chatccc 0.2.204 → 0.2.206

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.
@@ -1,7 +1,9 @@
1
1
  import { readFile, writeFile, mkdir, rename, unlink } from "node:fs/promises";
2
2
  import { dirname, join } from "node:path";
3
3
 
4
- import { USER_DATA_DIR, ts } from "./config.ts";
4
+ import { USER_DATA_DIR, ts } from "./config.ts";
5
+ import { createAgentActivityTracker } from "./agent-activity.ts";
6
+ import type { AgentActivity } from "./agent-activity.ts";
5
7
 
6
8
  // ---------------------------------------------------------------------------
7
9
  // stream-state.json — 每个 session 的流式输出持久化文件
@@ -11,12 +13,14 @@ export const STREAMS_DIR = join(USER_DATA_DIR, "state", "streams");
11
13
 
12
14
  export interface StreamState {
13
15
  sessionId: string;
14
- status: "running" | "done" | "stopped" | "error";
16
+ status: "running" | "done" | "stopped" | "error" | "auto_ended";
15
17
  accumulatedContent: string;
16
18
  /** 本轮会话中 LLM 输出的全部文本内容(所有 text block 的累加)。
17
19
  * 命名含 "final" 但实为"全部累积文本",并非仅"最终一段回复"。
18
20
  * 参见 session.ts 的 AccumulatorState 注释。 */
19
- finalReply: string;
21
+ finalReply: string;
22
+ /** Current user-visible work phase for running progress cards. */
23
+ activity?: AgentActivity;
20
24
  /** The turn whose terminal text reply has already been delivered to IM. */
21
25
  finalReplySentTurn?: number;
22
26
  finalReplySentAt?: number;
@@ -28,8 +32,10 @@ export interface StreamState {
28
32
  tool: string;
29
33
  /** Set by stop-stuck-loop to prevent the session from being resumed.
30
34
  * The orchestrator checks this before resuming and creates a new session instead. */
31
- stuckAt?: number;
32
- }
35
+ stuckAt?: number;
36
+ /** Set when the shared response watchdog ends a turn after three minutes without new characters. */
37
+ autoEndedAt?: number;
38
+ }
33
39
 
34
40
  function getStreamStatePath(sessionId: string): string {
35
41
  return join(STREAMS_DIR, `${sessionId}.json`);
@@ -122,16 +128,18 @@ export async function markFinalReplySent(sessionId: string, turnCount: number, s
122
128
  await writeStreamState(state);
123
129
  }
124
130
 
125
- export function createEmptyStreamState(sessionId: string, cwd: string, tool: string, turnCount: number): StreamState {
126
- return {
131
+ export function createEmptyStreamState(sessionId: string, cwd: string, tool: string, turnCount: number): StreamState {
132
+ const now = Date.now();
133
+ return {
127
134
  sessionId,
128
135
  status: "running",
129
- accumulatedContent: "",
130
- finalReply: "",
136
+ accumulatedContent: "",
137
+ finalReply: "",
138
+ activity: createAgentActivityTracker(now).activity,
131
139
  chunkCount: 0,
132
140
  turnCount,
133
141
  contextTokens: 0,
134
- updatedAt: Date.now(),
142
+ updatedAt: now,
135
143
  cwd,
136
144
  tool,
137
145
  };