Skip to content

fix(filters): include custom agents in usage and conversation lists - #1029

Merged
xintaofei merged 5 commits into
spacering-net:mainfrom
Adam-Dalloul:fix/custom-agent-conversation-filter
Oct 27, 2026
Merged

xintaofei merged 5 commits into
spacering-net:mainfrom
Adam-Dalloul:fix/custom-agent-conversation-filter

Conversation

@Adam-Dalloul

@Adam-Dalloul Adam-Dalloul commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Custom agents can be missing from the Token Usage and Manage Conversations filters. Include configured agents and agents with saved conversations, retain selected agents after their registration is removed, and use their current display names in both the filters and usage breakdown. Selecting an agent sends its exact ID. Narrow conversation rows also retain their titles and metadata.

This PR now contains only the filters and agent facets. Recording and native usage recovery are separate changes so their accounting contracts can be reviewed independently.

Validation: 63 UI tests, 52 token-usage/service tests, TypeScript, scoped ESLint, server/MCP/CLI Clippy and ordinary production compilation passed. The strengthened regressions exercise rendered breakdown renames, removed-agent filter IDs, and configured names that differ from the fallback. Browser checks passed at 1365/390/320px and Arabic RTL at 390px, including exact filtering and estimate updates using fixture data.

@Adam-Dalloul Adam-Dalloul changed the title fix(conversations): include custom agents in the management filter fix(usage): include custom agents and preserve their token totals Oct 24, 2026
@Adam-Dalloul
Adam-Dalloul marked this pull request as draft October 24, 2026 19:03
@Adam-Dalloul
Adam-Dalloul marked this pull request as ready for review October 24, 2026 19:27
@xintaofei

Copy link
Copy Markdown
Collaborator

@Adam-Dalloul thanks for this, and for the thorough description and checks. A lot of it is careful work:

  • The isolated-home gate. It only accepts the official adapter with an explicit CLAUDE_CONFIG_DIR override, refuses the built-in's home and ~/.claude (canonicalized, case-insensitive on Windows), and follows spawn's empty-value rule.
  • Turn keys are namespaced per session.
  • The projection change keeps usage for a turn with no output without letting an orphan footer create a turn.
  • The filters list configured agents by name, follow renames, and keep a selection after its registration is gone.

We're not going to merge it in its current form, though. The usage half has two problems that I think need a design decision rather than a patch:

  1. §1 One usage source per session drops recorded usage after a context reset. This is the main one.
  2. §2 PromptResponse.usage doesn't mean the same thing for every agent it's recorded for. Built-in Command Code and TRAE turns can be over-counted.

§3 covers smaller things, and the end has a suggestion for splitting this up.

§1 One source per session drops recorded usage after a context reset

This applies to custom claude-agent-acp agents with an isolated CLAUDE_CONFIG_DIR, the only case native recovery handles. For each session in the continuation chain, native_usage::read picks one source, in this order:

  1. Claude's own <CLAUDE_CONFIG_DIR>/projects/*/<session id>.jsonl, whenever it yields any usage.
  2. Saved native facts.
  3. Only then, that session's ACP transcript (native_usage.rs#L153-L180).

The description puts it as "new native records replace overlapping ACP counts". That assumes the native file named after the ACP session id covers the whole ACP session. With claude-agent-acp, the file stops covering it in two everyday flows.

Approving a plan with "Yes, clear context …". This is the first option in the ExitPlanMode prompt whenever there's a plan (tools.ts#L73-L95, v0.94.0). Choosing it does the following:

So <ACP session id>.jsonl ends at the plan. The implementation and everything after it land in a file nothing links to. codeg's built-in Claude history has the same truncation; it's noted as unsolved in registry.rs#L1425-L1430.

/clear. Claude rolls over to a new <uuid>.jsonl while the ACP session id stays the same (claude.rs#L1288-L1292). native_usage deliberately doesn't follow rollovers (native_usage.rs#L120-L124).

In both flows, the ACP transcript keeps receiving PromptResponse.usage for the turns after the reset, which is exactly what this PR starts recording. But as long as the original file yields any usage for that session, or saved native facts exist for it, those facts win and the session's ACP records are never read.

Example: you plan in plan mode, approve with clear context, let the implementation run, then continue for a few turns. The dashboard shows only what was spent before the approval. The rest was recorded and is then dropped.

The same rule also freezes a session whose native file goes away while the chat continues:

  • Its saved native facts keep winning (native_usage.rs#L160-L162), so the ACP usage of turns completed afterwards in that session is ignored.
  • If no other session in the chain supplies fresh facts, the result is KeepRecorded and the sync settles without rewriting anything (token_usage.rs#L1059-L1062).

The obvious fixes fall short because neither source is complete on its own. I ran claude-agent-acp 0.94.0 (the version codeg pins) against a local stub model, with one prompt that started a background sub-agent:

  • The response's usage was 4,000 in / 10 out.
  • _meta.quota.model_usage in the same response was 6,000 / 15. The sub-agent's 2,000 / 5 isn't in usage.
  • The adapter also leaves autonomous results out of the per-prompt tally on purpose (acp-agent.ts#L6924-L6936).

Claude's own transcript does include sub-agent spend. So "native wins" loses the post-reset work, and "ACP only" loses sub-agent spend.

Shortcuts I looked at
  • Take the larger of the two totals per session. This is never worse than now. But it still loses the post-reset work whenever the pre-reset part, with its sub-agents, is the larger one.
  • Follow /clear with find_clear_rollover_successor.
    • It matches a sibling file that starts with a /clear record within five minutes of the old file's last record. When two sessions in the same project both clear within that window, it can pick the other session's file.
    • It also does nothing for clear-context.
  • Switch to ACP from the reset onwards.

So recovery needs a policy for combining the two sources per turn, or a reliable way to find the post-reset file. We'd like to settle that policy before code.

§2 PromptResponse.usage doesn't mean the same thing everywhere

The PR records response.usage for every agent whose history codeg keeps as an ACP transcript: custom agents, ZCode, and the built-in TRAE and Command Code (agent.rs#L80-L86, connection.rs#L13976-L13984). parse_usage then reads it as cache-exclusive: input + output + cache read + cache write (acp_native.rs#L621-L635). Two of those built-ins report something else.

Command Code (command-code@1.86.3, the version codeg pins; read from the published bundle):

  • promptResult returns usage as a running total since the session was opened, because each turn_end is added to sessionUsage.
  • The per-prompt figure is only in _meta.usage, with cacheReadTokens/cacheWriteTokens spellings that parse_usage doesn't read.
  • Its counters come from the AI SDK's totalUsage. Command Code's own cost estimate treats inputTokens as including cache: estimateCatalogCostUsd prices max(0, inputTokens − cacheReadTokens − cacheWriteTokens) as fresh input.
  • So three 1,000-token prompts in one opening of a session are stored as 1,000 + 2,000 + 3,000, and on top of that any cache reads are counted twice.

TRAE CLI 0.209.1. I ran a turn against a local stub model with 1,234 input tokens (1,000 of them cached) and 56 output.

  • It came back as usage: {inputTokens: 1234, cachedReadTokens: 1000, outputTokens: 56, totalTokens: 1290}.
  • TRAE's own _meta["_trae/tokenUsage"].turnDisplay gives the fresh input as 234.
  • parse_usage would store that turn as 2,290 tokens instead of 1,290.

This affects turns recorded after upgrading:

  • Command Code is overcounted when more than one prompt response is recorded during the same opening of a session and an earlier one had usage, because the running totals are summed. Reopening the session resets the total. It is also overcounted whenever input was cached.
  • TRAE is overcounted whenever input was cached.

The same applies to hand-registered custom agents running those CLIs, with ids like command-code or trae that predate the built-ins (agent.rs#L176-L181).

For other custom agents, the field's meaning isn't settled yet:

  • The schema describes it as usage "for a prompt turn", but its fields as "across session" / "across all turns" (agent.rs#L3433-L3445).
  • The end-turn token usage RFD is kept in Draft (end-turn-token-usage.mdx#L14), and its first open question is exactly per-turn vs cumulative (#L95-L97).

claude-agent-acp reports per prompt and cache-exclusive (acp-agent.ts#L11855-L11880), so recording it as-is is right for the Claude custom agents in your description. For adapters we don't recognize, we'd want an explicit rule rather than an assumption.

§3 Smaller things

  • Stopped turns record nothing.
    • On Stop, codeg deliberately doesn't write a turn end (connection.rs#L14292-L14300).
    • The late cancelled response is awaited in the background and dropped (connection.rs#L14383-L14385), so its usage never reaches the transcript.
    • This isn't a regression, since nothing was recorded before.
    • For Command Code, usage it had already counted during a stopped prompt (it adds each internal turn_end to the running total) does show up in the next response from the same open session. That is one reason to difference that total rather than read _meta.usage. It can't recover spend the adapter never reported.
  • Re-registering a deleted agent can drop earlier sessions' saved usage.
    • Deleting a custom agent with its transcripts (custom_agents.rs#L140-L149) also removes the continuation headers, so a later sync only walks the current session.
    • Suppose the same id is registered again with an eligible isolated home. The next sync of that conversation (after a new turn, or a full rebuild) reads fresh native facts for the current session and replaces the conversation's rows with them.
    • Saved facts are only carried over for sessions the walk visits (native_usage.rs#L128-L134), and acp-usage: rows aren't carried over at all (native_usage.rs#L93-L95). So the earlier sessions' usage is gone.
    • While the agent stays deleted, the rows are kept.
  • A few tests would still pass with the behaviour they cover broken:
    • token-usage-page.test.tsx doesn't exercise the breakdown labels: by_agent is empty and the charts are mocked. Your description reports Chromium checks covering these labels.
    • "keeps a removed agent from saved chats selectable even when its filter returns no rows" never asserts that selecting the removed agent sends agent_type: "custom:retired-reviewer". A change that dropped an unknown filter to null would still pass.
    • "keeps custom accounts reachable by name in the overflow menu" uses names identical to the humanized ids (Claude Code 2 for custom:claude-code-2), so it can't tell a configured name from the fallback.

Suggested way forward

  1. The filter work. This is the management dialog, the Token Usage filter, and facet_agents. It is independent of the usage changes and looks good to me, so it could be split out and reviewed on its own.

  2. Recording on its own. This is the Cargo feature, record_turn_end, and the projection change.

    • Command Code and TRAE need to be either normalized or left out for now:
      • Command Code: difference successive running totals, with a new baseline each time the session is opened, and take cache out of inputTokens. Also decide where a stopped prompt's share goes; otherwise it lands on the next recorded response, under that response's model.
      • TRAE: take cache out of inputTokens. feat: 为 TRAE CLI 会话添加原生 token 使用量的导入和统计 #1019 also changes TRAE usage, so the two will need to agree.
    • It also needs an explicit rule for custom adapters we don't recognize.
  3. Native recovery as a separate PR. It should combine the sources per turn instead of picking one per session. The rule has to cover:

    • turns that predate recorded ACP usage;
    • turns the native file no longer covers;
    • turns both sources cover, keeping native's sub-agent spend without double-counting the carried pre-reset part.

    I'm happy to talk the policy through in an issue first.

Your tests and CI pass; they just don't exercise the adapter behaviour or the cleanup/re-registration case described above. If I've misread any of it, please say so and I'll take another look. That applies especially if you have a session where native-first gives the right total after a clear-context approval.

@Adam-Dalloul Adam-Dalloul changed the title fix(usage): include custom agents and preserve their token totals fix(filters): include custom agents in usage and conversation lists Oct 27, 2026
@Adam-Dalloul

Adam-Dalloul commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor Author

@xintaofei, this PR now contains only the filter fixes and strengthened tests; recording is separate in #1048. I reproduced the reset/resume cases on 0.97.0 and opened #1047 for the recovery policy.

@xintaofei
xintaofei merged commit 8670ef5 into spacering-net:main Oct 27, 2026
13 checks passed
xintaofei added a commit that referenced this pull request Oct 28, 2026
This release brings folder-specific tabs and split layouts, HTML previews in replies, native MiniMax Code support and OpenCode 2 integration, alongside easier model selection, more flexible task delivery and improved usage reporting.

## New

- **Tabs can follow the selected folder**: enable “Tabs follow folder” in the sidebar’s View options to switch conversations, files and split layouts together while preserving drafts, unsaved edits and running conversations. (#1039, @fengpanhe)
- **HTML/CSS cards and charts can appear directly in replies**: enable “Chat HTML rendering” in Settings → Appearance to preview static HTML alongside Markdown, including during streaming, and switch back to the source when needed. (#1041, @ana52070)
- **MiniMax Code joins the built-in agents**, connecting to your installed `mcode` with its existing login and provider settings, with support for MCP tools and multi-agent delegation. (#1028, @xy3xy3)
- **Model fields can fetch and list your provider’s models directly**, with search, refresh and retry controls for Claude Code, Gemini CLI, OpenCode and other supported agents.
- **Codex model management is gathered into one section**, where you can choose the built-in or provider list, select models and refresh automatically while retaining the last working list if a refresh fails.
- **Tasks ready for review can open pull requests on GitHub, GitLab and Gitea/Forgejo**, including tasks created without an issue, with the option to keep the task open and push later changes to the same request.
- **ZCode supports unified Skills management**, including browsing, editing, importing and installing skills through codeg’s settings. (#1021, @jackie-cqz)

## Improved

- **OpenCode moves to 2.2.0**, with updated provider connections, permissions, MCP and plugin management that preserve comments in JSONC configuration files.
- **OpenCode conversations show form questions, scripts and background sub-agent progress**, and saved conversations include the newer database’s compaction records, command exit codes and media attachments.
- **Claude Code moves to claude-agent-acp 0.98.0**, with dedicated monitor steps showing the watched command or address, plus progress and trigger details for work started by background tasks or scheduled wakeups.
- **Claude Code’s sandbox network permission cards name the destination host**, making it easier to decide whether to allow a connection.
- **Codex moves to codex-acp 2.3.0**, reducing the wait to reopen a fork’s parent conversation to about a minute and improving saved tool output and error messages.
- **Cline, CodeBuddy, Kimi Code, Grok, Cursor, Antigravity, ZCode and Command Code are updated**, with compatibility adjustments for their current tools and configuration.
- **Bundled Superpowers skills move to v7.0.1**, adding session diagnostics for repeated work, plan drift and unusual costs, alongside improved planning, execution, review and standalone skill compatibility.
- **Hermes conversations offer model selection grouped by provider and a mode selector**, restoring your choices when you reopen the conversation.
- **Creating a task from a message opens the editor over the current conversation**, with the message and project filled in so you can save without leaving what you were reading.
- **The activity timeline uses clearer grey backgrounds, text hierarchy and icon spacing**, with a collapse action at the bottom of expanded steps that brings their header back into view.
- **Command rows explain outcomes such as no matches, false conditions, differing files and timeouts**, while command output stays folded by default.
- **TRAE CLI usage comes from its native records and includes sub-agent consumption**, giving conversations and usage reports more complete token totals. (#1019, @fengpanhe)

## Fixed

- **Antigravity’s native questions appear as interactive cards**, with selected answers preserved after reopening and historical multi-select, written-in and skipped answers displayed correctly. (#1043, @ana52070)
- **OpenCode 2 delegations display as sub-agent tasks with the correct conversation links**, including after reopening and when several delegations run in parallel. (#1020, @Liang-HZ)
- **Files with Chinese or other non-ASCII names, and renamed files, show correct change counts and diff previews** in the Changes panel and task details. (#1022, @MaxFreedomPollard)
- **Usage and Manage Conversations filters include custom agents and show their current names**, making their conversations and consumption easier to find. (#1029, @Adam-Dalloul)
- **Conversations using the official Claude adapter retain reported per-prompt usage and costs after reopening**, including custom agents, whose linked native sessions are also skipped during new imports to avoid duplicate usage counts. (#1048, @Adam-Dalloul)
- **Conversations retain their recorded duration even without token data**, and reported turn usage is preserved when a Remote Control message ends the reply.
- **A Codex reply that continues after automatic context compaction stays together in history**, instead of splitting into separate replies with duplicate activity headers and footers.
- **Claude advisor results remain visible after reopening**, in both the main conversation and sub-agent conversations.
- **A Kimi Code conversation that is busy in another client reports that it is in use**, instead of switching the conversation to a new empty session.
- **Dragging agents to reorder them in Settings keeps the list in place**, while selecting another agent still scrolls it into view. (#1033, @xyalter)
- **Agents that depend on installation scripts, including Hermes Agent, install correctly with npm 12.**
- **Fixed a Windows issue where ending an agent session could leave Git Bash with a missing temporary directory**, causing later commands to fail.
- **The macOS desktop app avoids the system’s low-swap suspension**, which could leave every conversation unresponsive while the agents kept running.
- **Multi-agent tool calls stop waiting when codeg remains unresponsive**, preventing them from hanging indefinitely.

## Note

- **OpenCode now requires version 2.0 or later**, so upgrade any 1.x installation before opening conversations and use plugins compatible with OpenCode 2.
- **OpenCode 2 does not support SSE MCP servers**, so use streamable HTTP when the server offers it, or leave OpenCode out of that server’s assignments.
- **The macOS standalone server now retains Full Disk Access and other privacy permissions across future updates**, but moving from an older build to this release requires granting those permissions once more.

-----------------------------

# 发布版本 0.41.0

这一版加入了按文件夹切换标签页和分屏布局、对话内 HTML 预览、MiniMax Code 原生支持和 OpenCode 2 适配,同时改进模型选择、任务交付和用量统计。

## 新增

- **标签页可以跟随当前文件夹切换**——在侧栏「视图选项」中开启「标签页跟随文件夹」,即可一起切换各文件夹的会话、文件和分屏布局,并保留草稿、未保存的修改和正在运行的对话。(#1039,@fengpanhe)
- **AI 回复中的 HTML/CSS 卡片和图表可以直接预览**——在「设置 → 外观」开启「聊天 HTML 渲染」,即可在流式回复中查看与 Markdown 混排的静态 HTML,并随时切回源码。(#1041,@ana52070)
- **新增内置智能体 MiniMax Code**,可连接已安装的 `mcode`,沿用已有登录和供应商配置,并支持 MCP 工具与多智能体委派。(#1028,@xy3xy3)
- **模型输入框可以直接获取并列出供应商提供的模型**,支持搜索、刷新和失败重试,适用于 Claude Code、Gemini CLI、OpenCode 等智能体。
- **Codex 的模型集中在同一处管理**,可切换内置或供应商列表、勾选模型并自动刷新,刷新失败时保留上次可用的列表。
- **待验收的任务可以直接创建 GitHub、GitLab 和 Gitea/Forgejo 的拉取请求**,无需先关联 Issue,也可以在交付后保留任务,继续处理并更新同一个 PR。
- **ZCode 接入统一的技能管理**,可以在 codeg 设置中查看、编辑、导入和安装技能。(#1021,@jackie-cqz)

## 改进

- **OpenCode 升级到 2.2.0**,供应商连接、权限、MCP 和插件管理均适配新版,并保留 JSONC 配置文件中的注释。
- **OpenCode 会话支持展示表单提问、脚本执行和后台子智能体进度**,历史会话也能读取新版数据库中的压缩记录、命令退出码和媒体附件。
- **Claude Code 升级到 claude-agent-acp 0.98.0**,监控任务会单独展示正在监听的命令或地址,后台任务和定时唤醒触发的工作也能查看进度与触发原因。
- **Claude Code 的沙箱联网授权会明确显示目标主机**,方便确认当前请求要连接哪里。
- **Codex 升级到 codex-acp 2.3.0**,分叉后重新打开父会话的等待时间缩短至约一分钟,历史工具输出和错误提示也更易读。
- **同步更新 Cline、CodeBuddy、Kimi Code、Grok、Cursor、Antigravity、ZCode 和 Command Code**,并适配新版工具记录和配置行为。
- **内置 Superpowers 技能更新到 v7.0.1**,新增会话诊断来分析重复工作、计划偏离和异常开销,同时改进计划编写、执行、审核及技能单独安装的兼容性。
- **Hermes 会话支持按供应商分组选择模型和切换运行模式**,重新打开会话后会恢复之前的选择。
- **从消息创建任务时,编辑窗口直接在当前对话上打开**,自动带入消息内容和所属项目,保存任务无需离开正在阅读的会话。
- **执行过程采用更清晰的灰色背景、文字层次和图标间距**,展开的步骤列表底部可一键收起,并自动回到对应标题。
- **命令结果会直接说明「无匹配」「条件不成立」「有差异」「超时」等含义**,命令输出默认保持收起,按需展开查看。
- **TRAE CLI 用量统计改为读取原生记录,并计入子智能体消耗**,会话和用量报表中的 token 总量更加完整。(#1019,@fengpanhe)

## 修复

- **Antigravity 的原生提问会显示为可直接回答的交互卡片**,重新打开后仍能看到已选答案,历史中的多选、自填和跳过记录也能正确展示。(#1043,@ana52070)
- **OpenCode 2 的委派会正确显示为子智能体任务并关联对应会话**,重新打开或同时委派多个任务时也能正确查看。(#1020,@Liang-HZ)
- **中文等非 ASCII 文件名和重命名文件能正确显示增删行数与差异预览**,覆盖「变更」面板和任务详情。(#1022,@MaxFreedomPollard)
- **用量统计和「管理会话」的筛选包含自定义智能体,并显示当前名称**,查找对应会话和消耗更方便。(#1029,@Adam-Dalloul)
- **使用官方 Claude 适配器的会话会保留每轮返回的用量与费用**,自定义智能体也适用,新导入时还会跳过已关联的原生会话,避免重复统计。(#1048,@Adam-Dalloul)
- **没有 token 数据的会话仍会保留已记录的执行耗时**,远程控制消息结束当前回复时,也不会丢失本轮已报告的用量。
- **Codex 在自动压缩上下文后继续生成的回复,回看时会保持完整**,不会再拆成两条并重复显示执行过程和统计。
- **Claude 顾问模型的回答会保留在历史中**,重新打开主会话或子智能体会话后都能查看。
- **Kimi Code 会话被其他客户端占用时会正确提示**,不会再误建空会话并切换过去。
- **在设置中拖动智能体排序时,列表不会再突然跳回当前选中项**,切换智能体时仍会自动滚动到对应位置。(#1033,@xyalter)
- **使用 npm 12 也能正确安装 Hermes Agent 等依赖安装脚本的智能体。**
- **修复 Windows 上结束智能体会话后,Git Bash 临时目录失效的问题**,避免后续命令因找不到临时目录而失败。
- **修复 macOS 因交换空间耗尽而挂起 codeg 的问题**,避免智能体仍在运行、所有会话却一起失去响应。
- **多智能体工具调用在 codeg 长时间失去响应时会结束等待**,避免一直卡住。

## 注意

- **OpenCode 现在要求 2.0 及以上版本**,请先升级已有的 1.x 安装再打开会话,并换用兼容 OpenCode 2 的插件。
- **OpenCode 2 不支持 SSE 类型的 MCP 服务器**,如果服务器提供 streamable HTTP,请改用该方式,否则不要为该服务器选择 OpenCode。
- **macOS 独立服务器版在后续更新中可以保留「完全磁盘访问」等隐私权限**,但从旧版首次升级到本版时,需要重新授予一次权限。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants