JSONL 看起来很简单:每个换行符分隔一个对象。但实时编程 Agent transcript 还会遇到尾行未写完、单行负载异常大、事件重复,以及旧完成事件被后续活动覆盖等问题。
解析前先限制读取边界
应该使用流式读取和明确的单行策略,不能把无限增长的 transcript 一次性装进字符串。Agent Island v1.7.1 的平台实现并不完全相同:macOS Claude reader 有 64 MiB backstop,Windows reader 会在 JSON 解析前跳过超过 1,000,000 字符的行。
这两个数字不能包装成统一限制。它们来自不同的已发布实现,但目标相同:异常行、格式错误行和部分写入不能拖垮整个文件扫描。
只投影会改变状态的字段
把整条复杂记录反序列化成大模型,会让状态逻辑意外依赖无关 payload。监控器只需要更小的字段投影。
Claude 事件会使用 type、uuid、timestamp、message.stop_reason、isSidechain、isApiErrorMessage 和 toolEndsTurn。Codex 事件会检查 type、payload.type、payload.turn_id、role、timestamp、completed_at 和 started_at 等字段。
有边界地读取单行
-> 解析 JSON
-> 提取 provider 专属字段
-> 记录事件身份和语义时间
-> 按顺序归约会话状态
完成只是候选,不是永久事实
完成形态事件属于某一个回合。更晚的用户消息或开始事件说明会话已经继续,归约器必须允许后续活动覆盖旧完成。
这可以避免下一回合开始后,监控器仍被旧完成状态固定。也说明为什么只看文件修改时间不够:同一个 transcript 里可以包含多个回合。
排除假完成外壳
限流和 API 错误的 assistant 外壳不是成功完成。sidechain 或子 Agent 完成也不自动等于主线程交接。模型出现 stop marker 后,工具活动仍可能继续。
provider 专属门禁必须先于通用完成归约执行,否则语法完全合法的 JSON 仍会触发语义错误的提醒。
文件变化后重新归约
Agent Island 监听 .jsonl 文件变化,同时保留 polling 兜底。事件驱动降低延迟,轮询用于恢复漏掉的 watcher 通知。当前跳过的部分尾行,可以在下一次变化后重新读取。
可以按路径、大小和修改时间缓存未变化文件,但源文件变化后必须失效。缓存只是性能优化,不能冻结旧状态。
应保留的测试
空行或坏行不阻断后续记录;部分尾行追加后可以读取;异常大行遵守平台策略;重复事件不会产生第二次提醒;后续用户或开始事件覆盖旧完成;API 错误不变成 completed;sidechain 结束不呼叫父会话用户;漏掉的 watcher 事件由 polling 恢复。
安全解析 JSONL 不只是“JSON 合法”。它还包括有边界的 I/O、provider 事件语义、顺序、去重和刷新策略。
