chatccc 0.2.263 → 0.2.264

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.
@@ -92,10 +92,16 @@ export function createDshAdapter(options = {}) {
92
92
  const task = (async () => {
93
93
  try {
94
94
  await runtime.start();
95
+ // DSH 引擎在 LLM 调用失败时不会让 run() reject:错误被写进 turn/end 事件
96
+ // 的 reason(kind="error")后,session 进入 idle,run() 返回空 finalResponse。
97
+ // 这里把第一个 turn 错误收集起来,run() 结束后重新抛出,交给 session.ts
98
+ // 的统一终态错误分类与脱敏展示,避免飞书里"静默失败"。
99
+ let turnError = null;
95
100
  const result = await runtime.run(userText, {
96
101
  sessionId,
97
102
  onNotification: (notification) => {
98
103
  rawLog?.writeLine(JSON.stringify(notification));
104
+ turnError ??= extractTurnError(notification);
99
105
  const message = notificationToMessage(notification);
100
106
  if (message)
101
107
  queue.push(message);
@@ -104,10 +110,24 @@ export function createDshAdapter(options = {}) {
104
110
  if (result.finalResponse) {
105
111
  rawLog?.writeLine(JSON.stringify({ type: "run.result", result }));
106
112
  queue.push({ type: "assistant", blocks: [{ type: "text_final", text: result.finalResponse }], isFinalResponse: true });
113
+ completed = true;
114
+ }
115
+ else if (turnError) {
116
+ queue.fail(turnError);
117
+ }
118
+ else {
119
+ // 引擎正常结束但零输出(无错误、无回复):给出明确提示,避免用户只看到"失败"。
120
+ queue.push({
121
+ type: "assistant",
122
+ blocks: [{ type: "text_final", text: "DeepSeek Harness 本轮未产生任何回复(引擎未报告错误)。" }],
123
+ isFinalResponse: true,
124
+ });
125
+ completed = true;
126
+ }
127
+ if (completed) {
128
+ knownSessions.set(sessionId, { sessionId, cwd, lastModified: Date.now(), model: options.model ?? "deepseek-v4-flash" });
129
+ queue.end();
107
130
  }
108
- completed = true;
109
- knownSessions.set(sessionId, { sessionId, cwd, lastModified: Date.now(), model: options.model ?? "deepseek-v4-flash" });
110
- queue.end();
111
131
  }
112
132
  catch (error) {
113
133
  queue.fail(error instanceof Error ? error : new Error(String(error)));
@@ -136,6 +156,32 @@ export function createDshAdapter(options = {}) {
136
156
  },
137
157
  };
138
158
  }
159
+ /**
160
+ * 从 DSH 引擎的 session.event 里提取第一个 turn/end 错误。
161
+ *
162
+ * DSH 引擎(dsh-agent-loop)在 turn 失败时把错误持久化到 `turn/end` 事件的
163
+ * `data.reason`(`{ kind: "error", error: { message, code, status? } }`),随后
164
+ * `kick()` 吞掉该错误并让 session 进入 idle。SDK 的 `run()` 因此正常返回空
165
+ * `finalResponse`,而不是 reject。此函数把该错误还原成 Error,供 prompt()
166
+ * 重新抛出,复用 session.ts 的统一终态错误分类(401/429/网络等)与脱敏。
167
+ */
168
+ function extractTurnError(notification) {
169
+ if (notification.method !== "session.event")
170
+ return null;
171
+ const event = asRecord(notification.params.event);
172
+ if (!event || event.type !== "turn/end")
173
+ return null;
174
+ const data = asRecord(event.data);
175
+ const reason = asRecord(data?.reason);
176
+ if (!reason || reason.kind !== "error")
177
+ return null;
178
+ const failure = asRecord(reason.error);
179
+ const code = typeof failure?.code === "string" ? failure.code : "";
180
+ const status = typeof failure?.status === "number" ? `HTTP ${failure.status}` : "";
181
+ const message = typeof failure?.message === "string" ? failure.message : "";
182
+ const detail = [status, code ? `[${code}]` : "", message].filter(Boolean).join(" ").trim();
183
+ return new Error(detail || "DeepSeek Harness 引擎报告了未提供详情的执行错误");
184
+ }
139
185
  function notificationToMessage(notification) {
140
186
  if (notification.method === "session.status") {
141
187
  return notification.params.status === "running"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chatccc",
3
- "version": "0.2.263",
3
+ "version": "0.2.264",
4
4
  "description": "Feishu bot bridge for Claude Code",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",