feat(timeout): add dsh-timeout and converge bash + web_fetch onto it

Timeout timing/classification was re-implemented three ways across the
tool-bearing capabilities, with the fusion of timeout+cancel and the
timeout-vs-cancel reason recovery being the error-prone parts. Extract that
shared half into a zero-dependency @deepseek-ai/dsh-timeout library
(clampTimeout/deadline/timeoutOf/TimeoutReason) and leave the non-shareable
hard-kill in each capability, per the timeout-library RFC.

bash: run() owns the deadline; runBash drops its killTimer and no longer
classifies (SpawnSpec/SpawnOutcome lose timeoutMs/timedOut/aborted), so the
public timedOut/aborted booleans become mutually-exclusive first-abort
classifications. web_fetch: the hand-rolled controller/timer/listener/
signal.reason dance is replaced by provider-owned deadline/timeoutOf, keeping
the WEB_FETCH_TIMEOUT / WEB_ABORTED contract. fs stays timeout-free (README
states why).
This commit is contained in:
Dudu-0223
2026-07-06 16:23:52 +08:00
parent 9c0cd392b9
commit 8615e019d3
23 changed files with 638 additions and 91 deletions

View File

@@ -9,6 +9,7 @@ Inter-package dependencies among the `@deepseek-ai/dsh-*` harness packages, deri
flowchart TD
subgraph group_util["packages/util"]
pkg_brand["brand"]
pkg_timeout["timeout"]
end
subgraph group_llm["packages/llm"]
pkg_llm["llm"]
@@ -86,6 +87,7 @@ flowchart TD
pkg_session --> pkg_llm
pkg_system_prompt --> pkg_llm
pkg_bash_local --> pkg_bash
pkg_bash_local --> pkg_timeout
pkg_fs --> pkg_brand
pkg_fs --> pkg_llm
pkg_web --> pkg_llm
@@ -97,6 +99,7 @@ flowchart TD
pkg_fs_policy --> pkg_fs
pkg_compact --> pkg_llm
pkg_compact --> pkg_session
pkg_web_fetch_local --> pkg_timeout
pkg_web_fetch_local --> pkg_web
pkg_web_search_deepseek --> pkg_web
pkg_web_search_exa --> pkg_web
@@ -205,6 +208,7 @@ flowchart TD
| Package | Group | Depends on |
| --- | --- | --- |
| [`brand`](../packages/util/brand) | `util` | — |
| [`timeout`](../packages/util/timeout) | `util` | — |
| [`app-boot`](../packages/ui/app-boot) | `ui` | — |
| [`llm`](../packages/llm/llm) | `llm` | [`brand`](../packages/util/brand) |
| [`bash`](../packages/bash/bash) | `bash` | [`brand`](../packages/util/brand) |
@@ -212,14 +216,14 @@ flowchart TD
| [`llm-pi-ai`](../packages/llm/llm-pi-ai) | `llm` | [`llm`](../packages/llm/llm) |
| [`session`](../packages/core/session) | `core` | [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm) |
| [`system-prompt`](../packages/core/system-prompt) | `core` | [`llm`](../packages/llm/llm) |
| [`bash-local`](../packages/bash/bash-local) | `bash` | [`bash`](../packages/bash/bash) |
| [`bash-local`](../packages/bash/bash-local) | `bash` | [`bash`](../packages/bash/bash), [`timeout`](../packages/util/timeout) |
| [`fs`](../packages/fs/fs) | `fs` | [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm) |
| [`web`](../packages/web/web) | `web` | [`llm`](../packages/llm/llm) |
| [`agent`](../packages/core/agent) | `core` | [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt) |
| [`fs-local`](../packages/fs/fs-local) | `fs` | [`fs`](../packages/fs/fs) |
| [`fs-policy`](../packages/fs/fs-policy) | `fs` | [`fs`](../packages/fs/fs) |
| [`compact`](../packages/compact/compact) | `compact` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
| [`web-fetch-local`](../packages/web/web-fetch-local) | `web` | [`web`](../packages/web/web) |
| [`web-fetch-local`](../packages/web/web-fetch-local) | `web` | [`timeout`](../packages/util/timeout), [`web`](../packages/web/web) |
| [`web-search-deepseek`](../packages/web/web-search-deepseek) | `web` | [`web`](../packages/web/web) |
| [`web-search-exa`](../packages/web/web-search-exa) | `web` | [`web`](../packages/web/web) |
| [`web-search-perplexity`](../packages/web/web-search-perplexity) | `web` | [`web`](../packages/web/web) |