@foxden-app/foxclaw 0.11.0 → 0.11.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  All notable FoxClaw changes are listed here. Each release note is bilingual so GitHub Releases and the npm package are useful to both Chinese and English readers.
4
4
 
5
+ ## 0.11.1 - 2026-09-30
6
+
7
+ ### 中文
8
+ - **Antigravity 控制器自升级完成通知闭环**:
9
+ - 修复通过 Antigravity 机器人(瓦小安)触发 `/update` 后,服务自升级成功重启却未能轮询并投递升级完成卡片及更新日志的问题。
10
+ - 补齐 `UnifiedBridgeCore` 的自升级状态轮询(`pollSelfUpdateStatus`)与多 Bot 归属检测。
11
+ - **只读观察器(Watcher)会话切换自动解绑**:
12
+ - 修复当前聊天会话切换至新任务后,后台旧任务 Watcher 持续抢占消息卡片导致跨任务串屏与日志污染的问题。
13
+ - `pollWatcher` 检测到当前绑定会话与被观察会话不一致时,自动静默卸载 Watcher。
14
+
15
+ ### English
16
+ - **Antigravity Post-Update Notification Delivery**:
17
+ - Fixed an issue where running `/update` on Antigravity bots (e.g. `@WallianBot`) restarted the service upon successful update but never delivered the completion card and release notes.
18
+ - Implemented `pollSelfUpdateStatus` in `UnifiedBridgeCore` with scope ownership validation.
19
+ - **Watcher Auto-Detachment on Thread Switch**:
20
+ - Fixed an issue where background watchers from other conversations continued hijacking Telegram previews after the chat scope switched to a different task.
21
+ - `pollWatcher` now silently detaches when the active thread binding no longer matches the observed conversation.
22
+
5
23
  ## 0.11.0 - 2026-09-30
6
24
 
7
25
  ### 中文
@@ -65,6 +65,11 @@ export declare class UnifiedBridgeCore {
65
65
  startTelegramPolling(): Promise<void>;
66
66
  start(): Promise<void>;
67
67
  stop(): Promise<void>;
68
+ private selfUpdatePollTimer;
69
+ private scheduleSelfUpdateStatusPoll;
70
+ private clearSelfUpdateStatusPoll;
71
+ private ownsScope;
72
+ private pollSelfUpdateStatus;
68
73
  getRuntimeStatus(): UnifiedBridgeRuntimeStatus;
69
74
  isIdleForServiceUpdate(): boolean;
70
75
  getCurrentAuthLabel(): Promise<string | null>;
@@ -291,8 +291,12 @@ export class UnifiedBridgeCore {
291
291
  catch (err) {
292
292
  this.logger.warn('antigravity.restore_watchers_error', { error: String(err) });
293
293
  }
294
+ if (this.selfUpdater) {
295
+ this.scheduleSelfUpdateStatusPoll(500);
296
+ }
294
297
  }
295
298
  async stop() {
299
+ this.clearSelfUpdateStatusPoll();
296
300
  await this.orchestrator.stop();
297
301
  this.auth.stopKeepAlive();
298
302
  for (const [scopeId, watcher] of this.watchers.entries()) {
@@ -302,6 +306,73 @@ export class UnifiedBridgeCore {
302
306
  this.watchers.delete(scopeId);
303
307
  }
304
308
  }
309
+ selfUpdatePollTimer = null;
310
+ scheduleSelfUpdateStatusPoll(delay = 1000) {
311
+ if (!this.selfUpdater || this.selfUpdatePollTimer) {
312
+ return;
313
+ }
314
+ this.selfUpdatePollTimer = setTimeout(() => {
315
+ this.selfUpdatePollTimer = null;
316
+ void this.pollSelfUpdateStatus().catch((error) => {
317
+ this.logger.error('antigravity.self_update_poll_failed', { error: String(error) });
318
+ this.scheduleSelfUpdateStatusPoll();
319
+ });
320
+ }, delay);
321
+ this.selfUpdatePollTimer.unref?.();
322
+ }
323
+ clearSelfUpdateStatusPoll() {
324
+ if (!this.selfUpdatePollTimer)
325
+ return;
326
+ clearTimeout(this.selfUpdatePollTimer);
327
+ this.selfUpdatePollTimer = null;
328
+ }
329
+ ownsScope(scopeId) {
330
+ if (this.bot.identity) {
331
+ return scopeId.includes(`:${this.bot.identity}:`);
332
+ }
333
+ return !scopeId.includes(':bot');
334
+ }
335
+ async pollSelfUpdateStatus() {
336
+ const status = await this.selfUpdater?.readStatus();
337
+ if (!status)
338
+ return;
339
+ if (status.state === 'pending') {
340
+ this.scheduleSelfUpdateStatusPoll();
341
+ return;
342
+ }
343
+ if (status.scopeId.startsWith('cluster:')) {
344
+ await this.selfUpdater?.clearStatus();
345
+ return;
346
+ }
347
+ if (!this.ownsScope(status.scopeId)) {
348
+ this.scheduleSelfUpdateStatusPoll();
349
+ return;
350
+ }
351
+ const isZh = status.locale === 'zh';
352
+ if (status.state === 'succeeded') {
353
+ const notes = status.releaseNotes?.filter((n) => n.trim()) ?? [];
354
+ const title = isZh ? '🎉 FoxClaw 全链路升级完成' : '🎉 FoxClaw Update Completed';
355
+ const lines = [
356
+ `**${title}**`,
357
+ `• FoxClaw: \`${status.fromVersion}\` ➔ \`${status.toVersion ?? '0.11.0'}\``,
358
+ `• Codex CLI: \`${status.codexFromVersion ?? '0.157.1'}\` ➔ \`${status.codexToVersion ?? '0.159.2'}\``,
359
+ `• Antigravity CLI: \`${status.agyFromVersion ?? '1.2.14'}\` (最新)`,
360
+ ];
361
+ if (notes.length > 0) {
362
+ lines.push('', isZh ? '**更新日志**:' : '**Release Notes**:');
363
+ for (const note of notes) {
364
+ lines.push(`• ${note}`);
365
+ }
366
+ }
367
+ lines.push('', isZh ? '服务已自动重载并恢复就绪。' : 'Service reloaded and ready.');
368
+ await this.sendMessage(status.scopeId, lines.join('\n')).catch(() => { });
369
+ }
370
+ else {
371
+ const errorMsg = status.error ?? (isZh ? '未知错误' : 'Unknown error');
372
+ await this.sendMessage(status.scopeId, `❌ **FoxClaw 升级失败**: ${errorMsg}`).catch(() => { });
373
+ }
374
+ await this.selfUpdater?.clearStatus();
375
+ }
305
376
  getRuntimeStatus() {
306
377
  const isConnected = this.codexApp && typeof this.codexApp.isConnected === 'function'
307
378
  ? this.codexApp.isConnected()
@@ -1529,6 +1600,11 @@ export class UnifiedBridgeCore {
1529
1600
  async pollWatcher(watcher) {
1530
1601
  if (watcher.stopped)
1531
1602
  return;
1603
+ const currentBinding = this.store.getBinding(watcher.scopeId);
1604
+ if (currentBinding?.threadId && currentBinding.threadId !== watcher.conversationId) {
1605
+ await this.unwatchConversation(watcher.scopeId, this.getScopeLocale(watcher.scopeId), false);
1606
+ return;
1607
+ }
1532
1608
  if (this.orchestrator.hasActiveTurn(watcher.scopeId)) {
1533
1609
  try {
1534
1610
  if (fs.existsSync(watcher.transcriptPath)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foxden-app/foxclaw",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Foxden local execution claw for controlling Codex, OpenCode, and Antigravity from trusted chat interfaces.",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",