# @deepseek-ai/dsh-tasks-local

[English](README.md) | 中文

[`@deepseek-ai/dsh-tasks`](../tasks/README.md) 注册表约定的进程本地实现：`LocalTaskService` 把每条记录保存在内存中，按 kind 签发 `<kind>-N` id，并且只交出全新快照，从不交出实时状态。它没有配置；作为插件加载后即注册为 `ctx.tasks`。

## 生命周期

任务属于其所有者和后端，而不是生产方工具 fiber，因此重载生产方或接口不会停止任务。某个所有者的第一个任务会把一个会被等待的 effect 附加到对应 `Agent` 对象的 scope 上。所有者的 dispose（资源释放）会取消该对象的任务，等待生产方完全停稳，并移除其快照；复用的 agent（智能体）id 或会话 id 无法重定向旧的清理操作。

服务 dispose 会关闭监听器、取消所有存活任务、等待其记录完成，并从仍存活的所有者 scope 中分离 effect。如果销毁期间的取消操作抛出异常，服务会强制将记录标为失败，并警告工作可能成为孤立工作，而不会死锁。取消操作已返回但 `done` 始终未结算时，系统无法将其与缓慢停止区分开，销毁过程可能因此停滞。

结算遵循首次结算优先原则：最早出现的终止结果（生产方结算、作为 `failed` 隔离处理的 `done` 拒绝，或销毁时的强制失败）只记录一次，也只通知监听器一次；各监听器的故障会单独隔离，随后释放等待方。挂起的等待会在监听器运行前把任务标记为已报告，因此呈现完成情况的表层不会重复发出通知。

表层与监听器按注册方所在的 scope 分层，形状与 tools 注册表一致：一次注册归档到其注册上下文的 scope，一次读取则把全局层与所有者的 scope 链求并集。因此一个进程级注册表能逐所有者地回答逐所有者的问题——对自身组合未附加任何表层的所有者，无论其他组合附加了多少，`start()` 都会拒绝并抛出 `background tasks unavailable: no control surface serves this agent (load @deepseek-ai/dsh-tool-tasks in its composition)`；一次结算也只会抵达其所有者所属组合注册的监听器。

## 模型体验

通过生产方插件和 [`dsh-tool-tasks`](../tool-tasks/README.md) 间接影响；它们会呈现任务 id、输出、状态、取消和完成通知。

#### KV Cache 影响

不会直接导致 KV Cache 失效；请求前缀变更由上述消费方负责。

## 已知限制与暂缓事项

- **任务只存在于进程本地**：记录会随 harness 进程终止而消失；持久或跨重启执行需要一个单独实现该 seam 的后端。
- **静默无效的取消可能使销毁过程停滞**：只有显式抛出异常才能安全地强制标为失败。
