teapot-coding-agent 0.17.4 → 0.17.6

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.
@@ -377,6 +377,45 @@ export class Agent {
377
377
  return;
378
378
  const last = lineage[lineage.length - 1];
379
379
  const msgs = rebuildMessagesFrom(lineage);
380
+ // Rebuild lifetime stats from the log: turns/tools/tokens/compactions are
381
+ // SESSION totals, so a reload must not reset them to zero. Counted over
382
+ // the whole file (not just the current branch) to match what the runtime
383
+ // panel showed before the restart.
384
+ for (const e of own) {
385
+ if (e.type === "state") {
386
+ const d = e.data;
387
+ if (d.detail === "llm turn start")
388
+ this.stats.turns++;
389
+ }
390
+ else if (e.type === "tool_result") {
391
+ this.stats.toolCalls++;
392
+ }
393
+ else if (e.type === "usage") {
394
+ const u = e.data;
395
+ this.stats.inputTokens += u.inputTokens ?? 0;
396
+ this.stats.outputTokens += u.outputTokens ?? 0;
397
+ this.stats.cachedInputTokens += u.cachedInputTokens ?? 0;
398
+ }
399
+ else if (e.type === "system_note") {
400
+ const d = e.data;
401
+ if (d.event === "context-compacted")
402
+ this.stats.compactions++;
403
+ }
404
+ }
405
+ // last usage seeds the context gauge right after reload
406
+ for (let i = own.length - 1; i >= 0; i--) {
407
+ if (own[i].type === "usage") {
408
+ const u = own[i].data;
409
+ if (typeof u.inputTokens === "number") {
410
+ this.lastUsage = {
411
+ input: u.inputTokens,
412
+ output: u.outputTokens ?? 0,
413
+ ...(u.cachedInputTokens ? { cached: u.cachedInputTokens } : {}),
414
+ };
415
+ break;
416
+ }
417
+ }
418
+ }
380
419
  if (msgs.length > 0) {
381
420
  this.messages = msgs;
382
421
  this.currentBranch = last.branch;
@@ -935,9 +974,13 @@ export class Agent {
935
974
  await this.log.append("usage", this.currentSession, this.currentBranch, res.usage);
936
975
  }
937
976
  const m = res.message;
977
+ // sanitize() fills empty content with "(tool call)" for providers that
978
+ // reject blank content — that placeholder is request-only and must NOT
979
+ // reach the timeline as if the agent had said something
980
+ const isPlaceholder = m.content === "(tool call)" || m.content === "(no content)";
938
981
  await this.log.append("message", this.currentSession, this.currentBranch, {
939
982
  role: "assistant",
940
- content: m.content ?? "",
983
+ content: isPlaceholder ? "" : (m.content ?? ""),
941
984
  toolCalls: m.tool_calls?.map((c) => ({ id: c.id, name: c.function.name })),
942
985
  reasoning: res.reasoning,
943
986
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teapot-coding-agent",
3
- "version": "0.17.4",
3
+ "version": "0.17.6",
4
4
  "description": "A lightweight, always-on multi-agent harness for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-or-later",