一个 Claude Code 或 Codex 会话,当它最近一个有意义的事件关闭了当前回合、且之后没有新的用户活动开启另一个回合时,才算结束。它只有在此前被观察到在工作、随后停止产出新鲜会话活动且没有完成标记时,才算卡住。光是安静,两种状态都证明不了
这个区分对提醒很要紧。把一次安静的工具调用当成结束,用户会被过早打断;把一次旧的完成当成新鲜的,同一个闹钟会在每次启动 App 之后又回来
读最近一个有意义的事件
会话记录文件里装的不只是对话回合,还可能有标题、模式变更、记账、工具结果和子 Agent 流量。因此最新的那行 JSON 未必是最新的状态变化
对 Claude Code 来说,一个主链上的助手事件带 end_turn、stop_sequence 或 stop 可以关闭这个回合;之后的一个用户事件会开启另一个回合,并取消那个已完成状态。对 Codex 来说,task_complete 或 turn/completed 关闭一个回合,而 task_started、turn/started 或之后的一条用户消息会让会话重新变成活跃
解析器从后往前走,直到找到这些事件之一。完成之后的元数据不会改变回合身份,也不会改变它的语义时间戳
最近一个有意义的事件 分类
助手输出,无终止标记 工作中
任务开始或用户消息 工作中
主回合已完成 轮到你了
元数据或标题变更 维持先前状态
近期没有有意义的活动 空闲或卡住
排除假的完成标记
有两种记录看起来像一个结束的回合,却并没有把控制权交还给用户
更老的 Claude Code 记录可能把子 Agent 事件混进主 JSONL,并用 isSidechain 标记。子 Agent 可能在主回合继续跑的时候结束,所以在给主会话分类时,sidechain 的完成事件会被忽略
Claude Code 也可能用带 stop_sequence 的助手信封写一条限流或 API 错误消息。isApiErrorMessage 这个标记把它与正常完成区分开。这个会话需要的是错误或额度处理,不是一次「轮到你了」闹钟
这些例外都有发布测试覆盖。样本包括:主回合进行中的一次 sidechain 完成、主完成之后的 sidechain 流量,以及一行长得像终止助手事件的 API 错误
语义时间优先于文件时间
文件修改时间回答的是「字节什么时候变的」,它回答不了「对话什么时候换了状态」
Claude Desktop 会在某些回合完成之后写 lastActivityAt 作为记账。在观察到的会话里,这次写入落在助手事件之后几秒。如果任何更新的桌面时间戳都立刻压掉完成,那么闹钟会不会出现,就取决于哪次扫描先发生
Agent Island 在一个 Claude 回合结束之后保留 25 秒的记账宽限。这段区间内的桌面活动不会抹掉这次完成;而远在它之后的活动,说明用户回来了或者另一个回合开始了,于是旧闹钟被压掉
同一条规则也修好了另一个过期状态问题:碰一下旧记录去更新标题,不能让一周前的完成复活。挂在用户或助手事件上的那个时间戳,仍然是事实来源
新鲜度把事件变成状态
一个完成标记不能永远保持可行动,一个卡住标签也不能
在已发布的 1.7.1 状态模型里,18 秒内的活动立刻算活跃。一个没有完成的会话在头五分钟里保持工作中。如果监控此前看到它在工作、随后活动安静了下来,它可以显示卡住,最长 15 分钟。一个已完成的回合在 needsYou 里停留 20 分钟。所有会话注意力在 30 分钟后过期
新鲜的输出或开始事件 工作中
20 分钟以内的完成 轮到你了
此前在工作,现在安静 卡住(上限 15 分钟)
语义活动超过 30 分钟 空闲
这些是保守的界面窗口,不是关于 Agent 内部的声称。五分钟这条界线证明不了崩溃,它标记的是「从观察到的活动」变成「一段值得瞄一眼的间隔」
证据变了就把提醒撤回
每来一个有意义的事件,会话状态就被重新修订一次。提醒层应该遵循同一条规则
Agent Island 在投递一条新的轮到你了提醒之前会等一秒。一次快速回复或后续写入可以取消这次待投递。如果用户在面板出现之后才回复,下一次记录扫描会把这个回合从活跃的「需要你」集合里移除,并关掉面板
App 启动后的第一次扫描按历史处理,而不是当新闻。一个早于本次监控运行的已结束回合会被记录下来,但不会触发新鲜闹钟。一个十二小时的记忆键窗口也防止同一个已确认回合在重启之后又回来
这个状态不声称什么
本地状态伴侣分类的是可观测的会话事件。它没法知道一个长时间运行的命令是否健康、一个 Agent 的推理是否有用,或者一个任务还剩多久。它也不该从一个不动的进程图标或者一个安静的终端推断出完成
实际的判断树保持很窄:找到最近一个有意义的主回合事件、把它与更新的活动比较、套用一个有界的新鲜度窗口,并在证据变化时撤回结果
Agent Island 1.7.1 对 Claude Code 与 Codex 用的就是这个本地模型。项目免费,采用 MIT 许可。可以看 这些逐线程状态在多会话下怎么合并,或者读更聚焦的 Claude Code 状态监控指南
