Skip to content

/instances returns unbounded list of historical known instances #36

Description

@NorveraFlorent

~/.forge-hub/state/_hub/instance-identities.json 持久化所有曾连 Hub 的 instance,每个新 forked PID 都是新 ID 写一条(instance-manager.ts:194 register、:219 ready、:242 ws-close、setTag/setDescription/setChannels 等共 8 个 saveIdentity callsite),永不剔除

routes/instances.ts:9 handleInstancesroutes/health.ts:35 buildInstanceListinstance-manager.ts:117 listKnownInstances 把保存的 identities 全量 union 当前 in-memory instances 返回,无 filter,无 query 参数支持。

实测累积

时间 条目 响应大小
2026-05-12 258 15 KB
2026-05-27 645 67 KB

单用户机器累积速度 ~26 entries/day。

影响

  1. 响应跨过下游消费者 pipe buffer 阈值会触发死锁(见 forge-launcher 配套 issue)
  2. 即使消费者没 bug,每次 enrichScanResults 都全量 fetch 也是 IO + JSON 解析的线性浪费
  3. 历史 stale 条目里 ~85% 没 description/tag(645 → 99 有标识 = 546 是纯噪声)

建议修法

默认行为不要改(避免破坏现有客户端契约),走 query 参数:

GET /instances              → 现有行为(all known,含 stale)
GET /instances?include=live → 只返当前在线
GET /instances?include=tagged → 在线 + 有 description/tag 的离线(供 menubar 之类的回放)

配套:长期可在 hub 启动时 GC instance-identities.json——剔除 >30 天 lastSeenAt 且无 description/tag 的条目。

临时绕过

python3 -c "
import json
p='$HOME/.forge-hub/state/_hub/instance-identities.json'
d=json.load(open(p))
kept={k:v for k,v in d.items() if v.get('description') or v.get('tag')}
json.dump(kept, open(p,'w'), indent=2, ensure_ascii=False)
print(f'{len(d)} -> {len(kept)}')
"
launchctl kickstart -k gui/$(id -u)/com.forge-hub

listKnownInstances 只读不写,trim 不会被自动回填。

环境

  • forge-hub: HEAD-19628bb
  • Bun 1.3.14
  • macOS 25.5.0

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions