@jerryliang122/openclaw-qqbot 1.0.4 → 1.0.5

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/dist/index.d.cts CHANGED
@@ -860,8 +860,13 @@ declare class StreamingController {
860
860
  private session;
861
861
  /** QQ 已接受的最新文本 — 单源真理 */
862
862
  private lastAcceptedFull;
863
- /** 已成功发送的分片数(降级:=0 则走静态消息兜底) */
863
+ /** 已成功发送的分片数(降级:=0 且无外部投递则走静态消息兜底) */
864
864
  private sentChunkCount;
865
+ /**
866
+ * 标记:内容已通过非流式通道成功投递(如 ask_user 按钮卡片)。
867
+ * 置 true 后 handleFinalize 不再走 fallback 路径,避免框架误报 outcome=error。
868
+ */
869
+ private _deliveredExternally;
865
870
  /** 同步标志:收到第一个 onPartialReply 即置 true(不等 async 完成) */
866
871
  private _hasStarted;
867
872
  /** 串行队列 */
@@ -882,6 +887,11 @@ declare class StreamingController {
882
887
  get hasStarted(): boolean;
883
888
  get isTerminal(): boolean;
884
889
  get shouldFallbackToStatic(): boolean;
890
+ /**
891
+ * 告知控制器内容已通过外部通道投递(如 ask_user 卡片)。
892
+ * 后续 finalize() 不会走 fallback 路径,框架不会误报 outcome=error。
893
+ */
894
+ markDeliveredExternally(): void;
885
895
  onPartialReply(text: string): Promise<void>;
886
896
  finalize(): Promise<void>;
887
897
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jerryliang122/openclaw-qqbot",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "QQ Bot channel plugin for OpenClaw (independently maintained fork)",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -298,6 +298,8 @@ export async function dispatchToOpenClaw(
298
298
  try {
299
299
  await bot.sendTextWithKeyboard(replyTarget, text, keyboard as never);
300
300
  outboundSendOk++;
301
+ // 标记流式控制器:内容已通过外部通道投递,finalize 不走 fallback
302
+ streamingController?.markDeliveredExternally();
301
303
  dlog?.debug(`[question] sent ask_user with keyboard questionId=${questionId} options=${optionValues.length}`);
302
304
  return;
303
305
  } catch (err) {
@@ -331,6 +333,8 @@ export async function dispatchToOpenClaw(
331
333
  await bot.sendTextWithKeyboard(replyTarget, cardText, keyboard as never);
332
334
  outboundSendOk++;
333
335
  }
336
+ // 标记流式控制器:内容已通过外部通道投递,finalize 不走 fallback
337
+ streamingController?.markDeliveredExternally();
334
338
  dlog?.debug(`[question] sent multi-question ask_user questionId=${questionId} questions=${questions.length}`);
335
339
  return;
336
340
  } catch (err) {
@@ -51,9 +51,15 @@ export class StreamingController {
51
51
  /** QQ 已接受的最新文本 — 单源真理 */
52
52
  private lastAcceptedFull = '';
53
53
 
54
- /** 已成功发送的分片数(降级:=0 则走静态消息兜底) */
54
+ /** 已成功发送的分片数(降级:=0 且无外部投递则走静态消息兜底) */
55
55
  private sentChunkCount = 0;
56
56
 
57
+ /**
58
+ * 标记:内容已通过非流式通道成功投递(如 ask_user 按钮卡片)。
59
+ * 置 true 后 handleFinalize 不再走 fallback 路径,避免框架误报 outcome=error。
60
+ */
61
+ private _deliveredExternally = false;
62
+
57
63
  /** 同步标志:收到第一个 onPartialReply 即置 true(不等 async 完成) */
58
64
  private _hasStarted = false;
59
65
 
@@ -87,7 +93,15 @@ export class StreamingController {
87
93
  }
88
94
 
89
95
  get shouldFallbackToStatic(): boolean {
90
- return this.isTerminal && this.sentChunkCount === 0;
96
+ return this.isTerminal && this.sentChunkCount === 0 && !this._deliveredExternally;
97
+ }
98
+
99
+ /**
100
+ * 告知控制器内容已通过外部通道投递(如 ask_user 卡片)。
101
+ * 后续 finalize() 不会走 fallback 路径,框架不会误报 outcome=error。
102
+ */
103
+ markDeliveredExternally(): void {
104
+ this._deliveredExternally = true;
91
105
  }
92
106
 
93
107
  // ── 入口 ──
@@ -212,6 +226,9 @@ export class StreamingController {
212
226
  } else if (this.sentChunkCount > 0 && this.lastAcceptedFull) {
213
227
  // 未提供 sendStatic → 降级标记,由上层兜底发送
214
228
  this.transition('failed', 'finalize:no_sendstatic');
229
+ } else if (this._deliveredExternally) {
230
+ // 内容已通过外部通道投递(如 ask_user 卡片),非失败
231
+ this.transition('done', 'finalize');
215
232
  } else {
216
233
  this.transition('done', 'finalize:fallback');
217
234
  }
@@ -227,8 +244,8 @@ export class StreamingController {
227
244
  }
228
245
 
229
246
  // 无会话 — 视有无下发决定终态
230
- if (this.sentChunkCount > 0) {
231
- this.transition('done', 'finalize:no_session');
247
+ if (this.sentChunkCount > 0 || this._deliveredExternally) {
248
+ this.transition('done', this.sentChunkCount > 0 ? 'finalize:no_session' : 'finalize');
232
249
  } else {
233
250
  this.transition('done', 'finalize:fallback');
234
251
  }