@foxden-app/foxclaw 0.13.8 → 0.13.9

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,18 @@
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.13.9 - 2026-10-06
6
+
7
+ ### 中文
8
+
9
+ - 小结归档的 Token 总/入/出/缓存采用人类可读单位:低于千保持整数,按量级使用 K、M、G,缺失计数保留“—”。
10
+ - Antigravity 有中间响应步骤时,按原生步骤编号识别真实小结:进入后续工具或响应步骤后独立推送之前的说明,任务完成后合并为一条计时与用量归档,最终回答独立保留。忽略重复和迟到的已收纳步骤;只有最终回答的轮次保留原展示,不生成额外小结。DSH 继续按原生消息边界采用相同归档流程。
11
+
12
+ ### English
13
+
14
+ - Format archive total/input/output/cached token counts using human-readable K, M, and G units, retaining raw counts below one thousand and “—” for unavailable values.
15
+ - Recognize actual intermediate Antigravity responses by native step index. Send preceding explanations separately when a later tool or response step begins, then consolidate them into a timed usage archive while keeping the final answer separate. Ignore duplicate and late collected steps. Turns with only a final response keep their existing presentation. DSH continues using the same archive flow through native message boundaries.
16
+
5
17
  ## 0.13.8 - 2026-10-06
6
18
 
7
19
  ### 中文
@@ -104,6 +104,17 @@ export class AntigravityEngineAdapter {
104
104
  let subagentTracker = null;
105
105
  let pollTimer = null;
106
106
  let turnFinished = false;
107
+ let pendingResponse;
108
+ const collectedResponses = new Set();
109
+ const collectResponseBefore = (stepIndex) => {
110
+ if (!pendingResponse || stepIndex <= pendingResponse.stepIndex)
111
+ return;
112
+ if (pendingResponse.text.trim() && !collectedResponses.has(pendingResponse.stepIndex)) {
113
+ collectedResponses.add(pendingResponse.stepIndex);
114
+ emitter.emit('commentary', { messageId: `agy:${pendingResponse.conversationId}:${pendingResponse.stepIndex}`, text: pendingResponse.text });
115
+ }
116
+ pendingResponse = undefined;
117
+ };
107
118
  const ensureTracker = (convId) => {
108
119
  if (!convId || subagentTracker)
109
120
  return;
@@ -164,9 +175,14 @@ export class AntigravityEngineAdapter {
164
175
  }
165
176
  switch (ev.kind) {
166
177
  case 'text':
178
+ if (collectedResponses.has(ev.stepIndex) || (pendingResponse && ev.stepIndex < pendingResponse.stepIndex))
179
+ break;
180
+ collectResponseBefore(ev.stepIndex);
181
+ pendingResponse = { stepIndex: ev.stepIndex, conversationId: ev.conversationId, text: ev.accumulatedText };
167
182
  emitter.emit('delta', ev.delta);
168
183
  break;
169
184
  case 'tool':
185
+ collectResponseBefore(ev.stepIndex);
170
186
  emitter.emit('tool', {
171
187
  name: ev.toolName,
172
188
  args: ev.parameters,
@@ -1,10 +1,11 @@
1
1
  import { escapeTelegramHtml } from './html.js';
2
2
  import { renderTelegramMarkdownRichHtml } from './rich_markdown.js';
3
+ import { formatMetricTokenCount } from '../store/token_usage.js';
3
4
  export function commentaryArchiveHeader(archive) {
4
5
  const zh = archive.locale === 'zh';
5
6
  const seconds = Math.max(0, Math.round((archive.endedAt - archive.startedAt) / 1000));
6
7
  const duration = seconds < 60 ? `${seconds}s` : `${Math.floor(seconds / 60)}m${seconds % 60}s`;
7
- const count = (n) => typeof n === 'number' && Number.isFinite(n) ? Math.round(Math.max(0, n)).toLocaleString('en-US') : '—';
8
+ const count = (n) => typeof n === 'number' && Number.isFinite(n) ? formatMetricTokenCount(n) : '—';
8
9
  const usage = archive.usage;
9
10
  const total = usage?.totalTokens ?? (usage?.inputTokens !== undefined && usage.outputTokens !== undefined ? usage.inputTokens + usage.outputTokens : undefined);
10
11
  return `${zh ? '总时间' : 'Total time'}: ${duration} ${zh ? 'Token(总/入/出/缓存)' : 'Tokens (total/in/out/cache)'}: ${[total, usage?.inputTokens, usage?.outputTokens, usage?.cachedTokens].map(count).join('/')}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foxden-app/foxclaw",
3
- "version": "0.13.8",
3
+ "version": "0.13.9",
4
4
  "description": "Foxden local execution claw for controlling Codex, OpenCode, Antigravity, and DeepSeek Harness from trusted chat interfaces.",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",