diff --git a/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.i18n.yaml new file mode 100644 index 0000000000..270d93300e --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# side as of the last confirmed-consistent state. Both languages carry equal authority; +# after editing either side, bring the other along and re-record with: +# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.md +2026-08-13-session-content-search-opt-in.md: 2d14b2def00186c2957dc03ae712fbcb63d2c820 +2026-08-13-session-content-search-opt-in.zh.md: dbde561c82cebdbf51ad31b1cd22c908c8d0f327 diff --git a/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.md b/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.md new file mode 100644 index 0000000000..2d14b2def0 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.md @@ -0,0 +1,32 @@ +# Agent Note: Session content search ships opt-in through openAt never + +Status: implemented + +English | [中文](2026-08-13-session-content-search-opt-in.zh.md) + +## Problem + +The shipped bundles mounted the SQLite session-query provider with the full-text index live (`openAt: first-search`), so every default deployment carried a derived FTS index and the Web sidebar offered content search. Whether a deployment wants that index — its node:sqlite import, per-search source reconciliation, and derived storage — is a deployment choice, and the product default is to ship without it; the model-facing search tools were already opt-in and unmounted (the [not-shipped-default decision](../feature/2026-08-02-session-search-not-shipped-default.md)). + +Turning the capability off by unmounting the plugin row is not viable. `ApiProxyService` declares `sessionQuery` as a required injection, so without the provider the whole host API gateway stays unloaded and the Web GUI never boots. Session-log export traces subagent descendants through `ctx.sessionQuery.traceSession`, and a subagent fork resolves its Workspace through the same lineage trace — both would need optional-service guards plus a replacement lineage source, roughly tripling the change surface while losing exact reads everywhere. + +## Decision + +Content search is enforced off at the provider. `openAt: 'never'` is a third opening phase on `@deepseek-ai/dsh-session-query-sqlite`: `searchSessions` and `searchEvents` fail with the typed `SESSION_QUERY_SEARCH_DISABLED` code before any request normalization, node:sqlite is never imported or opened, and no source observation or reconciliation runs. Every inherited `ctx.sessionQuery` exact read, filter, and trace keeps working, so session export, fork Workspace inheritance, and title reads are unaffected. + +`SESSION_QUERY_SEARCH_DISABLED` joins the closed `SessionQueryErrorCode` taxonomy, and the `tool-session-query` service boundary maps it to the model-safe message `session search is disabled in this deployment`. + +The base bundle sets `openAt: never` on the `session-query-sqlite` row and the web bundle's restatement keeps it; enabling content search is a one-line `openAt` override (`first-search` or `startup`) in a later patch layer, typically with a durable `path`. The host `session.search` endpoint reports the provider failure through its existing error path, and the Web sidebar keeps its designed degradation: local title/workspace matching plus the content-search-unavailable notice. The CLI compat spec pins the shipped `openAt: never` rows, while the web e2e scaffold keeps content search enabled — its seeded-session scenarios navigate by content search, and those runs are the assembled coverage for the opt-in path. + +## Alternatives considered + +- **Unmount the plugin row** (`disabled: true` in the base patch): rejected — the api-gateway's required `sessionQuery` injection keeps the whole host API unloaded, and making that injection optional forces guards plus a header-walk lineage fallback in session export and fork resolution. +- **Disable at the consumers** (the host `session.search` endpoint or the sidebar): rejected — enforcement belongs to the operation that makes the decision; opt-in model tools or any other consumer would still reach the index. +- **A separate boolean beside `openAt`**: rejected — the opening phase already owns when SQLite starts; `never` extends the same axis instead of adding a second knob that can contradict it. + +## Consequences + +- Default deployments run no derived index: no node:sqlite import or experimental-SQLite startup warning, no reconciliation work, no derived database on disk. Sidebar search matches session titles and workspace names only. +- Search failures under the default are typed and stable rather than incidental, so callers distinguish a deployment choice from an index fault (`SESSION_QUERY_INDEX_FAILED`). +- Re-enabling content search is per-deployment configuration, not a code change, and restores the full FTS behavior unchanged. +- Compositions that mount the search tools without overriding `openAt` get the model-safe disabled message on every search call; enabling the tools implies enabling the index. diff --git a/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.zh.md b/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.zh.md new file mode 100644 index 0000000000..dbde561c82 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.zh.md @@ -0,0 +1,32 @@ +# Agent Note: 会话内容搜索通过 openAt never 以 opt-in 方式交付 + +Status: implemented + +[English](2026-08-13-session-content-search-opt-in.md) | 中文 + +## 问题 + +交付的 bundle 之前以启用状态挂载 SQLite 会话查询提供方的全文索引(`openAt: first-search`),因此每个默认部署都携带一个派生 FTS 索引,Web 侧边栏提供内容搜索。一个部署是否需要该索引——它的 node:sqlite 导入、每次搜索的来源对账和派生存储——是部署自身的选择,产品默认不携带它交付;面向模型的搜索工具此前已经是 opt-in 且未挂载(见[非默认交付决策](../feature/2026-08-02-session-search-not-shipped-default.md))。 + +通过卸载插件行来关闭该能力不可行。`ApiProxyService` 将 `sessionQuery` 声明为必需注入,没有该提供方时整个宿主 API 网关保持未加载,Web GUI 无法启动。会话日志导出通过 `ctx.sessionQuery.traceSession` 追踪子代理后代,子代理分叉也通过同一血缘追踪解析其 Workspace——两者都需要可选服务守卫加一个替代血缘来源,改动面大约扩大三倍,同时使精确读取在所有地方消失。 + +## 决策 + +内容搜索在提供方处强制关闭。`openAt: 'never'` 是 `@deepseek-ai/dsh-session-query-sqlite` 的第三个打开阶段:`searchSessions` 和 `searchEvents` 在任何请求规范化之前就以类型化的 `SESSION_QUERY_SEARCH_DISABLED` 代码失败,node:sqlite 绝不会被导入或打开,也不运行任何来源观察或对账。`ctx.sessionQuery` 上继承的全部精确读取、过滤和跟踪保持可用,因此会话导出、分叉的 Workspace 继承和标题读取不受影响。 + +`SESSION_QUERY_SEARCH_DISABLED` 加入封闭的 `SessionQueryErrorCode` 分类,`tool-session-query` 的服务边界将它映射为模型安全消息 `session search is disabled in this deployment`。 + +base bundle 在 `session-query-sqlite` 行上设置 `openAt: never`,web bundle 的重述保持该值;启用内容搜索只需在后续 patch 层用一行覆盖 `openAt`(`first-search` 或 `startup`),通常同时配一个持久 `path`。宿主 `session.search` 端点沿现有错误路径报告提供方失败,Web 侧边栏保持其既有降级:本地标题/工作区匹配加内容搜索不可用提示。CLI 兼容性测试固定交付的 `openAt: never` 行,而 Web e2e 脚手架保持内容搜索启用——其种子会话场景通过内容搜索导航,这些运行也是 opt-in 路径的装配级覆盖。 + +## 曾考虑的替代方案 + +- **卸载插件行**(在 base patch 中 `disabled: true`)——否决:api-gateway 的必需 `sessionQuery` 注入会使整个宿主 API 保持未加载,而把该注入改为可选需要守卫加上会话导出与分叉解析中的 header 遍历血缘回退。 +- **在消费方处关闭**(宿主 `session.search` 端点或侧边栏)——否决:强制应由做出决定的操作执行;opt-in 的模型工具或任何其他消费方仍会触达索引。 +- **在 `openAt` 旁增加独立布尔开关**——否决:打开阶段已经拥有"SQLite 何时启动"这一轴;`never` 延伸同一根轴,而不是增加一个可能与之矛盾的第二个旋钮。 + +## 结果 + +- 默认部署不运行任何派生索引:没有 node:sqlite 导入或实验性 SQLite 启动警告,没有对账工作,磁盘上没有派生数据库。侧边栏搜索只匹配会话标题和工作区名称。 +- 默认状态下的搜索失败是类型化且稳定的,调用方可以把部署选择与索引故障(`SESSION_QUERY_INDEX_FAILED`)区分开。 +- 重新启用内容搜索是逐部署配置而非代码改动,并原样恢复完整的 FTS 行为。 +- 挂载搜索工具但未覆盖 `openAt` 的组合,每次搜索调用都会得到模型安全的已禁用消息;启用工具意味着同时启用索引。 diff --git a/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.i18n.yaml b/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.i18n.yaml index 1a4d923540..b9a8b2e9c8 100644 --- a/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.md -2026-08-02-session-search-not-shipped-default.md: c1bfd7f8e354a4480c5635619514fe782ea71d2c -2026-08-02-session-search-not-shipped-default.zh.md: 9b80c549425c26055700480dd57f1a0a7d01e4a8 +2026-08-02-session-search-not-shipped-default.md: 60d1f424d5a9029a00b3f195d1f6e6baf2790d1e +2026-08-02-session-search-not-shipped-default.zh.md: 221613ae1aef93cd72734e4c328d822a88b64227 diff --git a/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.md b/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.md index c1bfd7f8e3..60d1f424d5 100644 --- a/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.md +++ b/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.md @@ -12,7 +12,7 @@ The [shipped-roster decision](2026-07-31-even-out-shipped-tool-rosters.md) made The shipped TUI, Web, and headless surfaces do not mount `@deepseek-ai/dsh-tool-session-query`, and no shipped agent preset carries it. The consumer stays opt-in exactly as the model-facing-session-query-tools note describes: the ACP example's [`session-query.cordis.yml`](../../../../examples/acp-agent/session-query.cordis.yml) and its snapshot counterpart remain the mounted reference, and a custom composition can mount the package with the timeout and spill policies. -The `ctx.sessionQuery` service itself stays mounted. `session-query-sqlite` remains a base row — the TUI's `session-reference` consumes it for `/resume` — and the Web overlay keeps patching it to an in-memory index for the browser content search. Only the model-facing consumer is removed. +The `ctx.sessionQuery` service itself stays mounted. `session-query-sqlite` remains a base row — the TUI's `session-reference` consumes it for `/resume` — with its full-text index off by default (`openAt: never`; the [content-search opt-in decision](../architecture/2026-08-13-session-content-search-opt-in.md)), and the Web overlay keeps its in-memory values for deployments that enable content search. Only the model-facing consumer is removed. ## Alternatives considered diff --git a/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.zh.md b/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.zh.md index 9b80c54942..221613ae1a 100644 --- a/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.zh.md +++ b/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.zh.md @@ -12,7 +12,7 @@ Status: implemented 交付的 TUI、Web 与无头 surface 均不挂载 `@deepseek-ai/dsh-tool-session-query`,交付的 agent preset 也都不包含它。该消费方仍保持 opt-in,与面向模型的会话查询工具决策所述完全一致:ACP(Agent Client Protocol)示例的 [`session-query.cordis.yml`](../../../../examples/acp-agent/session-query.cordis.yml) 及其快照对侧文件仍是挂载参考,自定义组合也可以连同超时与 spill 策略一起挂载该包。 -`ctx.sessionQuery` 服务本身保持挂载。`session-query-sqlite` 仍是 base 的一行,TUI 的 `session-reference` 消费它来实现 `/resume`,Web overlay 也继续把它 patch 成内存索引,供浏览器内容搜索使用。被移除的只有面向模型的消费方。 +`ctx.sessionQuery` 服务本身保持挂载。`session-query-sqlite` 仍是 base 的一行,TUI 的 `session-reference` 消费它来实现 `/resume`;其全文索引默认关闭(`openAt: never`,见[内容搜索 opt-in 决策](../architecture/2026-08-13-session-content-search-opt-in.md)),Web overlay 保留内存索引取值,供启用内容搜索的部署使用。被移除的只有面向模型的消费方。 ## 曾考虑的替代方案 diff --git a/LICENSE b/LICENSE index d03c77437e..c1f7a78e89 100644 --- a/LICENSE +++ b/LICENSE @@ -1,28 +1,21 @@ -BSD 3-Clause License +MIT License -Copyright (c) 2026, DeepSeek +Copyright (c) 2026 DeepSeek -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.i18n.yaml b/README.i18n.yaml index a71b0b8ade..573a3ffedb 100644 --- a/README.i18n.yaml +++ b/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write README.md -README.md: 891098974433535fa65863c80c512d3818e75955 -README.zh.md: 7a5b1a9219c8442fca7deabdff45ee4323bba840 +README.md: 646262f0b8317a48cab9aa84bab87b7a2b8e85ec +README.zh.md: 892da6f48cd8b60dd61332ec412f604a8062b27d diff --git a/README.md b/README.md index 8910989744..646262f0b8 100644 --- a/README.md +++ b/README.md @@ -2,31 +2,29 @@ English | [中文](README.zh.md) -DeepSeek Harness (`dsh`) is an open-source coding agent and plugin-based agent harness. +DeepSeek Harness (`dsh`) is an open-source agent harness developed by [DeepSeek AI](https://deepseek.com). -It uses an architecture where **everything is a plugin**. +It uses an architecture where **everything is a plugin**, and is powered by [Cordis](https://github.com/cordiverse/cordis). -## Internal testing notice +## Developer preview -DeepSeek Harness is under internal testing. Features and interfaces may change. - -Session Logs stay local by default. Set `DSH_TELEMETRY_MODE=FEEDBACK_ONLY` to share a Session Log only when submitting feedback, or `DSH_TELEMETRY_MODE=FULL` to upload continuously; `FULL` also enables dsh-sdk command telemetry reporting an anonymous ID, the command result, and redacted project configuration. Send feedback through the internal WeChat group. +DeepSeek Harness is currently in _developer preview_ and is iterating rapidly. **THERE WILL BE COMPATIBILITY-BREAKING CHANGES.** ## Run -Install Node.js ^22.19 or >= 24 and pnpm 11, then run the published package: +### Run from `npm` + +Install `Node.js`, then run: ```sh npx @deepseek-ai/dsh web ``` -The command initializes the Web profile and prints the Web UI URL, which is `http://127.0.0.1:3080` by default. Open it, add a DeepSeek API key under **Settings → Models**, then start a session. The invoking directory is the default workspace; try `Summarize this repository and identify its main packages.` - -Continue with the [Web UI guide](docs/user/guide/index.md). +The command starts the Web UI, served at `http://127.0.0.1:3080` by default. See [Web UI guide](docs/user/guide/index.md). ### Run from source -To run a repository checkout instead: +To run from a repository checkout: ```sh git clone https://github.com/deepseek-ai/deepseek-harness.git @@ -36,37 +34,23 @@ pnpm run build pnpm dsh web ``` -`pnpm run build` prepares the repository artifacts. `pnpm dsh web` starts the Web UI without rebuilding and opens the same path. +## Community and support -## Profiles and plugins +- Feel free to submit feedback or bug reports through [GitHub Discussions](https://github.com/deepseek-ai/deepseek-harness/discussions). +- Add the [`dsh-plugin`](https://github.com/topics/dsh-plugin) topic to your plugin repository for discoverability. -A profile is an ordered list of plugin bundles. The shipped `web` profile powers `dsh web`. Manage a profile with `dsh plugin --profile `, which forwards the remaining arguments to pnpm in that profile's directory: +## Contributing -```sh -npx -p @deepseek-ai/dsh dsh plugin --profile web add -npx -p @deepseek-ai/dsh dsh plugin --profile web remove -``` - -`add`, `remove`, `update`, `why`, and other pnpm commands work unchanged. The command initializes a missing profile before changing its packages and updates its bundle list from installed packages that declare `dsh.bundle`. See the [CLI reference](apps/cli/reference/README.md#plugin-management) for the exact behavior. - -The [CLI reference](apps/cli/README.md) covers headless execution and custom profiles. The [Python SDK](python/README.md) and [examples](examples/README.md) cover programmatic and custom compositions. - -## Community - -Follow DeepSeek Harness on Twitter for project updates. +See [CONTRIBUTING.md](CONTRIBUTING.md). ## Development -Start with the [development guide](docs/development.md) and read the [architecture](docs/architecture.md) before changing packages. +Start with the [development guide](docs/development.md) and [architecture documentation](docs/architecture.md). For agents, follow [AGENTS.md](AGENTS.md). ## License -[BSD 3-Clause](LICENSE) +[MIT](LICENSE) Third-party dependencies and their licenses are disclosed in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md). - -## Contributing - -Read [CONTRIBUTING.md](CONTRIBUTING.md) before contributing to this repository. diff --git a/README.zh.md b/README.zh.md index 7a5b1a9219..892da6f48c 100644 --- a/README.zh.md +++ b/README.zh.md @@ -2,28 +2,25 @@ [English](README.md) | 中文 -DeepSeek Harness(`dsh`)是一款开源 coding agent(编程智能体),也是一个基于插件的 agent harness(智能体框架)。 +DeepSeek Harness(`dsh`)是由 [DeepSeek AI](https://deepseek.com) 开发的开源 agent harness(智能体框架)。 -它采用了**一切皆插件**的架构。 +它采用**一切皆插件**的架构,并由 [Cordis](https://github.com/cordiverse/cordis) 驱动。 -## 内测说明 - -DeepSeek Harness 正处于内部测试阶段,功能和接口可能发生变化。 - -Session Log 默认留在本地。设置 `DSH_TELEMETRY_MODE=FEEDBACK_ONLY` 可仅在提交反馈时共享 Session Log,设置 `DSH_TELEMETRY_MODE=FULL` 可持续上传;`FULL` 同时会启用 dsh-sdk 命令遥测,上报匿名 ID、命令结果以及脱敏后的项目配置。请通过内部企业微信群反馈问题和建议。 +## 开发者预览 +DeepSeek Harness 目前处于 _开发者预览_ 阶段,正在快速迭代。**未来将出现破坏兼容性的变更。** ## 运行 -请先安装 Node.js(版本要求:`^22.19` 或 `>=24`)和 pnpm 11,然后运行已发布的包: +### 通过 `npm` 运行 + +安装 `Node.js`,然后运行: ```sh npx @deepseek-ai/dsh web ``` -该命令会初始化 Web profile 并打印 Web UI 地址,默认地址为 `http://127.0.0.1:3080`。打开该地址,在**设置 → 模型**中添加 DeepSeek API 密钥,然后启动一个会话。运行命令时所在的目录将作为默认工作区;你可以尝试输入 `Summarize this repository and identify its main packages.`。 - -下一步请阅读 [Web UI 指南](docs/user/guide/index.md)。 +该命令会启动 Web UI,默认地址为 `http://127.0.0.1:3080`。详见 [Web UI 指南](docs/user/guide/index.md)。 ### 从源码运行 @@ -37,41 +34,23 @@ pnpm run build pnpm dsh web ``` -`pnpm run build` 会准备仓库产物。`pnpm dsh web` 不会重新构建,而是直接启动同一个 Web UI。 +## 社区与支持 -## Profile 与插件 - -profile 由一组按顺序排列的插件组合包构成。随附的 `web` profile 用于运行 `dsh web`。使用 `dsh plugin --profile ` 管理 profile;该命令会在对应 profile 目录中将剩余参数转发给 pnpm: - -```sh -npx -p @deepseek-ai/dsh dsh plugin --profile web add -npx -p @deepseek-ai/dsh dsh plugin --profile web remove -``` - -`add`、`remove`、`update`、`why` 等 pnpm 命令均可直接使用。该命令会先初始化不存在的 profile,再修改其中的包,并根据声明了 `dsh.bundle` 的已安装包更新 bundle 列表。具体行为见 [CLI 参考](apps/cli/reference/README.md#plugin-management)。 - -[CLI(命令行界面)参考](apps/cli/README.md)介绍 headless 执行与自定义 profile。[Python SDK](python/README.md) 和[示例](examples/README.md)介绍程序化组合与自定义组合。 - -## 社区 - -扫描二维码,或打开 DeepSeek Harness 微信社区申请页面 申请加入。 - -

- DeepSeek Harness 微信社区二维码 -

- -## 开发 - -请先阅读[开发指南](docs/development.md);修改包之前,请阅读[架构文档](docs/architecture.md)。 - -面向 agent:遵循 [AGENTS.md](AGENTS.md)。 - -## 许可证 - -[BSD 3-Clause](LICENSE) - -第三方依赖及其许可证见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。 +- 欢迎通过 [GitHub Discussions](https://github.com/deepseek-ai/deepseek-harness/discussions) 提交反馈或 bug 报告。 +- 为你的插件仓库添加 [`dsh-plugin`](https://github.com/topics/dsh-plugin) 主题,便于被发现。 ## 参与贡献 -向本仓库贡献前,请阅读 [CONTRIBUTING.md](CONTRIBUTING.md)。 +参见 [CONTRIBUTING.md](CONTRIBUTING.md)。 + +## 开发 + +请先阅读[开发指南](docs/development.md)与[架构文档](docs/architecture.md)。 + +面向 agent:请遵循 [AGENTS.md](AGENTS.md)。 + +## 许可证 + +[MIT](LICENSE) + +第三方依赖及其许可证见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。 diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 49d5e15b47..92b218ff33 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -3,7 +3,7 @@ # Third-Party Notices -DeepSeek Harness is licensed under [BSD 3-Clause](LICENSE). It depends on the third-party software listed below. Each project remains under its own license; nothing in this file changes those terms. +DeepSeek Harness is licensed under [MIT](LICENSE). It depends on the third-party software listed below. Each project remains under its own license; nothing in this file changes those terms. This file lists **direct** dependencies declared by the workspace and the explicitly disclosed official Claude platform payload closure. It is generated from the workspace manifests by `scripts/gen-third-party-notices.ts`: a pre-commit hook regenerates it whenever a staged file changes one of its inputs, and `scripts/gen-third-party-notices.spec.ts` asserts in the test lane that the committed bytes match. Deleting a manifest runs no hook, so that case is caught by the assertion instead. Run `pnpm run verify-third-party-notices` for the standalone check. diff --git a/apps/cli/README.i18n.yaml b/apps/cli/README.i18n.yaml index 9285fa6c1d..f270fdf882 100644 --- a/apps/cli/README.i18n.yaml +++ b/apps/cli/README.i18n.yaml @@ -3,4 +3,4 @@ # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write apps/cli/README.md README.md: 9a8d722b044ed5d8e31e3c27e54f8c9ef0839f82 -README.zh.md: dc40a4a6f54f99507bccb6b989aee0015e9604b3 +README.zh.md: 7889b4180b5ce2f65550f98708d498f324ac349d diff --git a/apps/cli/README.zh.md b/apps/cli/README.zh.md index dc40a4a6f5..7889b4180b 100644 --- a/apps/cli/README.zh.md +++ b/apps/cli/README.zh.md @@ -2,22 +2,22 @@ [English](README.md) | 中文 -`dsh` 命令是 profile 的产品启动器:profile 是按序叠放的插件组合包 patch 层,之上再叠加用户自己的覆盖层。[`src/args.ts`](src/args.ts) 负责命令语法,[`src/bin.ts`](src/bin.ts) 只加载选中的运行器。无效命令、来自其他模式的选项、配置错误和启动失败都会以非零状态退出。 +`dsh` 是 DeepSeek Harness 中用于启动 profile 的命令;profile 由多个插件组合包 patch 层按顺序叠加而成,其上再应用用户自己的覆盖配置。[`src/args.ts`](src/args.ts) 负责命令语法,[`src/bin.ts`](src/bin.ts) 只加载选中的运行器。无效命令、来自其他模式的选项、配置错误和启动失败都会以非零状态退出。 ## 入口模式 | 命令 | 用途 | |---|---| | `dsh --profile ` | 启动位于 `$DSH_HOME/profiles/` 的指定 profile。 | -| `dsh --profile headless "job"` | 运行一个新的持久化会话,打印最终答案并退出。 | +| `dsh --profile headless "job"` | 运行一个全新的持久化会话,打印最终答案并退出。 | | `dsh web` | `--profile web` 的别名。 | | `dsh plugin --profile ` | 通过在 profile 目录中转发给 pnpm 来管理该 profile 的插件。 | -调用目录是默认 workspace 根目录。`web` 和 `headless` profile 在首次使用时会从随附模板自动初始化;其他任何 profile 都必须通过 `dsh plugin` 创建。 +运行命令时所在的目录将作为默认 workspace 根目录。`web` 和 `headless` profile 在首次使用时会从随附模板自动初始化;其他任何 profile 都必须通过 `dsh plugin` 创建。 ## 应用参数 -启动器只解析属于自己的 flag,并把其后的一切交给启动起来的 profile,任何注入它的应用插件都可以解析这份共享的不可变快照([`dsh-cmdline`](../../packages/boot/cmdline/README.md))。因此启动器的 flag 必须写在前面,而启动器不认识的第一个 token 就是应用参数的起点: +启动器只解析自身的 flag,并将其后的所有内容交给已启动的 profile;注入该 profile 的任意应用插件都可以解析这份共享的不可变快照([`dsh-cmdline`](../../packages/boot/cmdline/README.md))。因此,启动器的 flag 必须写在最前面;启动器无法识别的第一个 token 标志着应用参数的开始: ```sh dsh --profile web --port 8080 # --port belongs to the web app @@ -29,19 +29,19 @@ dsh --help # the launcher's own help ## Profile -profile 目录包含一个 `package.json`(树外插件依赖,加上 profile manifest(元数据清单)`dsh.profile` 及其有序的 `bundles` 列表)和一个 `cordis.patch.yml`(用户自己的 patch 层)。 +profile 目录包含一个 `package.json`,其中记录树外插件依赖,以及 profile manifest(元数据清单)`dsh.profile` 和其中按顺序排列的 `bundles` 列表;还包含一个 `cordis.patch.yml`,其中保存用户自己的 patch 层。 -配置树在空根之上组合: -- 先按 `dsh.profile.bundles` 顺序应用各组合包的 patch -- 然后是 profile 的 `cordis.patch.yml`,然后是 home 级的 `$DSH_HOME/cordis.patch.yml` -- 最后是 `--patch` overlay +配置树以空根为起点,依次叠加以下配置层: +- `dsh.profile.bundles` 中各组合包的 patch +- profile 自身的 `cordis.patch.yml`,然后是 home 级的 `$DSH_HOME/cordis.patch.yml` +- `--patch` 指定的覆盖层 -`dsh.profile.bundles` 中列出的组合包先从 dsh 安装目录解析(`@deepseek-ai/dsh-base`、`@deepseek-ai/dsh-web-app`、`@deepseek-ai/dsh-headless`),再从 profile 自己的 `node_modules` 解析;pnpm 把树外插件安装在后者。 +`dsh.profile.bundles` 中列出的组合包先从 dsh 安装目录解析(`@deepseek-ai/dsh-base`、`@deepseek-ai/dsh-web-app`、`@deepseek-ai/dsh-headless`),再从 profile 自身的 `node_modules` 解析;pnpm 会将树外插件安装到该目录。 使用 `--dump-default-config` 和 `--dump-config` 可在不启动的情况下检查组合后的配置树。 -[CLI(命令行界面)行为参考](reference/README.md)负责确切的层优先级、flag、关闭行为、部署默认值和源码执行。 +层的确切优先级、flag、关闭行为、部署默认值和源码执行方式,以 [CLI(命令行界面)行为参考](reference/README.md)为准。 ## 开发 -生产运行需要已构建的包与前端产物。请在仓库根目录单独运行 `pnpm run build`,然后使用 `pnpm dsh ` 运行 TypeScript 入口并转发所有参数;模块解析约定由[源码执行参考](reference/README.md#source-execution)负责。 +生产运行需要已构建的包与前端产物。请在仓库根目录单独运行 `pnpm run build`,然后使用 `pnpm dsh ` 运行 TypeScript 入口并转发所有参数;模块解析约定以[源码执行参考](reference/README.md#source-execution)为准。 diff --git a/apps/cli/package.json b/apps/cli/package.json index 50251dbc9a..ff7cc07407 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -18,7 +18,7 @@ "lib/*.js", "config" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/cordis-plugin-hmr": "workspace:^", "@deepseek-ai/cordis-plugin-include": "workspace:^", diff --git a/apps/cli/reference/README.i18n.yaml b/apps/cli/reference/README.i18n.yaml index 89fb45feb7..02938478cc 100644 --- a/apps/cli/reference/README.i18n.yaml +++ b/apps/cli/reference/README.i18n.yaml @@ -3,4 +3,4 @@ # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write apps/cli/reference/README.md README.md: 0b23db293c304807b5959f5eae9a2faf868caa62 -README.zh.md: 1ca91fb69c3ed34d925f6b8a6454866e82c8dcf7 +README.zh.md: d812c7cd0d1efaa69b135925f3e922668539781b diff --git a/apps/cli/reference/README.zh.md b/apps/cli/reference/README.zh.md index 1ca91fb69c..d812c7cd0d 100644 --- a/apps/cli/reference/README.zh.md +++ b/apps/cli/reference/README.zh.md @@ -2,25 +2,25 @@ [English](README.md) | 中文 -本参考定义 profile、web 别名、插件管理和配置 dump 命令模式。参数由 [`src/args.ts`](../src/args.ts) 统一解析,[`src/bin.ts`](../src/bin.ts) 只动态导入选中的运行器。 +本参考定义 profile 启动、web 别名、插件管理和配置 dump 等命令模式。argv 由 [`src/args.ts`](../src/args.ts) 统一解析一次,[`src/bin.ts`](../src/bin.ts) 只会动态导入选中的运行器。 ## Profile 启动 -`dsh --profile ` 启动位于 `$DSH_HOME/profiles/` 的 profile。生效配置树在空根节点之上按以下顺序逐层组合:profile manifest(元数据清单)的 `dsh.profile.bundles` 列表所列的各个组合包 patch、profile 自身的 `cordis.patch.yml`、home 级的 `$DSH_HOME/cordis.patch.yml`(各 profile 共享的机器本地偏好,因此优先级高于逐 profile 的层)、以及按 argv 顺序的各个 `--patch ` overlay。后应用的层按行胜出;patch 替换目标行完整的 `config` 值,而不是深度合并各键,并且可以插入新行。配置解析、schema 校验、模块解析或插件启动失败会得到报告并以非零状态退出。收到 SIGINT 或 SIGTERM 时,挂载的根节点会先 dispose(资源释放)再退出。 +`dsh --profile ` 启动位于 `$DSH_HOME/profiles/` 的 profile。生效配置树以空根节点为起点,依次叠加 profile manifest(元数据清单)的 `dsh.profile.bundles` 列表中指定的各组合包 patch、profile 自身的 `cordis.patch.yml`、home 级的 `$DSH_HOME/cordis.patch.yml`(这是各 profile 共享的机器本地偏好,因此优先于逐 profile 配置层),以及按 argv 顺序指定的各个 `--patch ` 覆盖层。对同一配置行,后应用的层优先。patch 会替换目标行的整个 `config` 值,而不是深度合并其中的键;patch 也可以插入新行。配置解析、schema 校验、模块解析或插件启动失败时,系统会报告错误并以非零状态退出。收到 SIGINT 或 SIGTERM 时,挂载的根节点会先 dispose(资源释放)再退出。 -组合包名称先从 dsh 安装解析,再从 profile 目录解析。因此内置组合包(`@deepseek-ai/dsh-base`、`@deepseek-ai/dsh-web-app`、`@deepseek-ai/dsh-headless`)总是来自与正在运行的 `dsh` 相同的安装;树外组合包来自 profile 由 pnpm 管理的 `node_modules`。任何 patch 行中的裸插件 `name` 通过 profile 目录的 Node 父目录逐级查找解析,该查找可达到持续维护的安装后备目录 `$DSH_HOME/profiles/node_modules`(安装的应用和组合包所依赖的每个包对应一个符号链接,每次启动时修复)。 +组合包名称先从 dsh 安装目录解析,再从 profile 目录解析。因此,内置组合包(`@deepseek-ai/dsh-base`、`@deepseek-ai/dsh-web-app`、`@deepseek-ai/dsh-headless`)始终来自当前运行的 `dsh` 所属的安装;树外组合包则来自 profile 中由 pnpm 管理的 `node_modules`。patch 行中的裸插件 `name` 会从 profile 目录开始,按照 Node 的模块解析规则逐级向父目录查找,直至由 dsh 维护的安装后备目录 `$DSH_HOME/profiles/node_modules`。该目录为 dsh 安装中的应用和组合包所依赖的每个包各维护一个符号链接,并在每次启动时修复这些链接。 `web` 和 `headless` profile 首次使用时会从随附模板自动初始化(`web`:base + web-app;`headless`:base + headless)。其他缺失的 profile 会显式报错,并提示运行 `dsh plugin --profile add `。 ### 应用参数 -启动器自己的 flag 写在最前面,并在它不认识的第一个 token 处结束;从那里开始的一切都通过 `ctx.cmdlineArgs` 原样交给启动起来的 profile,任何注入它的应用插件都可以解析([`dsh-cmdline`](../../../packages/boot/cmdline/README.md))。因此 `dsh --profile web --port 8080` 到达的是 web 应用的 `--port`,`dsh --profile web --help` 打印的是该应用的 help 且什么也不启动,而 `dsh --help`(没有可以交付的 profile)打印的是启动器自己的 help。`-V`/`--version` 写在应用参数边界之前时会打印启动器的版本。 +启动器自身的 flag 必须写在最前面,并在遇到第一个无法识别的 token 时结束;从该 token 开始的所有内容都会通过 `ctx.cmdlineArgs` 原样交给已启动的 profile,注入该 profile 的任意应用插件都可以解析这些内容([`dsh-cmdline`](../../../packages/boot/cmdline/README.md))。因此,`dsh --profile web --port 8080` 会将 `--port` 交给 web 应用;`dsh --profile web --help` 只打印该应用的帮助信息,不启动应用;`dsh --help` 没有可供交付参数的 profile,因此会打印启动器自身的帮助信息。`-V`/`--version` 位于应用参数边界之前时,会打印启动器的版本。 -一套组合只挂载一次。普通插件注入 `cmdlineArgs`、解析本应用参数,并把结果作为服务提供出去;由 flag 配置的每一行都会注入该服务,Loader 会等服务激活后再求值该行配置(`port: !!js ctx.webStartup.port ?? 3080`),因此 flag 胜过写在它旁边的值。该优先级要求配置行保留这一表达式;若用户 patch 用字面量替换整份 `config`,运行时读取也会随之消失。help 和被拒绝的参数会请求退出——拒绝时以非零状态,help 时以 0——且不会激活依赖提供方服务的行。在线编辑 `cordis.patch.yml` 会针对仍然在线的服务重新求值表达式,因此不会重置已在服务的端口。 +每套组合只会挂载一次。普通插件注入 `cmdlineArgs`,解析所属应用的参数,并将解析结果作为服务提供。每个从 flag 取值的配置行都会注入该服务;Loader 会等到服务激活后,再对该行的配置求值(`port: !!js ctx.webStartup.port ?? 3080`),因此 flag 的优先级高于配置行中写明的值。要维持这一优先级,配置行必须保留该表达式;如果用户 patch 用字面量替换整个 `config`,也会随之移除运行时读取。帮助参数和被拒绝的参数都会请求退出:参数被拒绝时以非零状态退出,显示帮助时以 0 退出;依赖该提供方服务的配置行不会激活。在线编辑 `cordis.patch.yml` 时,系统会根据仍在运行的服务重新计算表达式,因此不会重置当前正在使用的端口。 启动器的 flag 必须写在应用参数之前,且启动器的解析器会消耗掉一个 `--`:必须以字面量 `--` 送达应用的参数需要写成 `-- --`。如果应用的第一个参数恰好等于 `web` 或 `plugin`,会选择对应的子命令。`ctx.cmdlineArgs.get()` 是共享的不可变读取:多个插件可以解析同一份快照,没有读取方的 profile 则会忽略自己的应用参数。 -随附的各应用持有这些命令行: +随附的应用接受以下命令行参数: | Profile | 参数 | |---|---| @@ -36,11 +36,11 @@ dsh --profile web --dump-default-config dsh --profile web --patch ./extra.yml --dump-config ``` -`--dump-default-config` 只打印组合包各层;`--dump-config` 额外加上 profile 的 `cordis.patch.yml`、home 级的 `$DSH_HOME/cordis.patch.yml` 和 `--patch` overlay。两者都会打印注释,标明每行由哪个文件提供,以及哪些 overlay 修改过它;`!!js` 表达式保持未求值,找不到目标的 patch 会报告到 stderr。dump 从不运行应用命令行提供方,因此它展示的是任何应用参数被解析之前的组合配置树,并拒绝携带应用参数的调用。 +`--dump-default-config` 只打印组合包各层;`--dump-config` 额外加上 profile 的 `cordis.patch.yml`、home 级的 `$DSH_HOME/cordis.patch.yml` 和 `--patch` overlay。两者都会打印注释,标明每行由哪个文件提供,以及哪些 overlay 修改过它;`!!js` 表达式保持未求值,找不到目标的 patch 会报告到 stderr。dump 操作不会运行应用的命令行参数提供方,因此展示的是解析任何应用参数之前的组合配置树;如果调用中包含应用参数,dump 会拒绝该调用。 ## 插件管理 -`dsh plugin --profile ` 在 profile 缺失时先初始化它(有随附模板的用模板,其他名称只装 `@deepseek-ai/dsh-base`),然后以 profile 目录为工作目录,把 `` 转发给 `pnpm`:`add`、`remove`、`why`、`update` 及其他所有 pnpm 子命令都照常可用;pnpm 必须在 PATH 上。相对路径 spec(`.`、`../plugin` 及其 `file:`/`link:` 形式)会先锚定到调用目录,因此在插件 checkout 中执行 `add .` 安装的是该 checkout,而不是 profile。每次成功运行后,`dsh.profile.bundles` 都会与已安装状态对齐:每个解析到 manifest 中声明了 `"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }` 的包的依赖加入层栈(因此让包获得该声明的 `update` 会将其激活),没有组合包声明的依赖保持为普通依赖并给出一次性警告,已移除的依赖则退出层栈。 +`dsh plugin --profile ` 在 profile 缺失时先初始化它(有随附模板的用模板,其他名称只装 `@deepseek-ai/dsh-base`),然后以 profile 目录为工作目录,把 `` 转发给 `pnpm`:`add`、`remove`、`why`、`update` 及其他所有 pnpm 子命令都照常可用;pnpm 必须在 PATH 上。相对路径 spec(`.`、`../plugin` 及其 `file:`/`link:` 形式)会先锚定到调用目录,因此在插件 checkout 中执行 `add .` 安装的是该 checkout,而不是 profile。每次成功运行后,系统都会根据当前安装状态更新 `dsh.profile.bundles`:如果某项依赖解析到的包在 manifest 中声明了 `"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }`,该依赖就会加入配置层栈;如果某项依赖在 `update` 后获得该声明,也会随即激活。没有组合包声明的依赖仍作为普通依赖保留,并显示一次性警告;已移除的依赖则从配置层栈中删除。 ```sh dsh plugin --profile tui add github:deepseek-harness/turtle-ui @@ -48,7 +48,7 @@ dsh plugin --profile tui remove turtle-ui dsh --profile tui ``` -Git 托管、随附源码的插件在安装期间通过其 `prepare` 脚本构建,而 pnpm ≥10 在消费方允许之前会阻止该脚本:首次 `add` 会失败并给出 pnpm 的 `allowBuilds` 提示(以及 dsh 指向该 profile 的 `pnpm-workspace.yaml` 的指引);把打印出的键复制到那里并重新运行即可。安装已构建的 tarball 或本地 checkout 不需要任何允许。 +随源码发布的 Git 托管插件会在安装期间通过 `prepare` 脚本构建,而 pnpm ≥10 默认会阻止该脚本,直到使用方明确允许。首次运行 `add` 会失败,并显示 pnpm 的 `allowBuilds` 提示;dsh 还会提示应修改该 profile 的 `pnpm-workspace.yaml`。将输出的键复制到该文件后,重新运行命令即可。安装已经构建好的 tarball 或本地 checkout 时,无需加入 `allowBuilds`。 ## Web 别名 @@ -63,9 +63,9 @@ dsh web --help 生产 Web 运行器需要已构建的包和前端产物(`pnpm run build`)。默认服务地址是 `http://127.0.0.1:3080`。绑定所有网络接口时,还会信任机器自动发现的 LAN IP 字面量;`--trusted-host` 可添加 `/api` 浏览器信任围栏接受的具名 authority。 -进程关闭时会给插件树最多 5 秒完成 dispose。第一次 `SIGINT`/`SIGTERM` 启动该优雅排空——`SIGTERM` 是监督进程的普通停止请求,在所有 surface 上以 0 退出,`SIGINT` 报告 130;第二次信号强制立即退出。如果一次性运行正常结束时已经卡在 dispose 中,第一次 `Ctrl+C` 就会升格并立即退出,而不会被吞掉。 +进程关闭时,插件树最多有 5 秒完成 dispose。首次收到 `SIGINT` 或 `SIGTERM` 时会开始优雅排空:`SIGTERM` 是监督进程发出的常规停止请求,在所有运行模式下都以 0 退出;`SIGINT` 则报告 130。第二次收到信号时会立即强制退出。如果一次性运行在正常结束时已经卡在 dispose 阶段,第一次按下 `Ctrl+C` 就会直接升级为强制退出,而不会被忽略。 -所有模式都将调用目录作为默认 workspace 根目录,以 65,536 字节渲染预算加载适用的 `AGENTS.md` 或 `CLAUDE.md` 指令,并使用内存 SQLite 会话内容索引。每次 profile 启动都监视两个 `cordis.patch.yml` 层(profile 与 home)的有效编辑并以事务方式重新应用;一次性 surface 经由有界关闭退出,关闭会先 dispose 监视器。 +所有模式都将运行命令时所在的目录作为默认 workspace 根目录,以 65,536 字节渲染预算加载适用的 `AGENTS.md` 或 `CLAUDE.md` 指令,并使用内存 SQLite 会话内容索引。每次启动 profile 时,系统都会监视 profile 与 home 两个 `cordis.patch.yml` 配置层的有效变更,并以事务方式重新应用;一次性运行模式通过有界关闭流程退出,该流程会先 dispose 监视器。 新会话默认使用 `workspace-write` 权限预设。Bash 和文件系统修改仅限于会话 workspace 与平台临时根目录;读取、网络访问和进程可见性不受限制。`DSH_PERMISSION_MODE` 更改进程后备值。General settings 中存储的权限影响后续 Web 会话,不改变已打开的会话。 @@ -75,8 +75,7 @@ dsh web --help 基础组合包挂载原生 DeepSeek 适配器、settings 与凭据提供方、稳定的 `web_search` 和已禁用的会话遥测。提供方凭据依次从继承环境、`$DSH_HOME/.credentials.yaml`、调用目录的 `.env` 和 `$DSH_HOME/.env` 解析;受管文档从不物化进 `process.env`,而两个 `.env` 文件都是普通启动环境层。搜索使用 `DEEPSEEK_API_KEY` 并接受 `DEEPSEEK_SEARCH_BASE_URL`;只有 patch 层插入提供方并启用 `web_fetch` 后,该工具才可用。 -会话遥测默认留在本地。`DSH_TELEMETRY_MODE=FULL` 将每条已投影会话事件作为 OTLP/HTTP 日志流式发送,`DSH_TELEMETRY_MODE=FEEDBACK_ONLY` 则仅在记录反馈时上传会话日志后缀。`DSH_TELEMETRY_OTLP_URL` 选择其他 collector,任何非空 `DSH_TELEMETRY_DISABLED` 仍是具有最高优先级的硬性退出开关。随附基础配置没有遥测脱敏规则,因此显式启用的导出可能包含消息文本、工具参数与结果以及 workspace 路径;该部署决策由[默认关闭 Agent Note](../../../.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.md)负责。 - +会话遥测默认留在本地。`DSH_TELEMETRY_MODE=FULL` 将每条已投影会话事件作为 OTLP/HTTP 日志流式发送,`DSH_TELEMETRY_MODE=FEEDBACK_ONLY` 则仅在记录反馈时上传会话日志后缀。`DSH_TELEMETRY_OTLP_URL` 选择其他 collector。任何非空的 `DSH_TELEMETRY_DISABLED` 都是具有最终效力的遥测强制关闭开关。随附基础配置没有遥测脱敏规则,因此显式启用的导出可能包含消息文本、工具参数和结果,以及 workspace 路径;相关部署决策见[默认关闭 Agent Note](../../../.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.md)。 通过 `dsh plugin --profile add ` 安装外部插件组合包。安装的包拥有其依赖,并贡献其声明的 `cordis.patch.yml` 层。CLI 还随附 `@deepseek-ai/dsh-mcp-client` 作为供 patch 层使用的依赖,但默认不启用 MCP 服务器,因为每条服务器命令都是 agent(智能体)沙箱之外的受信任可执行代码。 diff --git a/apps/cli/tests/lazy-search-startup.compat.spec.ts b/apps/cli/tests/lazy-search-startup.compat.spec.ts index b1477a63d0..c563c850e6 100644 --- a/apps/cli/tests/lazy-search-startup.compat.spec.ts +++ b/apps/cli/tests/lazy-search-startup.compat.spec.ts @@ -21,15 +21,22 @@ import { describe, expect, it } from 'vitest' const repoRoot = fileURLToPath(new URL('../../../', import.meta.url)) const builtBin = join(repoRoot, 'apps/cli/lib/bin.js') const webDist = join(repoRoot, 'apps/web/dist/index.html') -// The web bundle's patch owns the session-query-sqlite lazy-open row. -const configPath = join(repoRoot, 'packages/bundle/web-app/cordis.patch.yml') +// Full-text session search ships off (`openAt: never` on both layers): the +// base patch carries the default, and the web restatement must not re-enable it. +const baseConfigPath = join(repoRoot, 'packages/bundle/base/cordis.patch.yml') +const webConfigPath = join(repoRoot, 'packages/bundle/web-app/cordis.patch.yml') const requireBuiltArtifacts = process.env.DSH_REQUIRE_BUILT_CLI_SMOKE === '1' interface ConfigRow { id?: string + disabled?: unknown config?: { openAt?: unknown } } +interface PatchEntry extends ConfigRow { + insert?: ConfigRow[] +} + const jsExprType = new yaml.Type('tag:yaml.org,2002:js', { kind: 'scalar', construct: value => String(value), @@ -92,12 +99,20 @@ function runBuiltWeb(cwd: string): Promise<{ stdout: string; stderr: string; cod } describe.skipIf(!requireBuiltArtifacts)('built CLI lazy-search startup', () => { - it('boots and disposes the shipped composition without a SQLite startup warning', async () => { + it('boots and disposes the shipped composition with full-text search off by default', async () => { expect(existsSync(builtBin), `missing built CLI ${resolve(builtBin)}; run pnpm build`).toBe(true) expect(existsSync(webDist), `missing Web dist ${resolve(webDist)}; run pnpm run build:web`).toBe(true) - const rows = yaml.load(await readFile(configPath, 'utf8'), { schema: configSchema }) as ConfigRow[] - const searchRow = rows.find(row => row.id === 'session-query-sqlite') - expect(searchRow?.config?.openAt).toBe('first-search') + const baseRows = (yaml.load(await readFile(baseConfigPath, 'utf8'), { schema: configSchema }) as PatchEntry[]) + .flatMap(entry => entry.insert ?? [entry]) + const webRows = (yaml.load(await readFile(webConfigPath, 'utf8'), { schema: configSchema }) as PatchEntry[]) + .flatMap(entry => entry.insert ?? [entry]) + const baseRow = baseRows.find(row => row.id === 'session-query-sqlite') + const webRow = webRows.find(row => row.id === 'session-query-sqlite') + expect(baseRow?.config?.openAt).toBe('never') + expect(baseRow?.disabled).toBeUndefined() + // The web restatement keeps the shipped default; opting in is a later layer's override. + expect(webRow?.config?.openAt).toBe('never') + expect(webRow?.disabled).toBeUndefined() const cwd = await mkdtemp(join(tmpdir(), 'dsh-cli-lazy-search-')) try { diff --git a/apps/web/package.json b/apps/web/package.json index f6dd190d91..32d6c06d78 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -24,7 +24,7 @@ "dev": "vite", "watch": "vite build --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/dsh-client-web": "workspace:^", "react": "^18.2.0", diff --git a/apps/web/tests/scaffold.ts b/apps/web/tests/scaffold.ts index 1c3fb67e85..970ff7b139 100644 --- a/apps/web/tests/scaffold.ts +++ b/apps/web/tests/scaffold.ts @@ -391,6 +391,10 @@ export async function launchWebScaffold(options: LaunchOptions = {}): Promise void`:注册一个受信任、带类型的同进程定义,其中必须包含规范的 `output` 声明。所在层由调用上下文的作用域决定:普通插件上下文会全局注册;agent 的 `agent.ctx` 只为该 agent 注册,并在此处遮蔽同名全局工具。同一层内名称重复会抛出;非原生模式还会拒绝保留的 `run_code` 传输名称。缺失或不受支持的输出声明,以及非正数或非有限的 `timeoutMs`,都会使注册失败。可选的同步 `finalizeContent` 回调会在调用开始时创建快照;在所有流水线结果(包括实体化其他结果字段时发现的错误)规范化之后,它只能替换最终面向模型的内容。随调用 fiber dispose(资源释放)。 -- `ctx.tools.presentAs(mode: ToolPresentationMode): () => void`:为本 agent 选择面向模型的呈现方式,仅对该 agent 遮蔽 `mode` 配置;从普通上下文调用会抛出(进程级呈现方式是那个配置字段),同一 scope 内第二次声明也会抛出。code 类模式还会为该 agent 注册它自己的 `tools:sdk` 段。清单本身不变——`schemas(agent)` 报告的仍是该 agent 的能力,仅组装结果中的工具会被折叠。随调用方 fiber dispose。 +- `ctx.tools.register(definition: ToolDefinition): () => void`:注册一个受信任、带类型的同进程定义,其中必须包含规范的 `output` 声明。所在层由调用上下文的作用域决定:普通插件上下文会全局注册;agent 的 `agent.ctx` 只为该 agent 注册,并在此处遮蔽同名全局工具。同一层内名称重复会抛出;非原生模式还会拒绝保留的 `run_code` 传输名称。缺失或不受支持的输出声明,以及非正数或非有限的 `timeoutMs`,都会使注册失败。可选的同步 `finalizeContent` 回调会在调用开始时纳入快照;在所有流水线结果(包括实体化其他结果字段时发现的错误)规范化之后,它只能替换最终面向模型的内容。该注册会随调用方 fiber 一同 dispose(资源释放)。 +- `ctx.tools.presentAs(mode: ToolPresentationMode): () => void`:为本 agent 选择面向模型的呈现方式,仅对该 agent 遮蔽 `mode` 配置;从普通上下文调用会抛出(进程级呈现方式是那个配置字段),同一 scope 内第二次声明也会抛出。code 类模式还会为该 agent 注册它自己的 `tools:sdk` 段。工具目录保持不变:`schemas(agent)` 仍会报告该 agent 的能力;只有组装结果中的工具列表会按所选呈现方式收束。随调用方 fiber dispose。 - `ctx.tools.restrict(filter)`:对全局工具应用 agent 作用域的允许/拒绝掩码;从普通上下文调用会抛出。筛选器在注册时创建快照;多个掩码取交集,随后再合并作用域本地工具。拒绝掩码会接纳后来出现且未点名的全局工具,而允许掩码会排除后来出现的名称。未知、本地或保留名称以及空筛选器都会被拒绝。这是实时可见性组合,不是权限边界;参见[作用域安全非目标](../../../.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md#security-and-authority-are-non-goals)。 -- `ctx.tools.get(name: string, scope?: ScopeKey): ToolDefinition | undefined`:按某个作用域所见的结果解析(应用遮蔽;被限制掉的全局工具视为不存在)。呈现器会传入发起调用的 agent,使卡片与实际执行内容一致。 +- `ctx.tools.get(name: string, scope?: ScopeKey): ToolDefinition | undefined`:返回指定作用域可见的解析结果,其中已应用名称遮蔽;被作用域限制排除的全局工具会被视为不存在。呈现器会传入发起调用的 agent,使卡片与实际执行内容一致。 - `ctx.tools.schemas(scope?: ScopeKey): ToolSchema[]`:返回该作用域可见的所有 schema(不含 `execute` 函数)。已交付工具的 schema 收录在 [docs/tool-catalog.md](../../../docs/tool-catalog.md) 中;该目录通过启动每个工具插件并采集此方法的结果生成(参见[工具 schema 目录 Agent Note](../../../.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.md))。 - `ctx.tools.guard(guard: ToolGuard): () => void`:在 `tools/pre-execute` 之后注册单调同步执行守卫:返回理由会拒绝调用,返回 `undefined` 则保持原决定。普通上下文守卫全局生效;`agent.ctx` 守卫只对该 agent 生效。后续 waterfall(瀑布式事件)监听器无法将守卫的拒绝重新变为允许。随调用 fiber dispose。 -- `ctx.tools.execute(exec)`:以无损方式快照并冻结参数,分配不透明 token,运行完整的策略/分发/结果流水线,然后在最终观测前独立快照权威结果。无效参数会进入同一结果路径,但不会到达策略或工具主体。环绕包装层只能替换 `signal`;注册表会在调用主体前立即重新融合调用方的原始信号。 +- `ctx.tools.execute(exec)`:以无损方式快照并冻结参数,分配不透明 token,运行完整的策略/分发/结果流水线,然后在最终观测前独立快照权威结果。无效参数会进入同一结果路径,但不会到达策略或工具主体。环绕包装层只能替换 `signal`;注册表会在进入工具主体之前,立即将调用方的原始信号重新合并到当前信号中。 - `ctx.tools.executionMode(exec)`:返回 `parallel` 的唯一条件是可见定义的 `isConcurrencySafe(exec.arguments)` 分类器恰好返回 `true`;未知、隐藏、未声明、无效或抛出异常的分类结果均为独占。 ### 注入的服务 @@ -32,11 +32,11 @@ tools: ### 取消 -取消采用协作方式,并等待完全停稳。每次类型化调用都提供由调用方拥有的 `AbortSignal`;工具主体通过必填的只读 `exec.signal` 接收它,只有 `tools/execute` 包装层可以临时替换这个必填信号。注册表会在替换期间保留调用方取消,并且绝不会在已启动的同进程 Promise 尚未结算时提前返回。工具主体调用前发生的取消为 `ABORTED_BEFORE_DISPATCH`;调用主体后的取消只能把成功结果替换为 `ABORTED`。拒绝、包装层失败、工具失败、后置策略失败或由超时机制产生的 `TOOL_TIMEOUT` 仍保留更具体的结果。入口处已中止的调用会实体化并冻结参数,随后跳过所有策略和分发阶段,只发布一个结果。每个异步工具都必须观测或转发该信号,并且只能在自身拥有的工作停止后结算。[工具取消 Agent Note](../../../.agents/notes/implemented/architecture/2026-07-19-cooperative-tool-cancellation.md) 规定完整约定和强制终止边界。 +取消采用协作方式,并等待完全停稳。每次类型化调用都提供由调用方拥有的 `AbortSignal`;工具主体通过必填的只读 `exec.signal` 接收它,只有 `tools/execute` 包装层可以临时替换这个必填信号。注册表会在替换期间保留调用方取消,并且绝不会在已启动的同进程 Promise 尚未结算时提前返回。工具主体调用前发生的取消为 `ABORTED_BEFORE_DISPATCH`;工具主体被调用后发生的取消,只能将成功结果替换为 `ABORTED`。拒绝、包装层失败、工具失败、后置策略失败或由超时机制产生的 `TOOL_TIMEOUT` 仍保留更具体的结果。入口处已中止的调用会实体化并冻结参数,随后跳过所有策略和分发阶段,只发布一个结果。每个异步工具都必须观测或转发该信号,并且只能在其负责的工作停止后结算。[工具取消 Agent Note](../../../.agents/notes/implemented/architecture/2026-07-19-cooperative-tool-cancellation.md) 规定完整约定和强制终止边界。 ### 实时事件 -实时注册表流水线先经过 3 个可变换的 waterfall,再经过由定义拥有的内容终结器,最后发布仅供观测的 `tools/result` 事件;注册表变更有意作为不过滤的共享状态通知。确切签名、分发 mode、作用域筛选和失败隔离约定位于 [tools.md](../../../docs/subsystems/tools.md#cordis-surface) 的生成区块,完整顺序则在生成的[工具执行流水线](../../../docs/tool-execution-pipeline.md)中可视化。`tools/result` 是实时事件;名称相近的 `tool/result` 是 agent loop 随后追加的持久会话事件。 +实时注册表流水线先经过 3 道可转换的 waterfall,再经过由工具定义持有的内容终结器,最后发布仅供观测的 `tools/result` 事件;注册表变更通知有意不作过滤,并作为共享状态通知发布。确切签名、分发 mode、作用域筛选和失败隔离约定位于 [tools.md](../../../docs/subsystems/tools.md#cordis-surface) 的生成区块,完整顺序则在生成的[工具执行流水线](../../../docs/tool-execution-pipeline.md)中可视化。`tools/result` 是实时事件;名称相近的 `tool/result` 是 agent loop 随后追加的持久会话事件。 ### 关键类型 @@ -102,16 +102,16 @@ ctx.tools.register(defineTool({ ### 强制执行的原始 JSON Schema 子集 -`JsonSchemaNode` 是工具输出、Code Mode 生成、subagent 和工作流共享的原始对应类型。它允许任意 JSON 根、一个仅含 annotation 的无约束 JSON 节点,以及恰好匹配一个分支的 `oneOf`;annotation 必须保持为无损 JSON。`assertSupportedJsonSchema()` 拒绝不受支持的构造,而 `validateJsonSchemaValue()` 返回带路径的违规信息。subagent 和工作流通过 `assertObjectJsonSchema()` 与 `ObjectJsonSchema` 保留调用方定义的对象根要求,而不是依赖共享词汇的限制。 +`JsonSchemaNode` 是工具输出、Code Mode 生成、subagent 和工作流共享的原始 JSON Schema 对应类型。它允许任意 JSON 根、仅含注解且不施加约束的 JSON 节点,以及恰好匹配一个分支的 `oneOf`;注解必须保持为无损 JSON。`assertSupportedJsonSchema()` 拒绝不受支持的构造,而 `validateJsonSchemaValue()` 返回带路径的违规信息。subagent 和工作流通过 `assertObjectJsonSchema()` 与 `ObjectJsonSchema` 保留调用方定义的对象根要求,而不是依赖共享词汇的限制。 -### 工具拥有的 UI 呈现 +### 由工具定义的 UI 呈现 -工具可以选择拥有纯 `presentCall()` 和 `presentResult()` 呈现意图,使 UI 无需特殊处理工具名称: +工具可以选择通过纯函数 `presentCall()` 和 `presentResult()` 定义呈现意图,使 UI 无需针对工具名称编写特殊逻辑: - 调用视图为 `{ card: 'generic', title, kind?, rawInput?, content?, locations? }`、`{ card: 'terminal', title, description?, cwd? }` 或 `{ card: 'diff', title, diffs, locations? }`。 -- 结果视图为 `{ card: 'generic', title?, content? }`、`{ card: 'terminal', title?, output?, exitCode?, signal? }`、`{ card: 'diff', title?, diffs }`、`{ card: 'search', shape, title?, truncated, total, … }`(已完成的发现型搜索——`shape: 'matches'`(grep)为按文件分组的匹配,`shape: 'paths'`(glob)为扁平路径列表,配 `truncated`/`total` 使 UI 永不把被截断的结果当作完整结果呈现;该视图不携带结果文本,且搜索没有 `card: 'search'` 的调用时对应视图)、`{ card: 'read', title?, path, offset, lines, totalLines, lang?, content? }`(已完成的文件读取→带行号、可选语法高亮的代码视图;`offset` 是窗口请求的 1-based 起始行,即使 `lines` 为空也保留;`lines` 是 `{ number, text }[]`,保留每一行的文件行号,`content` 是无读取能力的 UI 回退时使用的去信封文本)或 `{ card: 'web', kind: 'search' | 'fetch', title?, … }`(已完成的 web 检索;`kind` 各分支携带结构化的搜索来源或抓取摘要,不具备 `web` 能力的 UI 回退到原始结果内容)。 +- 结果视图为 `{ card: 'generic', title?, content? }`、`{ card: 'terminal', title?, output?, exitCode?, signal? }`、`{ card: 'diff', title?, diffs }`、`{ card: 'search', shape, title?, truncated, total, … }`(已完成的发现型搜索——`shape: 'matches'`(grep)为按文件分组的匹配,`shape: 'paths'`(glob)为扁平路径列表,配 `truncated`/`total` 使 UI 永不把被截断的结果当作完整结果呈现;该视图不携带结果文本,且搜索没有 `card: 'search'` 的调用时对应视图)、`{ card: 'read', title?, path, offset, lines, totalLines, lang?, content? }`(已完成的文件读取→带行号、可选语法高亮的代码视图;`offset` 是窗口请求的 1-based 起始行,即使 `lines` 为空也保留;`lines` 是 `{ number, text }[]`,保留每一行的文件行号,`content` 是去除读取结果外层封装后的正文,供不支持读取视图的 UI 回退显示)或 `{ card: 'web', kind: 'search' | 'fetch', title?, … }`(已完成的 web 检索;`kind` 各分支携带结构化的搜索来源或抓取摘要,不具备 `web` 能力的 UI 回退到原始结果内容)。 -返回 `undefined` 会选择通用回退。呈现器只依赖其参数和持久结果,因为 UI 会在实时流式输出和日志回放期间调用它们。`output.presentationMeta(args, value)` 为直接接口调用派生 JSON 元数据;该元数据随 `tool/result` 持久化并传回 `presentResult`,而规范值本身仍只存在于执行局部,绝不会回放。嵌套 Code 分发不会计算元数据。`defineTool` 会软验证较旧的日志参数并回退,而不会使回放崩溃。`dsh-tool-bash` 与 `dsh-tool-fs` 是参考实现;[规范输出 Agent Note](../../../.agents/notes/implemented/architecture/2026-07-20-canonical-tool-output-contract.md) 规定值/呈现拆分,[呈现意图 Agent Note](../../../.agents/notes/implemented/architecture/2026-07-02-tool-render-intent-union.md) 规定卡片词汇。 +返回 `undefined` 会选择通用回退。呈现器只依赖其参数和持久结果,因为 UI 会在实时流式输出和日志回放期间调用它们。`output.presentationMeta(args, value)` 为直接的顶层调用派生 JSON 元数据;该元数据随 `tool/result` 持久化并传回 `presentResult`,而规范值本身仍只存在于执行局部,绝不会回放。嵌套 Code 分发不会计算元数据。`defineTool` 会软验证较旧的日志参数并回退,而不会使回放崩溃。`dsh-tool-bash` 与 `dsh-tool-fs` 是参考实现;[规范输出 Agent Note](../../../.agents/notes/implemented/architecture/2026-07-20-canonical-tool-output-contract.md) 规定值/呈现拆分,[呈现意图 Agent Note](../../../.agents/notes/implemented/architecture/2026-07-02-tool-render-intent-union.md) 规定卡片词汇。 ### Code Mode @@ -119,10 +119,10 @@ ctx.tools.register(defineTool({ 在 `code`(而非 `both`)下,该传输同时也是模型唯一可用的入口:模型直呼其他任何可见工具名,都会在创建执行时、早于 `tools/pre-execute`、审批 `ask` 和 guards 解析为 `UNKNOWN_TOOL`,因此没有任何一方会观察或批准一个注定失败的调用。拒绝信息会给出正确路径(`only \`run_code\` is callable directly — call \`\` from inside a \`run_code\` program instead`),因为同一份提示词刚刚声明过那个工具,只说 `unknown tool` 会被读成部署损坏。SDK 子分发携带外层执行的 `parent` token,不受此限制,因此程序保留 SDK 声明的全部绑定。参见[执行器塌缩 note](../../../.agents/notes/implemented/bug-fix/2026-08-07-code-mode-executor-collapse.md)、[Code Mode 基础](../../../.agents/notes/implemented/feature/2026-06-15-code-mode.md)、[类型化返回约定](../../../.agents/notes/implemented/feature/2026-07-20-code-mode-typed-tool-returns.md)和[代码运行时 seam](../../code-runtime/README.md)。可以运行 `pnpm run demo:code-mode` 试用。 -- **SDK 段**(`tools:sdk`,顺序 150):一个惰性提示词段,每次组装时都会重新生成与所加载运行时语言相符的 SDK 文本。TypeScript 形态发出 `JsonValue`、精确的 `ToolArgsMap` / `ToolOutputMap`、`ToolName`、`ToolCallError` 声明、面向调用作用域可见最终能力的映射 `tools` 命名空间(特殊名称使用带引号的键),以及固定用法说明;Python 形态(`ctx.codeRuntime.language === 'python'`)发出等价的具名 `TypedDict` 与一个带相同用法说明的 `tools` 对象。其输出具有确定性:工具按字典序排列;工具集合不变时,文本逐字节相同(有利于前缀 cache)。两个代码生成器都已导出,且绝不会在提示词组装期间抛出:`jsonSchemaToTs` 处理统一 schema 的每种构造并将不受支持的原始构造降级为 `unknown`;`jsonSchemaToPy` 同理,降级为 `Any`(当某字段名不是合法的 `TypedDict` 属性时,或在 SDK 渲染之外被调用时——`TypedDict` 声明所需的命名上下文由该渲染提供——整个对象降级为 `dict[str, Any]`)。 -- **分发桥接层**(`run_code` 的 execute):每个绑定调用都会在分发前快照为无损 JSON(`undefined`、`BigInt`、循环、稀疏数组、`-0` 和特殊对象会使该次调用被拒绝),经由每次运行独有、复用原生并发约定的池调度——调用严格按提交顺序启动,连续的 `isConcurrencySafe` 调用最多可重叠经校验的 `maxParallelSubCalls` 配置个(默认 10;设为 `1` 即恢复串行分发),被分类为独占的调用先排空池、单独运行并阻挡其后的调用——以外层执行的不透明 token 作为 `parent`,并经过完整的 pre-execute → guards → execute → post-execute → result 流水线。成功会返回策略处理后的最终规范值;失败以一条消息到达 worker,并成为 `ToolCallError(toolName, message)`。每个已启动的子调用在进入流水线时记录一条 `tool/code-dispatch-start` 事件(确定性 id `:code:`,按提交顺序编号),并以一条携带完整模型可见 `content`/`isError` 结果的 `tool/code-dispatch` 事件完结(采用 `tool/result` 词汇,因此 UI 会沿原生路径呈现子调用——这对事件的 `time` 字段承载每个子调用的计时);因 run 结算而被放弃的排队调用两者都不记录。`deriveMessages()` 既不公开这两个事件,也不持久化规范值。token 关联让以提交为语义的观察器能够把内部成功延迟到最终 `run_code` 结果,而无需公开实时外层执行;普通工具副作用不会回滚。每个子调用的 `additionalContexts` 条目都会按分发顺序通过外层 `ToolRunContext` 延迟;循环只在父级 `run_code` 结果之后追加这些上下文,从而保持相邻关系,并且即使程序后来失败,也会保留各自的来源/元数据。 +- **SDK 段**(`tools:sdk`,顺序 150):一个在组装时求值的提示词段,每次组装都会重新生成与所加载运行时语言相符的 SDK 文本。TypeScript 形态会生成 `JsonValue`、精确的 `ToolArgsMap` / `ToolOutputMap`、`ToolName`、`ToolCallError` 声明,以及映射调用作用域最终可见工具的 `tools` 命名空间(特殊名称使用带引号的键),并附带固定的使用说明;Python 形态(`ctx.codeRuntime.language === 'python'`)发出等价的具名 `TypedDict` 与一个带相同用法说明的 `tools` 对象。其输出具有确定性:工具按字典序排列;工具集合不变时,文本逐字节相同(有利于前缀 cache)。两个代码生成器都已导出,且绝不会在提示词组装期间抛出:`jsonSchemaToTs` 处理统一 schema 的每种构造并将不受支持的原始构造降级为 `unknown`;`jsonSchemaToPy` 同理,降级为 `Any`(当某字段名不是合法的 `TypedDict` 属性时,或在 SDK 渲染之外被调用时——`TypedDict` 声明所需的命名上下文由该渲染提供——整个对象降级为 `dict[str, Any]`)。 +- **分发桥接层**(`run_code` 的 execute):每个绑定调用都会在分发前快照为无损 JSON(`undefined`、`BigInt`、循环、稀疏数组、`-0` 和特殊对象会使该次调用被拒绝),经由每次运行独有、复用原生并发约定的池调度——调用严格按提交顺序启动,连续的 `isConcurrencySafe` 调用最多可重叠经校验的 `maxParallelSubCalls` 配置个(默认 10;设为 `1` 即恢复串行分发),被分类为独占的调用先排空池、单独运行并阻挡其后的调用——以外层执行的不透明 token 作为 `parent`,并经过完整的 pre-execute → guards → execute → post-execute → result 流水线。成功会返回策略处理后的最终规范值;失败以一条消息到达 worker,并成为 `ToolCallError(toolName, message)`。每个已启动的子调用在进入流水线时记录一条 `tool/code-dispatch-start` 事件(确定性 id `:code:`,按提交顺序编号),并以一条携带完整模型可见 `content`/`isError` 结果的 `tool/code-dispatch` 事件完结(采用 `tool/result` 词汇,因此 UI 会沿原生路径呈现子调用——这对事件的 `time` 字段承载每个子调用的计时);因 run 结算而被放弃的排队调用两者都不记录。`deriveMessages()` 既不公开这两个事件,也不持久化规范值。token 关联使按提交语义工作的观察器可以延后提交内部调用的成功结果,直到最终 `run_code` 结果确定,而无需暴露进行中的外层执行;普通工具副作用不会回滚。每个子调用的 `additionalContexts` 条目都会按分发顺序通过外层 `ToolRunContext` 延迟;循环只在父级 `run_code` 结果之后追加这些上下文,从而保持相邻关系,并且即使程序后来失败,也会保留各自的来源/元数据。 - **结算纪律**:桥接层拥有一个运行作用域的中止机制;该中止会跟随传入的外层信号,并在运行因任何原因结算时触发,因此预算耗尽会中止正在运行的子工具,而不会将其遗留。桥接层随后会在返回之前排空队列,使每个 `tool/code-dispatch` 都落在仍打开的轮次内。失败的运行会抛出 `CodeRunFailedError`(`code: 'CODE_RUN_FAILED'`,message = 失败类型 + 已捕获日志),流水线会将其转换为模型可据以自我修正的结构化 `isError`。 -- **结果大小**:中间绑定值会完整传入 worker 进程,且没有逐绑定字节上限。`run_code` 返回规范的 `{ logs: string[], result?: JsonValue }`;字符串原样呈现,其他所有存在的 JSON 根都通过栈安全的美化 JSON 遍历呈现,总缩进最多为 10 个字符(更深的子树保持紧凑),`null` 保持显式,而缺少 `result` 表示程序返回 `undefined`。worker 可配置的 `maxOutputBytes`(默认 64 MiB)只应用于组合序列化后的外层日志数组、完成值或失败消息载荷;固定的结果 envelope 语法和呈现空白不计入该上限。无效和超限的完成会明确失败,只有此外层结果可以使用普通 spill。 +- **结果大小**:中间绑定值会完整传入 worker 进程,且没有逐绑定字节上限。`run_code` 返回规范的 `{ logs: string[], result?: JsonValue }`;字符串原样呈现,其他所有存在的 JSON 根都通过栈安全的美化 JSON 遍历呈现,总缩进最多为 10 个字符(更深的子树保持紧凑),`null` 保持显式,而缺少 `result` 表示程序返回 `undefined`。worker 可配置的 `maxOutputBytes`(默认 64 MiB)只应用于组合序列化后的外层日志数组、完成值或失败消息载荷;固定的结果封装语法和呈现空白不计入该上限。无效和超限的完成会明确失败,只有这个外层结果可以按常规 spill 机制处理。 ### 并行执行 @@ -177,7 +177,7 @@ The available tools: #### 模型看到的内容 -循环会保留模型发出的参数和注册表的最终内容。任何抛出或被拒绝的调用都会恰好变为 `Error: `。Code Mode 只返回外层程序打印的行和呈现后的返回值;两者都为空时返回 `(run_code completed with no output)`;失败时返回 `Error: code run failed (): `,并根据是否存在已捕获内容,在其后附加 `Captured output:` 与捕获的行。内部分发事件只保留在日志中;后置执行监听器可以在结果之后追加带来源归属的上下文。 +循环会保留模型发出的参数和注册表的最终内容。任何抛出异常或遭到拒绝的调用,都会转换为确切的 `Error: `。Code Mode 只返回外层程序打印的行和呈现后的返回值;两者都为空时返回 `(run_code completed with no output)`;失败时返回 `Error: code run failed (): `,并根据是否存在已捕获内容,在其后附加 `Captured output:` 与捕获的行。内部分发事件只保留在日志中;后置执行监听器可以在结果之后追加带来源归属的上下文。 #### Token 影响 @@ -192,7 +192,7 @@ The available tools: - **并发策略不是事件门禁**:`executionMode()` 直接读取已解析的工具定义;插件只能在自身拥有的定义上声明分类器。 - **`tools/pre-execute` 有意不允许改写 `exec.arguments`**:否则日志记录和呈现的参数会与实际运行内容失去同步;改写设计记录在[拟议的 Agent Note](../../../.agents/notes/proposed/feature/2026-06-30-pre-tool-input-rewrite.md)中。 - **调用方定义的 subagent 与工作流结构化输出仍要求对象根**:这是消费方层面的守卫;共享 schema 词汇和工具输出支持任意 JSON 根。 -- **定义上的 `timeoutMs` 仅为声明**:注册表绝不会强制执行截止时间;要强制执行,必须使用 `@deepseek-ai/dsh-tool-call-timeout-policy` 包装层。 -- **Code Mode 的 SDK 语言跟随已加载的那个运行时,且呈现方式按 agent 而非按工具**:`mode: code`/`both` 会拒绝组装提示词,除非 `ctx.codeRuntime.language` 有已注册的 SDK 渲染器(TypeScript 或 Python);作用域限制/遮蔽与 `presentAs` 会选择每个 agent 的可见绑定及其形态,但在同一个 agent 内不能让一个工具仅使用 Native,而另一个仅使用 Code。 +- **定义中的 `timeoutMs` 仅作声明之用**:注册表绝不会强制执行截止时间;要强制执行,必须使用 `@deepseek-ai/dsh-tool-call-timeout-policy` 包装层。 +- **Code Mode 的 SDK 语言由当前加载的运行时决定,且呈现方式按 agent 而非按工具**:`mode: code`/`both` 会拒绝组装提示词,除非 `ctx.codeRuntime.language` 有已注册的 SDK 渲染器(TypeScript 或 Python);作用域限制/遮蔽与 `presentAs` 会选择每个 agent 的可见绑定及其形态,但在同一个 agent 内不能让一个工具仅使用 Native,而另一个仅使用 Code。 - **Code Mode 中间值只存在于执行局部,且没有字节上限**:这些规范的类型化值无法从会话回放重建,并可能耗尽进程或 worker 内存;只有外层 `run_code` 输出受 worker 可配置的硬上限约束。每个子调用的持久日志副本则确实有上限:`tools/code-dispatch-log` waterfall 允许 spill 策略把过大的 `tool/code-dispatch` 内容替换为预览加定位符([原理](../../../.agents/notes/implemented/feature/2026-07-26-code-dispatch-log-spill.md))。 - **每次运行都会获得全新的 `run_code` 状态**:MVP 不采用持久 REPL 风格内核(跨调用状态不会出现在日志中);参见 [Code Mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-code-mode.md)。 diff --git a/packages/core/tools/package.json b/packages/core/tools/package.json index aa1fe55317..b472b72eae 100644 --- a/packages/core/tools/package.json +++ b/packages/core/tools/package.json @@ -39,7 +39,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-code-runtime": "workspace:^", diff --git a/packages/credentials/credentials-local/package.json b/packages/credentials/credentials-local/package.json index 9ce945ec19..3e6336abf9 100644 --- a/packages/credentials/credentials-local/package.json +++ b/packages/credentials/credentials-local/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-atomic-write": "workspace:^", "@deepseek-ai/dsh-credentials": "workspace:^", diff --git a/packages/credentials/credentials/package.json b/packages/credentials/credentials/package.json index d513b026d2..c4e9b22fc2 100644 --- a/packages/credentials/credentials/package.json +++ b/packages/credentials/credentials/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/e2b/e2b/package.json b/packages/e2b/e2b/package.json index da84d0f370..50619aab9b 100644 --- a/packages/e2b/e2b/package.json +++ b/packages/e2b/e2b/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/e2b/fs-e2b/package.json b/packages/e2b/fs-e2b/package.json index f85fa57e80..e4cad4d1dd 100644 --- a/packages/e2b/fs-e2b/package.json +++ b/packages/e2b/fs-e2b/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-e2b": "workspace:^", "@deepseek-ai/dsh-fs": "workspace:^", diff --git a/packages/e2b/subprocess-e2b/package.json b/packages/e2b/subprocess-e2b/package.json index 24e72d4811..9d939df557 100644 --- a/packages/e2b/subprocess-e2b/package.json +++ b/packages/e2b/subprocess-e2b/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-e2b": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/examples/acp-demo/package.json b/packages/examples/acp-demo/package.json index 73a7b09a99..a3791b086a 100644 --- a/packages/examples/acp-demo/package.json +++ b/packages/examples/acp-demo/package.json @@ -38,7 +38,7 @@ "lib/bin.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", "@deepseek-ai/cordis-plugin-loader": "workspace:^", diff --git a/packages/examples/agent-spine-demo/package.json b/packages/examples/agent-spine-demo/package.json index a7d181afb5..5a7b1e3cb6 100644 --- a/packages/examples/agent-spine-demo/package.json +++ b/packages/examples/agent-spine-demo/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis-plugin-timer": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", diff --git a/packages/examples/jsonrpc-demo/package.json b/packages/examples/jsonrpc-demo/package.json index 7eaa061bbc..f756389787 100644 --- a/packages/examples/jsonrpc-demo/package.json +++ b/packages/examples/jsonrpc-demo/package.json @@ -43,7 +43,7 @@ "lib/packaged-bin.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/dsh-app-boot": "workspace:^" }, diff --git a/packages/extensions/cordis-client-runner/package.json b/packages/extensions/cordis-client-runner/package.json index e6b3d128db..fe183445d0 100644 --- a/packages/extensions/cordis-client-runner/package.json +++ b/packages/extensions/cordis-client-runner/package.json @@ -44,7 +44,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-api-remotes": "workspace:^", diff --git a/packages/extensions/cordis-host-runner/package.json b/packages/extensions/cordis-host-runner/package.json index 33307e816e..263a673466 100644 --- a/packages/extensions/cordis-host-runner/package.json +++ b/packages/extensions/cordis-host-runner/package.json @@ -47,7 +47,7 @@ "lib/typert.remote-client.js", "lib/typert.remote-client.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "workspace:^", "zod": "^4.4.3" diff --git a/packages/extensions/tool-cordis/package.json b/packages/extensions/tool-cordis/package.json index b1a290b307..d1badb3d1f 100644 --- a/packages/extensions/tool-cordis/package.json +++ b/packages/extensions/tool-cordis/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-cordis-host-runner": "workspace:^", diff --git a/packages/extensions/ui-cordis/package.json b/packages/extensions/ui-cordis/package.json index 9140540481..9e16d3a4a5 100644 --- a/packages/extensions/ui-cordis/package.json +++ b/packages/extensions/ui-cordis/package.json @@ -48,7 +48,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-client-connection": "workspace:^", diff --git a/packages/feedback/command-feedback/package.json b/packages/feedback/command-feedback/package.json index cebf4c9514..62a0b6e6fc 100644 --- a/packages/feedback/command-feedback/package.json +++ b/packages/feedback/command-feedback/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-commands": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/feedback/message-feedback/package.json b/packages/feedback/message-feedback/package.json index d437ad6fa6..92fd1b69e1 100644 --- a/packages/feedback/message-feedback/package.json +++ b/packages/feedback/message-feedback/package.json @@ -47,7 +47,7 @@ "lib/typert.remote-client.js", "lib/typert.remote-client.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/fs/fs-local/package.json b/packages/fs/fs-local/package.json index c91bd7fc60..e1a08d5b26 100644 --- a/packages/fs/fs-local/package.json +++ b/packages/fs/fs-local/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/fs/fs-observation-policy/package.json b/packages/fs/fs-observation-policy/package.json index 0fe92162d5..a58f7dffa1 100644 --- a/packages/fs/fs-observation-policy/package.json +++ b/packages/fs/fs-observation-policy/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/fs/fs-sandbox/package.json b/packages/fs/fs-sandbox/package.json index 21d36276ad..14bb7688ad 100644 --- a/packages/fs/fs-sandbox/package.json +++ b/packages/fs/fs-sandbox/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-fs-local": "workspace:^", diff --git a/packages/fs/fs/package.json b/packages/fs/fs/package.json index 7e9576d2ab..0b7fa7de95 100644 --- a/packages/fs/fs/package.json +++ b/packages/fs/fs/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/fs/tool-fs-search/package.json b/packages/fs/tool-fs-search/package.json index 98aba6c9b8..fb605640e2 100644 --- a/packages/fs/tool-fs-search/package.json +++ b/packages/fs/tool-fs-search/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@vscode/ripgrep": "^1.18.0", "@deepseek-ai/schemastery": "workspace:^" diff --git a/packages/fs/tool-fs/package.json b/packages/fs/tool-fs/package.json index d4be8e7409..52afc01c71 100644 --- a/packages/fs/tool-fs/package.json +++ b/packages/fs/tool-fs/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "diff": "^9.0.0", "@deepseek-ai/schemastery": "workspace:^" diff --git a/packages/fs/tool-str-replace-editor/package.json b/packages/fs/tool-str-replace-editor/package.json index 88d36dc1e8..0ba3199de1 100644 --- a/packages/fs/tool-str-replace-editor/package.json +++ b/packages/fs/tool-str-replace-editor/package.json @@ -29,7 +29,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/goal/command-goal/package.json b/packages/goal/command-goal/package.json index cb099cf4a7..37856f82c1 100644 --- a/packages/goal/command-goal/package.json +++ b/packages/goal/command-goal/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-commands": "workspace:^", "@deepseek-ai/dsh-goal": "workspace:^", diff --git a/packages/goal/goal-round-driver/package.json b/packages/goal/goal-round-driver/package.json index 577fd6c523..04039bccf5 100644 --- a/packages/goal/goal-round-driver/package.json +++ b/packages/goal/goal-round-driver/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-goal": "workspace:^", diff --git a/packages/goal/goal/package.json b/packages/goal/goal/package.json index 89962d272f..7a70042efd 100644 --- a/packages/goal/goal/package.json +++ b/packages/goal/goal/package.json @@ -51,7 +51,7 @@ "lib/typert.remote-client.js", "lib/typert.remote-client.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^", diff --git a/packages/goal/tool-goal/package.json b/packages/goal/tool-goal/package.json index 8a5f5f9c07..a55b4aecc2 100644 --- a/packages/goal/tool-goal/package.json +++ b/packages/goal/tool-goal/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-goal": "workspace:^", diff --git a/packages/guard/repeat-tool-reminder/package.json b/packages/guard/repeat-tool-reminder/package.json index 923a00bb16..3ce74bf325 100644 --- a/packages/guard/repeat-tool-reminder/package.json +++ b/packages/guard/repeat-tool-reminder/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "workspace:^" }, diff --git a/packages/guard/timeout-policy/package.json b/packages/guard/timeout-policy/package.json index 4c4ad88b31..1f79e44170 100644 --- a/packages/guard/timeout-policy/package.json +++ b/packages/guard/timeout-policy/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/hooks/hook-protocol/package.json b/packages/hooks/hook-protocol/package.json index d3152ab035..9f10386e1c 100644 --- a/packages/hooks/hook-protocol/package.json +++ b/packages/hooks/hook-protocol/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/hooks/hooks-claude-code/package.json b/packages/hooks/hooks-claude-code/package.json index 82798ab10c..a3bd642b42 100644 --- a/packages/hooks/hooks-claude-code/package.json +++ b/packages/hooks/hooks-claude-code/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "workspace:^" }, diff --git a/packages/hooks/hooks-codex/package.json b/packages/hooks/hooks-codex/package.json index 2f7866eef5..340c2ceb22 100644 --- a/packages/hooks/hooks-codex/package.json +++ b/packages/hooks/hooks-codex/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "workspace:^" }, diff --git a/packages/host/apiproxy/package.json b/packages/host/apiproxy/package.json index 298d53ac47..307581a3f3 100644 --- a/packages/host/apiproxy/package.json +++ b/packages/host/apiproxy/package.json @@ -43,7 +43,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", diff --git a/packages/host/directory-picker-auto/package.json b/packages/host/directory-picker-auto/package.json index 1afeac29fb..d79af2594e 100644 --- a/packages/host/directory-picker-auto/package.json +++ b/packages/host/directory-picker-auto/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "workspace:^", "@deepseek-ai/cordis-plugin-loader": "workspace:^", diff --git a/packages/host/directory-picker-browse/package.json b/packages/host/directory-picker-browse/package.json index 169bb3dc59..5749e795fa 100644 --- a/packages/host/directory-picker-browse/package.json +++ b/packages/host/directory-picker-browse/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/dsh-host-directory-picker": "workspace:^", "@deepseek-ai/schemastery": "workspace:^" diff --git a/packages/host/directory-picker-native/package.json b/packages/host/directory-picker-native/package.json index f7627d179e..62c375f5fa 100644 --- a/packages/host/directory-picker-native/package.json +++ b/packages/host/directory-picker-native/package.json @@ -35,7 +35,7 @@ "lib/worker.cjs", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/dsh-host-directory-picker": "workspace:^", "@deepseek-ai/dsh-native-command": "workspace:^", diff --git a/packages/host/directory-picker/package.json b/packages/host/directory-picker/package.json index a62321267a..f197d31250 100644 --- a/packages/host/directory-picker/package.json +++ b/packages/host/directory-picker/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/host/frontend-static/package.json b/packages/host/frontend-static/package.json index 9f0efc8e71..5cbd0d8628 100644 --- a/packages/host/frontend-static/package.json +++ b/packages/host/frontend-static/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-host-webserver": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/host/plugin-inventory/package.json b/packages/host/plugin-inventory/package.json index 1267665bc1..99833b8ea9 100644 --- a/packages/host/plugin-inventory/package.json +++ b/packages/host/plugin-inventory/package.json @@ -47,7 +47,7 @@ "lib/typert.remote-client.js", "lib/typert.remote-client.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "zod": "^4.4.3" }, diff --git a/packages/host/webserver/package.json b/packages/host/webserver/package.json index 340ce1208b..891fa49b23 100644 --- a/packages/host/webserver/package.json +++ b/packages/host/webserver/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^" diff --git a/packages/identity/anonymous-user-id/package.json b/packages/identity/anonymous-user-id/package.json index d470813313..604b308f15 100644 --- a/packages/identity/anonymous-user-id/package.json +++ b/packages/identity/anonymous-user-id/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/interaction/commands/package.json b/packages/interaction/commands/package.json index 3e4fb3108a..c08b1294a4 100644 --- a/packages/interaction/commands/package.json +++ b/packages/interaction/commands/package.json @@ -51,7 +51,7 @@ "lib/typert.remote-client.js", "lib/typert.remote-client.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", diff --git a/packages/interaction/permission-presets/package.json b/packages/interaction/permission-presets/package.json index 3f9265e76c..3b3160baae 100644 --- a/packages/interaction/permission-presets/package.json +++ b/packages/interaction/permission-presets/package.json @@ -39,7 +39,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-commands": "workspace:^", diff --git a/packages/interaction/tool-ask-user/package.json b/packages/interaction/tool-ask-user/package.json index 6fc2702b34..af45d56ab1 100644 --- a/packages/interaction/tool-ask-user/package.json +++ b/packages/interaction/tool-ask-user/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/interaction/user-approval/package.json b/packages/interaction/user-approval/package.json index eb22896e4a..aa1e6a5ee7 100644 --- a/packages/interaction/user-approval/package.json +++ b/packages/interaction/user-approval/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", diff --git a/packages/interaction/user-questions/package.json b/packages/interaction/user-questions/package.json index 71e35da0bf..04b7355dd1 100644 --- a/packages/interaction/user-questions/package.json +++ b/packages/interaction/user-questions/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/jobs/jobs-local/package.json b/packages/jobs/jobs-local/package.json index 5a536915ca..4b1120a92d 100644 --- a/packages/jobs/jobs-local/package.json +++ b/packages/jobs/jobs-local/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/jobs/jobs/package.json b/packages/jobs/jobs/package.json index fcac4eae3d..83235ec22b 100644 --- a/packages/jobs/jobs/package.json +++ b/packages/jobs/jobs/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", diff --git a/packages/jobs/tool-jobs/package.json b/packages/jobs/tool-jobs/package.json index 776afa4081..73ddb5f657 100644 --- a/packages/jobs/tool-jobs/package.json +++ b/packages/jobs/tool-jobs/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "workspace:^" }, diff --git a/packages/llm/llm-deepseek/package.json b/packages/llm/llm-deepseek/package.json index d27bec0b66..9c86b3c98e 100644 --- a/packages/llm/llm-deepseek/package.json +++ b/packages/llm/llm-deepseek/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-credentials": "workspace:^", "@deepseek-ai/dsh-launch-environment": "workspace:^", diff --git a/packages/llm/llm-pi-ai/package.json b/packages/llm/llm-pi-ai/package.json index 5d386cac67..5c2845394e 100644 --- a/packages/llm/llm-pi-ai/package.json +++ b/packages/llm/llm-pi-ai/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-credentials": "workspace:^", diff --git a/packages/llm/llm-retry/package.json b/packages/llm/llm-retry/package.json index 5455065f37..e6c3013da1 100644 --- a/packages/llm/llm-retry/package.json +++ b/packages/llm/llm-retry/package.json @@ -34,7 +34,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", diff --git a/packages/llm/llm/package.json b/packages/llm/llm/package.json index 7c171595e3..c6018de902 100644 --- a/packages/llm/llm/package.json +++ b/packages/llm/llm/package.json @@ -43,7 +43,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", diff --git a/packages/llm/token-meter/package.json b/packages/llm/token-meter/package.json index 3c917e7d8e..efaf61ef86 100644 --- a/packages/llm/token-meter/package.json +++ b/packages/llm/token-meter/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-compaction": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/lsp/lsp-stdio/package.json b/packages/lsp/lsp-stdio/package.json index a57a6bcff1..04088296fb 100644 --- a/packages/lsp/lsp-stdio/package.json +++ b/packages/lsp/lsp-stdio/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-fs": "workspace:^", diff --git a/packages/lsp/lsp/package.json b/packages/lsp/lsp/package.json index 8e06c85d1b..4f16df5a2f 100644 --- a/packages/lsp/lsp/package.json +++ b/packages/lsp/lsp/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/lsp/tool-lsp/package.json b/packages/lsp/tool-lsp/package.json index b9bd0e083b..bd4bda1388 100644 --- a/packages/lsp/tool-lsp/package.json +++ b/packages/lsp/tool-lsp/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/mcp/mcp-client/package.json b/packages/mcp/mcp-client/package.json index 858be7d289..d42b425730 100644 --- a/packages/mcp/mcp-client/package.json +++ b/packages/mcp/mcp-client/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/plan/plan-mode/package.json b/packages/plan/plan-mode/package.json index 5d6e8eaace..d13c7606b1 100644 --- a/packages/plan/plan-mode/package.json +++ b/packages/plan/plan-mode/package.json @@ -39,7 +39,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-commands": "workspace:^", diff --git a/packages/preset/agent-presets/package.json b/packages/preset/agent-presets/package.json index 929ed4ed62..241cf74ce7 100644 --- a/packages/preset/agent-presets/package.json +++ b/packages/preset/agent-presets/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", "@deepseek-ai/cordis-plugin-loader": "workspace:^", diff --git a/packages/preset/persona/package.json b/packages/preset/persona/package.json index cd6181a87c..24fb8660a1 100644 --- a/packages/preset/persona/package.json +++ b/packages/preset/persona/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", diff --git a/packages/runtime-diagnostics/invariants/package.json b/packages/runtime-diagnostics/invariants/package.json index e836e829eb..41d8c631e1 100644 --- a/packages/runtime-diagnostics/invariants/package.json +++ b/packages/runtime-diagnostics/invariants/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "workspace:^" }, diff --git a/packages/sandbox/sandbox-local/package.json b/packages/sandbox/sandbox-local/package.json index c363453692..57918c351b 100644 --- a/packages/sandbox/sandbox-local/package.json +++ b/packages/sandbox/sandbox-local/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/sandbox/sandbox-policy/package.json b/packages/sandbox/sandbox-policy/package.json index f5efe42255..06ea90d1cf 100644 --- a/packages/sandbox/sandbox-policy/package.json +++ b/packages/sandbox/sandbox-policy/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/sandbox/sandbox-windows-acl/package.json b/packages/sandbox/sandbox-windows-acl/package.json index 031d08bf63..7faad86ea0 100644 --- a/packages/sandbox/sandbox-windows-acl/package.json +++ b/packages/sandbox/sandbox-windows-acl/package.json @@ -36,7 +36,7 @@ "lib/types-*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/sandbox/sandbox/package.json b/packages/sandbox/sandbox/package.json index ac5ea6c542..00ebcfd612 100644 --- a/packages/sandbox/sandbox/package.json +++ b/packages/sandbox/sandbox/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/schedule/schedule/package.json b/packages/schedule/schedule/package.json index 78acd49f8c..f7e2fd6406 100644 --- a/packages/schedule/schedule/package.json +++ b/packages/schedule/schedule/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", diff --git a/packages/sdk/client/package.json b/packages/sdk/client/package.json index 938de7f9f7..6e8d4d5dd9 100644 --- a/packages/sdk/client/package.json +++ b/packages/sdk/client/package.json @@ -29,7 +29,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/sdk/protocol/package.json b/packages/sdk/protocol/package.json index f7f8fed39a..966d35d538 100644 --- a/packages/sdk/protocol/package.json +++ b/packages/sdk/protocol/package.json @@ -29,7 +29,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/sdk/server/package.json b/packages/sdk/server/package.json index a2b1b5731a..aad971d714 100644 --- a/packages/sdk/server/package.json +++ b/packages/sdk/server/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "workspace:^" }, diff --git a/packages/session-query/session-log-export/package.json b/packages/session-query/session-log-export/package.json index 080e1fd559..b020ce301b 100644 --- a/packages/session-query/session-log-export/package.json +++ b/packages/session-query/session-log-export/package.json @@ -20,7 +20,7 @@ }, "files": ["lib/index.js", "lib/invariant.js", "lib/client.js", "lib/types/**/*.d.ts"], "scripts": { "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "workspace:^", "@deepseek-ai/dsh-client-locale": "workspace:^", diff --git a/packages/session-query/session-query-sqlite/README.i18n.yaml b/packages/session-query/session-query-sqlite/README.i18n.yaml index 44142481a8..1553fb84d9 100644 --- a/packages/session-query/session-query-sqlite/README.i18n.yaml +++ b/packages/session-query/session-query-sqlite/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write packages/session-query/session-query-sqlite/README.md -README.md: 846f79bd8383a8114a6d1329e7dbe931a67d98d0 -README.zh.md: e84e521dd5f392dbcede1e1dd957e4ce0a9bc50f +README.md: 25257ddbe672d47faf39e1472a1bd882205d8c4e +README.zh.md: 584e466a5042334e22797a6c2794cce910844d5a diff --git a/packages/session-query/session-query-sqlite/README.md b/packages/session-query/session-query-sqlite/README.md index 846f79bd83..25257ddbe6 100644 --- a/packages/session-query/session-query-sqlite/README.md +++ b/packages/session-query/session-query-sqlite/README.md @@ -16,7 +16,7 @@ All three surfaces (`current`, `shadowed`, and `log-only`) are searchable by def The service requires `ctx.sessions` and observes optional `ctx.sessionPersistence` dynamically. One serialized state machine compares source-qualified lightweight durable snapshot revisions, non-mutatingly inspects only new or changed logs, extracts shared semantic documents, reconciles changes transactionally, and runs the query. Session queries never invoke the persistence backend's crash-repairing `load()`; an owner attaching during inspection cannot mutate its log, and the stable-observation retry makes the result live-preferred. The TEMP live row still records persisted availability, and the durable base refreshes after that live owner detaches. Repeated queries and an unchanged same-store reopen perform no full durable-log inspection; switching stores, or observing new, changed, deleted, or externally load-repaired sources, reconciles on the next stable observation. Source or transaction failure commits nothing, and the next search retries. -`openAt: startup` is the default: service activation imports `node:sqlite`, opens the handle, and fails before publication when the index is invalid. `openAt: first-search` publishes the service as ACTIVE without importing the SQLite module or opening a handle; the first concurrent searches share one readiness promise, and disposal before any search opens nothing. This mode supports compositions that need clean Node 22 startup output by deferring SQLite's experimental warning until the first actual search; it does not suppress a warning at that point. An invalid database likewise fails the first search instead of service activation. +`openAt: startup` is the default: service activation imports `node:sqlite`, opens the handle, and fails before publication when the index is invalid. `openAt: first-search` publishes the service as ACTIVE without importing the SQLite module or opening a handle; the first concurrent searches share one readiness promise, and disposal before any search opens nothing. This mode supports compositions that need clean Node 22 startup output by deferring SQLite's experimental warning until the first actual search; it does not suppress a warning at that point. An invalid database likewise fails the first search instead of service activation. `openAt: never` turns full-text search off for the deployment: `searchSessions` and `searchEvents` fail with `SESSION_QUERY_SEARCH_DISABLED` before any request normalization, node:sqlite is never imported or opened, and no source observation or reconciliation runs, while every inherited exact read, filter, and trace on `ctx.sessionQuery` keeps working. Persisted FTS rows live in a dedicated derived database. Connection-local TEMP tables hold live rows, which shadow the durable base for the same session and reveal it when the live owner disappears. Unmounting persistence hides durable rows without discarding the cache; remounting reconciles it. Closing or reopening the database drops every live overlay while retaining persisted rows. @@ -27,7 +27,7 @@ The database is disposable but reset is guarded: every recognized schema version | Key | Default | Contract | |---|---:|---| | `path` | required | Dedicated derived-index SQLite path; `:memory:` is supported. Missing filesystem paths are created owner-only on POSIX filesystems. | -| `openAt` | `startup` | `startup` opens before service activation completes; `first-search` defers the SQLite module and handle until search. | +| `openAt` | `startup` | `startup` opens before service activation completes; `first-search` defers the SQLite module and handle until search; `never` disables full-text search (typed `SESSION_QUERY_SEARCH_DISABLED` failures) while inherited reads stay available. | | `journalMode` | `wal` | `wal`, `delete`, `truncate`, or `persist`. | | `defaultLimit` | `20` | Page size when a request omits `limit`; at most `Number.MAX_SAFE_INTEGER - 1`. | | `maxLimit` | `100` | Largest accepted request page size; at most `Number.MAX_SAFE_INTEGER - 1`. | diff --git a/packages/session-query/session-query-sqlite/README.zh.md b/packages/session-query/session-query-sqlite/README.zh.md index e84e521dd5..584e466a50 100644 --- a/packages/session-query/session-query-sqlite/README.zh.md +++ b/packages/session-query/session-query-sqlite/README.zh.md @@ -16,7 +16,7 @@ 该服务需要 `ctx.sessions`,并动态观察可选的 `ctx.sessionPersistence`。一个串行化状态机比较来源限定的轻量持久化快照修订,仅以不修改日志的方式检查新日志或已更改日志,提取共享语义文档,以事务方式对账变更,然后运行查询。会话查询绝不会调用持久化后端会修复崩溃的 `load()`;检查期间接入的活动所有者无法修改其日志,稳定观察重试使结果优先使用实时来源。TEMP 实时行仍会记录持久化可用性,而持久基库会在该活动所有者脱离后刷新。重复查询以及同一存储未发生变化的重新打开操作不会执行完整持久化日志检查;切换存储,或观察到新增、已更改、已删除或经外部 load 修复的来源时,会在下次稳定观察时对账。来源或事务失败不会提交任何内容,下一次搜索会重试。 -`openAt: startup` 是默认值:服务激活会导入 `node:sqlite` 并打开句柄;如果索引无效,则会在服务发布前失败。`openAt: first-search` 会将服务以 ACTIVE 状态发布,同时不导入 SQLite 模块也不打开句柄;首批并发搜索共享同一个就绪 promise,在任何搜索前 dispose(资源释放)服务时也不会导入模块或打开句柄。此模式通过把 SQLite 的实验性警告推迟到首次实际搜索,支持需要干净 Node 22 启动输出的组合;它不会抑制届时的警告。无效数据库同样会使首次搜索失败,而不是服务激活失败。 +`openAt: startup` 是默认值:服务激活会导入 `node:sqlite` 并打开句柄;如果索引无效,则会在服务发布前失败。`openAt: first-search` 会将服务以 ACTIVE 状态发布,同时不导入 SQLite 模块也不打开句柄;首批并发搜索共享同一个就绪 promise,在任何搜索前 dispose(资源释放)服务时也不会导入模块或打开句柄。此模式通过把 SQLite 的实验性警告推迟到首次实际搜索,支持需要干净 Node 22 启动输出的组合;它不会抑制届时的警告。无效数据库同样会使首次搜索失败,而不是服务激活失败。`openAt: never` 为该部署关闭全文搜索:`searchSessions` 和 `searchEvents` 在任何请求规范化之前就以 `SESSION_QUERY_SEARCH_DISABLED` 失败,node:sqlite 绝不会被导入或打开,也不运行任何来源观察或对账,而 `ctx.sessionQuery` 上继承的全部精确读取、过滤和跟踪保持可用。 持久化 FTS 行位于专用派生数据库中。连接本地 TEMP 表保存实时行,这些行会遮蔽同一会话的持久化基库,并在实时所有者消失后使其重新可见。卸载持久化会隐藏持久行,但不会丢弃缓存;重新挂载会对账缓存。关闭或重新打开数据库会删除全部实时覆盖层,但保留持久行。 @@ -27,7 +27,7 @@ | 键 | 默认值 | 约定 | |---|---:|---| | `path` | 必填 | 专用派生索引 SQLite 路径;支持 `:memory:`。在 POSIX 文件系统上,缺失的文件系统路径会以仅所有者可访问的方式创建。 | -| `openAt` | `startup` | `startup` 会在服务激活完成前打开;`first-search` 把 SQLite 模块与句柄推迟到搜索时再加载和打开。 | +| `openAt` | `startup` | `startup` 会在服务激活完成前打开;`first-search` 把 SQLite 模块与句柄推迟到搜索时再加载和打开;`never` 关闭全文搜索(以类型化的 `SESSION_QUERY_SEARCH_DISABLED` 失败),继承的读取保持可用。 | | `journalMode` | `wal` | `wal`、`delete`、`truncate` 或 `persist`。 | | `defaultLimit` | `20` | 请求省略 `limit` 时的分页大小;最多为 `Number.MAX_SAFE_INTEGER - 1`。 | | `maxLimit` | `100` | 接受的最大请求分页大小;最多为 `Number.MAX_SAFE_INTEGER - 1`。 | diff --git a/packages/session-query/session-query-sqlite/package.json b/packages/session-query/session-query-sqlite/package.json index 42be5f5ef2..1644203ecd 100644 --- a/packages/session-query/session-query-sqlite/package.json +++ b/packages/session-query/session-query-sqlite/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", diff --git a/packages/session-query/session-query-sqlite/src/index.ts b/packages/session-query/session-query-sqlite/src/index.ts index eb2ceaee3a..1c4569df4c 100644 --- a/packages/session-query/session-query-sqlite/src/index.ts +++ b/packages/session-query/session-query-sqlite/src/index.ts @@ -82,8 +82,8 @@ export const SESSION_QUERY_SQLITE_SNIPPET_CHARS = 240 // One transient source change gets a retry; repeated churn fails rather than monopolizing the queue. const STABLE_OBSERVATION_ATTEMPTS = 2 -/** SQLite module/handle opening phase. */ -export type OpenAt = 'startup' | 'first-search' +/** SQLite module/handle opening phase; `never` disables full-text search entirely. */ +export type OpenAt = 'startup' | 'first-search' | 'never' /** Combined session-query configuration backed by SQLite full-text search. */ export interface Config extends SessionQueryConfig { @@ -93,7 +93,13 @@ export interface Config extends SessionQueryConfig { * POSIX filesystems; existing modes are preserved. */ path: string - /** Open the SQLite module and handle at service activation or the first search. Defaults to `startup`. */ + /** + * Open the SQLite module and handle at service activation or the first + * search, or `never` to disable full-text search: the inherited exact + * reads, filters, and traces stay available, while `searchSessions` and + * `searchEvents` fail with `SESSION_QUERY_SEARCH_DISABLED` and SQLite is + * never imported or opened. Defaults to `startup`. + */ openAt?: OpenAt /** SQLite journal mode. Defaults to `wal`. */ journalMode?: JournalMode @@ -192,7 +198,7 @@ export class SqliteSessionQueryEngine extends SessionQueryEngine { static Config: z = z.object({ path: z.string().required(), - openAt: z.union(['startup', 'first-search'] as const).default('startup'), + openAt: z.union(['startup', 'first-search', 'never'] as const).default('startup'), journalMode: z.union(['wal', 'delete', 'truncate', 'persist'] as const).default('wal'), defaultLimit: z.number().step(1).min(1).max(SQLITE_MAX_PAGE_LIMIT).default(SESSION_QUERY_SQLITE_DEFAULT_LIMIT), maxLimit: z.number().step(1).min(1).max(SQLITE_MAX_PAGE_LIMIT).default(SESSION_QUERY_SQLITE_MAX_LIMIT), @@ -251,6 +257,7 @@ export class SqliteSessionQueryEngine extends SessionQueryEngine { request: SessionSearchRequest, exec?: SessionSearchExecContext, ): Promise> { + this._assertSearchEnabled() const normalized = normalizeSessionRequest(request, this.config) const signal = exec?.signal return this._serialized(signal, async () => { @@ -278,6 +285,7 @@ export class SqliteSessionQueryEngine extends SessionQueryEngine { request: SessionEventSearchRequest, exec?: SessionSearchExecContext, ): Promise { + this._assertSearchEnabled() const normalized = normalizeEventRequest(request, this.config) const signal = exec?.signal return this._serialized(signal, async () => { @@ -310,6 +318,19 @@ export class SqliteSessionQueryEngine extends SessionQueryEngine { return this._closePromise } + /** + * Refuse full-text calls under `openAt: 'never'` before any request + * normalization or SQLite work, so a disabled deployment never imports + * node:sqlite, opens the index, or observes sources. + */ + private _assertSearchEnabled(): void { + if (this.config.openAt !== 'never') return + throw new SessionQueryError( + 'session search is disabled: this deployment configures the session-query index with openAt "never"', + 'SESSION_QUERY_SEARCH_DISABLED', + ) + } + private async _close(): Promise { this._closed = true await this._tail @@ -991,7 +1012,7 @@ function resolveConfig(config: Config): ResolvedConfig { if (typeof resolved.path !== 'string' || resolved.path.trim().length === 0) { throw invalidConfig('path must not be blank') } - const openPhases: readonly string[] = ['startup', 'first-search'] + const openPhases: readonly string[] = ['startup', 'first-search', 'never'] if (!openPhases.includes(resolved.openAt)) throw invalidConfig('openAt is not supported') assertPageLimit('defaultLimit', resolved.defaultLimit) assertPageLimit('maxLimit', resolved.maxLimit) diff --git a/packages/session-query/session-query-sqlite/tests/sqlite.spec.ts b/packages/session-query/session-query-sqlite/tests/sqlite.spec.ts index dc791758f0..0a565fe021 100644 --- a/packages/session-query/session-query-sqlite/tests/sqlite.spec.ts +++ b/packages/session-query/session-query-sqlite/tests/sqlite.spec.ts @@ -231,6 +231,36 @@ describe('SQLite session search', () => { await expect(stat(path)).rejects.toMatchObject({ code: 'ENOENT' }) }) + it('refuses search in never mode while inherited reads and traces keep working', async () => { + const path = await temporaryPath('never-mode.db') + const ctx = new Context() + await ctx.plugin(SessionStore) + const search = await ctx.plugin(SqliteSessionQueryEngine, { path, openAt: 'never' }) + const service = ctx.sessionQuery as SqliteSessionQueryEngine + expect(service.config.openAt).toBe('never') + + const parent = SessionId('never-parent') + const child = SessionId('never-child') + ctx.sessions.create(parent, { seed: messageEvents('never opened needle'), meta: { createdAt: 10 } }) + ctx.sessions.create(child, { meta: { parentSession: parent, createdAt: 20 } }) + + await expect(service.searchSessions({ query: 'needle' })) + .rejects.toThrow(expectCode('SESSION_QUERY_SEARCH_DISABLED')) + await expect(service.searchEvents({ sessionId: parent, query: 'needle' })) + .rejects.toThrow(expectCode('SESSION_QUERY_SEARCH_DISABLED')) + + expect((await service.listSessions()).map(record => record.header.id).sort()) + .toEqual([child, parent]) + const lineage = await service.traceSession(parent) + expect(lineage.complete).toBe(true) + expect(lineage.descendants.map(node => node.session.header.id)).toEqual([child]) + + // The disabled index never touches the filesystem, in mount, use, or disposal. + await expect(stat(path)).rejects.toMatchObject({ code: 'ENOENT' }) + await search.dispose() + await expect(stat(path)).rejects.toMatchObject({ code: 'ENOENT' }) + }) + it('opens once on the first search and reuses readiness for later searches', async () => { const ctx = new Context() await ctx.plugin(SessionStore) diff --git a/packages/session-query/session-query/package.json b/packages/session-query/session-query/package.json index 2616a0f9b8..ce88a9665b 100644 --- a/packages/session-query/session-query/package.json +++ b/packages/session-query/session-query/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/session-query/session-query/src/config.ts b/packages/session-query/session-query/src/config.ts index a449799193..99039bcbfa 100644 --- a/packages/session-query/session-query/src/config.ts +++ b/packages/session-query/session-query/src/config.ts @@ -31,6 +31,7 @@ export type SessionQueryErrorCode = | 'SESSION_QUERY_INVALID_SURFACE' | 'SESSION_QUERY_INVALID_WINDOW' | 'SESSION_QUERY_PERSISTENCE_FAILED' + | 'SESSION_QUERY_SEARCH_DISABLED' | 'SESSION_QUERY_SESSION_NOT_FOUND' | 'SESSION_QUERY_STALE_CURSOR' | 'SESSION_QUERY_SOURCE_CONFLICT' diff --git a/packages/session-query/tool-session-query/package.json b/packages/session-query/tool-session-query/package.json index 0a8d06177f..58bd6ee7ef 100644 --- a/packages/session-query/tool-session-query/package.json +++ b/packages/session-query/tool-session-query/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/session-query/tool-session-query/src/service-boundary.ts b/packages/session-query/tool-session-query/src/service-boundary.ts index 9fbfc0c55c..98bc8e8dc9 100644 --- a/packages/session-query/tool-session-query/src/service-boundary.ts +++ b/packages/session-query/tool-session-query/src/service-boundary.ts @@ -71,6 +71,10 @@ const SAFE_SESSION_QUERY_FAILURES = { code: 'SESSION_QUERY_PERSISTENCE_FAILED', message: 'session history storage is unavailable', }, + SESSION_QUERY_SEARCH_DISABLED: { + code: 'SESSION_QUERY_SEARCH_DISABLED', + message: 'session search is disabled in this deployment', + }, SESSION_QUERY_SESSION_NOT_FOUND: { code: 'SESSION_QUERY_SESSION_NOT_FOUND', message: 'session was not found', diff --git a/packages/session/session-checkpoint-policy/package.json b/packages/session/session-checkpoint-policy/package.json index 9db44dff5b..a2b275ed29 100644 --- a/packages/session/session-checkpoint-policy/package.json +++ b/packages/session/session-checkpoint-policy/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/session/session-persistence-jsonl/package.json b/packages/session/session-persistence-jsonl/package.json index 75f22345f7..cd48bbae0b 100644 --- a/packages/session/session-persistence-jsonl/package.json +++ b/packages/session/session-persistence-jsonl/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", diff --git a/packages/session/session-persistence-sqlite/package.json b/packages/session/session-persistence-sqlite/package.json index 5b42515f05..f824b9b3a8 100644 --- a/packages/session/session-persistence-sqlite/package.json +++ b/packages/session/session-persistence-sqlite/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", diff --git a/packages/session/session-persistence/package.json b/packages/session/session-persistence/package.json index 4c65040655..f42b496e6d 100644 --- a/packages/session/session-persistence/package.json +++ b/packages/session/session-persistence/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/session/session-projection-cache/package.json b/packages/session/session-projection-cache/package.json index 013280a282..1697967808 100644 --- a/packages/session/session-projection-cache/package.json +++ b/packages/session/session-projection-cache/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "workspace:^", "zod": "^4.4.3" diff --git a/packages/session/session-projection/package.json b/packages/session/session-projection/package.json index 29b6c49afc..cdf61ac3a3 100644 --- a/packages/session/session-projection/package.json +++ b/packages/session/session-projection/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "zod": "^4.4.3" }, diff --git a/packages/session/session-stats/package.json b/packages/session/session-stats/package.json index 7e76fa403c..c7006a5061 100644 --- a/packages/session/session-stats/package.json +++ b/packages/session/session-stats/package.json @@ -39,7 +39,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/session/session-telemetry-otel/package.json b/packages/session/session-telemetry-otel/package.json index 85a7cba650..37b5893cce 100644 --- a/packages/session/session-telemetry-otel/package.json +++ b/packages/session/session-telemetry-otel/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@opentelemetry/api": "^1.9.1", "@opentelemetry/api-logs": "^0.220.0", diff --git a/packages/session/session-telemetry/package.json b/packages/session/session-telemetry/package.json index a66d459edd..132545f502 100644 --- a/packages/session/session-telemetry/package.json +++ b/packages/session/session-telemetry/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/session/session-title-all-prompts-llm/package.json b/packages/session/session-title-all-prompts-llm/package.json index 77d566e143..c165327beb 100644 --- a/packages/session/session-title-all-prompts-llm/package.json +++ b/packages/session/session-title-all-prompts-llm/package.json @@ -25,7 +25,7 @@ "./package.json": "./package.json" }, "files": ["lib/index.js", "lib/invariant.js", "lib/types/**/*.d.ts"], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/session/session-title-first-prompt-llm/package.json b/packages/session/session-title-first-prompt-llm/package.json index e1e02f1319..0e53d07e7f 100644 --- a/packages/session/session-title-first-prompt-llm/package.json +++ b/packages/session/session-title-first-prompt-llm/package.json @@ -25,7 +25,7 @@ "./package.json": "./package.json" }, "files": ["lib/index.js", "lib/invariant.js", "lib/types/**/*.d.ts"], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/session/session-title-llm/package.json b/packages/session/session-title-llm/package.json index e4450f893f..10d63c1d89 100644 --- a/packages/session/session-title-llm/package.json +++ b/packages/session/session-title-llm/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/session/session-title/package.json b/packages/session/session-title/package.json index 38251d295e..8a014863fe 100644 --- a/packages/session/session-title/package.json +++ b/packages/session/session-title/package.json @@ -39,7 +39,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/settings/settings-file/package.json b/packages/settings/settings-file/package.json index b1f7ee6c48..0cdbdbef35 100644 --- a/packages/settings/settings-file/package.json +++ b/packages/settings/settings-file/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-atomic-write": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/settings/settings/package.json b/packages/settings/settings/package.json index 838f1795cf..4208b479d4 100644 --- a/packages/settings/settings/package.json +++ b/packages/settings/settings/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/shell/bash-local/package.json b/packages/shell/bash-local/package.json index db37056045..db1c919311 100644 --- a/packages/shell/bash-local/package.json +++ b/packages/shell/bash-local/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/shell/bash-sandbox/package.json b/packages/shell/bash-sandbox/package.json index dcc81057e4..ac0c510be3 100644 --- a/packages/shell/bash-sandbox/package.json +++ b/packages/shell/bash-sandbox/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-bash-local": "workspace:^", diff --git a/packages/shell/pwsh-local/package.json b/packages/shell/pwsh-local/package.json index 48deb6f5c0..f6882f5c3e 100644 --- a/packages/shell/pwsh-local/package.json +++ b/packages/shell/pwsh-local/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/shell/pwsh-sandbox/package.json b/packages/shell/pwsh-sandbox/package.json index 35ca00e95d..74f1c5b3c1 100644 --- a/packages/shell/pwsh-sandbox/package.json +++ b/packages/shell/pwsh-sandbox/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/shell/shell-env/package.json b/packages/shell/shell-env/package.json index f1c0f493d0..f5ef9d869a 100644 --- a/packages/shell/shell-env/package.json +++ b/packages/shell/shell-env/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/shell/shell/package.json b/packages/shell/shell/package.json index 77cc920f9b..ab8a31dd7d 100644 --- a/packages/shell/shell/package.json +++ b/packages/shell/shell/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", diff --git a/packages/shell/tool-bash-persistent/package.json b/packages/shell/tool-bash-persistent/package.json index 0f66e0f6a3..14648a2231 100644 --- a/packages/shell/tool-bash-persistent/package.json +++ b/packages/shell/tool-bash-persistent/package.json @@ -29,7 +29,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/shell/tool-bash/package.json b/packages/shell/tool-bash/package.json index 8442431acf..e762320465 100644 --- a/packages/shell/tool-bash/package.json +++ b/packages/shell/tool-bash/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-shell": "workspace:^", diff --git a/packages/shell/tool-pwsh/package.json b/packages/shell/tool-pwsh/package.json index 6b8fd62535..195940e82b 100644 --- a/packages/shell/tool-pwsh/package.json +++ b/packages/shell/tool-pwsh/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-shell": "workspace:^", diff --git a/packages/skill/skill-badge/package.json b/packages/skill/skill-badge/package.json index efa5bc89cd..d012804e96 100644 --- a/packages/skill/skill-badge/package.json +++ b/packages/skill/skill-badge/package.json @@ -30,7 +30,7 @@ "assets", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-skill": "workspace:^", diff --git a/packages/skill/skill-filesystem/package.json b/packages/skill/skill-filesystem/package.json index 75d33ee2c0..954a843c2b 100644 --- a/packages/skill/skill-filesystem/package.json +++ b/packages/skill/skill-filesystem/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/skill/skill/package.json b/packages/skill/skill/package.json index b75f15d76f..4688a93064 100644 --- a/packages/skill/skill/package.json +++ b/packages/skill/skill/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/skill/tool-skill/package.json b/packages/skill/tool-skill/package.json index fd6474dbc1..19b10f8bb6 100644 --- a/packages/skill/tool-skill/package.json +++ b/packages/skill/tool-skill/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/spill/spill-local/package.json b/packages/spill/spill-local/package.json index 73442355de..07c2134591 100644 --- a/packages/spill/spill-local/package.json +++ b/packages/spill/spill-local/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-spill": "workspace:^", diff --git a/packages/spill/spill-policy/package.json b/packages/spill/spill-policy/package.json index f945700067..f74a5c4135 100644 --- a/packages/spill/spill-policy/package.json +++ b/packages/spill/spill-policy/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/spill/spill/package.json b/packages/spill/spill/package.json index e056612939..3d0f444b1d 100644 --- a/packages/spill/spill/package.json +++ b/packages/spill/spill/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/storage/storage-domain/package.json b/packages/storage/storage-domain/package.json index 53c445f24f..aa8983a712 100644 --- a/packages/storage/storage-domain/package.json +++ b/packages/storage/storage-domain/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-storage": "workspace:^", diff --git a/packages/storage/storage-json/package.json b/packages/storage/storage-json/package.json index efeff3d0a2..5c04e79096 100644 --- a/packages/storage/storage-json/package.json +++ b/packages/storage/storage-json/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-storage": "workspace:^", diff --git a/packages/storage/storage-sqlite/package.json b/packages/storage/storage-sqlite/package.json index d645336b65..88d5958419 100644 --- a/packages/storage/storage-sqlite/package.json +++ b/packages/storage/storage-sqlite/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-storage": "workspace:^", diff --git a/packages/storage/storage/package.json b/packages/storage/storage/package.json index 39be8894fe..f4f39039b0 100644 --- a/packages/storage/storage/package.json +++ b/packages/storage/storage/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/subagent/subagent-acp/package.json b/packages/subagent/subagent-acp/package.json index 2bab91c006..72f725f040 100644 --- a/packages/subagent/subagent-acp/package.json +++ b/packages/subagent/subagent-acp/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/subagent/subagent-claude-code/package.json b/packages/subagent/subagent-claude-code/package.json index 90a6d1734b..ec5da9e8ac 100644 --- a/packages/subagent/subagent-claude-code/package.json +++ b/packages/subagent/subagent-claude-code/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/subagent/subagent-codex/package.json b/packages/subagent/subagent-codex/package.json index 450fd0319e..269bf2e996 100644 --- a/packages/subagent/subagent-codex/package.json +++ b/packages/subagent/subagent-codex/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/subagent/subagent-dsh-sdk/package.json b/packages/subagent/subagent-dsh-sdk/package.json index 64d76226b8..f7eac52a8e 100644 --- a/packages/subagent/subagent-dsh-sdk/package.json +++ b/packages/subagent/subagent-dsh-sdk/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/subagent/subagent-fork-in-process/package.json b/packages/subagent/subagent-fork-in-process/package.json index a4f5070728..5ccbe0e465 100644 --- a/packages/subagent/subagent-fork-in-process/package.json +++ b/packages/subagent/subagent-fork-in-process/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/subagent/subagent-in-process-driver/package.json b/packages/subagent/subagent-in-process-driver/package.json index 47fa41e924..f3398a76e7 100644 --- a/packages/subagent/subagent-in-process-driver/package.json +++ b/packages/subagent/subagent-in-process-driver/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/subagent/subagent-spawn-in-process/package.json b/packages/subagent/subagent-spawn-in-process/package.json index 45ae2cbb68..8c2c71c9c9 100644 --- a/packages/subagent/subagent-spawn-in-process/package.json +++ b/packages/subagent/subagent-spawn-in-process/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", diff --git a/packages/subagent/subagent/package.json b/packages/subagent/subagent/package.json index 1c0d5175cc..87ec069782 100644 --- a/packages/subagent/subagent/package.json +++ b/packages/subagent/subagent/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "zod": "^4.4.3" }, diff --git a/packages/subagent/tool-subagent-control/package.json b/packages/subagent/tool-subagent-control/package.json index e46cd25dce..6be2ae1d26 100644 --- a/packages/subagent/tool-subagent-control/package.json +++ b/packages/subagent/tool-subagent-control/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/subagent/tool-subagent-report/package.json b/packages/subagent/tool-subagent-report/package.json index 81db20b020..b3c8083f8c 100644 --- a/packages/subagent/tool-subagent-report/package.json +++ b/packages/subagent/tool-subagent-report/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/subagent/tool-subagent/package.json b/packages/subagent/tool-subagent/package.json index a9443b4340..b1a73d0e8c 100644 --- a/packages/subagent/tool-subagent/package.json +++ b/packages/subagent/tool-subagent/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/subprocess/subprocess-local/package.json b/packages/subprocess/subprocess-local/package.json index a45c23b3a2..7581f54183 100644 --- a/packages/subprocess/subprocess-local/package.json +++ b/packages/subprocess/subprocess-local/package.json @@ -34,7 +34,7 @@ "scripts": { "postinstall": "node scripts/ensure-spawn-helper.mjs" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", diff --git a/packages/subprocess/subprocess/package.json b/packages/subprocess/subprocess/package.json index 31060039ac..5d2d4fa09d 100644 --- a/packages/subprocess/subprocess/package.json +++ b/packages/subprocess/subprocess/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/terminal/terminal-bash/package.json b/packages/terminal/terminal-bash/package.json index 3ffe485d63..cad0c60fba 100644 --- a/packages/terminal/terminal-bash/package.json +++ b/packages/terminal/terminal-bash/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/terminal/terminal/package.json b/packages/terminal/terminal/package.json index 8feb02e555..f0dc5e84c7 100644 --- a/packages/terminal/terminal/package.json +++ b/packages/terminal/terminal/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", diff --git a/packages/terminal/tool-terminal/package.json b/packages/terminal/tool-terminal/package.json index 77a719a6c7..6eebf5d33e 100644 --- a/packages/terminal/tool-terminal/package.json +++ b/packages/terminal/tool-terminal/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "workspace:^" }, diff --git a/packages/test-support/acp-snapshot/package.json b/packages/test-support/acp-snapshot/package.json index d8527bec98..a0a3697896 100644 --- a/packages/test-support/acp-snapshot/package.json +++ b/packages/test-support/acp-snapshot/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@agentclientprotocol/sdk": "0.25.1", "@deepseek-ai/dsh-loader-smoke": "workspace:*", diff --git a/packages/test-support/agent-loop-testkit/package.json b/packages/test-support/agent-loop-testkit/package.json index b672a5e141..4e0bb8aa9c 100644 --- a/packages/test-support/agent-loop-testkit/package.json +++ b/packages/test-support/agent-loop-testkit/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/test-support/client-runtime/package.json b/packages/test-support/client-runtime/package.json index fc8a15c12d..9a6fb3a7a0 100644 --- a/packages/test-support/client-runtime/package.json +++ b/packages/test-support/client-runtime/package.json @@ -25,7 +25,7 @@ "./src/*": "./src/*", "./package.json": "./package.json" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@testing-library/dom": "^10.4.1", "@testing-library/react": "^16.3.2", diff --git a/packages/test-support/llm-mock-server/package.json b/packages/test-support/llm-mock-server/package.json index a833b1bc75..2555c27275 100644 --- a/packages/test-support/llm-mock-server/package.json +++ b/packages/test-support/llm-mock-server/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/test-support/llm-replay/package.json b/packages/test-support/llm-replay/package.json index 0980ff39a6..3d5d70010b 100644 --- a/packages/test-support/llm-replay/package.json +++ b/packages/test-support/llm-replay/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-compaction": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/test-support/loader-smoke/package.json b/packages/test-support/loader-smoke/package.json index a7d74c3d87..20e6c1a6d8 100644 --- a/packages/test-support/loader-smoke/package.json +++ b/packages/test-support/loader-smoke/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "execa": "^10.0.0", "tsx": "^4.22.4" diff --git a/packages/todo/tool-todo/package.json b/packages/todo/tool-todo/package.json index 7ba38ec00d..c14ac4358b 100644 --- a/packages/todo/tool-todo/package.json +++ b/packages/todo/tool-todo/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "workspace:^", "zod": "^4.4.3" diff --git a/packages/typert/generator/package.json b/packages/typert/generator/package.json index 798280a11c..39136c2877 100644 --- a/packages/typert/generator/package.json +++ b/packages/typert/generator/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.13", "typescript": "^6.0.3" diff --git a/packages/typert/loader/package.json b/packages/typert/loader/package.json index 59b0e64dfb..20a7172175 100644 --- a/packages/typert/loader/package.json +++ b/packages/typert/loader/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/typert/protocol/package.json b/packages/typert/protocol/package.json index a125e47088..7b5c6b4d91 100644 --- a/packages/typert/protocol/package.json +++ b/packages/typert/protocol/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/typert/registry/package.json b/packages/typert/registry/package.json index 707020b148..7c34532970 100644 --- a/packages/typert/registry/package.json +++ b/packages/typert/registry/package.json @@ -51,7 +51,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/dsh-typert-protocol": "workspace:^", "zod": "^4.4.3" diff --git a/packages/util/atomic-write/package.json b/packages/util/atomic-write/package.json index f0cfaddd82..964fcba265 100644 --- a/packages/util/atomic-write/package.json +++ b/packages/util/atomic-write/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/util/brand/package.json b/packages/util/brand/package.json index cd1de2a0e9..63a9bd0ac8 100644 --- a/packages/util/brand/package.json +++ b/packages/util/brand/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/util/home-paths/package.json b/packages/util/home-paths/package.json index 1480cdad81..3bd0db8091 100644 --- a/packages/util/home-paths/package.json +++ b/packages/util/home-paths/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/util/launch-environment/package.json b/packages/util/launch-environment/package.json index 5c6c392673..eeea9a70ee 100644 --- a/packages/util/launch-environment/package.json +++ b/packages/util/launch-environment/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/util/native-command/package.json b/packages/util/native-command/package.json index 5dcf7c7627..36547ffee9 100644 --- a/packages/util/native-command/package.json +++ b/packages/util/native-command/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/util/output-retention/package.json b/packages/util/output-retention/package.json index ee603c1c0f..cdd47c905c 100644 --- a/packages/util/output-retention/package.json +++ b/packages/util/output-retention/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/util/timeout/package.json b/packages/util/timeout/package.json index e447103f62..cbe16cfcaf 100644 --- a/packages/util/timeout/package.json +++ b/packages/util/timeout/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/cordis": "workspace:^" diff --git a/packages/web/tool-web/package.json b/packages/web/tool-web/package.json index b2d5b3449f..ecc7717b2b 100644 --- a/packages/web/tool-web/package.json +++ b/packages/web/tool-web/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/web/web-fetch-http/package.json b/packages/web/web-fetch-http/package.json index ed50476aed..0089033964 100644 --- a/packages/web/web-fetch-http/package.json +++ b/packages/web/web-fetch-http/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", diff --git a/packages/web/web-search-deepseek/package.json b/packages/web/web-search-deepseek/package.json index 82326a7900..55bd7ecdf2 100644 --- a/packages/web/web-search-deepseek/package.json +++ b/packages/web/web-search-deepseek/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-credentials": "workspace:^", diff --git a/packages/web/web-search-exa/package.json b/packages/web/web-search-exa/package.json index 4beac7501a..ae0aa563cf 100644 --- a/packages/web/web-search-exa/package.json +++ b/packages/web/web-search-exa/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-launch-environment": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/web/web-search-perplexity/package.json b/packages/web/web-search-perplexity/package.json index 922da3a951..7f4aa73079 100644 --- a/packages/web/web-search-perplexity/package.json +++ b/packages/web/web-search-perplexity/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-launch-environment": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/web/web/package.json b/packages/web/web/package.json index 4bf230b7a4..16db0b092c 100644 --- a/packages/web/web/package.json +++ b/packages/web/web/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/workflow/tool-ralph/package.json b/packages/workflow/tool-ralph/package.json index 081bfae0ed..ca7b5f4889 100644 --- a/packages/workflow/tool-ralph/package.json +++ b/packages/workflow/tool-ralph/package.json @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/workflow/tool-workflow/package.json b/packages/workflow/tool-workflow/package.json index f40b8d25bb..6abde88c22 100644 --- a/packages/workflow/tool-workflow/package.json +++ b/packages/workflow/tool-workflow/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/workflow/workflow-worker-thread/package.json b/packages/workflow/workflow-worker-thread/package.json index 6c54083821..4f32c42493 100644 --- a/packages/workflow/workflow-worker-thread/package.json +++ b/packages/workflow/workflow-worker-thread/package.json @@ -35,7 +35,7 @@ "lib/worker.cjs", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", diff --git a/packages/workflow/workflow/package.json b/packages/workflow/workflow/package.json index e0e5f77e7e..1b689da55a 100644 --- a/packages/workflow/workflow/package.json +++ b/packages/workflow/workflow/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", diff --git a/packages/workspace/workspace/package.json b/packages/workspace/workspace/package.json index ef456e859d..abcd7bc903 100644 --- a/packages/workspace/workspace/package.json +++ b/packages/workspace/workspace/package.json @@ -35,7 +35,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-storage-domain": "workspace:^", diff --git a/python/sdk-runtime/pyproject.toml b/python/sdk-runtime/pyproject.toml index 9481d33889..090efc6139 100644 --- a/python/sdk-runtime/pyproject.toml +++ b/python/sdk-runtime/pyproject.toml @@ -8,7 +8,7 @@ version = "0.0.0.dev0" description = "Pinned DeepSeek Harness runtime for the Python SDK" readme = "README.md" requires-python = ">=3.10" -license = "BSD-3-Clause" +license = "MIT" authors = [{ name = "DeepSeek" }] [project.urls] diff --git a/python/sdk/README.i18n.yaml b/python/sdk/README.i18n.yaml index 74be3fa3a3..23ae780335 100644 --- a/python/sdk/README.i18n.yaml +++ b/python/sdk/README.i18n.yaml @@ -3,4 +3,4 @@ # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write python/sdk/README.md README.md: 9de0791f1394640ccdf757ecc170a9e803d49969 -README.zh.md: d3300ddd0ae1805fb2abb4001108eee20dd60484 +README.zh.md: c1c0c673216eb0170546d488bd18bc743639ad0b diff --git a/python/sdk/README.zh.md b/python/sdk/README.zh.md index d3300ddd0a..c1c0c67321 100644 --- a/python/sdk/README.zh.md +++ b/python/sdk/README.zh.md @@ -19,9 +19,9 @@ with DeepSeekHarness() as harness: result = harness.run("Say hi.") ``` -`DeepSeekHarness` 会保留延迟启动的运行时子进程,以供多次调用复用。请像上例一样将其用作上下文管理器,或在用完后显式调用 `close()`。 +`DeepSeekHarness` 会保留其按需启动的运行时子进程,以便在多次调用之间复用。请像上例一样将其用作上下文管理器,或在使用完毕后显式调用 `close()`。 -默认情况下,SDK 启动 `deepseek-harness-runtime-bin` 包内置的单文件 `dsh-jsonrpc-agent` 可执行程序,并通过 `DSH_CORDIS_CONFIG` 注入该包的默认配置(stdio JSON-RPC 服务器、`agent-core`、预载的 DeepSeek 适配器、配有显式组合语义检查点策略的 JSONL 会话持久化、本地 bash)。要运行自己的插件组合,请在配置里保留 `@deepseek-ai/dsh-sdk-jsonrpc-server` 条目,并传入 Cordis 配置路径。 +默认情况下,SDK 会启动 `deepseek-harness-runtime-bin` 包内置的单文件可执行程序 `dsh-jsonrpc-agent`,并通过 `DSH_CORDIS_CONFIG` 注入该包的默认配置,其中包括 stdio JSON-RPC 服务器、agent core(智能体核心)、预载的 DeepSeek 适配器、采用显式组合语义检查点策略的 JSONL 会话持久化,以及本地 bash。要运行自己的插件组合,请在配置中保留 `@deepseek-ai/dsh-sdk-jsonrpc-server` 配置项,并传入 Cordis 配置文件路径。 ```py from deepseek_harness import DeepSeekHarness @@ -35,14 +35,14 @@ with DeepSeekHarness( result = harness.run("Make the requested code change.") ``` -`provider` 用于选择当前 Cordis 组合已注册的提供方路由;`model` 是该适配器解析的模型 ID。`max_tokens` 是可选的正整数,用于限制根 agent(智能体)及其进程内后代每次请求的输出 token;省略时由提供方默认值控制。压缩摘要继续使用压缩插件单独配置的上限。内置默认组合注册 `deepseek-official`。自定义组合可以挂载 `llm-pi-ai`,在其中配置各提供方的凭据与端点,再选择 pi-ai 已安装目录中的任意提供方/模型组合。 +`provider` 选择指定 Cordis 组合所注册的提供方路由;`model` 是该适配器解析出的模型 ID。`max_tokens` 是一个可选的正整数,用于限制根 agent 及其进程内后代在每次请求中输出的 token 数量;省略该参数时,由提供方的默认行为决定输出上限。压缩摘要继续使用压缩插件单独配置的上限。内置默认组合注册 `deepseek-official`。自定义组合可以挂载 `llm-pi-ai`,在其中配置各提供方专属的凭据和端点,并选择 pi-ai 已安装 catalog 中存在的任意提供方/模型组合。 -[Python SDK 教程](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/guide/python-sdk.md)提供不使用 Web UI 的顺序安装与首次运行路径。[`jsonrpc-agent` 示例](https://github.com/deepseek-ai/deepseek-harness/blob/master/examples/jsonrpc-agent/README.md)归属该教程使用的完整独立 Cordis 文件。 +[Python SDK 教程](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/guide/python-sdk.md)提供一套无需使用 Web UI、按步骤完成安装和首次运行的流程。该教程所用的完整独立 Cordis 配置文件位于 [`jsonrpc-agent` 示例](https://github.com/deepseek-ai/deepseek-harness/blob/master/examples/jsonrpc-agent/README.md)中。 -`Session.run()` 拥有一个从提示词进入持久 inbox 时开始、到整个 agent 下一次进入空闲状态为止的活动区间,并返回 `RunResult(session_id, final_response, finish_reason, events, notifications, session_root)`。`final_response` 是该区间内根会话最后提交的助手文本。`finish_reason` 是该区间内根会话最后一个 `turn/end` 的 `kind`,例如 `completed`、`max-tokens` 或 `error`;没有轮次结束时为 `None`。缺少字符串 `data.reason.kind` 的 `turn/end` 违反运行时协议,并会抛出 `SdkProtocolError`。两个结果字段描述的都是自有活动区间,而不是因果上归属于该提示词的输出或结束原因。steering(中途引导)、注入的上下文和其他排队工作都可能在进入空闲状态前参与其中。 +`Session.run()` 的活动区间从其提示词被持久 inbox 接收时开始,到整个 agent 下一次进入空闲状态时结束,并返回 `RunResult(session_id, final_response, finish_reason, events, notifications, session_root)`。`final_response` 是该区间内根会话最后提交的助手文本。`finish_reason` 是该区间内根会话最后一个 `turn/end` 的 `kind`,例如 `completed`、`max-tokens` 或 `error`;没有轮次结束时为 `None`。缺少字符串 `data.reason.kind` 的 `turn/end` 违反运行时协议,并会抛出 `SdkProtocolError`。这两个结果字段描述的是 `Session.run()` 所界定的活动区间,并不表示某项输出或结束原因在因果上归属于该提示词。steering(中途引导)、注入的上下文和其他排队工作,也可能在 agent 进入空闲状态前参与这段活动。 -`HarnessClient` 会在运行时进程的生命周期内保留已发现的 subagent(子 agent)祖先关系。每次执行 `Session.run()` 时,`RunResult.notifications` 与 `on_notification` 会按协议传输顺序收到根会话及所有已知后代的通知,其中包括嵌套 subagent 的生命周期事件与会话事件。`RunResult.events` 只包含根会话事件,因此后代消息不会覆盖根会话回复。底层 `session_prompt()` 会立即返回已排队消息的 `MessageId`;绕过 `Session.run()` 的调用方必须自行负责后续的活动边界。 +`HarnessClient` 会在运行时进程的整个生命周期内保留已发现的 subagent 谱系。每次执行 `Session.run()` 时,`RunResult.notifications` 与 `on_notification` 会按协议传输顺序收到根会话及所有已知后代的通知,其中包括嵌套 subagent 的生命周期事件与会话事件。`RunResult.events` 只包含根会话事件,因此后代消息不会覆盖根会话回复。底层 `session_prompt()` 会立即返回已排队消息的 `MessageId`;绕过 `Session.run()` 的调用方必须自行负责后续的活动边界。 -同样的行为也可以通过 `DSH_CORDIS_CONFIG` 为运行时子进程选定。注入逻辑位于 `HarnessClient.start()`,因此底层客户端的默认启动也具有此行为:当启动解析到内置运行时,且 `cordis` 与非空的 `DSH_CORDIS_CONFIG` 均未设置时(运行时把空值视为缺省,注入检查与之一致),使用内置的默认配置;显式给出 `runtime_bin`、`bridge_bin` 或 `launch_args_override` 则完全禁用注入。运行时载体(生产用 exe 与仅限开发的 `node` 闭包)及其获取方式见 [sdk-runtime README](https://github.com/deepseek-ai/deepseek-harness/blob/master/python/sdk-runtime/README.md)。 +也可以通过 `DSH_CORDIS_CONFIG` 为运行时子进程指定配置。注入逻辑位于 `HarnessClient.start()`,因此底层客户端按默认方式启动时也具有该行为:如果启动方式最终解析为内置运行时,且既没有设置 `cordis`,也没有设置非空的 `DSH_CORDIS_CONFIG`(运行时将空值视为未设置,注入检查也是如此),系统就会使用内置默认配置;显式指定 `runtime_bin`、`bridge_bin` 或 `launch_args_override` 时,则会完全禁用该注入。运行时载体(生产用 exe 与仅限开发的 `node` 闭包)及其获取方式见 [sdk-runtime README](https://github.com/deepseek-ai/deepseek-harness/blob/master/python/sdk-runtime/README.md)。 -`cwd` 与 `runtime_cwd` 会在启动子进程、注入环境变量和协议握手前解析为绝对路径。公开 API 只暴露真正生效的选项:部署的角色设定与持久化配置归 `cordis.yml` 管理,而 `session_root` 继续作为设置 `DSH_SESSION_ROOT` 的高层便捷选项。 +`cwd` 与 `runtime_cwd` 会在启动子进程、注入环境变量和协议握手前解析为绝对路径。公开 API 只暴露由 SDK 直接应用的选项:部署 persona 和持久化配置应在 `cordis.yml` 中定义;`session_root` 则保留为设置 `DSH_SESSION_ROOT` 的高层便捷参数。 diff --git a/python/sdk/pyproject.toml b/python/sdk/pyproject.toml index 246e44ee26..5e91546e73 100644 --- a/python/sdk/pyproject.toml +++ b/python/sdk/pyproject.toml @@ -8,7 +8,7 @@ version = "0.0.0.dev0" description = "Python SDK for DeepSeek Harness" readme = "README.md" requires-python = ">=3.10" -license = "BSD-3-Clause" +license = "MIT" authors = [{ name = "DeepSeek" }] dependencies = [ "pydantic>=2.12,<3", diff --git a/python/sdk/tests/test_release_version.py b/python/sdk/tests/test_release_version.py index 3bff2df3f9..7ff9b15d59 100644 --- a/python/sdk/tests/test_release_version.py +++ b/python/sdk/tests/test_release_version.py @@ -77,6 +77,7 @@ def test_stage_sdk_keeps_distribution_module_and_runtime_pin_distinct(tmp_path: pyproject = (destination / "pyproject.toml").read_text() assert 'name = "deepseek-harness-sdk"' in pyproject assert 'version = "1.2.3"' in pyproject + assert 'license = "MIT"' in pyproject assert '"deepseek-harness-runtime-bin==1.2.3"' in pyproject assert 'license-files = ["LICENSE"]' in pyproject assert (destination / "LICENSE").read_bytes() == (ROOT / "LICENSE").read_bytes() @@ -103,6 +104,7 @@ def test_stage_runtime_copies_platform_payload( runtime_dir = destination / "src" / "deepseek_harness_runtime" / "runtime" assert {path.name: path.read_bytes() for path in runtime_dir.glob("dsh-jsonrpc-agent-pkg-*")} == expected pyproject = (destination / "pyproject.toml").read_text() + assert 'license = "MIT"' in pyproject assert 'license-files = ["LICENSE", "THIRD_PARTY_NOTICES.md"]' in pyproject assert (destination / "platforms.json").read_bytes() == ( ROOT / "python" / "sdk-runtime" / "platforms.json" diff --git a/scripts/build-python-release.py b/scripts/build-python-release.py index 755dc46c44..18660b3411 100644 --- a/scripts/build-python-release.py +++ b/scripts/build-python-release.py @@ -234,9 +234,9 @@ def verify_wheel( raise RuntimeError( f"{wheel} has distribution name {metadata.get('Name')}, expected {expected_distribution}" ) - if metadata.get("License-Expression") != "BSD-3-Clause": + if metadata.get("License-Expression") != "MIT": raise RuntimeError( - f"{wheel} has license expression {metadata.get('License-Expression')}, expected BSD-3-Clause" + f"{wheel} has license expression {metadata.get('License-Expression')}, expected MIT" ) expected_license_files = ["LICENSE"] if package == "sdk" else ["LICENSE", "THIRD_PARTY_NOTICES.md"] license_files = [Path(name).name for name in metadata.get_all("License-File") or []] diff --git a/scripts/gen-third-party-notices.ts b/scripts/gen-third-party-notices.ts index 613fc6ce85..f2411f5eff 100644 --- a/scripts/gen-third-party-notices.ts +++ b/scripts/gen-third-party-notices.ts @@ -691,7 +691,7 @@ export function render(): string { # Third-Party Notices -DeepSeek Harness is licensed under [BSD 3-Clause](LICENSE). It depends on the third-party software listed below. Each project remains under its own license; nothing in this file changes those terms. +DeepSeek Harness is licensed under [MIT](LICENSE). It depends on the third-party software listed below. Each project remains under its own license; nothing in this file changes those terms. This file lists **direct** dependencies declared by the workspace and the explicitly disclosed official Claude platform payload closure. It is generated from the workspace manifests by \`scripts/gen-third-party-notices.ts\`: a pre-commit hook regenerates it whenever a staged file changes one of its inputs, and \`scripts/gen-third-party-notices.spec.ts\` asserts in the test lane that the committed bytes match. Deleting a manifest runs no hook, so that case is caught by the assertion instead. Run \`pnpm run verify-third-party-notices\` for the standalone check. diff --git a/scripts/run-gates.spec.ts b/scripts/run-gates.spec.ts index d07385b744..f2218ad210 100644 --- a/scripts/run-gates.spec.ts +++ b/scripts/run-gates.spec.ts @@ -83,6 +83,15 @@ describe('gate graph validation', () => { expect(ids).toContain('public-repository-links') }) + it.each(['ci-primary', 'ci-static', 'check-all'] as const)( + 'keeps the DSH package license policy in %s', + (mode) => { + const ids = withPnpmEntrypoint(() => gatesForMode(mode).map(subject => subject.id)) + + expect(ids).toContain('dsh-package-licenses') + }, + ) + it('keeps native Windows coverage blocking while portability inventory remains observational', () => { const gates = withPnpmEntrypoint(() => gatesForMode('ci-windows-complete')) const byId = new Map(gates.map(subject => [subject.id, subject])) diff --git a/scripts/run-gates.ts b/scripts/run-gates.ts index 4290b5a428..e0b07041c0 100644 --- a/scripts/run-gates.ts +++ b/scripts/run-gates.ts @@ -246,6 +246,7 @@ function ciSharedStaticGates(): Gate[] { return [ pnpmScript('runtime-closure', 'verify-runtime-closure', { label: 'runtime closure' }), pnpmScript('constraints', 'constraints'), + pnpmScript('dsh-package-licenses', 'verify-dsh-package-licenses', { label: 'DSH package licenses' }), pnpmScript('package-invariants', 'verify-package-invariants', { label: 'package invariants' }), pnpmScript('cordis-config', 'verify-cordis-config', { label: 'Cordis config' }), pnpmScript('issue-management', 'test:issue-management', { label: 'Issue management policy' }), @@ -557,6 +558,7 @@ function hygieneLeafGates(options: { artifactNeeds?: string[] } = {}): Gate[] { pnpmScript('knip', 'knip'), pnpmScript('publint', 'publint', artifactOptions), pnpmScript('constraints', 'constraints'), + pnpmScript('dsh-package-licenses', 'verify-dsh-package-licenses', { label: 'DSH package licenses' }), pnpmScript('package-invariants', 'verify-package-invariants', { label: 'package invariants' }), builtPackageInvariantsGate(options.artifactNeeds), pnpmScript('node-next-types', 'verify-node-next-types', { diff --git a/scripts/snapshots/translation-prompt-v4/request-response.expected.json b/scripts/snapshots/translation-prompt-v4/request-response.expected.json index 21585b4930..586d082204 100644 --- a/scripts/snapshots/translation-prompt-v4/request-response.expected.json +++ b/scripts/snapshots/translation-prompt-v4/request-response.expected.json @@ -8,11 +8,11 @@ }, { "role": "user", - "content": "# DeepSeek Harness\n\nEnglish | [中文](README.zh.md)\n\nDeepSeek Harness (`dsh`) is an open-source coding agent and plugin-based agent harness.\n\nIt uses an architecture where **everything is a plugin**.\n\n## Internal testing notice\n\nDeepSeek Harness is under internal testing. Features and interfaces may change.\n\nSession Logs stay local by default. Set `DSH_TELEMETRY_MODE=FEEDBACK_ONLY` to share a Session Log only when submitting feedback, or `DSH_TELEMETRY_MODE=FULL` to upload continuously; `FULL` also enables dsh-sdk command telemetry reporting an anonymous ID, the command result, and redacted project configuration. Send feedback through the internal WeChat group.\n\n## Run\n\nInstall Node.js ^22.19 or >= 24 and pnpm 11, then run the published package:\n\n```sh\nnpx @deepseek-ai/dsh web\n```\n\nThe command initializes the Web profile and prints the Web UI URL, which is `http://127.0.0.1:3080` by default. Open it, add a DeepSeek API key under **Settings → Models**, then start a session. The invoking directory is the default workspace; try `Summarize this repository and identify its main packages.`\n\nContinue with the [Web UI guide](docs/user/guide/index.md).\n\n### Run from source\n\nTo run a repository checkout instead:\n\n```sh\ngit clone https://github.com/deepseek-ai/deepseek-harness.git\ncd deepseek-harness\npnpm install\npnpm run build\npnpm dsh web\n```\n\n`pnpm run build` prepares the repository artifacts. `pnpm dsh web` starts the Web UI without rebuilding and opens the same path.\n\n## Profiles and plugins\n\nA profile is an ordered list of plugin bundles. The shipped `web` profile powers `dsh web`. Manage a profile with `dsh plugin --profile `, which forwards the remaining arguments to pnpm in that profile's directory:\n\n```sh\nnpx -p @deepseek-ai/dsh dsh plugin --profile web add \nnpx -p @deepseek-ai/dsh dsh plugin --profile web remove \n```\n\n`add`, `remove`, `update`, `why`, and other pnpm commands work unchanged. The command initializes a missing profile before changing its packages and updates its bundle list from installed packages that declare `dsh.bundle`. See the [CLI reference](apps/cli/reference/README.md#plugin-management) for the exact behavior.\n\nThe [CLI reference](apps/cli/README.md) covers headless execution and custom profiles. The [Python SDK](python/README.md) and [examples](examples/README.md) cover programmatic and custom compositions.\n\n## Community\n\nFollow DeepSeek Harness on Twitter for project updates.\n\n## Development\n\nStart with the [development guide](docs/development.md) and read the [architecture](docs/architecture.md) before changing packages.\n\nFor agents, follow [AGENTS.md](AGENTS.md).\n\n## License\n\n[BSD 3-Clause](LICENSE)\n\nThird-party dependencies and their licenses are disclosed in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).\n\n## Contributing\n\nRead [CONTRIBUTING.md](CONTRIBUTING.md) before contributing to this repository.\n" + "content": "# DeepSeek Harness\n\nEnglish | [中文](README.zh.md)\n\nDeepSeek Harness (`dsh`) is an open-source agent harness developed by [DeepSeek AI](https://deepseek.com).\n\nIt uses an architecture where **everything is a plugin**, and is powered by [Cordis](https://github.com/cordiverse/cordis).\n\n## Developer preview\n\nDeepSeek Harness is currently in _developer preview_ and is iterating rapidly. **THERE WILL BE COMPATIBILITY-BREAKING CHANGES.**\n\n## Run\n\n### Run from `npm`\n\nInstall `Node.js`, then run:\n\n```sh\nnpx @deepseek-ai/dsh web\n```\n\nThe command starts the Web UI, served at `http://127.0.0.1:3080` by default. See [Web UI guide](docs/user/guide/index.md).\n\n### Run from source\n\nTo run from a repository checkout:\n\n```sh\ngit clone https://github.com/deepseek-ai/deepseek-harness.git\ncd deepseek-harness\npnpm install\npnpm run build\npnpm dsh web\n```\n\n## Community and support\n\n- Feel free to submit feedback or bug reports through [GitHub Discussions](https://github.com/deepseek-ai/deepseek-harness/discussions).\n- Add the [`dsh-plugin`](https://github.com/topics/dsh-plugin) topic to your plugin repository for discoverability.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Development\n\nStart with the [development guide](docs/development.md) and [architecture documentation](docs/architecture.md).\n\nFor agents, follow [AGENTS.md](AGENTS.md).\n\n## License\n\n[MIT](LICENSE)\n\nThird-party dependencies and their licenses are disclosed in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).\n" }, { "role": "assistant", - "content": "# DeepSeek Harness\n\n[English](README.md) | 中文\n\nDeepSeek Harness(`dsh`)是一款开源 coding agent(编程智能体),也是一个基于插件的 agent harness(智能体框架)。\n\n它采用了**一切皆插件**的架构。\n\n## 内测说明\n\nDeepSeek Harness 正处于内部测试阶段,功能和接口可能发生变化。\n\nSession Log 默认留在本地。设置 `DSH_TELEMETRY_MODE=FEEDBACK_ONLY` 可仅在提交反馈时共享 Session Log,设置 `DSH_TELEMETRY_MODE=FULL` 可持续上传;`FULL` 同时会启用 dsh-sdk 命令遥测,上报匿名 ID、命令结果以及脱敏后的项目配置。请通过内部企业微信群反馈问题和建议。\n\n\n## 运行\n\n请先安装 Node.js(版本要求:`^22.19` 或 `>=24`)和 pnpm 11,然后运行已发布的包:\n\n```sh\nnpx @deepseek-ai/dsh web\n```\n\n该命令会初始化 Web profile 并打印 Web UI 地址,默认地址为 `http://127.0.0.1:3080`。打开该地址,在**设置 → 模型**中添加 DeepSeek API 密钥,然后启动一个会话。运行命令时所在的目录将作为默认工作区;你可以尝试输入 `Summarize this repository and identify its main packages.`。\n\n下一步请阅读 [Web UI 指南](docs/user/guide/index.md)。\n\n### 从源码运行\n\n如需从仓库源码运行:\n\n```sh\ngit clone https://github.com/deepseek-ai/deepseek-harness.git\ncd deepseek-harness\npnpm install\npnpm run build\npnpm dsh web\n```\n\n`pnpm run build` 会准备仓库产物。`pnpm dsh web` 不会重新构建,而是直接启动同一个 Web UI。\n\n## Profile 与插件\n\nprofile 由一组按顺序排列的插件组合包构成。随附的 `web` profile 用于运行 `dsh web`。使用 `dsh plugin --profile ` 管理 profile;该命令会在对应 profile 目录中将剩余参数转发给 pnpm:\n\n```sh\nnpx -p @deepseek-ai/dsh dsh plugin --profile web add \nnpx -p @deepseek-ai/dsh dsh plugin --profile web remove \n```\n\n`add`、`remove`、`update`、`why` 等 pnpm 命令均可直接使用。该命令会先初始化不存在的 profile,再修改其中的包,并根据声明了 `dsh.bundle` 的已安装包更新 bundle 列表。具体行为见 [CLI 参考](apps/cli/reference/README.md#plugin-management)。\n\n[CLI(命令行界面)参考](apps/cli/README.md)介绍 headless 执行与自定义 profile。[Python SDK](python/README.md) 和[示例](examples/README.md)介绍程序化组合与自定义组合。\n\n## 社区\n\n扫描二维码,或打开 DeepSeek Harness 微信社区申请页面 申请加入。\n\n

\n \"DeepSeek\n

\n\n## 开发\n\n请先阅读[开发指南](docs/development.md);修改包之前,请阅读[架构文档](docs/architecture.md)。\n\n面向 agent:遵循 [AGENTS.md](AGENTS.md)。\n\n## 许可证\n\n[BSD 3-Clause](LICENSE)\n\n第三方依赖及其许可证见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。\n\n## 参与贡献\n\n向本仓库贡献前,请阅读 [CONTRIBUTING.md](CONTRIBUTING.md)。\n" + "content": "# DeepSeek Harness\n\n[English](README.md) | 中文\n\nDeepSeek Harness(`dsh`)是由 [DeepSeek AI](https://deepseek.com) 开发的开源 agent harness(智能体框架)。\n\n它采用**一切皆插件**的架构,并由 [Cordis](https://github.com/cordiverse/cordis) 驱动。\n\n## 开发者预览\n\nDeepSeek Harness 目前处于 _开发者预览_ 阶段,正在快速迭代。**未来将出现破坏兼容性的变更。**\n\n## 运行\n\n### 通过 `npm` 运行\n\n安装 `Node.js`,然后运行:\n\n```sh\nnpx @deepseek-ai/dsh web\n```\n\n该命令会启动 Web UI,默认地址为 `http://127.0.0.1:3080`。详见 [Web UI 指南](docs/user/guide/index.md)。\n\n### 从源码运行\n\n如需从仓库源码运行:\n\n```sh\ngit clone https://github.com/deepseek-ai/deepseek-harness.git\ncd deepseek-harness\npnpm install\npnpm run build\npnpm dsh web\n```\n\n## 社区与支持\n\n- 欢迎通过 [GitHub Discussions](https://github.com/deepseek-ai/deepseek-harness/discussions) 提交反馈或 bug 报告。\n- 为你的插件仓库添加 [`dsh-plugin`](https://github.com/topics/dsh-plugin) 主题,便于被发现。\n\n## 参与贡献\n\n参见 [CONTRIBUTING.md](CONTRIBUTING.md)。\n\n## 开发\n\n请先阅读[开发指南](docs/development.md)与[架构文档](docs/architecture.md)。\n\n面向 agent:请遵循 [AGENTS.md](AGENTS.md)。\n\n## 许可证\n\n[MIT](LICENSE)\n\n第三方依赖及其许可证见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。\n" }, { "role": "user", diff --git a/scripts/verify-dsh-package-licenses.spec.ts b/scripts/verify-dsh-package-licenses.spec.ts new file mode 100644 index 0000000000..d7520ee2e5 --- /dev/null +++ b/scripts/verify-dsh-package-licenses.spec.ts @@ -0,0 +1,59 @@ +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { dirname, join } from 'node:path' +import { afterEach, describe, expect, it } from 'vitest' +import { inspectDshPackageLicenses } from './verify-dsh-package-licenses.ts' + +const roots: string[] = [] + +afterEach(() => { + for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true }) +}) + +function writeManifest(root: string, file: string, manifest: Record): void { + const path = join(root, file) + mkdirSync(dirname(path), { recursive: true }) + writeFileSync(path, `${JSON.stringify(manifest, null, 2)}\n`) +} + +function createWorkspace(): string { + const root = mkdtempSync(join(tmpdir(), 'dsh-package-licenses-')) + roots.push(root) + writeManifest(root, 'package.json', { + name: '@deepseek-ai/dsh-root', + license: 'MIT', + workspaces: ['apps/*', 'packages/*/*', 'vendor/*'], + }) + return root +} + +describe('DSH package license gate', () => { + it('checks root, unhyphenated CLI, and dsh-prefixed package names while ignoring other families', () => { + const root = createWorkspace() + writeManifest(root, 'apps/cli/package.json', { name: '@deepseek-ai/dsh', license: 'MIT' }) + writeManifest(root, 'packages/core/agent/package.json', { + name: '@deepseek-ai/dsh-agent', + license: 'BSD-3-Clause', + }) + writeManifest(root, 'vendor/cordis/package.json', { + name: '@deepseek-ai/cordis', + license: 'BSD-3-Clause', + }) + + expect(inspectDshPackageLicenses(root)).toEqual({ + packageCount: 3, + failures: [ + 'packages/core/agent/package.json: @deepseek-ai/dsh-agent must declare "license": "MIT"; found "BSD-3-Clause".', + ], + }) + }) + + it('rejects a missing license declaration', () => { + const root = createWorkspace() + writeManifest(root, 'packages/core/agent/package.json', { name: '@deepseek-ai/dsh-agent' }) + + expect(inspectDshPackageLicenses(root).failures).toEqual([ + 'packages/core/agent/package.json: @deepseek-ai/dsh-agent must declare "license": "MIT"; found undefined.', + ]) + }) +}) diff --git a/scripts/verify-dsh-package-licenses.ts b/scripts/verify-dsh-package-licenses.ts new file mode 100644 index 0000000000..e4206c30db --- /dev/null +++ b/scripts/verify-dsh-package-licenses.ts @@ -0,0 +1,89 @@ +/** + * Enforce the MIT license declaration for repository-owned DSH npm packages. + * @module scripts/verify-dsh-package-licenses + */ + +import { globSync, readFileSync } from 'node:fs' +import { resolve, sep } from 'node:path' + +const ROOT = resolve(import.meta.dirname, '..') +const DSH_PACKAGE_NAME = /^@deepseek-ai\/dsh(?:-|$)/ + +/** Result of checking every DSH package reachable through the root workspace list. */ +export interface DshPackageLicenseReport { + /** Number of DSH package manifests checked. */ + packageCount: number + /** Repository-relative diagnostics for non-MIT declarations. */ + failures: string[] +} + +function readManifest(root: string, file: string): Record { + const parsed: unknown = JSON.parse(readFileSync(resolve(root, file), 'utf8')) + if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) { + throw new Error(`verify-dsh-package-licenses: ${file} must contain a JSON object.`) + } + return parsed as Record +} + +function isStringArray(value: unknown): value is string[] { + return Array.isArray(value) && value.every((entry: unknown) => typeof entry === 'string') +} + +function workspaceManifestPaths(root: string): string[] { + const rootManifest = readManifest(root, 'package.json') + const workspaces = rootManifest.workspaces + if (!isStringArray(workspaces)) { + throw new Error('verify-dsh-package-licenses: package.json workspaces must be a string array.') + } + + const files = new Set(['package.json']) + for (const pattern of workspaces) { + for (const file of globSync(`${pattern}/package.json`, { cwd: root })) { + files.add(file) + } + } + return [...files].sort() +} + +function printable(value: unknown): string { + return value === undefined ? 'undefined' : JSON.stringify(value) +} + +/** + * Check every DSH npm package declared by the repository workspace. + * @param root - absolute repository root containing the workspace package.json. + * @returns the checked package count and every non-MIT declaration. + */ +export function inspectDshPackageLicenses(root: string): DshPackageLicenseReport { + let packageCount = 0 + const failures: string[] = [] + + for (const file of workspaceManifestPaths(root)) { + const manifest = readManifest(root, file) + const name = manifest.name + if (typeof name !== 'string' || !DSH_PACKAGE_NAME.test(name)) continue + + packageCount++ + if (manifest.license !== 'MIT') { + const normalizedFile = file.split(sep).join('/') + failures.push( + `${normalizedFile}: ${name} must declare "license": "MIT"; found ${printable(manifest.license)}.`, + ) + } + } + + return { packageCount, failures } +} + +if (process.argv[1] && import.meta.filename === resolve(process.argv[1])) { + const report = inspectDshPackageLicenses(ROOT) + if (report.failures.length > 0) { + process.stderr.write('verify-dsh-package-licenses: non-MIT DSH package declarations found:\n') + for (const failure of report.failures) process.stderr.write(` ${failure}\n`) + process.exitCode = 1 + } else { + process.stdout.write( + `verify-dsh-package-licenses: ${String(report.packageCount)} DSH package(s) checked; all declare MIT.\n`, + ) + } +} diff --git a/website/.vitepress/config.ts b/website/.vitepress/config.ts index e451ecb68c..86e22c7706 100644 --- a/website/.vitepress/config.ts +++ b/website/.vitepress/config.ts @@ -5,7 +5,7 @@ import { resolve } from 'node:path' import type { DefaultTheme, PageData } from 'vitepress' import type { ViteDevServer } from 'vite' import { withMermaid } from 'vitepress-plugin-mermaid' -import { landingLink, orderedPages, routeLink, sectionSpec, type DocsLocale, type DocsPage } from '../docs.ts' +import { landingLink, orderedPages, routeLink, sectionSpec, type DocsLocale, type DocsPage, type DocsSidebar } from '../docs.ts' import { docsSourceFiles, projectDocs } from '../../scripts/project-doc-site.ts' projectDocs() @@ -31,6 +31,77 @@ function sidebar(locale: DocsLocale, collection: NonNullable + +/** + * Guide sidebar with direct links into the first development and reference pages. + * + * @param locale - Route tree whose guide sidebar is being built. + * @returns Guide groups followed by top-level links to the other documentation modules. + */ +function guideSidebar(locale: DocsLocale): DefaultTheme.SidebarItem[] { + const { guide, develop, reference } = guideModules[locale] + return [ + ...sidebar(locale, guide), + ...[develop, reference].map(({ label, collection }) => ({ + text: label, + link: landingLink(locale, collection), + })), + ] +} + +/** + * Navigation-bar items for the modules the guide sidebar links into, reading + * their labels and collections from the shared per-locale record. + * + * @param locale - Route tree the navigation items belong to. + * @returns The module items for the locale's navigation bar. + */ +function moduleNav(locale: DocsLocale): DefaultTheme.NavItem[] { + const { develop, reference } = guideModules[locale] + const routePrefix = locale === 'root' ? '' : '/en' + return [ + { text: develop.label, link: landingLink(locale, develop.collection), activeMatch: `^${routePrefix}/develop/` }, + { text: reference.label, link: landingLink(locale, reference.collection), activeMatch: `^${routePrefix}/reference/` }, + ] +} + function watchCanonicalDocs(server: ViteDevServer): void { const sources = docsSourceFiles() server.watcher.add(sources) @@ -196,12 +267,11 @@ export default withMermaid({ themeConfig: { siteTitle: siteTitle('技术预览'), nav: [ - { text: '入门', link: landingLink('root', 'zh-guide'), activeMatch: '^/guide/' }, - { text: '开发', link: landingLink('root', 'zh-develop'), activeMatch: '^/develop/' }, - { text: '参考', link: landingLink('root', 'zh-reference'), activeMatch: '^/reference/' }, + { text: '入门', link: landingLink('root', guideModules.root.guide), activeMatch: '^/guide/' }, + ...moduleNav('root'), ], sidebar: { - '/guide/': sidebar('root', 'zh-guide'), + '/guide/': guideSidebar('root'), '/develop/': sidebar('root', 'zh-develop'), '/reference/': sidebar('root', 'zh-reference'), }, @@ -223,12 +293,11 @@ export default withMermaid({ themeConfig: { siteTitle: siteTitle('Preview'), nav: [ - { text: 'Guide', link: landingLink('en', 'en-guide'), activeMatch: '^/en/guide/' }, - { text: 'Develop', link: landingLink('en', 'en-develop'), activeMatch: '^/en/develop/' }, - { text: 'Reference', link: landingLink('en', 'en-reference'), activeMatch: '^/en/reference/' }, + { text: 'Guide', link: landingLink('en', guideModules.en.guide), activeMatch: '^/en/guide/' }, + ...moduleNav('en'), ], sidebar: { - '/en/guide/': sidebar('en', 'en-guide'), + '/en/guide/': guideSidebar('en'), '/en/develop/': sidebar('en', 'en-develop'), '/en/reference/': sidebar('en', 'en-reference'), },